rhi: gl: Optimize context/surface changes

When there is a context with a surface current, keep on using
that whenever ensureContext() is called without specifying a
QWindow.

Consider the following sequence:
    <component A>
      beginOffscreenFrame
      render to texture 1
      endOffscreenFrame
    <component B>
      beginOffscreenFrame
      render to texture 2
      endOffscreenFrame
    <component C>
      beginFrame (with swapchain)
      render something using texture 1 and 2
      endFrame
    repeat all over again, continuously

(in practice this is what a top level widget with QOpenGLWidgets
and/or QQuickWidgets in it would lead to with the QRhi migration
in place)

Besides being more readable, the new version recognizes that resource
and offscreen operations do not need one specific surface (like the
one QOffscreenSurface every GL backend of QRhi has), but are functional
with any surface (or with surfaceless even) as long as the context is
correct. Thus with the above example we can work with only ever making
the one QWindow current.

Change-Id: I633071cae88f02e1d45e445ee55c8a58f9ec5a8c
Pick-to: 6.2
Fixes: QTBUG-96405
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
This commit is contained in:
Laszlo Agocs 2021-11-17 18:23:21 +01:00
parent 24022bc760
commit c1899ca310
2 changed files with 24 additions and 12 deletions

View File

@ -501,21 +501,33 @@ QRhiGles2::QRhiGles2(QRhiGles2InitParams *params, QRhiGles2NativeHandles *import
}
}
static inline QSurface *currentSurfaceForCurrentContext(QOpenGLContext *ctx)
{
if (QOpenGLContext::currentContext() != ctx)
return nullptr;
QSurface *currentSurface = ctx->surface();
if (!currentSurface)
return nullptr;
if (currentSurface->surfaceClass() == QSurface::Window && !currentSurface->surfaceHandle())
return nullptr;
return currentSurface;
}
bool QRhiGles2::ensureContext(QSurface *surface) const
{
bool nativeWindowGone = false;
if (surface && surface->surfaceClass() == QSurface::Window && !surface->surfaceHandle()) {
if (!surface) {
if (currentSurfaceForCurrentContext(ctx))
return true;
surface = fallbackSurface;
nativeWindowGone = true;
}
if (!surface)
} else if (surface->surfaceClass() == QSurface::Window && !surface->surfaceHandle()) {
surface = fallbackSurface;
if (needsMakeCurrent)
needsMakeCurrent = false;
else if (!nativeWindowGone && QOpenGLContext::currentContext() == ctx && (surface == fallbackSurface || ctx->surface() == surface))
} else if (!needsMakeCurrentDueToSwap && currentSurfaceForCurrentContext(ctx) == surface) {
return true;
}
needsMakeCurrentDueToSwap = false;
if (!ctx->makeCurrent(surface)) {
if (ctx->isValid()) {
@ -1788,7 +1800,7 @@ QRhi::FrameOpResult QRhiGles2::endFrame(QRhiSwapChain *swapChain, QRhi::EndFrame
if (swapChainD->surface && !flags.testFlag(QRhi::SkipPresent)) {
ctx->swapBuffers(swapChainD->surface);
needsMakeCurrent = true;
needsMakeCurrentDueToSwap = true;
} else {
f->glFlush();
}

View File

@ -902,7 +902,7 @@ public:
QSurface *fallbackSurface = nullptr;
QWindow *maybeWindow = nullptr;
QOpenGLContext *maybeShareContext = nullptr;
mutable bool needsMakeCurrent = false;
mutable bool needsMakeCurrentDueToSwap = false;
QOpenGLExtensions *f = nullptr;
uint vao = 0;
struct Caps {