c++openglserver-side-renderingx11glx

How to resize an existing pbuffer surface in GLX/OpenGL?


I am using GLX pbuffer surface to render OpenGL applications in Linux. Here is a sample:

GLOffscreenBuffer::GLOffscreenBuffer(unsigned width, unsigned height)
    : m_width(width)
    , m_height(height)
    , m_display(XOpenDisplay(0))
    , m_pbuffer(0)
    , m_context(0)
{
    if (!m_display) {
        std::cerr << "Error: XOpenDisplay()\n";
        return;
    }

    static const int configAttributes[] = {
        GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT,
        GLX_RENDER_TYPE, GLX_RGBA_BIT,
        GLX_RED_SIZE, 8,
        GLX_GREEN_SIZE, 8,
        GLX_BLUE_SIZE, 8,
        GLX_ALPHA_SIZE, 8,
        GLX_DOUBLEBUFFER, GL_FALSE,
        0
    };
    int configCount;
    GLXFBConfig* config = glXChooseFBConfig(m_display, 0, configAttributes, &configCount);
    if (!configCount) {
        std::cerr << "Error: glXChooseFBConfig()\n";
        XFree(config);
        XCloseDisplay(m_display);
        return;
    }

    static const int pbufferAttributes[] = {
        GLX_PBUFFER_WIDTH, static_cast<int>(width),
        GLX_PBUFFER_HEIGHT, static_cast<int>(height),
        0
    };
    m_pbuffer = glXCreatePbuffer(m_display, config[0], pbufferAttributes);
    if (!m_pbuffer) {
        std::cerr << "Error: glXCreatePbuffer()\n";
        XFree(config);
        XCloseDisplay(m_display);
        return;
    }

    m_context = glXCreateNewContext(m_display, config[0], GLX_RGBA_TYPE, 0, GL_TRUE);
    XFree(config);
    if (!m_context) {
        std::cerr << "Error: glXCreateNewContext()\n";
        glXDestroyPbuffer(m_display, m_pbuffer);
        XCloseDisplay(m_display);
        return;
    }
}

But I don't know how to resize this pbuffer surface when handling a X11 resizing event. It would be better if you can provide a demo.


Solution

  • To put it simply, you can't resize a pbuffer. The only way is to destroy the old buffer and create a new one.

    e.g.

    //in order to receive configure events,
    //StructureNotifyMask must be set in the event mask
    //e.g. XSelectInput(dpy, win, StructureNotifyMask);
    
    XEvent evt;
    XNextEvent(dpy, &evt);
    
    switch (evt.type) {
    
        case ConfigureNotify:
    
            if (m_pbuffer) {
                glXDestroyPbuffer(...);
            }
    
            //width : evt.xconfigure.width;
            //height: evt.xconfigure.height;
            m_pbuffer = glXCreatePbuffer(...);
    
        break;
    
    }
    

    Note: As @datenwolf pointed it out in the comments, render-to-texture is best done via Framebuffer objects.