From c8d48a877743c5c1f0dc71256192cab896a7bdae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 31 May 2020 20:13:35 +0200 Subject: [PATCH] Handle insets correctly for the in-game final screen blit. Should help #12982 in case of phones with inset cameras. --- GPU/Common/FramebufferCommon.cpp | 6 ++- GPU/Common/GPUStateUtils.cpp | 3 +- GPU/Common/PresentationCommon.cpp | 77 +++++++++++++++++++++---------- GPU/Common/PresentationCommon.h | 3 +- 4 files changed, 61 insertions(+), 28 deletions(-) diff --git a/GPU/Common/FramebufferCommon.cpp b/GPU/Common/FramebufferCommon.cpp index 8cdbeb88bc..548d82faef 100644 --- a/GPU/Common/FramebufferCommon.cpp +++ b/GPU/Common/FramebufferCommon.cpp @@ -655,13 +655,15 @@ void FramebufferManagerCommon::DrawPixels(VirtualFramebuffer *vfb, int dstX, int SetViewport2D(0, 0, vfb->renderWidth, vfb->renderHeight); draw_->SetScissorRect(0, 0, vfb->renderWidth, vfb->renderHeight); } else { - // We are drawing to the back buffer so need to flip. + // We are drawing directly to the back buffer so need to flip. + // Should more of this be handled by the presentation engine? if (needBackBufferYSwap_) std::swap(v0, v1); flags = g_Config.iBufFilter == SCALE_LINEAR ? DRAWTEX_LINEAR : DRAWTEX_NEAREST; flags = flags | DRAWTEX_TO_BACKBUFFER; + FRect frame = GetInsetScreenFrame(pixelWidth_, pixelHeight_); FRect rc; - CenterDisplayOutputRect(&rc, 480.0f, 272.0f, (float)pixelWidth_, (float)pixelHeight_, ROTATION_LOCKED_HORIZONTAL); + CenterDisplayOutputRect(&rc, 480.0f, 272.0f, frame, ROTATION_LOCKED_HORIZONTAL); SetViewport2D(rc.x, rc.y, rc.w, rc.h); draw_->SetScissorRect(0, 0, pixelWidth_, pixelHeight_); } diff --git a/GPU/Common/GPUStateUtils.cpp b/GPU/Common/GPUStateUtils.cpp index 273619042d..dc29213429 100644 --- a/GPU/Common/GPUStateUtils.cpp +++ b/GPU/Common/GPUStateUtils.cpp @@ -557,8 +557,9 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo } else { float pixelW = PSP_CoreParameter().pixelWidth; float pixelH = PSP_CoreParameter().pixelHeight; + FRect frame = GetInsetScreenFrame(pixelW, pixelH); FRect rc; - CenterDisplayOutputRect(&rc, 480, 272, pixelW, pixelH, ROTATION_LOCKED_HORIZONTAL); + CenterDisplayOutputRect(&rc, 480, 272, frame, ROTATION_LOCKED_HORIZONTAL); displayOffsetX = rc.x; displayOffsetY = rc.y; renderWidth = rc.w; diff --git a/GPU/Common/PresentationCommon.cpp b/GPU/Common/PresentationCommon.cpp index a18dde1722..871322073e 100644 --- a/GPU/Common/PresentationCommon.cpp +++ b/GPU/Common/PresentationCommon.cpp @@ -19,8 +19,10 @@ #include #include #include + #include "base/display.h" #include "base/timeutil.h" +#include "base/NativeApp.h" #include "file/vfs.h" #include "file/zip_read.h" #include "thin3d/thin3d.h" @@ -39,19 +41,40 @@ struct Vertex { uint32_t rgba; }; -void CenterDisplayOutputRect(FRect *rc, float origW, float origH, float frameW, float frameH, int rotation) { +FRect GetInsetScreenFrame(float pixelWidth, float pixelHeight) { + FRect rc = FRect{ + 0.0f, + 0.0f, + pixelWidth, + pixelHeight, + }; + + float left = System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_LEFT); + float right = System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_RIGHT); + float top = System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_TOP); + float bottom = System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_BOTTOM); + + // Adjust left edge to compensate for cutouts (notches) if any. + rc.x += left; + rc.w -= (left + right); + rc.y += top; + rc.h -= (top + bottom); + return rc; +} + +void CenterDisplayOutputRect(FRect *rc, float origW, float origH, const FRect &frame, int rotation) { float outW; float outH; bool rotated = rotation == ROTATION_LOCKED_VERTICAL || rotation == ROTATION_LOCKED_VERTICAL180; if (g_Config.iSmallDisplayZoomType == (int)SmallDisplayZoom::STRETCH) { - outW = frameW; - outH = frameH; + outW = frame.w; + outH = frame.h; } else { if (g_Config.iSmallDisplayZoomType == (int)SmallDisplayZoom::MANUAL) { - float offsetX = (g_Config.fSmallDisplayOffsetX - 0.5f) * 2.0f * frameW; - float offsetY = (g_Config.fSmallDisplayOffsetY - 0.5f) * 2.0f * frameH; + float offsetX = (g_Config.fSmallDisplayOffsetX - 0.5f) * 2.0f * frame.w; + float offsetY = (g_Config.fSmallDisplayOffsetY - 0.5f) * 2.0f * frame.h; // Have to invert Y for GL if (GetGPUBackend() == GPUBackend::OPENGL) { offsetY = offsetY * -1.0f; @@ -60,24 +83,24 @@ void CenterDisplayOutputRect(FRect *rc, float origW, float origH, float frameW, float smallDisplayW = origW * customZoom; float smallDisplayH = origH * customZoom; if (!rotated) { - rc->x = floorf(((frameW - smallDisplayW) / 2.0f) + offsetX); - rc->y = floorf(((frameH - smallDisplayH) / 2.0f) + offsetY); + rc->x = floorf(((frame.w - smallDisplayW) / 2.0f) + offsetX); + rc->y = floorf(((frame.h - smallDisplayH) / 2.0f) + offsetY); rc->w = floorf(smallDisplayW); rc->h = floorf(smallDisplayH); return; } else { - rc->x = floorf(((frameW - smallDisplayH) / 2.0f) + offsetX); - rc->y = floorf(((frameH - smallDisplayW) / 2.0f) + offsetY); + rc->x = floorf(((frame.w - smallDisplayH) / 2.0f) + offsetX); + rc->y = floorf(((frame.h - smallDisplayW) / 2.0f) + offsetY); rc->w = floorf(smallDisplayH); rc->h = floorf(smallDisplayW); return; } } else if (g_Config.iSmallDisplayZoomType == (int)SmallDisplayZoom::AUTO) { // Stretch to 1080 for 272*4. But don't distort if not widescreen (i.e. ultrawide of halfwide.) - float pixelCrop = frameH / 270.0f; + float pixelCrop = frame.h / 270.0f; float resCommonWidescreen = pixelCrop - floor(pixelCrop); - if (!rotated && resCommonWidescreen == 0.0f && frameW >= pixelCrop * 480.0f) { - rc->x = floorf((frameW - pixelCrop * 480.0f) * 0.5f); + if (!rotated && resCommonWidescreen == 0.0f && frame.w >= pixelCrop * 480.0f) { + rc->x = floorf((frame.h - pixelCrop * 480.0f) * 0.5f); rc->y = floorf(-pixelCrop); rc->w = floorf(pixelCrop * 480.0f); rc->h = floorf(pixelCrop * 272.0f); @@ -86,26 +109,26 @@ void CenterDisplayOutputRect(FRect *rc, float origW, float origH, float frameW, } float origRatio = !rotated ? origW / origH : origH / origW; - float frameRatio = frameW / frameH; + float frameRatio = frame.w / frame.h; if (origRatio > frameRatio) { // Image is wider than frame. Center vertically. - outW = frameW; - outH = frameW / origRatio; + outW = frame.w; + outH = frame.w / origRatio; // Stretch a little bit if (!rotated && g_Config.iSmallDisplayZoomType == (int)SmallDisplayZoom::PARTIAL_STRETCH) - outH = (frameH + outH) / 2.0f; // (408 + 720) / 2 = 564 + outH = (frame.h + outH) / 2.0f; // (408 + 720) / 2 = 564 } else { // Image is taller than frame. Center horizontally. - outW = frameH * origRatio; - outH = frameH; + outW = frame.h * origRatio; + outH = frame.h; if (rotated && g_Config.iSmallDisplayZoomType == (int)SmallDisplayZoom::PARTIAL_STRETCH) - outW = (frameH + outH) / 2.0f; // (408 + 720) / 2 = 564 + outW = (frame.h + outH) / 2.0f; // (408 + 720) / 2 = 564 } } - rc->x = floorf((frameW - outW) / 2.0f); - rc->y = floorf((frameH - outH) / 2.0f); + rc->x = floorf((frame.w - outW) / 2.0f + frame.x); + rc->y = floorf((frame.h - outH) / 2.0f + frame.y); rc->w = floorf(outW); rc->h = floorf(outH); } @@ -119,6 +142,10 @@ PresentationCommon::~PresentationCommon() { } void PresentationCommon::GetCardboardSettings(CardboardSettings *cardboardSettings) { + if (!g_Config.bEnableCardboardVR) { + cardboardSettings->enabled = false; + return; + } // Calculate Cardboard Settings float cardboardScreenScale = g_Config.iCardboardScreenSize / 100.0f; float cardboardScreenWidth = pixelWidth_ / 2.0f * cardboardScreenScale; @@ -131,7 +158,7 @@ void PresentationCommon::GetCardboardSettings(CardboardSettings *cardboardSettin float cardboardUserYShift = g_Config.iCardboardYShift / 100.0f * cardboardMaxYShift; float cardboardScreenY = cardboardMaxYShift + cardboardUserYShift; - cardboardSettings->enabled = g_Config.bEnableCardboardVR; + cardboardSettings->enabled = true; cardboardSettings->leftEyeXPosition = cardboardLeftEyeX; cardboardSettings->rightEyeXPosition = cardboardRightEyeX; cardboardSettings->screenYPosition = cardboardScreenY; @@ -253,7 +280,8 @@ bool PresentationCommon::BuildPostShader(const ShaderInfo *shaderInfo, const Sha } else if (shaderInfo->outputResolution) { // If the current shader uses output res (not next), we will use output res for it. FRect rc; - CenterDisplayOutputRect(&rc, 480.0f, 272.0f, (float)pixelWidth_, (float)pixelHeight_, g_Config.iInternalScreenRotation); + FRect frame = GetInsetScreenFrame((float)pixelWidth_, (float)pixelHeight_); + CenterDisplayOutputRect(&rc, 480.0f, 272.0f, frame, g_Config.iInternalScreenRotation); nextWidth = (int)rc.w; nextHeight = (int)rc.h; } @@ -499,8 +527,9 @@ void PresentationCommon::CopyToOutput(OutputFlags flags, int uvRotation, float u int lastHeight = srcHeight_; // These are the output coordinates. + FRect frame = GetInsetScreenFrame((float)pixelWidth_, (float)pixelHeight_); FRect rc; - CenterDisplayOutputRect(&rc, 480.0f, 272.0f, (float)pixelWidth_, (float)pixelHeight_, uvRotation); + CenterDisplayOutputRect(&rc, 480.0f, 272.0f, frame, uvRotation); if (GetGPUBackend() == GPUBackend::DIRECT3D9) { rc.x -= 0.5f; diff --git a/GPU/Common/PresentationCommon.h b/GPU/Common/PresentationCommon.h index 50f6508880..502ef318e9 100644 --- a/GPU/Common/PresentationCommon.h +++ b/GPU/Common/PresentationCommon.h @@ -45,7 +45,8 @@ struct FRect { float h; }; -void CenterDisplayOutputRect(FRect *rc, float origW, float origH, float frameW, float frameH, int rotation); +FRect GetInsetScreenFrame(float pixelWidth, float pixelHeight); +void CenterDisplayOutputRect(FRect *rc, float origW, float origH, const FRect &frame, int rotation); namespace Draw { class Buffer;