PDA

View Full Version : Rendering to a QGLWidget from a QThread - makeCurrent fails [solved]



neobrain
14th March 2012, 20:20
Hi there,
I'm currently writing a Qt4 GUI for an emulator and need to offload the rendering of a QGLWidget to a separate QThread. The reason for this is that since our GPU emulation is using OpenGL for rendering, we'd have to run emulation on the GUI thread, which is kinda awkward. I don't want to restructure the underlying emulator code (especially since it's supposed to be toolkit-independent) to avoid this (if that's even possible), so I figured the best way would be to leave the GUI thread as it is and let the emulation run on a separate QThread.
This article (http://doc.trolltech.com/qq/qq06-glimpsing.html#writingmultithreadedglapplications) suggests that this idea should be perfectly feasible. However, when I'm trying to implement it like described in the article, I get an "QGLContext::makeCurrent(): Failed." error whenever I'm calling glwidget->makeCurrent() from the QThread (glwidget->context()->isValid() returns true though). I've tried coding a minimal application that will test the implementation, and it also outputs makeCurrent errors:



#include <QtGui>
#include <QtOpenGL>
#include <X11/Xlib.h>

class MyGLWidget;
class MyThread : public QThread
{
public:
MyThread(MyGLWidget* _glw);
void run();

private:
MyGLWidget* glw;
};

class MyGLWidget : public QGLWidget
{
public:
MyGLWidget(QWidget* parent = NULL);

void start_rendering() { thread.start(); }
private:
MyThread thread;
};

MyThread::MyThread(MyGLWidget* _glw) : glw(_glw) {}
MyGLWidget::MyGLWidget(QWidget* parent) : QGLWidget(parent), thread(this) {}


void MyThread::run()
{
while(1) {
glw->makeCurrent(); // error
glClear(GL_COLOR_BUFFER_BIT);
glw->swapBuffers();
glw->doneCurrent();
}
}

int main(int argc, char* argv[])
{
QCoreApplication::setAttribute(Qt::AA_X11InitThrea ds); // or just XInitThreads();
QApplication app(argc, argv);

QMainWindow win;
MyGLWidget* glw = new MyGLWidget(&win);
win.setCentralWidget(glw);
win.show();
glw->start_rendering();

return app.exec();
}

Note that I'm running this on an openSUSE Linux system right now. I haven't had a chance to test it on a Windows machine, yet, but will do so once I get a chance.

Anyway, I would be REALLY thankful if anyone could help me out with this one, I've spent so many hours on this already without finding a solution. Thanks in advance!

neobrain
15th March 2012, 01:19
I just solved the problem.

For reference, I thought it wasn't necessary to overload the paintEvent and resizeEvent methods in QGLWidget. However, you need to do that because otherwise QGLWidget will internally keep calling makeCurrent, thus causing the makeCurrent calls in the QThread to fail.

FAQuiR
27th November 2014, 21:28
I just registered to say Thank you, No info anywhere that it NEEDS to be overloaded, even in documentation, so frustrating to find it only after so many hours of search.