首页 > 解决方案 > Qt - 如何使一个线程用于加载纹理和另一个线程用于运行paintGL()

问题描述

我创建了一个线程用于从图像加载纹理,另一个线程用于通过paintGL(). 但抛出异常。

  1. 我需要一把或几把锁吗?我担心使用锁可能会导致问题,因为这两个线程正在做不同的事情但共享相同的资源。

  2. 如何以 QOpenGLWidget 方式共享上下文?

记忆模型

OpenGL 使用的多线程模型建立在一个事实之上:同一个 OpenGL 上下文不能同时在多个线程中处于当前状态。虽然您可以在多个线程中拥有多个当前的 OpenGL 上下文,但您不能同时从两个线程操作单个上下文。

我已经添加了QOpenGLWidget::makeCurrent()ininitializeGL()QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts)in main(),但是没有用。它似乎比仅仅添加这些语句更复杂。

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

我的主窗口.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
}

标签: qtopengl

解决方案


推荐阅读