summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 7ac0184a16..446403f9b7 100644
--- a/src/gui/rhi/qrhi_p_p.h
+++ b/src/gui/rhi/qrhi_p_p.h
@@ -245,7 +245,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)
{
@@ -256,7 +262,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();
@@ -268,20 +274,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 3ef1fa394e..da7089edf9 100644
--- a/src/gui/rhi/qrhid3d11.cpp
+++ b/src/gui/rhi/qrhid3d11.cpp
@@ -1084,7 +1084,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());
@@ -1106,7 +1106,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 31364761a2..5b18ff3e96 100644
--- a/src/gui/rhi/qrhimetal.mm
+++ b/src/gui/rhi/qrhimetal.mm
@@ -1643,7 +1643,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;
@@ -1659,6 +1659,7 @@ void QRhiMetal::setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport)
if (cbD->currentGraphicsPipeline
&& !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);
@@ -1676,7 +1677,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 05a67e82de..832db33631 100644
--- a/src/gui/rhi/qrhivulkan.cpp
+++ b/src/gui/rhi/qrhivulkan.cpp
@@ -4927,7 +4927,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
->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());