带有Qt 5.1的共享QGLWidgets问题的螺纹OpenGL

riv*_*333 8 c++ qt qtgui qthread qtcore

我使用两个QGLWidgets.一个用于加载纹理,一个用于渲染,但它不起作用.

我在http://blog.qt.digia.com/blog/2011/06/03/threaded-opengl-in-4-8/上使用了以下说明

纹理上传线程上传许多(或大)纹理通常是一项昂贵的操作,因为数据量被推送到GPU.同样,这是可能不必要地阻止主线程的那些操作之一.在4.8中,您可以通过创建一对共享QGLWidgets来解决此问题.其中一个小部件在一个单独的线程中是最新的,但从未在屏幕上显示.主线程通知上传线程要上传哪些图像,上传线程只是在每个图像上调用bindTexture(),然后在每个图像完成时通知主线程,以便可以将其绘制到屏幕上.

使用Qt 4.8和MinGW它工作正常,但现在我使用Qt 5.1和MSVC.当我想让线程中的小部件变为当前时,我收到错误:

无法使QOpenGLContext在另一个线程中保持最新状态

我理解错误,但我该如何解决它.当我没有设置小部件当前我无法加载纹理(在bindTexture()函数冻结).我也想知道,为什么它适用于我的旧QT版本.当出现错误时,我可以按"忽略错误",程序无论如何都会加载纹理.

以下是一些示例代码:

加载纹理:

GLContext::GLContext(QWidget *parent, QGLWidget *myDisplayWidget) :
  QGLWidget(parent,myDisplayWidget)
{
}
Run Code Online (Sandbox Code Playgroud)

...

GLContext* myTextureWidget = new GLContext(this,myDisplayWidget);
Run Code Online (Sandbox Code Playgroud)

...

void TextureLoadingThread::run()
{    
    makeCurrent(); //Here is the bug!
    QImage *im = new QImage(filename);
    GLuint textid = myTextureWidget->bindTexture(*im, GL_TEXTURE_2D, GL_RGBA);
}
Run Code Online (Sandbox Code Playgroud)

编辑:

当我将myTextureWidget的上下文移动到它运行的线程时,但是当GUI将构建时,我从API获得makeCurrent Error(堆栈跟踪在QT5Widgetsd中的QLineEdit :: setPlaceHolderText函数中说明).当我在主窗口显示几秒后将myTextureWidget移动到线程时,一切正常.但是我怎么知道什么时候qt完成了所有GUI构建的东西?我使用QGLWidget视口将GUI绘制到QGraphicsView.

myTextureWidget->context()->moveToThread(myTextureLoadingThread);
Run Code Online (Sandbox Code Playgroud)

omg*_*die 4

在启动新线程并调用 makeCurrent() 之前,您必须启动 didCurrent() 例如

void QGLWidget::startRendering()
{
    doneCurrent();
    context()->moveToThread(mTextureLoadingThread);
}
Run Code Online (Sandbox Code Playgroud)

然后打电话

void TextureLoadingThread::run()
{    
    makeCurrent(); //Here is the bug!
    ...
}
Run Code Online (Sandbox Code Playgroud)

这就是我为解决此错误所做的事情。不幸的是,我没有使用线程进行渲染的完美解决方案。

// 编辑

我上传了一个示例:https ://dl.dropboxusercontent.com/u/165223/thread_example.zip