summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2021-03-10 11:06:23 +0100
committerAndy Shaw <andy.shaw@qt.io>2021-10-06 09:43:55 +0200
commitc0d3c9e0240e314b835c6585e26ad9b3bf21604d (patch)
tree88b68d3e45d2769d2bae620f2d3756ad66205461
parent45b7a14d592070ff28a1bc5fdf7abfcf09771c13 (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 (cherry picked from commit 83fb8fe208ec816df7d04c8247d5696d95f2cab1) Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
-rw-r--r--src/gui/rhi/qrhimetal.mm42
1 files changed, 34 insertions, 8 deletions
diff --git a/src/gui/rhi/qrhimetal.mm b/src/gui/rhi/qrhimetal.mm
index 5fe18c9827..acd53b3dfd 100644
--- a/src/gui/rhi/qrhimetal.mm
+++ b/src/gui/rhi/qrhimetal.mm
@@ -3738,10 +3738,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()
@@ -3800,13 +3832,7 @@ bool QMetalSwapChain::buildOrResize()
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();