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 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;
{
public:
MyThread(MyGLWidget* _glw);
void run();
private:
MyGLWidget* glw;
};
{
public:
MyGLWidget
(QWidget* parent
= NULL);
void start_rendering() { thread.start(); }
private:
MyThread thread;
};
MyThread::MyThread(MyGLWidget* _glw) : glw(_glw) {}
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_X11InitThreads);
// or just XInitThreads();
MyGLWidget* glw = new MyGLWidget(&win);
win.setCentralWidget(glw);
win.show();
glw->start_rendering();
return app.exec();
}
#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_X11InitThreads); // 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();
}
To copy to clipboard, switch view to plain text mode
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!
Bookmarks