openglcythonx11window-managersglx

Memory leak using GLX_EXT_texture_from_pixmap


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.


Solution

  • 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)