Я пишу заявление, которое:
- Непрерывно выводит материал за пределы экрана в конвейере, который имеет частный контекст OpenGL и частный поток
- Рисует некоторые из ранее отрисованных текстур в виджетах
Чтобы сделать это, мне нужно поделиться этими текстурами как с конвейером, так и с контекстами виджетов:
Подход 1: разделить все контексты
int main (int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
QApplication a(argc, argv);
// [...] Create and initialize the pipeline (private context)
// [...] Create a window with a widget that can display a texture (Qt creates a private context itself)
// [...] Set the texture to display in the widget with one created and rendered in the pipeline
}
К тому времени, когда я хочу нарисовать свою текстуру (в обратном вызове paintGL()
), glBindTexture
дает GL_INVALID_OPERATION
.
Графический отладчик показывает странную текстуру вместо моей: разделение контекста, похоже, не работает.
Подход 2: виджет имеет самостоятельно созданный контекст, который разделяет как конвейер, так и Qt
// [...] Create and initialize the pipeline (private context)
// [...] Create a window with a widget that can display a texture (Qt creates a private context itself)
// widget's initializeGL() callback gets called
void initializeGL()
{
initializeOpenGLFunctions();
m_secondContext.setShareContext(QOpenGLContext::currentContext());
m_secondContext.setShareContext(pipelineContext);
m_secondContext.create();
}
// use the second context during paintEvents
void paintGL()
{
auto contextBackup(QOpenGLContext::currentContext());
auto surfaceBackup(contextBackup->surface());
assert(m_secondContext->makeCurrent(surfaceBackup));
// [...] draw texture
contextBackup->makeCurrent(surfaceBackup);
}
Также не работает, выдает ту же ошибку, что и подход 1 + еще, что я не обнаружил.
Подход 3: Конвейер разделяет контекст виджетов
// [...] Create a window with a widget that can display a texture (Qt creates a private context itself)
// [...] Create and initialize the pipeline with the widgets context set as shared
// before calling create on the new pipeline context
void initializePipeline()
{
m_pipelineContext.setShareContext(widgetContext);
m_pipelineContext.create();
}
Это работает, НО это нежелательное решение, так как не позволяет создавать такие виджеты ПОСЛЕ инициализации конвейера
Вопросы, которые я задаю:
- Все три сценария должны дать один и тот же результат, что происходит, что я пропустил?
- Нужно ли добавлять специальные инструкции для распределения общего ресурса в общем контексте?
- Безопасен ли обмен контекстами? Например, могу ли я использовать общие ресурсы, не заботясь о взаимном исключении? (редактировать: использование одного не решает проблему)