I've created one thread that be used for loading textures from images and the other thread for drawing images on the screen via paintGL()
. But exception thrown.
Do I need a lock or locks? I'm worried that there may be problems caused by using locks, coz these two threads are doing different things but share the same resources.
How can I do share contexts in a QOpenGLWidget way?
The multithreading model that OpenGL uses is built on one fact: the same OpenGL context cannot be current within multiple threads simultaneously. While you can have multiple OpenGL contexts which are current in multiple threads, you cannot manipulate a single context simultaneously from two threads.
I'v added QOpenGLWidget::makeCurrent()
in initializeGL()
and QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts)
in main()
, but is's not working. It seems more complicated than just adding these statements.
MyOpenGLWidget.cpp
void MyOpenGLWidget::initializeGL()
{
QMutexLocker LOCKER(&mutext);
QOpenGLWidget::makeCurrent();
QOpenGLFunctions::initializeOpenGLFunctions();
// some other code here
}
void MyOpenGLWidget::loadTexture()
{
if (eof == true)
return;
QMutexLocker LOCKER(&mutext);
img_data = SOIL_load_image(path, &width, &height, &channels, SOIL_LOAD_RGB);
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &texture); // Access violation reading location thrown
// some other code here
}
void MyOpenGLWidget::paintGL()
{
QMutexLocker LOCKER(&mutext);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
MyGLThread.cpp
void MyGLThread::init(MyOpenGLWidget* widget)
{
gl_widget = widget;
}
void MyGLThread::loadTexture()
{
gl_widget->loadTexture();
}
void MyGLThread::run()
{
while (true) {
if (!gl_widget)
continue;
// some other code
loadTexture();
msleep(30);
}
}
MyMainWindow.cpp
MyMainWindow::MyMainWindow(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
gl = new MyOpenGLWidget(this);
gl_thread = new MyGLThread();
gl_thread->init(gl);
gl_thread->start();
// some other code
}