How to Use Opengl Without a Window Manager in Linux

How to use OpenGL without a window manager in Linux?

You don't have to install Gnome or KDE. These are used to managed windows, and you can launch graphical applications without having a window manager.

Therefore, you'll have to install a X server. The X server is responsible of drawing things on your screen. Without X server, you can't launch graphical applications.

Once X has been installed, launch it, export your DISPLAY environment variable, and the rest is like writing an OpenGL application which runs full screen :-)

OpenGL without X.org in linux

Update (Sep. 17, 2017):

NVIDIA recently published an article detailing how to use OpenGL on headless systems, which is a very similar use case as the question describes.

In summary:

  • Link to libOpenGL.so and libEGL.so instead of libGL.so. (Your linker options should therefore be -lOpenGL -lEGL
  • Call eglGetDisplay, then eglInitialize to initialize EGL.
  • Call eglChooseConfig with the config attribute EGL_SURFACE_TYPE followed with EGL_PBUFFER_BIT.
  • Call eglCreatePbufferSurface, then eglBindApi(EGL_OPENGL_API);, then eglCreateContext and eglMakeCurrent.

From that point on, do your OpenGL rendering as usual, and you can blit your pixel buffer surface wherever you like. This supplementary article from NVIDIA includes a basic example and an example for multiple GPUs. The PBuffer surface can also be replaced with a window surface or pixmap surface, according to the application needs.

I regret not doing more research on this on my previous edit, but oh well. Better answers are better answers.


Since my answer in 2010, there have been a number of major shakeups in the Linux graphics space. So, an updated answer:

Today, nouveau and the other DRI drivers have matured to the point where OpenGL software is stable and performs reasonably well in general. With the introduction of the EGL API in Mesa, it's now possible to write OpenGL and OpenGL ES applications on even Linux desktops.

You can write your application to target EGL, and it can be run without the presence of a window manager or even a compositor. To do so, you would call eglGetDisplay, eglInitialize, and ultimately eglCreateContext and eglMakeCurrent, instead of the usual glx calls to do the same.

I do not know the specific code path for working without a display server, but EGL accepts both X11 displays and Wayland displays, and I do know it is possible for EGL to operate without one. You can create GL ES 1.1, ES 2.0, ES 3.0 (if you have Mesa 9.1 or later), and OpenGL 3.1 (Mesa 9.0 or later) contexts. Mesa has not (as of Sep. 2013) yet implemented OpenGL 3.2 Core.

Notably, on the Raspberry Pi and on Android, EGL and GL ES 2.0 (1.1 on Android < 3.0) are supported by default. On the Raspberry Pi, I don't think Wayland yet works (as of Sep. 2013), but you do get EGL without a display server using the included binary drivers. Your EGL code should also be portable (with minimal modification) to iOS, if that interests you.


Below is the outdated, previously accepted post:

I'd like to open an OpenGL context without X in linux. Is there any way at all to do it?

I believe Mesa provides a framebuffer target. If it provides any hardware acceleration at all, it will only be with hardware for which there are open source drivers that have been adapted to support such a use.

Gallium3D is also immature, and support for this isn't even on the roadmap, as far as I know.

I'd like to get a solution that works with nvidia cards.

There isn't one. Period.

NVIDIA only provides an X driver, and the Nouveau project is still immature, and doesn't support the kind of use that you're looking for, as they are currently focused only on the X11 driver.

Launch OpenGL app straight from a windowless Linux Terminal

There are several parts to your task. Keep in mind that some of this can be very distro-specific; but since you said Ubuntu we'll talk Ubuntu!

Also you tagged this question C however I am starting off with a common Linux pattern: a native application with a Bash shell script wrapper. Perhaps once you get things working well you might fold that functionality into C if you have to.

Detecting whether X is running

Being root can help a lot. Some things that work.

  1. pgrep Xorg
  2. Check whether /var/lib/gdm/:0.Xauth exists. This will be there even if nobody has logged in but GDM is running.
  3. ls -l /home/*/.Xauthority (Even if you're not root you can at least confirm whether you are running X.

Piggybacking an existing X session

You did not specifically mention it but if you are root at the console, or if you want to run the app as the same user who is already logged in, it's pretty easy.

You have to get the DISPLAY and XAUTHORITY environment variables right, and once you do you can use the existing X display.

For DISPLAY you might just assume :0 or you could find an existing X program (x-session-manager is the GNOME standard) and read its environment from /proc/PID/environ. Variables are in key=value format delimited by a null byte. For example, if its PID is 12345:

cat /proc/12345/environ \
| ruby -ne 'puts $_.split("\0").select {|e| e.starts_with? "DISPLAY=" }'

For XAUTHORITY you could get it the same way. Or if you prefer guessing, it's almost always /home/whoever/.Xauthority

Once you have those two variables, running X code is easy, for example:

env DISPLAY=:0 XAUTHORITY=/home/brian/.Xauthority ./visualdiagnostics

Stopping X

This one is easy if you're root: /etc/init.d/gdm stop. killall Xorg will work too.

If you are a user, kill your own Xorg or x-session-manager process. (I'd welcome input from others for the canonical way to do this. Maybe some dbus-send message?)

Starting X

I would recommend xinit whose goal in life is to fire X and run exactly one program.

For example: xinit ./visualdiagnostics

You can also tell xinit what resolution to run X at which may or may not be important to you. (This becomes important in the full-screen section below.)

The problem with this is you will have no window manager— no maximize and minimize buttons. It's not just cosmetic. Usually an app is useless because a popup window cannot be moved or you cannot focus on the right input field. However if you have a special app it could be sufficient (see full-screen below).

The next step would be my answer to everything: another shell script wrapper! Something simple that starts the window manager and then becomes your program should work.

#!/bin/bash
#
# Start visualdiagnostics once xinit calls me.

/usr/bin/metacity& # Or ratpoison, or fluxbox, or compiz, etc.
exec ./visualdiagnostics

It's important to exec (become) the main program because once that first program exits, X will shut down.

Running fullscreen

I am not 100% certain on this. Some ideas:

  • Try the standard X -geometry parameters to set 0,0 as the upper-left corner and +x+y for your horizontal and vertical size. How do you know the size? Either you hard-coded it when you launched xinit or you could ask the X server. xwininfo -root will tell you and there is an xlib API call that would do that too—check the xwininfo source I guess.
  • Your app itself can request maximization and/or resizing to fill the screen. I'm not familiar but it is definitely in the X API.
  • Some of the more configurable window managers can be pre-configured to run you maximized already. This is probably what I personally would check first. Your wrapper script could create a $HOME/.fluxboxrc just by echoing some hard-coded configs > the file.

Summary

The others are right. X is not strictly necessary sine OpenGL can run against a framebuffer. However considering how ubiquitous X is and how much work has gone into automating it for distributions, I would probably invest my effort into the X route as it might be easier long-term even though it's a little convoluted.

(By the way, I sincerely hope when you say "terminal" you mean you are at the text console, not gnome-terminal that would be awful! :)

Linux draw on screen independent of windows manager

Create a regular window. Tell the WM to skip decorations ant to keep the window always on top. Use XFixesSetWindowShapeRegion() to separately set a circular output region and an empty input region. You need a compositing window manager XFixes extensions for this to work.

You can also make your window semi-transparent (this needs a compositing window manager).

A modern toolkit such as gtk should have easy to use APIs to do all of the above.

No OpenGL is needed at any stage.

Initializing OpenGL without GLUT

As luke noted, the code to create and bind the context is specific to each windowing platform.

Here are some functions to get you started in terms of initializing OpenGL on specific platforms:

Windows (a tutorial is here)

  • wglCreateContext(hDC)

Mac OS X -- OS X has essentially three options: Carbon, Cocoa, and the underlying Core Graphics Layer

  • The entire guide for Mac OS X OpenGL development
  • Carbon: aglCreateContext
  • Cocoa: Create (or subclass) an NSOpenGLView. They create their own context, and you can read their method documentation to find how to make it current.
  • CoreGraphicsLayer: CGLCreateContext

Linux

  • glx: glXCreateContext

OpenGL rendering - a window out ot the screen

When I draw a triangle and part (or whole) of that primitive is placed outside a viewing volume OpenGL performs clipping (before rasterization).

Clipping is a geometrical operation. When it comes to rasterization, everything happens on the pixel level.

It all comes down to Pixel Ownership.

In a plain, not composited windowing system, all windows share the same screen framebuffer. Each window is, well, a window (offset + size) into the screen framebuffer. When things get drawn to a window, using OpenGL or not, for every pixel it is tested if this pixel of the framebuffer actually belongs to the window; if some other, logical (and visible) window is in front, the pixel ownership tests will fail for these pixels and nothing gets drawn there (so that the window in front doesn't get overdrawn). That's why in a plain, uncomposited environment you can "screenshot" windows overlaying your OpenGL window with glReadPixels, because effectively that part of the framebuffer handed to OpenGL actually belongs to another window, but OpenGL doesn't know this.

Similarly, if a window is moved partially or completely off screen, the off-screen pixels will fail the pixel ownership test and nothing gets drawn there.

What happens if I use compositing window manager

Then every window has its very own framebuffer, which it completely owns. Pixel Ownership tests will never fail. You figure the rest.

What happenns in that OpenGL application?

To OpenGL it looks like all the pixels pass the ownership test when rasterizing. That's it.

Is there any GPU usage?

Pixel ownership test is so important, that even long before there were GPUs, the first generation of graphics cards did have the functionality required to implement pixel ownership tests. The function is easy to implement and hardwired so there's no difference with that regard.

However the more pixels fail the test, i.e. are not being touch, the less the GPU has to work in rasterization stage, to rendering throughput actually increases if the window is obscured or partially moved off-screen in a non-composited environment.

Backgroundless and Windowless OpenGL application

What do you mean by "windowless". A window is the (rectangular) region on screen to which you can draw with drawing operations. From your question however I have the impression, that you're actually asking about creating a window without decorations (i.e. title bar, etc.).

In Linux, or more precisely X11, the appearance of a window is controlled by two things: The Extended Window Manager Hints (EMWH) for a window under control of the window manager; the window manager is the actual program responsible for drawing the decorations and borders. And the Redirection Override flag, which controls, if a window actually gets to be under the control of a window manager. If you're asking about "backgroundless", then I presume you mean, transparent. First have a look at this video I made: http://www.youtube.com/watch?v=iHZfH1Qhonk Is this what you're after? Then what you actually want is a window with an Alpha channel in its framebuffer config (X11 XRender FBConfig), together with a compositing manager (which can, but isn't required to be a part of the window manager). The sourcecode for this program can be found at https://github.com/datenwolf/codesamples/tree/master/samples/OpenGL/x11argb_opengl_glsl

Or are you actually asking about a OpenGL context to which you can render a picture, but without it appearing on screen? That would then be an off-screen context and there are two ways for implementing this with X11:

  • Using a windowless PBuffer X11 drawable for the context

  • Using a hidden window together with a OpenGL Framebuffer Object

Both methods have each their pros and cons.



Related Topics



Leave a reply



Submit