From 518747aa86a50be62ecf92aeb309309b0d58a54a Mon Sep 17 00:00:00 2001 From: doop <56421834+dooplecks@users.noreply.github.com> Date: Tue, 5 May 2026 01:34:41 -0400 Subject: [PATCH] Map logical viewport/scissor to same region (#155) --- lib/gx/gx.cpp | 66 +++++++++++++++++++++++++++++---------------------- 1 file changed, 38 insertions(+), 28 deletions(-) diff --git a/lib/gx/gx.cpp b/lib/gx/gx.cpp index ad6fd08..2ffa1f2 100644 --- a/lib/gx/gx.cpp +++ b/lib/gx/gx.cpp @@ -246,6 +246,31 @@ Vec2 logical_fb_size() noexcept { return gfx::is_offscreen() ? gfx::get_render_target_size() : vi::configured_fb_size(); } +std::tuple calculate_inner_box(const int targetWidth, const int targetHeight, + const int logicalFbWidth, const int logicalFbHeight) noexcept { + if (g_gxState.viewportPolicy == AURORA_VIEWPORT_STRETCH) { + return { + 0.0f, + 0.0f, + static_cast(targetWidth), + static_cast(targetHeight), + }; + } else { + const auto scale = std::min(static_cast(targetWidth) / static_cast(logicalFbWidth), + static_cast(targetHeight) / static_cast(logicalFbHeight)); + const auto offsetX = + std::floor((static_cast(targetWidth) - static_cast(logicalFbWidth) * scale) * 0.5f); + const auto offsetY = + std::floor((static_cast(targetHeight) - static_cast(logicalFbHeight) * scale) * 0.5f); + return { + offsetX, + offsetY, + static_cast(targetWidth) - 2.0f * offsetX, + static_cast(targetHeight) - 2.0f * offsetY, + }; + } +} + gfx::Viewport map_logical_viewport(const gfx::Viewport& logicalViewport) noexcept { if (g_gxState.viewportPolicy == AURORA_VIEWPORT_NATIVE) { return logicalViewport; @@ -257,21 +282,14 @@ gfx::Viewport map_logical_viewport(const gfx::Viewport& logicalViewport) noexcep return logicalViewport; } - const bool stretch = g_gxState.viewportPolicy == AURORA_VIEWPORT_STRETCH; - const float scaleX = static_cast(targetWidth) / static_cast(logicalFbWidth); - const float scaleY = static_cast(targetHeight) / static_cast(logicalFbHeight); - const float scale = std::min(scaleX, scaleY); - const float xOffset = - stretch ? 0.f : (static_cast(targetWidth) - static_cast(logicalFbWidth) * scale) * 0.5f; - const float yOffset = - stretch ? 0.f : (static_cast(targetHeight) - static_cast(logicalFbHeight) * scale) * 0.5f; - const float mappedScaleX = stretch ? scaleX : scale; - const float mappedScaleY = stretch ? scaleY : scale; + const auto [offsetX, offsetY, innerWidth, innerHeight] = + calculate_inner_box(targetWidth, targetHeight, logicalFbWidth, logicalFbHeight); + return { - .left = xOffset + logicalViewport.left * mappedScaleX, - .top = yOffset + logicalViewport.top * mappedScaleY, - .width = logicalViewport.width * mappedScaleX, - .height = logicalViewport.height * mappedScaleY, + .left = offsetX + (logicalViewport.left / static_cast(logicalFbWidth)) * innerWidth, + .top = offsetY + (logicalViewport.top / static_cast(logicalFbHeight)) * innerHeight, + .width = (logicalViewport.width / static_cast(logicalFbWidth)) * innerWidth, + .height = (logicalViewport.height / static_cast(logicalFbHeight)) * innerHeight, .znear = logicalViewport.znear, .zfar = logicalViewport.zfar, }; @@ -288,21 +306,13 @@ gfx::ClipRect map_logical_scissor(const gfx::ClipRect& logicalScissor) noexcept return logicalScissor; } - const bool stretch = g_gxState.viewportPolicy == AURORA_VIEWPORT_STRETCH; - const float scaleX = static_cast(targetWidth) / static_cast(logicalFbWidth); - const float scaleY = static_cast(targetHeight) / static_cast(logicalFbHeight); - const float scale = std::min(scaleX, scaleY); - const float xOffset = - stretch ? 0.f : (static_cast(targetWidth) - static_cast(logicalFbWidth) * scale) * 0.5f; - const float yOffset = - stretch ? 0.f : (static_cast(targetHeight) - static_cast(logicalFbHeight) * scale) * 0.5f; - const float mappedScaleX = stretch ? scaleX : scale; - const float mappedScaleY = stretch ? scaleY : scale; + const auto [offsetX, offsetY, innerWidth, innerHeight] = + calculate_inner_box(targetWidth, targetHeight, logicalFbWidth, logicalFbHeight); - const float left = xOffset + static_cast(logicalScissor.x) * mappedScaleX; - const float top = yOffset + static_cast(logicalScissor.y) * mappedScaleY; - const float right = xOffset + static_cast(logicalScissor.x + logicalScissor.width) * mappedScaleX; - const float bottom = yOffset + static_cast(logicalScissor.y + logicalScissor.height) * mappedScaleY; + const float left = offsetX + (static_cast(logicalScissor.x) / static_cast(logicalFbWidth)) * innerWidth; + const float top = offsetY + (static_cast(logicalScissor.y) / static_cast(logicalFbHeight)) * innerHeight; + const float right = offsetX + (static_cast(logicalScissor.x + logicalScissor.width) / static_cast(logicalFbWidth)) * innerWidth; + const float bottom = offsetY + (static_cast(logicalScissor.y + logicalScissor.height) / static_cast(logicalFbHeight)) * innerHeight; const auto mappedLeft = std::clamp(static_cast(std::floor(left)), 0, static_cast(targetWidth)); const auto mappedTop = std::clamp(static_cast(std::floor(top)), 0, static_cast(targetHeight));