Qt如何在幕后分享OpenGL上下文?

时间:2019-05-21 16:44:22

标签: c++ qt opengl

我正在编写一个应用程序,

  • 在具有私有OpenGL上下文和私有线程的管道中连续在屏幕外渲染内容
  • 在小部件中绘制一些先前渲染的纹理

为此,我需要在管道和小部件上下文中共享这些纹理:

方法1:共享所有上下文

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
}

当我要绘制纹理(在paintGL()回调中)时,glBindTexture产生一个GL_INVALID_OPERATION
图形调试器显示的是奇怪的纹理而不是我的纹理:上下文共享似乎不起作用。

方法2:小部件具有一个自创建的上下文,该上下文共享管道和Qt管道

// [...] 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);
}

也不起作用,产生与方法1相同的错误,但我没有找到更多错误。

方法3:管道共享小部件上下文

// [...] 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();
}

这确实有效,但是这是一个不需要的解决方案,因为它不允许在管道初始化之后创建此类小部件

我要问的问题:

  • 所有这三种情况都应给出相同的结果,发生了什么,我错过了什么?
  • 是否需要添加特定的指令以在共享的上下文上分配共享资源?
  • 上下文共享线程安全吗?例如,我可以使用共享资源而不关心互斥吗? (编辑:使用一个不能解决任何问题)

1 个答案:

答案 0 :(得分:1)

为您解答:

  

是否需要添加特定的指令来分配共享资源   在共享的上下文中?

否。

  

上下文共享线程安全吗?例如我可以使用共享资源吗   不在乎互斥?

上下文共享不是线程安全的。共享是对OpenGL对象名称空间的整合。

但我怀疑这些答案根本无法帮助您。我将继续观察。您的错误很奇怪,因为GL_INVALID_OPERATION仅在glBindTexture的一种情况下生成:

  如果先前创建了纹理,则会生成

GL_INVALID_OPERATION   目标与 target 的目标不匹配。

这表示存在名称为textureHandle的纹理,但没有目标GL_TEXTURE_2D的纹理。也许纹理目标实际上是GL_TEXTURE_2D_MULTISAMPLE

当然,由于某种原因,共享可能无法正常工作。应该使用几乎所有图形调试器在每个上下文中列出对象,才能轻松找到它。在其中一个创建,然后查看是否在另一个弹出。