3

I need to shared data (textures, vertex-buffers,... ) across all OpenGL widgets in a application.

The following code isn't working:

I've found some solutions that have one main QGLWidget and other are constructed using this main widget. Unfortunately, I can't use this approach, because all my QGLWidgets are equal and almost certainly the first(main) created QGLWidget will be destroyed before others are.

Possible approach:

  • single shared OpenGL context between all QGLWidgets
  • not working: just one QGLWidget gets rendered correctly, others behave as they weren't rendered, corrupted/random data
  • error for each QGLWidget construction except first one:

    QGLWidget::setContext: Context must refer to this widget
    

Another approach:

  • main OpenGL context and create sub-context for each QGLWidget
  • not working: context->isSharing() returns false
  • code that I use for context creation, context1 and context2 are later passed to constructors of QGLWidgets:

    QGLContext *mainContext = new QGLContext(format), *context1, *context2;
    mainContext->create();
    context1 = new QGLContext(format);
    context1->create(mainContext);
    context2 = new QGLContext(format);
    context2->create(mainContext);
    cout << mainContext->isSharing() << " " << context1->isSharing() << endl;
    
asked Jan 6, 2014 at 17:29
3
  • The ... in your description of resource sharing concerns me. Not all OpenGL objects are shareable, particularly the entire class of objects referred to as containers. Container objects in OpenGL include things like Vertex Array Objects and Framebuffer Objects. To that end, the general state machine is stored per-context and this might explain why things behave as if they were "corrupted" or "random." Commented Jan 6, 2014 at 17:46
  • If I use single context, the second QGLWidget acts like it wasn't even rendered, like if glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) wasn't performed Commented Jan 6, 2014 at 17:48
  • That is not the same thing as context sharing. That is re-using the same context. Generally render contexts are associated with some rectangular region of your window at the lowest-level (not to be confused with the viewport mapping); Qt hides the window system implementation from you, but if you want to switch between widgets then you probably have to redefine this region somehow. This assumes, of course, that you are not drawing each widget in a different thread - because that opens an entirely different can of worms. Widgets have a makeCurrent method that should address this issue. Commented Jan 6, 2014 at 17:52

3 Answers 3

4

With regards to the first approach, you are not setting up sharing but trying to force the same context to be used with different QGLWidgets. As pointed out above, this is wrong and will not work.

Instead, create the QGLWidgets normally and pass the first QGLWidget in the shareWidget parameter when creating the others. This way you will get a separate context for each QGLWidget but they will all share with the context of the first one (and thus with each other). See http://qt-project.org/doc/qt-4.8/qglwidget.html#QGLWidget

Destroying the first widget before the others should not be an issue since the shared objects will be around until any of the sharing contexts are alive.

answered Jan 7, 2014 at 14:01
Sign up to request clarification or add additional context in comments.

2 Comments

That explains why first approach isn't working, but why second doesn't work too? Are the all contexts equal and every context can access data of every else?
Most likely create() fails (check the return value) since QGLContext cannot be used without a paint device (a pixmap or a QGLWidget). The relevant public APIs in QGLContext (e.g. the constructor that takes also a QPaintDevice) have long been obsoleted. Basically you should avoid using QGLContext directly. Just use QGLWidget and let it create and manage the contexts for you.
1

I realize that it has been almost a year since this question has been asked, but I believe the comment above may be inaccurate.

To be more precise, while it may be indeed invalid to use a single QGLContext with multiple QGLWidgets, this would be a limitation of Qt's OpenGL implementation rather than a limitation of OpenGL or the windowing system. It certainly seems valid to use the same context to render to multiple windows. For example, the functions wglMakeCurrent and SwapBuffers accept as parameters device handles alongside OpenGL context handles. To quote the wglMakeCurrent documentation:

The hdc parameter must refer to a drawing surface supported by OpenGL. It need not be the same hdc that was passed to wglCreateContext when hglrc was created, but it must be on the same device and have the same pixel format.

I do not even want to go into problems with SwapBuffers, since there are several bug reports all over the web regarding Qt5, which seems to force making the OpenGL context current unnecessarily before SwapBuffers is called.

answered Nov 24, 2015 at 8:48

Comments

1

This has been updated since QT 5.4 and you should now use QOpenGLWidget instead of QGLWidget. Global sharing of contexts has been written into QOpenGLWidget now so you don't have to code it yourself. You just need to enable the sharing flag Qt::AA_ShareOpenGLContexts before you create QGuiApplication.

answered Jan 13, 2016 at 17:24

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.