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

1

10

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?

Dubois answered 18/2, 2013 at 9:58 Comment(5)
You might have a perfectly good reason for using low-level libraries such as Xlib but I have to ask: have you considered using something much higher level such as QtOpenGL from PySide? The code you write using PySide will also work on multiple platforms (Windows, Linux, Mac) as opposed to the one you write using Xlib. Just a thought.Goings
No, PyOpenGL has no its own xlib implementation. Nothing on the Python side actually has. Python-xlib was last released in about 2009 so it's effectively dead. Use GLUT or one of the higher level toolkits.Juanitajuanne
@crayzeewulf: Yup, I have a good reason. I'm doing an X-windows hack involving drawing interactive OpenGL wallpapers to the desktop. It involves setting EMWH hints and a few other messy bits, so I doubt that Qt or whatever could do that.Dubois
@n.m.: Okay. Looks like Boost::Python may be my friend then. I'll post back if I end up doing that.Dubois
Michael, thanks for the explanation. Good luck with your hack. I have used ctypes for accessing similar low-level libraries before but had to translate the preprocessor macros by hand into equivalent Python functions. Sometimes there is no other option.Goings
C
5

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.

Chaffee answered 26/2, 2013 at 18:10 Comment(1)
"This is really horrible" - Agreed, though I'll reward this as this is exactly what I asked for. :) What I actually ended up doing was making some normal C++ utilities and wrapping it in Boost::Python so I only expose the necessary bits. Cheers!Dubois

© 2022 - 2024 — McMap. All rights reserved.