Search code examples
pythonopenglx11xlib

How do I use the xlib and OpenGL modules together with python?


I know it is possible to use Xlib and OpenGL together, with GLX (I've done it myself in C).

The problem is, how do I do this in python? The OpenGL module has GLX functionality [documentation], but it appears to be using C types and I have no idea (nor, it appears does anyone else) how to use the xlib types with PyOpenGL.

I also tried using ctypes and loading libraries directly, but ran into (obvious) problems when trying to use the C macros defined in the Xlib header file, like DefaultRootWindow.

Am I missing something obvious, like PyOpenGL having its own xlib implementation, or is this just not possible without some (compiled) module-writing?


Solution

  • You can't use python-xlib types directly with python-opengl. But you can use the fact that a window XID is just a number to use python-opengl on the same window.

    from Xlib import X, display
    from OpenGL import GL, GLX
    from OpenGL.raw._GLX import struct__XDisplay
    from ctypes import *
    
    # some python-xlib code...
    pd = display.Display()
    pw = pd.screen().root.create_window(50, 50, 200, 200, 0,
                                        pd.screen().root_depth,
                                        X.InputOutput, X.CopyFromParent)
    pw.map()
    
    # ensure that the XID is valid on the server
    pd.sync()
    
    # get the window XID
    xid = pw.__resource__()
    
    # a separate ctypes Display object for OpenGL.GLX
    xlib = cdll.LoadLibrary('libX11.so')
    xlib.XOpenDisplay.argtypes = [c_char_p]
    xlib.XOpenDisplay.restype = POINTER(struct__XDisplay)
    d = xlib.XOpenDisplay("")
    
    # use GLX to create an OpenGL context on the same window XID
    elements = c_int()
    configs = GLX.glXChooseFBConfig(d, 0, None, byref(elements))
    w = GLX.glXCreateWindow(d, configs[0], c_ulong(xid), None)
    context = GLX.glXCreateNewContext(d, configs[0], GLX.GLX_RGBA_TYPE, None, True)
    GLX.glXMakeContextCurrent(d, w, w, context)
    
    # some python-opengl code....
    GL.glShadeModel(GL.GL_FLAT)
    GL.glClearColor(0.5, 0.5, 0.5, 1.0)
    
    GL.glViewport(0, 0, 200, 200)
    GL.glMatrixMode(GL.GL_PROJECTION)
    GL.glLoadIdentity()
    GL.glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0)
    
    GL.glClear(GL.GL_COLOR_BUFFER_BIT)
    GL.glColor3f(1.0, 1.0, 0.0)
    GL.glRectf(-0.8, -0.8, 0.8, 0.8)
    
    # assume we got a double buffered fbConfig and show what we drew
    GLX.glXSwapBuffers(d, w)
    
    # a terrible end to a terrible piece of code...
    raw_input()
    

    This is really horrible though. (Error checking and choosing a sensible fbConfig omitted for clarity)

    It really should be possible to do all the necessary xlib calls with ctypes though. Pyglet, for example, manages somehow, but I'm not sure what specific problem you ran into.