Threaded OpenGL with QGLWidgets with Qt 5.1

I am using two QGLWidgets. One for loading textures and one for rendering, but it doesn't work.

I used the following explanation from http://blog.qt.digia.com/blog/2011/06/03/threaded-opengl-in-4-8/

Downloading a texture theme Loading many (or large) textures is usually an expensive operation due to the amount of data being transferred to the GPU. Again, this is one of those operations that can unnecessarily block the main thread. In 4.8, you can solve this problem by creating a couple of common QGLWidgets. One of the widgets runs in a separate thread, but is never displayed on the screen. The main thread informs the loading stream that the images are loading, and the loading stream simply calls bindTexture () on each of these images, and then notifies the main stream when each of them is complete so that it can be drawn on the screen.

It works fine with Qt 4.8 with MinGW, but now I am using Qt 5.1 with MSVC. I get an error when I want to make the widget in the stream current:

Cannot include QOpenGLContext in another thread

I understand the error, but how can I fix it. When I do not install the current widget, I canโ€™t load the textures (hang in the bindTexture () function). I also wonder why it works with my old version of QT. When an error appears, I can click โ€œignore errorโ€ and the program will load the textures anyway.

Here is a sample code:

Texture loading:

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); } 

EDIT:

When I move the myTextureWidget context to a stream, it works, but then I get a makeCurrent error from the API when building the GUI (the stack trace specified in the QLineEdit :: setPlaceHolderText function in QT5Widgetsd). When I move myTextureWidget to the stream a few seconds after showing the main window, everything works fine. But how can I find out when qt finished all GUI building materials? I am drawing a GUI in a QGraphicsView with a QGLWidget viewport.

 myTextureWidget->context()->moveToThread(myTextureLoadingThread); 
+6
source share
2 answers

Before starting a new thread and calling makeCurrent (), you need to initiate doneCurrent (), for example.

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

and then call

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

This is what I did to get around this error. Unfortunately, I don't have the perfect solution for using a stream for rendering.

// EDIT

I downloaded an example: https://dl.dropboxusercontent.com/u/165223/thread_example.zip

+3
source

Maybe it's too late, but I had the same problem and I found a solution, so here is what I did, hoping this would help future coders:

Omgodi was on the right track. I think you still get the same error, because the main thread also calls paintEvent (), which is probably trying to make the current current. However, the same context is already present in the second thread, hence the error.

So, you basically need to stop the main thread from trying to render in your widget while your second thread is active. I did this by adding a boolean attribute to my QGLWidget and set it to true before creating my second thread and returned to false when my thread was executed. Then I changed the paintEvent () of my widget only for display when the boolean value is set to false. Finally, I call the render function manually from the second thread. Here is the code:

 //GLWidget derives from QGLWidget: void GLWidget::paintEvent(QPaintEvent *e) { if ( !_second_thread_active ) render(); } //Then in your thread: void Thread::doWork() { //Do stuff render(); } 

Once your thread is complete, remember to send the context back from the second thread to the main thread!

 doneCurrent(); context()->moveToThread(&qapp->thread()); 

NTN

+1
source

Source: https://habr.com/ru/post/955319/


All Articles