Search code examples
openglwindowxlibglx

Xlib's `Window` vs. GLX's `GLXWindow` confusion


I'm looking through all sorts of example codes for OpenGL context creation with GLX and I'm confused about the two types of window objects: Window used by Xlib and GLXWindow used by GLX, because in some example codes they use Xlib's windows directly for rendering, while in others they additionally create GLX's windows.
My questions are:

  1. What's the difference between those two?
  2. Do I need to create both, or just Window will do?

The GLX 1.4 documentation (are there any more recent ones?) tells me to create the GLXWindow using glXCreateWindow, and this one takes Window as its third parameter. I'm not sure if this is supposed to be a parent window for GLXWindow, or that the Window is getting "wrapped" by GLXWindow, the documentation seems to be unclear on this. Does anyone know how is this supposed to work and the rationale behind it? And why some examples use GLXWindows, and some of them don't, and yet they still seem to be working just fine?

Another thing that confuses me is that some examples use glXCreateContext for creating their OpenGL contexts, while others (including the GLX 1.4 specification) use glXCreateNewContext. Both seem to be available in my version of the library, but I don't quite get what's the difference between them.

There's also glXMakeCurrent and glXMakeContextCurrent – another source of confusion for me.

Could anyone please explain me the differences between these slightly differently spelled functions / types, or send me to some online resources where I could learn about that myself?

Oh, one more thing: Is this stuff still relevant for modern OpenGL (the 3.0+, programmable pipeline one)? Or just some legacy junk I shouldn't be bashing my poor pony head against? :q


Solution

  • As I never hear about GLXWindow, I become curious what is it. Most discussions, do not clarify why this one is necessary, and spread only guesses, including my answer.

    First thing to clarify, is that GLXWindow has been introduced in GLX 1.3. Older versions, including GLX 1.2 define the following list of GLXDrawable: {Window, GLXPixmap}, with GLXPixmap created from off-screen X Pixmap. Specs does not clarify why GLXPixmap is needed on top of X Pixmap, while X Window can be used directly, but the guess is that something is missing in X Pixmap definition, which GLX needs to store within GLXPixmap...

    GLX 1.3 extended the definition of GLXDrawable as { GLXWindow, GLXPixmap, GLXPbuffer, Window }. So that you can see a new item GLXPbuffer, which was an attempt to improve off-screen rendering before Frame Buffer Objects (FBO) was introduced in OpenGL itself. Unlike pixmaps and windows, GLXPbuffer is created from scratch and has no relation in X. There is also a new GLXWindow with the note:

    For backwards compatibility with GLX versions 1.2 and earlier, a rendering context can also be used to render into a Window.

    So that GLXWindow looks more like an attempt to unify API (and internal logic) across all GLXDrawable, rather than a tool which fixes something, as it doesn't extend capabilities of X Window from a first glance.

    Does GLXWindow introduce something new? Actually, it does! GLX 1.3 also introduced a new function glXSelectEvent(), which allows to process GLX-specific events within X11 stream. So that the function works with GLXWindow and GLXPbuffer, but not with X Window (as it has been specifically created to distinguish GLX events from normal ones). Confusingly, the only GLX-specific event defined by specs is of type GLXPbufferClobberEvent, which seems more relevant to obsolete PBuffers and Window ancillary buffers (replaced by FBOs nowadays in core OpenGL specs).

    Therefore, personally I see no any practical reason for creating GLXWindow instead of using X Window itself rather than just following GLX specs recommendation (stating that using X Window is only for compatibility with applications written against older GLX versions) and using "cleaned up" API.

    Concerning glXCreateNewContext() vs glXCreateContext(), this is related to introduction of GLXFBConfig, as X Visual definition has been found insufficient to represent all necessary details. From specs:

    Calling glXCreateContext(dpy, visual, share list, direct) is equivalent to calling glXCreateNewContext(dpy, config, render type, share list, direct) where config is the GLXFBConfig identified by the GLX_FBCONFIG_ID attribute of visual.

    Concerning glXMakeCurrent() vs glXMakeContextCurrent(), the latter one introduced by newer GLX versions allows using different drawable and readable buffers in similar way as modern FBOs allow this, which is also clear from specs:

    Calling glXMakeCurrent(dpy, draw, ctx) is equivalent to calling glXMakeContextCurrent(dpy, draw, draw, ctx). Note that draw will be used for both the draw and read drawable.

    Concerning modern OpenGL 3+ usage, GLX is no problem here - just use GLX extensions like GLX_ARB_create_context_profile to create context (current Mesa library implementation provides higher OpenGL versions when creating Core Profile, but there usually no such different in case of proprietary drivers).

    Of course, you may consider using EGL instead (but it rather limits OpenGL context abilities as some options are missing compared to GLX) or Wayland/Mir stuff, if you are fanatic to new display servers and want to get rid of X from dependencies (Wayland implements Xlib compatibility layer, so that it is not a show stopper for now).