I am writing an application that:
- Continuously renders stuff offscreen in a pipeline that has private OpenGL context & private thread
- Draws some of the previously rendered textures in widgets
In order to do that I need to share those textures across both the pipeline and the widgets contexts:
Approach 1 : share all contexts
int main (int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
QApplication a(argc, argv);
// [...] Create and initialize the pipeline (private context)
// [...] Create a window with a widget that can display a texture (Qt creates a private context itself)
// [...] Set the texture to display in the widget with one created and rendered in the pipeline
}
By the time i want to draw my texture (in the paintGL()
callback), glBindTexture
yields a GL_INVALID_OPERATION
.
Graphics debugger shows a weird texture instead of mine : context sharing does not seem to work.
Approach 2 : widget have a self created context that shares both the pipeline and the Qt one
// [...] Create and initialize the pipeline (private context)
// [...] Create a window with a widget that can display a texture (Qt creates a private context itself)
// widget's initializeGL() callback gets called
void initializeGL()
{
initializeOpenGLFunctions();
m_secondContext.setShareContext(QOpenGLContext::currentContext());
m_secondContext.setShareContext(pipelineContext);
m_secondContext.create();
}
// use the second context during paintEvents
void paintGL()
{
auto contextBackup(QOpenGLContext::currentContext());
auto surfaceBackup(contextBackup->surface());
assert(m_secondContext->makeCurrent(surfaceBackup));
// [...] draw texture
contextBackup->makeCurrent(surfaceBackup);
}
Does not work either, yields same error as approach 1 + some more that i have not located.
Approach 3 : Pipeline share the widgets context
// [...] Create a window with a widget that can display a texture (Qt creates a private context itself)
// [...] Create and initialize the pipeline with the widgets context set as shared
// before calling create on the new pipeline context
void initializePipeline()
{
m_pipelineContext.setShareContext(widgetContext);
m_pipelineContext.create();
}
This does work, BUT it is an unwanted solution as it does not allow the creation of such widgets AFTER the pipeline initialization
Questions i am asking:
- All theses three scenarios should give the same result, what is happening, what did i miss ?
- Does one need to add specific instructions to allocate shared resource on a context that is shared?
- Is context sharing thread safe ? E.g can i use shared resources without caring about mutual exclusion ? (edit: using one does not solve any issue)
glFlush
orglFinish
to "commit" the context command queue? Because you should. - Andreas