summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntti Määttä <antti.maatta@qt.io>2022-10-19 09:04:54 +0300
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2022-10-21 05:01:45 +0000
commit495e4c6ad26142764042973914c3c928185f4781 (patch)
tree1ca6e78c77a9a4a6b2113526fd70d6d3995fdd9c
parent97866ffe4a0a625b45c88f5bc0bc35fe1df4ffe6 (diff)
downloadqtbase-495e4c6ad26142764042973914c3c928185f4781.tar.gz
QRhi: Allow negative viewport origin
Do not bound viewport rect to surface size, only scirror rect. Modifying the viewport will move the view origin changing the way the scene gets rendered. Task-number: QTBUG-106082 Change-Id: I105516bd460af87727d0e73f580b8cf6b748d87f Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io> (cherry picked from commit d46ad528727772362b710d68c27d963db81235c4) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/gui/rhi/qrhi_p_p.h41
-rw-r--r--src/gui/rhi/qrhid3d11.cpp4
-rw-r--r--src/gui/rhi/qrhimetal.mm5
-rw-r--r--src/gui/rhi/qrhivulkan.cpp5
4 files changed, 33 insertions, 22 deletions
diff --git a/src/gui/rhi/qrhi_p_p.h b/src/gui/rhi/qrhi_p_p.h
index 2a0cb7d631..fbc8be2e95 100644
--- a/src/gui/rhi/qrhi_p_p.h
+++ b/src/gui/rhi/qrhi_p_p.h
@@ -224,7 +224,13 @@ private:
friend class QRhiResourceUpdateBatchPrivate;
};
-template<typename T, size_t N>
+enum QRhiTargetRectBoundMode
+{
+ UnBounded,
+ Bounded
+};
+
+template<QRhiTargetRectBoundMode boundingMode, typename T, size_t N>
bool qrhi_toTopLeftRenderTargetRect(const QSize &outputSize, const std::array<T, N> &r,
T *x, T *y, T *w, T *h)
{
@@ -235,7 +241,7 @@ bool qrhi_toTopLeftRenderTargetRect(const QSize &outputSize, const std::array<T,
// or height. We must handle all other input gracefully, clamping to a zero
// width or height rect in the worst case, and ensuring the resulting rect
// is inside the rendertarget's bounds because some APIs' validation/debug
- // layers are allergic to out of bounds scissor or viewport rects.
+ // layers are allergic to out of bounds scissor rects.
const T outputWidth = outputSize.width();
const T outputHeight = outputSize.height();
@@ -247,20 +253,23 @@ bool qrhi_toTopLeftRenderTargetRect(const QSize &outputSize, const std::array<T,
*x = r[0];
*y = outputHeight - (r[1] + inputHeight);
-
- const T widthOffset = *x < 0 ? -*x : 0;
- const T heightOffset = *y < 0 ? -*y : 0;
- *w = *x < outputWidth ? qMax<T>(0, inputWidth - widthOffset) : 0;
- *h = *y < outputHeight ? qMax<T>(0, inputHeight - heightOffset) : 0;
-
- *x = qBound<T>(0, *x, outputWidth - 1);
- *y = qBound<T>(0, *y, outputHeight - 1);
-
- if (*x + *w > outputWidth)
- *w = qMax<T>(0, outputWidth - *x);
- if (*y + *h > outputHeight)
- *h = qMax<T>(0, outputHeight - *y);
-
+ *w = inputWidth;
+ *h = inputHeight;
+
+ if (boundingMode == Bounded) {
+ const T widthOffset = *x < 0 ? -*x : 0;
+ const T heightOffset = *y < 0 ? -*y : 0;
+ *w = *x < outputWidth ? qMax<T>(0, inputWidth - widthOffset) : 0;
+ *h = *y < outputHeight ? qMax<T>(0, inputHeight - heightOffset) : 0;
+
+ *x = qBound<T>(0, *x, outputWidth - 1);
+ *y = qBound<T>(0, *y, outputHeight - 1);
+
+ if (*x + *w > outputWidth)
+ *w = qMax<T>(0, outputWidth - *x);
+ if (*y + *h > outputHeight)
+ *h = qMax<T>(0, outputHeight - *y);
+ }
return true;
}
diff --git a/src/gui/rhi/qrhid3d11.cpp b/src/gui/rhi/qrhid3d11.cpp
index 0ac92e2266..89bfb57716 100644
--- a/src/gui/rhi/qrhid3d11.cpp
+++ b/src/gui/rhi/qrhid3d11.cpp
@@ -1090,7 +1090,7 @@ void QRhiD3D11::setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport)
// d3d expects top-left, QRhiViewport is bottom-left
float x, y, w, h;
- if (!qrhi_toTopLeftRenderTargetRect(outputSize, viewport.viewport(), &x, &y, &w, &h))
+ if (!qrhi_toTopLeftRenderTargetRect<UnBounded>(outputSize, viewport.viewport(), &x, &y, &w, &h))
return;
QD3D11CommandBuffer::Command &cmd(cbD->commands.get());
@@ -1112,7 +1112,7 @@ void QRhiD3D11::setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor)
// d3d expects top-left, QRhiScissor is bottom-left
int x, y, w, h;
- if (!qrhi_toTopLeftRenderTargetRect(outputSize, scissor.scissor(), &x, &y, &w, &h))
+ if (!qrhi_toTopLeftRenderTargetRect<Bounded>(outputSize, scissor.scissor(), &x, &y, &w, &h))
return;
QD3D11CommandBuffer::Command &cmd(cbD->commands.get());
diff --git a/src/gui/rhi/qrhimetal.mm b/src/gui/rhi/qrhimetal.mm
index bd761b4e15..33cdae7d35 100644
--- a/src/gui/rhi/qrhimetal.mm
+++ b/src/gui/rhi/qrhimetal.mm
@@ -1305,7 +1305,7 @@ void QRhiMetal::setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport)
// x,y is top-left in MTLViewportRect but bottom-left in QRhiViewport
float x, y, w, h;
- if (!qrhi_toTopLeftRenderTargetRect(outputSize, viewport.viewport(), &x, &y, &w, &h))
+ if (!qrhi_toTopLeftRenderTargetRect<UnBounded>(outputSize, viewport.viewport(), &x, &y, &w, &h))
return;
MTLViewport vp;
@@ -1320,6 +1320,7 @@ void QRhiMetal::setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport)
if (!QRHI_RES(QMetalGraphicsPipeline, cbD->currentGraphicsPipeline)->m_flags.testFlag(QRhiGraphicsPipeline::UsesScissor)) {
MTLScissorRect s;
+ qrhi_toTopLeftRenderTargetRect<Bounded>(outputSize, viewport.viewport(), &x, &y, &w, &h);
s.x = NSUInteger(x);
s.y = NSUInteger(y);
s.width = NSUInteger(w);
@@ -1337,7 +1338,7 @@ void QRhiMetal::setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor)
// x,y is top-left in MTLScissorRect but bottom-left in QRhiScissor
int x, y, w, h;
- if (!qrhi_toTopLeftRenderTargetRect(outputSize, scissor.scissor(), &x, &y, &w, &h))
+ if (!qrhi_toTopLeftRenderTargetRect<Bounded>(outputSize, scissor.scissor(), &x, &y, &w, &h))
return;
MTLScissorRect s;
diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp
index bcf5dab117..fd1ede2424 100644
--- a/src/gui/rhi/qrhivulkan.cpp
+++ b/src/gui/rhi/qrhivulkan.cpp
@@ -4929,7 +4929,7 @@ void QRhiVulkan::setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport
// x,y is top-left in VkViewport but bottom-left in QRhiViewport
float x, y, w, h;
- if (!qrhi_toTopLeftRenderTargetRect(outputSize, viewport.viewport(), &x, &y, &w, &h))
+ if (!qrhi_toTopLeftRenderTargetRect<UnBounded>(outputSize, viewport.viewport(), &x, &y, &w, &h))
return;
QVkCommandBuffer::Command &cmd(cbD->commands.get());
@@ -4951,6 +4951,7 @@ void QRhiVulkan::setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport
if (!QRHI_RES(QVkGraphicsPipeline, cbD->currentGraphicsPipeline)->m_flags.testFlag(QRhiGraphicsPipeline::UsesScissor)) {
QVkCommandBuffer::Command &cmd(cbD->commands.get());
VkRect2D *s = &cmd.args.setScissor.scissor;
+ qrhi_toTopLeftRenderTargetRect<Bounded>(outputSize, viewport.viewport(), &x, &y, &w, &h);
s->offset.x = int32_t(x);
s->offset.y = int32_t(y);
s->extent.width = uint32_t(w);
@@ -4973,7 +4974,7 @@ void QRhiVulkan::setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor)
// x,y is top-left in VkRect2D but bottom-left in QRhiScissor
int x, y, w, h;
- if (!qrhi_toTopLeftRenderTargetRect(outputSize, scissor.scissor(), &x, &y, &w, &h))
+ if (!qrhi_toTopLeftRenderTargetRect<Bounded>(outputSize, scissor.scissor(), &x, &y, &w, &h))
return;
QVkCommandBuffer::Command &cmd(cbD->commands.get());