9
votes

I have run into an issue that I am afraid is going to be very hard to resolve, at least as far as google searching has show me.

I have an Editor utility using Qt which creates multiple OpenGL contexts for different tools in the editor, their is a 'World' editor which hosts a QGLWidget of my games scene, and a material editor which has a 'preview' QGLWidget which displays the currently built material.

I have been able to get context sharing working fine, I use gDEBugger to see the OpenGL contexts, and they are sharing Textures, VBO's, shaders etc. But one stipulation has me wondering how this will work, you can't share Vertex Array Objects between contexts. As I understand it, Vertex Array Objects are the standard now, and we should really be using them as opposed to using VBO's without VAO's.

I have thought of a 2 ways to get around this but I don't exactly think either are ideal

  1. Generate the VAO's before each render, but this seems to defeat the purpose of the VAO's
  2. use a std::map to map a GL context to a VAO, if the current context does not have this VAO, then generate one for the said context, this seems bad and may not even work.

What other solutions are there that I am overlooking? I have also considered somehow having everything in one context and using seperate viewports for each required opengl widget, which I hoped would be possible but I am having no luck figuring it out using Qt and it's QGLWidget.

Edit

Ok, so I have tried to get this working but it is giving me alot of grief, I tried 2 different ways and they are both causing me errors.

1) I create a QGLContext, and then pass it to my QGLWidgets when they are being created.

QGLFormat    fmt = QGLFormat();
QGLContext*  pContext = new QGLContext(fmt);

QGLWidget*   pWidget1 = new QGLWidget(pContext);
someLayout->addWidget(pWidget1);

QGLWidget*   pWidget2 = new QGLWidget(pContext);
anotherLayout->addWidget(pWidget2);

The error here is that as soon as I add the widget to a layout, or set it as the central widget for a Main Window, it deletes the context, really weird. If I then try to pass in the context from the first widget to the second

QGLFormat    fmt = QGLFormat();
QGLContext*  pContext = new QGLContext(fmt);

QGLWidget*   pWidget1 = new QGLWidget(pContext);
someLayout->addWidget(pWidget1);

pContext = (QGLContext*)pWidget1->context();
QGLWidget*   pWidget2 = new QGLWidget(pContext);
anotherLayout->addWidget(pWidget2);

I Get a Qt error saying QGLWidget::setContext: Context must refer to this widget

2) I create my first widget and use it's context for all the others

QGLWidget* pWidget1 = new QGLWidget();

QGLContext* pContext = (QGLContext*)pWidget->context();
QGLWidget* pWidget2 = new QGLWidget(pContext);

This gives me the same error that I got from the end of my first method, it says QGLWidget::setContext: Context must refer to this widget.

Something is not right here and I feel I am missing something.

1
"we should really be using them as apposed to using VBO's without VAO's." How do you use VAOs instead of buffer objects? They contain references to buffer objects.Nicol Bolas
I said using Vertex Buffer Objects without generating and binding your own Vertex Array Object, where I have read that it is part of compatibility mode to simply use the VAO at '0' and are supposed to generate and bind your own for future safe code.user1294021
The term "Vertex Buffer Object" is shorthand for "I'm using buffer objects as source data for my vertex arrays." It does not mean "calling glVertexAttribPointer every frame." Using VAOs does not mean that the buffer objects stopped being the source of your vertex data.Nicol Bolas
Ok let me say this again, exactly as I put it before, I said using the VBO's WITHOUT using a user generated VAO, I didn't say using a VAO without any VBO attached to it, I meant using the default VAO that the compatibility mode of OpenGL keeps for backwards compatibility, which you do not have to generate or bind.user1294021

1 Answers

8
votes

You can't share VAOs for the same reason you can't share FBOs: They don't hold actual data, but are merely a collection of data holding buffer objects. BOs that hold data you can share.

However, why jump the hoops of context sharing at all? You can reuse a single OpenGL context for several windows, as long as the windows have the same visual format / FBConfig / PIXELFORMATDESCRIPTOR.

Have a look at the following QGLWidget constructor:

QGLWidget::QGLWidget (
    QGLContext * context, 
    QWidget * parent = 0, 
    const QGLWidget * shareWidget = 0, 
    Qt::WindowFlags f = 0 )

You can create a QGLWidget with an existing QGLContext. Either creates a stand-alone QGLContext and attach that to multiple windows, or create a main QGLWidget, and use the context created by that one. You can even destroy single QGLWidgets without loosing the context and the data within it, as long as there is at least one QGLWidget holding it.