macOS: Update NSOpenGLContext drawable on beginning of frame if needed

If the size or DPR of the window we're drawing to with QOpenGLContext
changes we need to call [NSOpenGLContext update] to recreate the backing
texture.

We were doing this in QCocoaGLContext::makeCurrent(), based on the
assumption that clients would always call makeCurrent() before drawing,
which is a documented requirement of QOpenGLContext:

  "To be able to support certain platforms, QOpenGLContext requires
  that you call makeCurrent() again before starting rendering a new
  frame, after calling swapBuffers()."

However RHI doesn't follow this rule, and skips makeCurrent() from
QRhiGles2::ensureContext() if the context is already current.

This was causing issues when moving a window between screens with
different device-pixel-ratios, as we were correctly rendering to
the window with the updated DPR, but we had not resized the target
texture to match.

Changing QRhiGles2::ensureContext() might be an option, but nowadays
we have QPlatformOpenGLContext::beginFrame(), which is guaranteed
to be called (by RHI, not by generic QOpenGLContext clients).

To cater for RHI we now call [NSOpenGLContext update] also from
the beginFrame callback.

Fixes: QTBUG-114873
Pick-to: 6.5
Change-Id: I9461135109fb1473ef9965f72f52beeb41b03680
Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
(cherry picked from commit 48c176e1b891428af504087b117a72bcaa806930)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Tor Arne Vestbø 2024-10-28 16:05:10 +01:00 committed by Qt Cherry-pick Bot
parent 945c8bf54d
commit 1696091c5b
2 changed files with 20 additions and 0 deletions

View File

@ -29,6 +29,7 @@ public:
void initialize() override; void initialize() override;
bool makeCurrent(QPlatformSurface *surface) override; bool makeCurrent(QPlatformSurface *surface) override;
void beginFrame() override;
void swapBuffers(QPlatformSurface *surface) override; void swapBuffers(QPlatformSurface *surface) override;
void doneCurrent() override; void doneCurrent() override;

View File

@ -332,6 +332,25 @@ bool QCocoaGLContext::makeCurrent(QPlatformSurface *surface)
return true; return true;
} }
void QCocoaGLContext::beginFrame()
{
QMacAutoReleasePool pool;
Q_ASSERT(context() && context()->surface());
auto *surface = context()->surface()->surfaceHandle();
Q_ASSERT(surface);
qCDebug(lcQpaOpenGLContext) << "Beginning frame for" << this
<< "in" << QThread::currentThread() << "for" << surface;
Q_ASSERT(surface->surface()->supportsOpenGL());
if (surface->surface()->surfaceClass() == QSurface::Window) {
if (m_needsUpdate.fetchAndStoreRelaxed(false))
update();
}
}
/*! /*!
Sets the drawable object of the NSOpenGLContext, which is the Sets the drawable object of the NSOpenGLContext, which is the
frame buffer that is the target of OpenGL drawing operations. frame buffer that is the target of OpenGL drawing operations.