Handle insets correctly for the in-game final screen blit.

Should help #12982 in case of phones with inset cameras.
This commit is contained in:
Henrik Rydgård 2020-05-31 20:13:35 +02:00
parent e559fc022f
commit c8d48a8777
4 changed files with 61 additions and 28 deletions

View File

@ -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_);
}

View File

@ -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;

View File

@ -19,8 +19,10 @@
#include <cmath>
#include <set>
#include <cstdint>
#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;

View File

@ -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;