Я создал один поток, который будет использоваться для загрузки текстур из изображений, а другой поток для рисования изображений на экране с помощью paintGL()
.Но исключение выдается.
Нужен ли замок или замки?Я обеспокоен тем, что могут быть проблемы, вызванные использованием блокировок, потому что эти два потока делают разные вещи, но используют одни и те же ресурсы.
Как я могу делиться контекстами в QOpenGLWidget способом?
Модель памяти
Модель многопоточности, которую использует OpenGL, основана на одном факте: один и тот же контекст OpenGL не может быть текущим в несколькихтемы одновременно.Хотя у вас может быть несколько контекстов OpenGL, текущих в нескольких потоках, вы не можете манипулировать одним контекстом одновременно из двух потоков.
Я добавил QOpenGLWidget::makeCurrent()
в initializeGL()
и QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts)
в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);
}
}
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
}