I'm writing a compositing X11 window manager using Cython. I've got the most important bits working, but creating GL textures from pixmaps is giving me trouble. Texture binding works, and renders properly, but the application leaks memory very quickly.
After getting a named pixmap from a window, a Texture
object is created with a function that accepts the X11 Pixmap
.
texture = Texture.create_from_pixmap(pixmap.id, (256, 256))
Texture.create_from_pixmap
calls bindTexImage
, which creates a GLXPixmap
from the X11 Pixmap
, binds it to the texture, and returns the GLXPixmap
. This GLXPixmap
is saved as a class variable in the Texture
object instance to be released when the Texture
is deleted.
cdef GLXPixmap bindTexImage(Pixmap pixmap):
cdef int *pixmap_attribs = [
GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT,
0x8000
]
cdef GLXPixmap glxpixmap
glxpixmap = glXCreatePixmap(window_info.display, configs[0], pixmap, pixmap_attribs)
# Commenting out this line fixes the memory leak
glx.glXBindTexImageEXT(window_info.display, glxpixmap, GLX_FRONT_EXT, NULL)
return glxpixmap
cdef void releaseTexImage(GLXPixmap glxpixmap):
glx.glXReleaseTexImageEXT(window_info.display, glxpixmap, GLX_FRONT_EXT)
In debugging the issue, I found that removing the call to glXBindTexImageEXT
fixes the memory leak, but I'm not yet familiar enough with OpenGL, GLX, and X11 to know where or why the memory is leaking.
It's worth mentioning that I've inserted print statements in both the bind and release functions to verify that the GLXPixmap
is being released properly, and as far as I can tell, it is.
In case it's relevant, complete code can be found here: https://github.com/jakogut/kivywm
EDIT: In rereading the specification (https://www.khronos.org/registry/OpenGL/extensions/EXT/GLX_EXT_texture_from_pixmap.txt)
I've stumbled across this paragraph, which seems relevant:
...The storage for the GLX pixmap will be freed when it is not current to any client and all color buffers that are bound to a texture object have been released.
As a helpful anonymous coder pointed out, there is a glXDestroyPixmap
function that is not mentioned in the Khronos documentation for glXCreatePixmap
. (https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glXCreatePixmap.xml)
Using this function to free the GLXPixmap after it's been released solved the memory leak.
EDIT: This was the fix:
cdef void releaseTexImage(GLXPixmap glxpixmap):
glx.glXReleaseTexImageEXT(window_info.display, glxpixmap, GLX_FRONT_EXT)
glXDestroyPixmap(window_info.display, glxpixmap)