qtopenglopenglcontext

Create Resources on Specific Context


I have a Qt OpenGL application that uses a QOpenGLWidget to render content. In another class (let's call it Resources), I want to create OpenGL resources like VBOs, VAO, shader programs, etc. for this widget. This creation method is not called by the QOpenGLWidget, but by an external caller.

For some reason, there exist two OpenGL contexts in my application (one is probably used for GUI stuff and the other for the QOpenGLWidget). Hence, when the resource creation method is called, I cannot be sure that the correct context is active. So when I call

QOpenGLVertexArrayObject vao;
vao.create();

in the Resources class, I cannot be sure that this VAO is created on the right context. The Resources class does not have access to the widget. Thus, context.makeCurrent() cannot be called (because I do not know the surface).

Is there a direct way to specify the context, on which the resources should be created? Storing the surface in the Resources file (along with the context) seems very untidy.


Solution

  • Apparently, there is no way to create resources on a specific context. I worked around this issue with the following structure:

    I created an interface OpenGLContextProvider, which is very simple:

    class OpenGLContextProvider
    {
    public:
        virtual void MakeOpenGLContextCurrent() = 0;
    };
    

    The OpenGL widget implements this interface:

    class GLView : public QOpenGLWidget, public OpenGLContextProvider
    {
        //...
    };
    void GLView::MakeOpenGLContextCurrent()
    {
        makeCurrent();
    }
    

    As such, the OpenGLContextProvider (i.e. the OpenGL widget) is injected into the Resource object's constructor. Before it needs the context, it calls the according method:

    void Resources::LoadSomeData()
    {
        //Load data...
    
        //Create OpenGL resources
        ctx->MakeOpenGLContextCurrent(); //ctx is of type OpenGLContextProvider*
        vao.create(); //is now on the correct context
        //etc.
    }