diff options
author | Laszlo Agocs <laszlo.agocs@qt.io> | 2021-03-10 11:06:23 +0100 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2021-03-10 17:32:44 +0000 |
commit | b130d16a27399497739a56bd1a5a824a6a5885b1 (patch) | |
tree | ba15220f8916b873b4899b9c81bf0617191e23ec /src | |
parent | b9091e4cec8be067509464ff068612a07ed4a95d (diff) |
rhi: metal: Use the layer as the single source of truth
...when it comes to the output size.
This mirrors what all other backends do. For example, with Vulkan
the only source of size is the surface (VkSurfaceKHR), never the
QWindow, even though we'd expect that the surface size equals
to window_size * dpr, and that's almost always true, but there
are exceptions. (e.g. we have seen bugs on Windows with some drivers
in high DPI situations where the Vulkan surface did not fully match
the window size, yet it is the surface, and only the surface, that
matters for rendering, i.e. viewports and such must match the surface,
not the native window)
With Metal we hit a similar problem on iOS: the QWindow's size*dpr
and what we calculate from the CAMetalLayer have a height difference
of 1.
Mitigate this by making QRhiSwapChain::surfacePixelSize() and the
calculation for currentPixelSize() done via the same route (the
CAMetalLayer). Otherwise, if there is a mismatch between what the
QWindow and the layer says, Qt Quick will think that there is a
resize happening (has happened) whenever starting a new frame, and that
has far reaching consequences (suboptimal performance, increased
memory usage by buffers, etc.)
Change-Id: I114df92bf35622c99f2747420fdce401db7705a6
Fixes: QTBUG-91438
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
(cherry picked from commit 83fb8fe208ec816df7d04c8247d5696d95f2cab1)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Diffstat (limited to 'src')
-rw-r--r-- | src/gui/rhi/qrhimetal.mm | 42 |
1 files changed, 34 insertions, 8 deletions
diff --git a/src/gui/rhi/qrhimetal.mm b/src/gui/rhi/qrhimetal.mm index 9e0655ef06..507f63b9a9 100644 --- a/src/gui/rhi/qrhimetal.mm +++ b/src/gui/rhi/qrhimetal.mm @@ -3787,10 +3787,42 @@ QRhiRenderTarget *QMetalSwapChain::currentFrameRenderTarget() return &rtWrapper; } +#ifdef TARGET_IPHONE_SIMULATOR +API_AVAILABLE(ios(13.0)) +#endif +static inline CAMetalLayer *layerForWindow(QWindow *window) +{ + Q_ASSERT(window); +#ifdef Q_OS_MACOS + NSView *view = reinterpret_cast<NSView *>(window->winId()); +#else + UIView *view = reinterpret_cast<UIView *>(window->winId()); +#endif + Q_ASSERT(view); + return static_cast<CAMetalLayer *>(view.layer); +} + QSize QMetalSwapChain::surfacePixelSize() { +#ifdef TARGET_IPHONE_SIMULATOR + if (@available(ios 13.0, *)) { +#endif + Q_ASSERT(m_window); - return m_window->size() * m_window->devicePixelRatio(); + CAMetalLayer *layer = d->layer; + if (!layer) + layer = layerForWindow(m_window); + + CGSize layerSize = layer.bounds.size; + layerSize.width *= layer.contentsScale; + layerSize.height *= layer.contentsScale; + return QSizeF::fromCGSize(layerSize).toSize(); + +#ifdef TARGET_IPHONE_SIMULATOR + } else { + return QSize(); + } +#endif } QRhiRenderPassDescriptor *QMetalSwapChain::newCompatibleRenderPassDescriptor() @@ -3849,13 +3881,7 @@ bool QMetalSwapChain::createOrResize() return false; } -#ifdef Q_OS_MACOS - NSView *view = reinterpret_cast<NSView *>(window->winId()); -#else - UIView *view = reinterpret_cast<UIView *>(window->winId()); -#endif - Q_ASSERT(view); - d->layer = static_cast<CAMetalLayer *>(view.layer); + d->layer = layerForWindow(window); Q_ASSERT(d->layer); chooseFormats(); |