diff options
author | Laszlo Agocs <laszlo.agocs@qt.io> | 2021-03-10 11:06:23 +0100 |
---|---|---|
committer | Laszlo Agocs <laszlo.agocs@qt.io> | 2021-03-10 16:20:53 +0100 |
commit | 83fb8fe208ec816df7d04c8247d5696d95f2cab1 (patch) | |
tree | a69d5def95f6123180d4b21940fd43c73482913d /src/gui/rhi/qrhimetal.mm | |
parent | 153716a914a8a3ab412578bc982647f0f7148025 (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
Pick-to: 6.1 6.0
Fixes: QTBUG-91438
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Diffstat (limited to 'src/gui/rhi/qrhimetal.mm')
-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 76d16b3e50..170c7a2ac6 100644 --- a/src/gui/rhi/qrhimetal.mm +++ b/src/gui/rhi/qrhimetal.mm @@ -3838,10 +3838,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() @@ -3900,13 +3932,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(); |