diff options
-rw-r--r-- | src/gui/rhi/qrhi_p_p.h | 41 | ||||
-rw-r--r-- | src/gui/rhi/qrhid3d11.cpp | 4 | ||||
-rw-r--r-- | src/gui/rhi/qrhimetal.mm | 5 | ||||
-rw-r--r-- | src/gui/rhi/qrhivulkan.cpp | 5 |
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()); |