Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix QNanoWidget OpenGL context usage #83

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

hartcw
Copy link
Contributor

@hartcw hartcw commented Apr 24, 2024

When using multiple QNanoWidgets, each widget will get a unique instance of a QOpenGLContext object. When the global instance of QNanoPainter is initialised, it happens against the OpenGL context owned by one of the QNanoWidgets (which ever is painted first).

This means that the global instance of QNanoPainter may not work correctly when used with other QNanoWidget instances. There are 2 things needed to fix this:

  • The app must enable the Qt::AA_ShareOpenGLContexts attribute. This allows the QNanoPainter to be initialised against one QOpenGLContext, but also used with other QOpenGLContexts.

  • The QNanoPainter should be initialised against the global shared QOpenGLContext that Qt maintains. This is because, on Windows, the QNanoPainter backend retrieves the OpenGL function pointers from the active QOpenGLContext, but then uses them as a global variable. This means that once that particular QOpenGLContext is destroyed (ie. the QNanoWidget is destroyed), the OpenGL function pointers are also destroyed, but the global QNanoPainter backend still continues to reference them.

@hartcw
Copy link
Contributor Author

hartcw commented Apr 25, 2024

May need to rework this patch, the QOpenGLContext::globalShareContext() has this note:

Warning: Do not attempt to make the context returned by this function current on any surface. Instead, you can create a new context which shares with the global one, and then make the new context current.

@hartcw hartcw force-pushed the dev-smartshooter5 branch from 2f83efb to dc18b48 Compare April 25, 2024 08:57
@QUItCoding
Copy link
Owner

I haven't really been using QNanoWidget other than in the simple example. So based on that note, patch should actually use
https://doc.qt.io/qt-6/qopenglcontext.html#setShareContext ?

@hartcw
Copy link
Contributor Author

hartcw commented Apr 28, 2024

I think that, if the QNanoPainter is going to be shared globally (with either QNanoWidget or QNanoQuickItemPainter), then QNanoPainter should create and own its own QOpenGLContext instance. And it should ensure that it is shared with the QOpenGLContext instance owned by the QNanoWidget (or QNanoQuickItemPainter).

For my usecase, I definitely want to use a global shared QNanoPainter, because I will be using the same opengl textures in multiple widgets, and it will save texture memory.

I'll rework this patch to add a QOpenGLContext member to the QNanoPainter class. That should fix both QNanoWidget and QNanoQuickItemPainter code paths when using multiple widgets/items.

Regarding using QOpenGLContext::setShareContext(), that is one way to implement it. The other simpler way is to set the Qt::AA_ShareOpenGLContexts attribute, then Qt will automatically handle this for us.

When using multiple QNanoWidgets, each widget will get a unique instance
of a QOpenGLContext object. When the global instance of QNanoPainter is
initialised, it happens against the OpenGL context owned by one of the
QNanoWidgets (which ever is painted first).

This means that the global instance of QNanoPainter may not work correctly
when used with other QNanoWidget instances. There are 2 things needed to
fix this:

- The app must enable the Qt::AA_ShareOpenGLContexts attribute.
  This allows the QNanoPainter to be initialised against one
  QOpenGLContext, but also used with other QOpenGLContexts.

- The QNanoPainter should maintain its own QOpenGLContext instance, and
  ensure the QNanoPainter backend is initialised against that. This is
  because, on Windows, the QNanoPainter backend retrieves the OpenGL
  function pointers from the active QOpenGLContext, but then uses them as
  a global variable. This means that once that particular QOpenGLContext
  is destroyed (ie. the QNanoWidget is destroyed), the OpenGL function
  pointers are also destroyed, but the global QNanoPainter backend still
  continues to reference them.
@hartcw hartcw force-pushed the dev-smartshooter5 branch from dc18b48 to d5a041f Compare April 29, 2024 07:32
@hartcw
Copy link
Contributor Author

hartcw commented Apr 29, 2024

@QUItCoding please recheck, I made some improvements to the patch.
With this, it should fix both QNanoWidget and QNanoQuickItem code paths.
And it means QNANO_ENABLE_PAINTER_SHARING can probably be removed.

Note. I've only tested the QNanoWidget and QNanoWindow paths, and not the QNanoQuickItem paths.

@QUItCoding
Copy link
Owner

Tested that Gallery / QNanoPainter features example crashes with this patch when swiping to right & left for while. There are also outputs "Attempting to create QWindow-based QOffscreenSurface outside the gui thread. Expect failures."

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants