与Qt 5.1共享QGLWidgets问题的线程化OpenGL [英] Threaded OpenGL with shared QGLWidgets issue with Qt 5.1

查看:167
本文介绍了与Qt 5.1共享QGLWidgets问题的线程化OpenGL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I use two QGLWidgets. One for loading textures and one for rendering, but it is not working.

我使用了以下解释 http://blog.qt.digia.com/blog/2011/06/03/threaded-opengl-in-4-8/

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

Texture uploading thread Uploading many (or large) textures is typically an expensive operation because of the amount of data being pushed to the GPU. Again, this is one of those operations that can unnecessarily block your main thread. In 4.8 you can solve this problem by creating a pair of shared QGLWidgets. One of the widgets is made current in a separate thread, but is never made visible on screen. The main thread informs the uploading thread which images to upload and the uploading thread simply calls bindTexture() on each of these images and then notifies the main thread when each one has finished so it can be drawn to screen.

使用Qt 4.8和MinGW可以正常工作,但是现在我将Qt 5.1和MSVC一起使用.想要使线程中的小部件为当前状态时出现错误:

With Qt 4.8 with MinGW it works fine, but now i use Qt 5.1 with MSVC. I am getting an error when I want make the widget in the thread current:

无法使QOpenGLContext在其他线程中成为当前

Cannot make QOpenGLContext current in a different thread

我了解该错误,但是我该如何解决.当我不设置当前小部件时,我无法加载纹理(在bindTexture()函数处冻结).我也想知道,为什么它可以与我的旧版QT一起使用.当错误出现时,我可以按忽略错误",并且程序仍然会加载纹理.

I understand the error but how can i fix it. When i don't set the widget current i can't load textures (freezed at the bindTexture() function). I also wondering, why it works with my old QT Version. When the error appears i can press "ignore error" and the programm loads the textures anyway.

以下是一些示例代码:

加载纹理:

GLContext::GLContext(QWidget *parent, QGLWidget *myDisplayWidget) :
  QGLWidget(parent,myDisplayWidget)
{
}

...

GLContext* myTextureWidget = new GLContext(this,myDisplayWidget);

...

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

当我将myTextureWidget的上下文移动到线程时,它可以工作,但是随后会在构建GUI时从API中获取makeCurrent错误(堆栈跟踪在QT5Widgetsd中的QLineEdit :: setPlaceHolderText函数中说).当我在显示主窗口几秒钟后将myTextureWidget移到线程上时,一切正常.但是我怎么知道qt什么时候完成了所有GUI的构建工作呢?我将GUI绘制到具有QGLWidget视口的QGraphicsView.

When i move the context of the myTextureWidget to the thread it works, but then i get the makeCurrent Error from the API when the GUI will build (the stack trace said at the QLine:setPlaceHolderText function in QT5Widgetsd). When i move the myTextureWidget to the thread some seconds after the mainwindow has been shown, all works fine. But how can i know when qt finished all GUI building Stuff? I draw the GUI to a QGraphicsView with a QGLWidget viewport.

myTextureWidget->context()->moveToThread(myTextureLoadingThread);

推荐答案

在启动新线程并调用makeCurrent()之前,必须先启动doneCurrent()例如.

Before you start the new Thread and call makeCurrent() you have to initiate doneCurrent() e.g.

void QGLWidget::startRendering()
{
    doneCurrent();
    context()->moveToThread(mTextureLoadingThread);
}

然后致电

void TextureLoadingThread::run()
{    
    makeCurrent(); //Here is the bug!
    ...
}

这是我为解决此错误所做的工作.不幸的是,我没有使用线程渲染的完美解决方案.

This is what i've done to work around this error. Unfortunately i don't have the perfect solution for using a thread for rendering.

//编辑

// EDIT

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

这篇关于与Qt 5.1共享QGLWidgets问题的线程化OpenGL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆