GLXINTRO(3G)

πŸ“¦ version 1.1, in centos-stream 9, fedora 43, fedora 44

πŸ‘‘ NAME πŸ‘‘

glXIntro β€” your little intro to OpenGL in the X window system. It lives in the 3G corner of the manual, and it's basically the group chat invite to the whole GLX saga. πŸ’–


🌈 OVERVIEW 🌈

Okay so bestie, listen. OpenGL (which other pages just call GL) is a high-performance, 3D-oriented renderer. In the X window system you get to it through the GLX extension. ✨

Wanna know if your X server even supports GLX, and if so, which version? Call glXQueryExtension and glXQueryVersion. That's the vibe check. πŸ”

GLX-extended servers make a subset of their visuals available for OpenGL rendering. And the drawables you create with those visuals? They can also be rendered with the core X renderer, plus the renderer of any other X extension that's compatible with all core X visuals. Versatile icon behaviour. πŸ’…

GLX also extends drawables with a bunch of buffers beyond the standard color buffer. We're talking:

  • back color buffers
  • auxiliary color buffers
  • a depth buffer
  • a stencil buffer
  • a color accumulation buffer

Some or all of these are included in each X visual that supports OpenGL. πŸŽ€

So, to render with OpenGL into an X drawable, first you gotta choose a visual that defines the OpenGL buffers you need. Use glXChooseVisual to make that selection easier. Need more control over the selection process? Then use XGetVisualInfo and glXGetConfig to pick among all the available visuals. 🧚

Then use that selected visual to create both a GLX context and an X drawable:

  • GLX contexts β†’ glXCreateContext
  • drawables β†’ XCreateWindow or glXCreateGLXPixmap

Finally, bind the context and the drawable together with glXMakeCurrent. That context/drawable pair becomes the current context and current drawable, and it's what all OpenGL commands use until glXMakeCurrent gets called again with different arguments. πŸ‘‘

Both core X commands and OpenGL commands can operate on the current drawable. BUT β€” and this is the part that matters β€” the X and OpenGL command streams are not synchronized, except at explicitly created boundaries generated by calling glXWaitGL, glXWaitX, XSync, and glFlush. No cap. 🚧


πŸ“ EXAMPLES πŸ“

Below is the minimum code required to create an RGBA-format X window that's compatible with OpenGL and to clear it to yellow. πŸ’›

The code is correct, but it does not include any error checking. Return values dpy, vi, cx, cmap, and win should all be tested. Fr fr. Test them. πŸ™ˆ
#include <GL/glx.h> #include <GL/gl.h> #include <unistd.h>

static int attributeListSgl[] = {      GLX_RGBA,      GLX_RED_SIZE,   1,
/*get the deepest buffer with 1 red bit*/      GLX_GREEN_SIZE, 1,
     GLX_BLUE_SIZE,  1,      None };

static int attributeListDbl[] = {      GLX_RGBA,      GLX_DOUBLE_BUFFER,
/*In case single buffering is not supported*/      GLX_RED_SIZE,   1,
     GLX_GREEN_SIZE, 1,      GLX_BLUE_SIZE,  1,      None };

static Bool WaitForNotify(Display *d, XEvent *e, char *arg) {
    return (e->type == MapNotify) && (e->xmap.window == (Window)arg); }

int main(int argc, char **argv) {
    Display *dpy;
    XVisualInfo *vi;
    Colormap cmap;
    XSetWindowAttributes swa;
    Window win;
    GLXContext cx;
    XEvent event;
    int swap_flag = FALSE;

    /* get a connection */
    dpy = XOpenDisplay(0);

    /* get an appropriate visual */
    vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributeListSgl);
    if (vi == NULL) {
       vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributeListDbl);
       swap_flag = TRUE;
    }

    /* create a GLX context */
    cx = glXCreateContext(dpy, vi, 0, GL_TRUE);

    /* create a color map */
    cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen),
                  vi->visual, AllocNone);

    /* create a window */
    swa.colormap = cmap;
    swa.border_pixel = 0;
    swa.event_mask = StructureNotifyMask;
    win = XCreateWindow(dpy, RootWindow(dpy, vi->screen), 0, 0, 100,
100,
                        0, vi->depth, InputOutput, vi->visual,
                        CWBorderPixel|CWColormap|CWEventMask, &swa);
    XMapWindow(dpy, win);
    XIfEvent(dpy, &event, WaitForNotify, (char*)win);

    /* connect the context to the window */
    glXMakeCurrent(dpy, win, cx);

    /* clear the buffer */
    glClearColor(1,1,0,1);
    glClear(GL_COLOR_BUFFER_BIT);
    glFlush();
    if (swap_flag) glXSwapBuffers(dpy,win);

    /* wait a while */
    sleep(10); }

πŸ’€ NOTES πŸ’€

  • A color map must be created and passed to XCreateWindow. See the example code right above, bestie, it's all there. 🎨
  • A GLX context must be created and attached to an X drawable before OpenGL commands can be executed. OpenGL commands issued while no context/drawable pair is current result in undefined behavior. Like, not a vibe. Don't do it. 😭
  • Exposure events indicate that all buffers associated with the specified window may be damaged and should be repainted. Some buffers of some visuals on some systems may never require repainting (the depth buffer, for example) β€” but it is incorrect to write a program assuming these buffers will not be damaged. Assume damage. Always. 🫢
  • GLX commands manipulate XVisualInfo structures rather than pointers to visuals or visual IDs. XVisualInfo structures contain visual, visualID, screen, and depth elements, plus other X-specific information. πŸ“¦

🌸 USING GLX EXTENSIONS 🌸

All supported GLX extensions have a corresponding definition in glx.h and a token in the extension string returned by glXQueryExtensionsString. For example: if the EXT_visual_info extension is supported, then this token is defined in glx.h and EXT_visual_info appears in the extension string returned by glXQueryExtensionsString. ✨

The definitions in glx.h can be used at compile time to determine if procedure calls corresponding to an extension exist in the library.

OpenGL itself has also been extended. Refer to glIntro for more information. πŸ¦‹


⭐ GLX 1.1 and GLX 1.2 ⭐

GLX 1.2 is now supported. It is backward compatible with GLX 1.1 and GLX 1.0. Slay.

  • GLX 1.2 corresponds to OpenGL version 1.1 and introduces the following new call: glGetCurrentDisplay.
  • GLX 1.1 corresponds to OpenGL version 1.0 and introduces the following new calls: glXQueryExtensionsString, glXQueryServerString, and glXGetClientString.

Call glQueryVersion to determine at runtime what version of GLX is available. glQueryVersion returns the version that is supported on the connection. So if 1.2 comes back, both the client and server support GLX 1.2. πŸ‘―

You can also check the GLX version at compile time: GLX_VERSION_1_1 will be defined in glx.h if GLX 1.1 calls are supported, and GLX_VERSION_1_2 will be defined if GLX 1.2 calls are supported. πŸŽ€


πŸŽ€ SEE ALSO πŸŽ€

glIntro, glFinish, glFlush, glXChooseVisual, glXCopyContext, glXCreateContext, glXCreateGLXPixmap, glXDestroyContext, glXGetClientString, glXGetConfig, glXIsDirect, glXMakeCurrent, glXQueryExtension, glXQueryExtensionsString, glXQueryServerString, glXQueryVersion, glXSwapBuffers, glXUseXFont, glXWaitGL, glXWaitX, XCreateColormap, XCreateWindow, XSync


And that's the whole page, bestie!! πŸ’œ This was the GLXINTRO page from the 3G manual β€” go forth and make your OpenGL-in-X dreams come true, you absolute main character. πŸ‘‘βœ¨πŸ¦‹

πŸ“¦ where this page comes from