From 67010ff2afd9f34ccb6ac1bcb04bdd083d800548 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 30 Oct 2025 11:18:20 +0100 Subject: [PATCH] Split the display layout config between landscape and portrait orientations --- Common/Math/geom2d.h | 7 +++ Common/System/Display.cpp | 4 ++ Common/System/Display.h | 3 +- Common/UI/UIScreen.cpp | 17 +++--- Common/UI/UIScreen.h | 4 +- Core/Config.cpp | 42 ++++++++------ Core/Config.h | 48 ++++++++++------ Core/ConfigSettings.h | 12 ---- Core/ControlMapper.cpp | 17 +++--- Core/ControlMapper.h | 9 ++- Core/HLE/sceDisplay.cpp | 8 ++- Core/HLE/sceDisplay.h | 4 ++ Core/HLE/sceIo.cpp | 8 ++- GPU/Common/FramebufferManagerCommon.cpp | 57 ++++++++++--------- GPU/Common/FramebufferManagerCommon.h | 22 ++++++-- GPU/Common/GPUStateUtils.cpp | 6 +- GPU/Common/GPUStateUtils.h | 4 +- GPU/Common/PresentationCommon.cpp | 58 ++++++++++--------- GPU/Common/PresentationCommon.h | 22 +++++--- GPU/D3D11/DrawEngineD3D11.cpp | 4 +- GPU/D3D11/GPU_D3D11.cpp | 6 +- GPU/D3D11/GPU_D3D11.h | 2 +- GPU/D3D11/StateMappingD3D11.cpp | 4 +- GPU/GLES/DrawEngineGLES.cpp | 4 +- GPU/GLES/GPU_GLES.cpp | 6 +- GPU/GLES/GPU_GLES.h | 2 +- GPU/GLES/StateMappingGLES.cpp | 4 +- GPU/GPUCommon.cpp | 8 +-- GPU/GPUCommon.h | 12 ++-- GPU/GPUCommonHW.cpp | 16 +++--- GPU/GPUCommonHW.h | 8 +-- GPU/Software/SoftGpu.cpp | 27 +++++---- GPU/Software/SoftGpu.h | 10 ++-- GPU/Vulkan/DrawEngineVulkan.cpp | 4 +- GPU/Vulkan/GPU_Vulkan.cpp | 10 ++-- GPU/Vulkan/GPU_Vulkan.h | 4 +- GPU/Vulkan/StateMappingVulkan.cpp | 4 +- Qt/mainwindow.cpp | 20 ++++--- Qt/mainwindow.h | 11 +++- UI/ControlMappingScreen.cpp | 4 +- UI/DisplayLayoutScreen.cpp | 74 ++++++++++++++----------- UI/EmuScreen.cpp | 52 ++++++++++++----- UI/GameSettingsScreen.cpp | 17 +++--- UI/IAPScreen.cpp | 2 +- UI/MainScreen.cpp | 2 +- UI/MiscScreens.cpp | 4 +- UI/NativeApp.cpp | 6 +- UI/OnScreenDisplay.cpp | 6 +- UI/PauseScreen.cpp | 2 +- UI/RemoteISOScreen.cpp | 2 +- UI/SavedataScreen.cpp | 2 +- UI/SimpleDialogScreen.cpp | 4 +- UI/TabbedDialogScreen.cpp | 2 +- UI/TouchControlVisibilityScreen.cpp | 2 +- UI/UIAtlas.cpp | 1 + Windows/MainWindow.cpp | 9 ++- Windows/MainWindowMenu.cpp | 70 +++++++++++++++++------ assets/ui_images/images.svg | 2 +- headless/Headless.cpp | 4 +- libretro/libretro.cpp | 12 +++- 60 files changed, 480 insertions(+), 317 deletions(-) diff --git a/Common/Math/geom2d.h b/Common/Math/geom2d.h index f50fbfda2e..5297faece6 100644 --- a/Common/Math/geom2d.h +++ b/Common/Math/geom2d.h @@ -31,6 +31,13 @@ enum Orientation { ORIENT_VERTICAL, }; +// Possibly, we'll add a mode for the book-style dual screen phones later. +// TODO: Find a better home for this! +enum class DeviceOrientation { + Landscape = 0, + Portrait = 1, +}; + // Workaround for X header, ugh. #undef Opposite diff --git a/Common/System/Display.cpp b/Common/System/Display.cpp index 12e54711d3..9904e020ec 100644 --- a/Common/System/Display.cpp +++ b/Common/System/Display.cpp @@ -6,6 +6,10 @@ DisplayProperties g_display; +DeviceOrientation DisplayProperties::GetDeviceOrientation() const { + return (dp_yres > dp_xres * 1.1f) ? DeviceOrientation::Portrait : DeviceOrientation::Landscape; +} + template void RotateRectToDisplayImpl(DisplayRect &rect, T curRTWidth, T curRTHeight) { switch (g_display.rotation) { diff --git a/Common/System/Display.h b/Common/System/Display.h index e5b6eb7ed6..0ecef7d910 100644 --- a/Common/System/Display.h +++ b/Common/System/Display.h @@ -2,6 +2,7 @@ #include "Common/Math/lin/matrix4x4.h" #include "Common/GPU/MiscTypes.h" +#include "Common/Math/geom2d.h" // This is meant to be a framework for handling DPI scaling etc. // For now, it just consists of these ugly globals. @@ -42,7 +43,7 @@ struct DisplayProperties { DisplayProperties(); void Print(); - + DeviceOrientation GetDeviceOrientation() const; // Returns true if the dimensions changed. // The first three parameters can take -1 to signify "unchanged". bool Recalculate(int new_pixel_xres, int new_pixel_yres, float new_scale_x, float new_scale_y, float customScale); diff --git a/Common/UI/UIScreen.cpp b/Common/UI/UIScreen.cpp index c66f4476ea..c5e299708e 100644 --- a/Common/UI/UIScreen.cpp +++ b/Common/UI/UIScreen.cpp @@ -16,17 +16,18 @@ static const bool ClickDebug = false; -UIScreen::UIScreen() - : Screen() { - lastPortrait_ = UsePortraitLayout(); +UIScreen::UIScreen() : Screen() { + lastOrientation_ = GetDeviceOrientation(); } UIScreen::~UIScreen() { delete root_; } -bool UIScreen::UsePortraitLayout() const { - return g_display.dp_yres > g_display.dp_xres * 1.1f; +// This is the source of truth for orientation for configuration and rendering. +DeviceOrientation UIScreen::GetDeviceOrientation() const { + // TODO: On some platforms, we can do a more sophisticated check. + return g_display.GetDeviceOrientation(); } void UIScreen::DoRecreateViews() { @@ -140,10 +141,10 @@ bool UIScreen::UnsyncKey(const KeyInput &key) { } void UIScreen::update() { - bool portrait = UsePortraitLayout(); - if (portrait != lastPortrait_) { + DeviceOrientation orientation = GetDeviceOrientation(); + if (orientation != lastOrientation_) { RecreateViews(); - lastPortrait_ = portrait; + lastOrientation_ = orientation; } DoRecreateViews(); diff --git a/Common/UI/UIScreen.h b/Common/UI/UIScreen.h index bfe257b99b..5fc9dea39e 100644 --- a/Common/UI/UIScreen.h +++ b/Common/UI/UIScreen.h @@ -63,7 +63,7 @@ protected: virtual void CreateViews() = 0; void RecreateViews() override { recreateViews_ = true; } - bool UsePortraitLayout() const; + DeviceOrientation GetDeviceOrientation() const; UI::ViewGroup *root_ = nullptr; Vec3 translation_ = Vec3(0.0f); @@ -81,7 +81,7 @@ protected: void DoRecreateViews(); bool recreateViews_ = true; - bool lastPortrait_; + DeviceOrientation lastOrientation_ = DeviceOrientation::Landscape; private: std::mutex eventQueueLock_; diff --git a/Core/Config.cpp b/Core/Config.cpp index 0e6f7576e1..6f2f66a0e0 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -80,6 +80,10 @@ static const std::vector defaultProAdhocServerList = { "socom.cc", "psp.gameplayer.club", // TODO: Add some saved recent history too? }; +bool DisplayLayoutConfig::InternalRotationIsPortrait() const { + return (iInternalScreenRotation == ROTATION_LOCKED_VERTICAL || iInternalScreenRotation == ROTATION_LOCKED_VERTICAL180) && !g_Config.bSkipBufferEffects; +} + std::string GPUBackendToString(GPUBackend backend) { switch (backend) { case GPUBackend::OPENGL: @@ -315,8 +319,6 @@ static const ConfigSetting generalSettings[] = { ConfigSetting("ScreenRotation", SETTING(g_Config, iScreenRotation), &DefaultScreenRotation, CfgFlag::DEFAULT), #endif - ConfigSetting("InternalScreenRotation", SETTING(g_Config, iInternalScreenRotation), ROTATION_LOCKED_HORIZONTAL, CfgFlag::PER_GAME), - ConfigSetting("BackgroundAnimation", SETTING(g_Config, iBackgroundAnimation), 1, CfgFlag::DEFAULT), ConfigSetting("TransparentBackground", SETTING(g_Config, bTransparentBackground), true, CfgFlag::DEFAULT), ConfigSetting("UITint", SETTING(g_Config, fUITint), 0.0, CfgFlag::DEFAULT), @@ -634,11 +636,25 @@ static std::string DefaultInfrastructureUsername() { return std::string(); } +// These were previously part of Graphics. +// It's instantiated into g_Config.displayLayoutLandscape and g_Config.displayLayoutPortrait. +static const ConfigSetting displayLayoutSettings[] = { + ConfigSetting("BufferFiltering", SETTING(g_Config.displayLayoutLandscape, iDisplayFilter), SCALE_LINEAR, CfgFlag::PER_GAME), + ConfigSetting("DisplayStretch", SETTING(g_Config.displayLayoutLandscape, bDisplayStretch), false, CfgFlag::PER_GAME), + ConfigSetting("DisplayOffsetX", SETTING(g_Config.displayLayoutLandscape, fDisplayOffsetX), 0.5f, CfgFlag::PER_GAME), + ConfigSetting("DisplayOffsetY", SETTING(g_Config.displayLayoutLandscape, fDisplayOffsetY), 0.5f, CfgFlag::PER_GAME), + ConfigSetting("DisplayScale", SETTING(g_Config.displayLayoutLandscape, fDisplayScale), 1.0f, CfgFlag::PER_GAME), + ConfigSetting("DisplayIntegerScale", SETTING(g_Config.displayLayoutLandscape, bDisplayIntegerScale), false, CfgFlag::PER_GAME), + ConfigSetting("DisplayAspectRatio", SETTING(g_Config.displayLayoutLandscape, fDisplayAspectRatio), 1.0f, CfgFlag::PER_GAME), + ConfigSetting("IgnoreScreenInsets", SETTING(g_Config.displayLayoutLandscape, bIgnoreScreenInsets), true, CfgFlag::PER_GAME), + ConfigSetting("InternalScreenRotation", SETTING(g_Config.displayLayoutLandscape, iInternalScreenRotation), ROTATION_LOCKED_HORIZONTAL, CfgFlag::PER_GAME), + ConfigSetting("EnableCardboardVR", SETTING(g_Config.displayLayoutLandscape, bEnableCardboardVR), false, CfgFlag::PER_GAME), + ConfigSetting("CardboardScreenSize", SETTING(g_Config.displayLayoutLandscape, iCardboardScreenSize), 50, CfgFlag::PER_GAME), + ConfigSetting("CardboardXShift", SETTING(g_Config.displayLayoutLandscape, iCardboardXShift), 0, CfgFlag::PER_GAME), + ConfigSetting("CardboardYShift", SETTING(g_Config.displayLayoutLandscape, iCardboardYShift), 0, CfgFlag::PER_GAME), +}; + static const ConfigSetting graphicsSettings[] = { - ConfigSetting("EnableCardboardVR", SETTING(g_Config, bEnableCardboardVR), false, CfgFlag::PER_GAME), - ConfigSetting("CardboardScreenSize", SETTING(g_Config, iCardboardScreenSize), 50, CfgFlag::PER_GAME), - ConfigSetting("CardboardXShift", SETTING(g_Config, iCardboardXShift), 0, CfgFlag::PER_GAME), - ConfigSetting("CardboardYShift", SETTING(g_Config, iCardboardYShift), 0, CfgFlag::PER_GAME), ConfigSetting("iShowStatusFlags", SETTING(g_Config, iShowStatusFlags), 0, CfgFlag::PER_GAME), ConfigSetting("GraphicsBackend", SETTING(g_Config, iGPUBackend), &DefaultGPUBackend, &GPUBackendTranslator::To, &GPUBackendTranslator::From, CfgFlag::DEFAULT | CfgFlag::REPORT), #if PPSSPP_PLATFORM(ANDROID) && PPSSPP_ARCH(ARM64) @@ -693,18 +709,10 @@ static const ConfigSetting graphicsSettings[] = { ConfigSetting("AppSwitchMode", SETTING(g_Config, iAppSwitchMode), (int)AppSwitchMode::DOUBLE_SWIPE_INDICATOR, CfgFlag::DEFAULT), #endif - ConfigSetting("BufferFiltering", SETTING(g_Config, iDisplayFilter), SCALE_LINEAR, CfgFlag::PER_GAME), - ConfigSetting("DisplayOffsetX", SETTING(g_Config, fDisplayOffsetX), 0.5f, CfgFlag::PER_GAME), - ConfigSetting("DisplayOffsetY", SETTING(g_Config, fDisplayOffsetY), 0.5f, CfgFlag::PER_GAME), - ConfigSetting("DisplayScale", SETTING(g_Config, fDisplayScale), 1.0f, CfgFlag::PER_GAME), - ConfigSetting("DisplayIntegerScale", SETTING(g_Config, bDisplayIntegerScale), false, CfgFlag::PER_GAME), - ConfigSetting("DisplayAspectRatio", SETTING(g_Config, fDisplayAspectRatio), 1.0f, CfgFlag::PER_GAME), - ConfigSetting("DisplayStretch", SETTING(g_Config, bDisplayStretch), false, CfgFlag::PER_GAME), ConfigSetting("DisplayCropTo16x9", SETTING(g_Config, bDisplayCropTo16x9), true, CfgFlag::PER_GAME), ConfigSetting("ImmersiveMode", SETTING(g_Config, bImmersiveMode), true, CfgFlag::PER_GAME), ConfigSetting("SustainedPerformanceMode", SETTING(g_Config, bSustainedPerformanceMode), false, CfgFlag::PER_GAME), - ConfigSetting("IgnoreScreenInsets", SETTING(g_Config, bIgnoreScreenInsets), true, CfgFlag::DEFAULT), ConfigSetting("ReplaceTextures", SETTING(g_Config, bReplaceTextures), true, CfgFlag::PER_GAME | CfgFlag::REPORT), ConfigSetting("SaveNewTextures", SETTING(g_Config, bSaveNewTextures), false, CfgFlag::PER_GAME | CfgFlag::REPORT), @@ -1068,6 +1076,8 @@ static const ConfigSectionSettings sectionDescs[] = { {(char *)&g_Config, "Theme", themeSettings, ARRAY_SIZE(themeSettings)}, {(char *)&g_Config, "VR", vrSettings, ARRAY_SIZE(vrSettings)}, {(char *)&g_Config, "Achievements", achievementSettings, ARRAY_SIZE(achievementSettings)}, + {(char *)&g_Config.displayLayoutLandscape, "Graphics", displayLayoutSettings, ARRAY_SIZE(displayLayoutSettings)}, // We re-use the old settings. + {(char *)&g_Config.displayLayoutPortrait, "DisplayLayout.Portrait", displayLayoutSettings, ARRAY_SIZE(displayLayoutSettings)}, }; const size_t numSections = ARRAY_SIZE(sectionDescs); @@ -1761,10 +1771,6 @@ void Config::GetReportingInfo(UrlEncoder &data) const { } } -bool Config::IsPortrait() const { - return (iInternalScreenRotation == ROTATION_LOCKED_VERTICAL || iInternalScreenRotation == ROTATION_LOCKED_VERTICAL180) && !bSkipBufferEffects; -} - void PlayTimeTracker::Start(const std::string &gameId) { if (gameId.empty()) { return; diff --git a/Core/Config.h b/Core/Config.h index 3f7d565fcb..f0b36e5a20 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -26,6 +26,7 @@ #include "Common/CommonTypes.h" #include "Common/File/Path.h" +#include "Common/Math/geom2d.h" #include "Core/ConfigValues.h" extern const char *PPSSPP_GIT_VERSION; @@ -62,6 +63,25 @@ private: struct ConfigSetting; +struct DisplayLayoutConfig { + int iDisplayFilter; // 1 = linear, 2 = nearest + bool bDisplayStretch; // Automatically matches the aspect ratio of the window. + float fDisplayOffsetX; + float fDisplayOffsetY; + float fDisplayScale; // Relative to the most constraining axis (x or y). + bool bDisplayIntegerScale; // Snaps scaling to integer scale factors in raw pixels. + float fDisplayAspectRatio; // Stored relative to the PSP's native ratio, so 1.0 is the normal pixel aspect ratio. + int iInternalScreenRotation; // The internal screen rotation angle. Useful for vertical SHMUPs and similar. + bool bIgnoreScreenInsets; // Android: Center screen disregarding insets if this is enabled. + + bool bEnableCardboardVR; // Cardboard Master Switch + int iCardboardScreenSize; // Screen Size (in %) + int iCardboardXShift; // X-Shift of Screen (in %) + int iCardboardYShift; // Y-Shift of Screen (in %) + + bool InternalRotationIsPortrait() const; +}; + struct Config { public: Config(); @@ -145,8 +165,7 @@ public: int iDisableHLE; int iForceEnableHLE; // This is the opposite of DisableHLE but can force on HLE even when we've made it permanently off. Only used in tests, not hooked up to the ini file yet. - int iScreenRotation; // The rotation angle of the PPSSPP UI. Only supported on Android and possibly other mobile platforms. - int iInternalScreenRotation; // The internal screen rotation angle. Useful for vertical SHMUPs and similar. + int iScreenRotation; // Screen rotation lock. Only supported on Android and possibly other mobile platforms. std::string sReportHost; std::vector vPinnedPaths; @@ -193,29 +212,20 @@ public: int iTexFiltering; // 1 = auto , 2 = nearest , 3 = linear , 4 = auto max quality bool bSmart2DTexFiltering; - bool bDisplayStretch; // Automatically matches the aspect ratio of the window. - int iDisplayFilter; // 1 = linear, 2 = nearest - float fDisplayOffsetX; - float fDisplayOffsetY; - float fDisplayScale; // Relative to the most constraining axis (x or y). - bool bDisplayIntegerScale; // Snaps scaling to integer scale factors in raw pixels. + // We'll carry over the old single layout into landscape for now. + DisplayLayoutConfig displayLayoutLandscape; + DisplayLayoutConfig displayLayoutPortrait; + bool bDisplayCropTo16x9; // Crops to 16:9 if the resolution is very close. - float fDisplayAspectRatio; // Stored relative to the PSP's native ratio, so 1.0 is the normal pixel aspect ratio. bool bImmersiveMode; // Mode on Android Kitkat 4.4 and later that hides the back button etc. bool bSustainedPerformanceMode; // Android: Slows clocks down to avoid overheating/speed fluctuations. - bool bIgnoreScreenInsets; // Android: Center screen disregarding insets if this is enabled. bool bShowImDebugger; int iFrameSkip; bool bAutoFrameSkip; - bool bEnableCardboardVR; // Cardboard Master Switch - int iCardboardScreenSize; // Screen Size (in %) - int iCardboardXShift; // X-Shift of Screen (in %) - int iCardboardYShift; // Y-Shift of Screen (in %) - int iWindowX; int iWindowY; int iWindowWidth; // Windows and other windowed environments @@ -644,7 +654,6 @@ public: void GetReportingInfo(UrlEncoder &data) const; - bool IsPortrait() const; int NextValidBackend(); bool IsBackendEnabled(GPUBackend backend); @@ -661,6 +670,13 @@ public: PlayTimeTracker &TimeTracker() { return playTimeTracker_; } + const DisplayLayoutConfig &GetDisplayLayoutConfig(DeviceOrientation orientation) const { + return orientation == DeviceOrientation::Portrait ? displayLayoutPortrait : displayLayoutLandscape; + } + DisplayLayoutConfig &GetDisplayLayoutConfig(DeviceOrientation orientation) { + return orientation == DeviceOrientation::Portrait ? displayLayoutPortrait : displayLayoutLandscape; + } + protected: void LoadStandardControllerIni(); diff --git a/Core/ConfigSettings.h b/Core/ConfigSettings.h index be3a0a2f55..22c23f3739 100644 --- a/Core/ConfigSettings.h +++ b/Core/ConfigSettings.h @@ -42,18 +42,6 @@ struct ConfigSetting { ConfigTouchPos touchPos; ConfigCustomButton customButton; }; - union SettingPtr { - bool *b; - int *i; - uint32_t *u; - uint64_t *lu; - float *f; - std::string *s; - std::vector *v; - Path *p; - ConfigTouchPos *touchPos; - ConfigCustomButton *customButton; - }; typedef bool (*BoolDefaultCallback)(); typedef int (*IntDefaultCallback)(); diff --git a/Core/ControlMapper.cpp b/Core/ControlMapper.cpp index 4730dbd8d3..d1f875d63a 100644 --- a/Core/ControlMapper.cpp +++ b/Core/ControlMapper.cpp @@ -150,7 +150,7 @@ void ControlMapper::SetCallbacks( std::function onVKey, std::function onVKeyAnalog, std::function updatePSPButtons, - std::function setPSPAnalog, + std::function setPSPAnalog, std::function setRawAnalog) { onVKey_ = onVKey; onVKeyAnalog_ = onVKeyAnalog; @@ -208,7 +208,7 @@ void ControlMapper::UpdateAnalogOutput(int stick) { } converted_[stick][0] = x; converted_[stick][1] = y; - setPSPAnalog_(stick, x, y); + setPSPAnalog_(iInternalScreenRotationCached_, stick, x, y); } void ControlMapper::ForceReleaseVKey(int vkey) { @@ -357,7 +357,7 @@ bool ControlMapper::UpdatePSPState(const InputMapping &changedMapping, double no // of crazy input combos if needed. int rotations = 0; - switch (g_Config.iInternalScreenRotation) { + switch (iInternalScreenRotationCached_) { case ROTATION_LOCKED_HORIZONTAL180: rotations = 2; break; case ROTATION_LOCKED_VERTICAL: rotations = 1; break; case ROTATION_LOCKED_VERTICAL180: rotations = 3; break; @@ -650,18 +650,19 @@ void ControlMapper::Axis(const AxisInput *axes, size_t count) { KeyMap::UnlockMappings(); } -void ControlMapper::Update(double now) { +void ControlMapper::Update(const DisplayLayoutConfig &config, double now) { + iInternalScreenRotationCached_ = config.iInternalScreenRotation; if (autoRotatingAnalogCW_) { // Clamp to a square float x = std::min(1.0f, std::max(-1.0f, 1.42f * (float)cos(now * -g_Config.fAnalogAutoRotSpeed))); float y = std::min(1.0f, std::max(-1.0f, 1.42f * (float)sin(now * -g_Config.fAnalogAutoRotSpeed))); - setPSPAnalog_(0, x, y); + setPSPAnalog_(iInternalScreenRotationCached_, 0, x, y); } else if (autoRotatingAnalogCCW_) { float x = std::min(1.0f, std::max(-1.0f, 1.42f * (float)cos(now * g_Config.fAnalogAutoRotSpeed))); float y = std::min(1.0f, std::max(-1.0f, 1.42f * (float)sin(now * g_Config.fAnalogAutoRotSpeed))); - setPSPAnalog_(0, x, y); + setPSPAnalog_(iInternalScreenRotationCached_, 0, x, y); } } @@ -727,7 +728,7 @@ void ControlMapper::onVKey(VirtKey vkey, bool down) { autoRotatingAnalogCCW_ = false; } else { autoRotatingAnalogCW_ = false; - setPSPAnalog_(0, 0.0f, 0.0f); + setPSPAnalog_(iInternalScreenRotationCached_, 0, 0.0f, 0.0f); } break; case VIRTKEY_ANALOG_ROTATE_CCW: @@ -736,7 +737,7 @@ void ControlMapper::onVKey(VirtKey vkey, bool down) { autoRotatingAnalogCCW_ = true; } else { autoRotatingAnalogCCW_ = false; - setPSPAnalog_(0, 0.0f, 0.0f); + setPSPAnalog_(iInternalScreenRotationCached_, 0, 0.0f, 0.0f); } break; default: diff --git a/Core/ControlMapper.h b/Core/ControlMapper.h index cde5ea6884..36c06193fc 100644 --- a/Core/ControlMapper.h +++ b/Core/ControlMapper.h @@ -7,11 +7,12 @@ #include #include +struct DisplayLayoutConfig; // Utilities for mapping input events to PSP inputs and virtual keys. // Main use is of course from EmuScreen.cpp, but also useful from control settings etc. class ControlMapper { public: - void Update(double now); + void Update(const DisplayLayoutConfig &config, double now); // Inputs to the table-based mapping // These functions are free-threaded. @@ -24,7 +25,7 @@ public: std::function onVKey, std::function onVKeyAnalog, std::function updatePSPButtons, - std::function setPSPAnalog, + std::function setPSPAnalog, std::function setRawAnalog); // Inject raw PSP key input directly, such as from touch screen controls. @@ -85,6 +86,8 @@ private: bool swapAxes_ = false; + int iInternalScreenRotationCached_ = 0; + // Protects basically all the state. // TODO: Maybe we should piggyback on the screenmanager mutex - it's always locked // when events come in here. @@ -96,7 +99,7 @@ private: std::function onVKey_; std::function onVKeyAnalog_; std::function updatePSPButtons_; - std::function setPSPAnalog_; + std::function setPSPAnalog_; std::function setRawAnalog_; }; diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index 22417b5172..f50c1d27d5 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -564,6 +564,12 @@ static void NotifyUserIfSlow() { } } +static DisplayLayoutConfig g_displayLayoutConfigCached; + +void __DisplaySetDisplayLayoutConfig(const DisplayLayoutConfig &config) { + g_displayLayoutConfigCached = config; +} + void __DisplayFlip(int cyclesLate) { _dbg_assert_(gpu); @@ -644,7 +650,7 @@ void __DisplayFlip(int cyclesLate) { } } if (nextFrame) { - gpu->CopyDisplayToOutput(fbReallyDirty); + gpu->CopyDisplayToOutput(g_displayLayoutConfigCached, fbReallyDirty); if (fbReallyDirty) { DisplayFireActualFlip(); } diff --git a/Core/HLE/sceDisplay.h b/Core/HLE/sceDisplay.h index bb134af815..2f8d05aa28 100644 --- a/Core/HLE/sceDisplay.h +++ b/Core/HLE/sceDisplay.h @@ -34,3 +34,7 @@ void __DisplaySetWasPaused(); void Register_sceDisplay_driver(); void __DisplayWaitForVblanks(const char* reason, int vblanks, bool callbacks = false); + +// Kinda hacky, but what can you do... we can't pass it through the jit etc. +struct DisplayLayoutConfig; +void __DisplaySetDisplayLayoutConfig(const DisplayLayoutConfig &config); diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index a812e836ea..e9805cd5c5 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -2061,23 +2061,25 @@ static u32 sceIoDevctl(const char *name, int cmd, u32 argAddr, int argLen, u32 o PSP_CoreParameter().fastForward = false; return hleLogDebug(Log::sceIo, 0); case EMULATOR_DEVCTL__GET_ASPECT_RATIO: + // NOTE: This currently only works correctly in landscape mode! if (Memory::IsValidAddress(outPtr)) { // TODO: Share code with CalculateDisplayOutputRect to take a few more things into account. // I have a planned further refactoring. float ar; - if (g_Config.bDisplayStretch) { + if (g_Config.displayLayoutLandscape.bDisplayStretch) { ar = (float)g_display.dp_xres / (float)g_display.dp_yres; } else { - ar = g_Config.fDisplayAspectRatio * (480.0f / 272.0f); + ar = g_Config.displayLayoutLandscape.fDisplayAspectRatio * (480.0f / 272.0f); } Memory::Write_Float(ar, outPtr); } return hleLogDebug(Log::sceIo, 0); case EMULATOR_DEVCTL__GET_SCALE: + // NOTE: This currently only works correctly in landscape mode! if (Memory::IsValidAddress(outPtr)) { // TODO: Maybe do something more sophisticated taking the longest side and screen rotation // into account, etc. - float scale = (float)g_display.dp_xres * g_Config.fDisplayScale / 480.0f; + float scale = (float)g_display.dp_xres * g_Config.displayLayoutLandscape.fDisplayScale / 480.0f; Memory::Write_Float(scale, outPtr); } return hleLogDebug(Log::sceIo, 0); diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 21fbe1cee0..e8ece5eb52 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -76,7 +76,7 @@ FramebufferManagerCommon::~FramebufferManagerCommon() { void FramebufferManagerCommon::Init(int msaaLevel) { // We may need to override the render size if the shader is upscaling or SSAA. NotifyDisplayResized(); - NotifyRenderResized(msaaLevel); + NotifyRenderResized(displayLayoutConfigCopy_, msaaLevel); } // Returns true if we need to stop the render thread @@ -110,17 +110,20 @@ bool FramebufferManagerCommon::UpdateRenderSize(int msaaLevel) { return newRender || newSettings; } -void FramebufferManagerCommon::CheckPostShaders() { +void FramebufferManagerCommon::CheckPostShaders(const DisplayLayoutConfig &config) { if (updatePostShaders_) { - presentation_->UpdatePostShader(); + presentation_->UpdatePostShader(config); updatePostShaders_ = false; } } -void FramebufferManagerCommon::BeginFrame() { +void FramebufferManagerCommon::BeginFrame(const DisplayLayoutConfig &config) { DecimateFBOs(); - presentation_->BeginFrame(); + presentation_->BeginFrame(config); currentRenderVfb_ = nullptr; + + // Hack. + displayLayoutConfigCopy_ = config; } bool FramebufferManagerCommon::PresentedThisFrame() const { @@ -647,7 +650,7 @@ void FramebufferManagerCommon::SetDepthFrameBuffer(bool isClearingDepth) { // Sanity check the depth buffer pointer. if (Memory::IsValidRange(currentRenderVfb_->z_address, currentRenderVfb_->width * 2)) { const u16 *src = (const u16 *)Memory::GetPointerUnchecked(currentRenderVfb_->z_address); - DrawPixels(currentRenderVfb_, 0, 0, (const u8 *)src, GE_FORMAT_DEPTH16, currentRenderVfb_->z_stride, currentRenderVfb_->width, currentRenderVfb_->height, RASTER_DEPTH, "Depth Upload"); + DrawPixels(nullptr, currentRenderVfb_, 0, 0, (const u8 *)src, GE_FORMAT_DEPTH16, currentRenderVfb_->z_stride, currentRenderVfb_->width, currentRenderVfb_->height, RASTER_DEPTH, "Depth Upload"); } } } @@ -1172,7 +1175,7 @@ void FramebufferManagerCommon::UpdateFromMemory(u32 addr, int size) { // TODO: This doesn't seem quite right anymore. fmt = displayFormat_; } - DrawPixels(vfb, 0, 0, Memory::GetPointerUnchecked(addr), fmt, vfb->fb_stride, vfb->width, vfb->height, RASTER_COLOR, "UpdateFromMemory_DrawPixels"); + DrawPixels(nullptr, vfb, 0, 0, Memory::GetPointerUnchecked(addr), fmt, vfb->fb_stride, vfb->width, vfb->height, RASTER_COLOR, "UpdateFromMemory_DrawPixels"); SetColorUpdated(vfb, gstate_c.skipDrawReason); } else { INFO_LOG(Log::FrameBuf, "Invalidating FBO for %08x (%dx%d %s)", vfb->fb_address, vfb->width, vfb->height, GeBufferFormatToString(vfb->fb_format)); @@ -1188,7 +1191,7 @@ void FramebufferManagerCommon::UpdateFromMemory(u32 addr, int size) { gstate_c.Dirty(DIRTY_FRAGMENTSHADER_STATE); } -void FramebufferManagerCommon::DrawPixels(VirtualFramebuffer *vfb, int dstX, int dstY, const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height, RasterChannel channel, const char *tag) { +void FramebufferManagerCommon::DrawPixels(const DisplayLayoutConfig *config, VirtualFramebuffer *vfb, int dstX, int dstY, const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height, RasterChannel channel, const char *tag) { textureCache_->ForgetLastTexture(); shaderManager_->DirtyLastShader(); float u0 = 0.0f, u1 = 1.0f; @@ -1206,15 +1209,16 @@ void FramebufferManagerCommon::DrawPixels(VirtualFramebuffer *vfb, int dstX, int draw_->SetScissorRect(0, 0, vfb->renderWidth, vfb->renderHeight); } else { _dbg_assert_(channel == RASTER_COLOR); + _dbg_assert_(config); // 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.iDisplayFilter == SCALE_LINEAR ? DRAWTEX_LINEAR : DRAWTEX_NEAREST; + flags = config->iDisplayFilter == SCALE_LINEAR ? DRAWTEX_LINEAR : DRAWTEX_NEAREST; flags = flags | DRAWTEX_TO_BACKBUFFER; - FRect frame = GetScreenFrame(pixelWidth_, pixelHeight_); + FRect frame = GetScreenFrame(config ? config->bIgnoreScreenInsets : false, pixelWidth_, pixelHeight_); FRect rc; - CalculateDisplayOutputRect(&rc, 480.0f, 272.0f, frame, ROTATION_LOCKED_HORIZONTAL); + CalculateDisplayOutputRect(*config, &rc, 480.0f, 272.0f, frame, ROTATION_LOCKED_HORIZONTAL); SetViewport2D(rc.x, rc.y, rc.w, rc.h); draw_->SetScissorRect(0, 0, pixelWidth_, pixelHeight_); } @@ -1512,7 +1516,7 @@ Draw::Texture *FramebufferManagerCommon::MakePixelTexture(const u8 *srcPixels, G return tex; } -bool FramebufferManagerCommon::DrawFramebufferToOutput(const u8 *srcPixels, int srcStride, GEBufferFormat srcPixelFormat) { +bool FramebufferManagerCommon::DrawFramebufferToOutput(const DisplayLayoutConfig &config, const u8 *srcPixels, int srcStride, GEBufferFormat srcPixelFormat) { textureCache_->ForgetLastTexture(); shaderManager_->DirtyLastShader(); @@ -1522,8 +1526,8 @@ bool FramebufferManagerCommon::DrawFramebufferToOutput(const u8 *srcPixels, int if (!pixelsTex) return false; - int uvRotation = useBufferedRendering_ ? g_Config.iInternalScreenRotation : ROTATION_LOCKED_HORIZONTAL; - OutputFlags flags = g_Config.iDisplayFilter == SCALE_LINEAR ? OutputFlags::LINEAR : OutputFlags::NEAREST; + int uvRotation = useBufferedRendering_ ? config.iInternalScreenRotation : ROTATION_LOCKED_HORIZONTAL; + OutputFlags flags = config.iDisplayFilter == SCALE_LINEAR ? OutputFlags::LINEAR : OutputFlags::NEAREST; if (needBackBufferYSwap_) { flags |= OutputFlags::BACKBUFFER_FLIPPED; } @@ -1534,7 +1538,7 @@ bool FramebufferManagerCommon::DrawFramebufferToOutput(const u8 *srcPixels, int presentation_->UpdateUniforms(textureCache_->VideoIsPlaying()); presentation_->SourceTexture(pixelsTex, 512, 272); - presentation_->CopyToOutput(flags, uvRotation, u0, v0, u1, v1); + presentation_->CopyToOutput(config, flags, uvRotation, u0, v0, u1, v1); // PresentationCommon sets all kinds of state, we can't rely on anything. gstate_c.Dirty(DIRTY_ALL); @@ -1550,7 +1554,7 @@ void FramebufferManagerCommon::SetViewport2D(int x, int y, int w, int h) { draw_->SetViewport(viewport); } -void FramebufferManagerCommon::CopyDisplayToOutput(bool reallyDirty) { +void FramebufferManagerCommon::CopyDisplayToOutput(const DisplayLayoutConfig &config, bool reallyDirty) { DownloadFramebufferOnSwitch(currentRenderVfb_); shaderManager_->DirtyLastShader(); @@ -1625,7 +1629,7 @@ void FramebufferManagerCommon::CopyDisplayToOutput(bool reallyDirty) { if (Memory::IsValidAddress(fbaddr)) { // The game is displaying something directly from RAM. In GTA, it's decoded video. // If successful, this effectively calls presentation_->NotifyPresent(); - if (!DrawFramebufferToOutput(Memory::GetPointerUnchecked(fbaddr), displayStride_, displayFormat_)) { + if (!DrawFramebufferToOutput(config, Memory::GetPointerUnchecked(fbaddr), displayStride_, displayFormat_)) { if (useBufferedRendering_) { // Bind and clear the backbuffer. This should be the first time during the frame that it's bound. draw_->BindFramebufferAsRenderTarget(nullptr, { Draw::RPAction::CLEAR, Draw::RPAction::CLEAR, Draw::RPAction::CLEAR }, "CopyDisplayToOutput_DrawError"); @@ -1689,8 +1693,8 @@ void FramebufferManagerCommon::CopyDisplayToOutput(bool reallyDirty) { textureCache_->ForgetLastTexture(); - int uvRotation = useBufferedRendering_ ? g_Config.iInternalScreenRotation : ROTATION_LOCKED_HORIZONTAL; - OutputFlags flags = g_Config.iDisplayFilter == SCALE_LINEAR ? OutputFlags::LINEAR : OutputFlags::NEAREST; + int uvRotation = useBufferedRendering_ ? config.iInternalScreenRotation : ROTATION_LOCKED_HORIZONTAL; + OutputFlags flags = config.iDisplayFilter == SCALE_LINEAR ? OutputFlags::LINEAR : OutputFlags::NEAREST; if (needBackBufferYSwap_) { flags |= OutputFlags::BACKBUFFER_FLIPPED; } @@ -1703,7 +1707,7 @@ void FramebufferManagerCommon::CopyDisplayToOutput(bool reallyDirty) { int actualHeight = (vfb->bufferHeight * vfb->renderHeight) / vfb->height; presentation_->UpdateUniforms(textureCache_->VideoIsPlaying()); presentation_->SourceFramebuffer(vfb->fbo, actualWidth, actualHeight); - presentation_->CopyToOutput(flags, uvRotation, u0, v0, u1, v1); + presentation_->CopyToOutput(config, flags, uvRotation, u0, v0, u1, v1); } else if (useBufferedRendering_) { WARN_LOG(Log::FrameBuf, "Using buffered rendering, and current VFB lacks an FBO: %08x", vfb->fb_address); } else { @@ -2179,7 +2183,7 @@ bool FramebufferManagerCommon::NotifyFramebufferCopy(u32 src, u32 dst, int size, const u8 *srcBase = Memory::GetPointerUnchecked(src); GEBufferFormat srcFormat = channel == RASTER_DEPTH ? GE_FORMAT_DEPTH16 : dstBuffer->fb_format; int srcStride = channel == RASTER_DEPTH ? dstBuffer->z_stride : dstBuffer->fb_stride; - DrawPixels(dstBuffer, 0, dstY, srcBase, srcFormat, srcStride, dstBuffer->width, dstH, channel, "MemcpyFboUpload_DrawPixels"); + DrawPixels(nullptr, dstBuffer, 0, dstY, srcBase, srcFormat, srcStride, dstBuffer->width, dstH, channel, "MemcpyFboUpload_DrawPixels"); SetColorUpdated(dstBuffer, skipDrawReason); RebindFramebuffer("RebindFramebuffer - Memcpy fbo upload"); // This is a memcpy, let's still copy just in case. @@ -2711,7 +2715,7 @@ bool FramebufferManagerCommon::NotifyBlockTransferBefore(u32 dstBasePtr, int dst WARN_LOG_ONCE(btud, Log::G3D, "Block transfer upload %08x -> %08x (%dx%d %d,%d bpp=%d %s)", srcBasePtr, dstBasePtr, width, height, dstX, dstY, bpp, RasterChannelToString(dstRect.channel)); FlushBeforeCopy(); const u8 *srcBase = Memory::GetPointerUnchecked(srcBasePtr) + (srcX + srcY * srcStride) * bpp; - DrawPixels(dstRect.vfb, dstX, dstY, srcBase, dstRect.vfb->Format(dstRect.channel), srcStride * bpp / 2, (int)(dstRect.w_bytes / 2), dstRect.h, dstRect.channel, "BlockTransferCopy_DrawPixelsDepth"); + DrawPixels(nullptr, dstRect.vfb, dstX, dstY, srcBase, dstRect.vfb->Format(dstRect.channel), srcStride * bpp / 2, (int)(dstRect.w_bytes / 2), dstRect.h, dstRect.channel, "BlockTransferCopy_DrawPixelsDepth"); RebindFramebuffer("RebindFramebuffer - UploadDepth"); return true; } @@ -2765,7 +2769,8 @@ void FramebufferManagerCommon::NotifyBlockTransferAfter(u32 dstBasePtr, int dstS bool isDisplayBuffer = CurrentDisplayFramebufAddr() == dstBasePtr; if (isPrevDisplayBuffer || isDisplayBuffer) { FlushBeforeCopy(); - DrawFramebufferToOutput(Memory::GetPointerUnchecked(dstBasePtr), dstStride, displayFormat_); + // HACK + DrawFramebufferToOutput(displayLayoutConfigCopy_, Memory::GetPointerUnchecked(dstBasePtr), dstStride, displayFormat_); return; } } @@ -2805,7 +2810,7 @@ void FramebufferManagerCommon::NotifyBlockTransferAfter(u32 dstBasePtr, int dstS // Resizing may change the viewport/etc. gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE); } - DrawPixels(dstRect.vfb, static_cast(dstX * dstXFactor), dstY, srcBase, dstRect.vfb->fb_format, static_cast(srcStride * dstXFactor), static_cast(dstRect.w_bytes / bpp * dstXFactor), dstRect.h, RASTER_COLOR, "BlockTransferCopy_DrawPixels"); + DrawPixels(nullptr, dstRect.vfb, static_cast(dstX * dstXFactor), dstY, srcBase, dstRect.vfb->fb_format, static_cast(srcStride * dstXFactor), static_cast(dstRect.w_bytes / bpp * dstXFactor), dstRect.h, RASTER_COLOR, "BlockTransferCopy_DrawPixels"); SetColorUpdated(dstRect.vfb, skipDrawReason); RebindFramebuffer("RebindFramebuffer - NotifyBlockTransferAfter"); } @@ -2832,11 +2837,11 @@ void FramebufferManagerCommon::NotifyDisplayResized() { updatePostShaders_ = true; } -void FramebufferManagerCommon::NotifyRenderResized(int msaaLevel) { +void FramebufferManagerCommon::NotifyRenderResized(const DisplayLayoutConfig &config, int msaaLevel) { gstate_c.skipDrawReason &= ~SKIPDRAW_NON_DISPLAYED_FB; int w, h, scaleFactor; - presentation_->CalculateRenderResolution(&w, &h, &scaleFactor, &postShaderIsUpscalingFilter_, &postShaderIsSupersampling_); + presentation_->CalculateRenderResolution(config, &w, &h, &scaleFactor, &postShaderIsUpscalingFilter_, &postShaderIsSupersampling_); PSP_CoreParameter().renderWidth = w; PSP_CoreParameter().renderHeight = h; PSP_CoreParameter().renderScaleFactor = scaleFactor; diff --git a/GPU/Common/FramebufferManagerCommon.h b/GPU/Common/FramebufferManagerCommon.h index 1424191292..581902596b 100644 --- a/GPU/Common/FramebufferManagerCommon.h +++ b/GPU/Common/FramebufferManagerCommon.h @@ -30,6 +30,7 @@ #include "Common/CommonTypes.h" #include "Common/Log.h" #include "Common/GPU/thin3d.h" +#include "Core/Config.h" #include "Core/ConfigValues.h" #include "GPU/GPU.h" #include "GPU/ge_constants.h" @@ -284,6 +285,7 @@ class DrawEngineCommon; class PresentationCommon; class ShaderManagerCommon; class TextureCacheCommon; +struct DisplayLayoutConfig; class FramebufferManagerCommon { public: @@ -301,7 +303,7 @@ public: } void Init(int msaaLevel); - virtual void BeginFrame(); + virtual void BeginFrame(const DisplayLayoutConfig &config); void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format); void DestroyFramebuf(VirtualFramebuffer *v); @@ -332,7 +334,7 @@ public: void RebindFramebuffer(const char *tag); std::vector GetFramebufferList() const; - void CopyDisplayToOutput(bool reallyDirty); + void CopyDisplayToOutput(const DisplayLayoutConfig &config, bool reallyDirty); bool NotifyFramebufferCopy(u32 src, u32 dest, int size, GPUCopyFlag flags, u32 skipDrawReason); void PerformWriteFormattedFromMemory(u32 addr, int size, int width, GEBufferFormat fmt); @@ -358,9 +360,10 @@ public: void ReadFramebufferToMemory(VirtualFramebuffer *vfb, int x, int y, int w, int h, RasterChannel channel, Draw::ReadbackMode mode); void DownloadFramebufferForClut(u32 fb_address, u32 loadBytes); - bool DrawFramebufferToOutput(const u8 *srcPixels, int srcStride, GEBufferFormat srcPixelFormat); + bool DrawFramebufferToOutput(const DisplayLayoutConfig &config, const u8 *srcPixels, int srcStride, GEBufferFormat srcPixelFormat); - void DrawPixels(VirtualFramebuffer *vfb, int dstX, int dstY, const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height, RasterChannel channel, const char *tag); + // TODO: Should split into one that uses config, and one that doesn't. + void DrawPixels(const DisplayLayoutConfig *config, VirtualFramebuffer *vfb, int dstX, int dstY, const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height, RasterChannel channel, const char *tag); size_t NumVFBs() const { return vfbs_.size(); } @@ -437,11 +440,11 @@ public: } void SetSafeSize(u16 w, u16 h); - void NotifyRenderResized(int msaaLevel); + void NotifyRenderResized(const DisplayLayoutConfig &config, int msaaLevel); virtual void NotifyDisplayResized(); void NotifyConfigChanged(); - void CheckPostShaders(); + void CheckPostShaders(const DisplayLayoutConfig &config); virtual void DestroyAllFBOs(); @@ -498,6 +501,11 @@ public: return vfbs_; } + // Hack, only needed for non-buffered rendering. + const DisplayLayoutConfig &GetDisplayLayoutConfigCopy() const { + return displayLayoutConfigCopy_; + } + protected: virtual void ReadbackFramebuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h, RasterChannel channel, Draw::ReadbackMode mode); // Used for when a shader is required, such as GLES. @@ -659,6 +667,8 @@ protected: // Depth readback helper state u8 *convBuf_ = nullptr; u32 convBufSize_ = 0; + + DisplayLayoutConfig displayLayoutConfigCopy_{}; }; // Should probably live elsewhere. diff --git a/GPU/Common/GPUStateUtils.cpp b/GPU/Common/GPUStateUtils.cpp index 382c4828ac..02c39d27c5 100644 --- a/GPU/Common/GPUStateUtils.cpp +++ b/GPU/Common/GPUStateUtils.cpp @@ -586,7 +586,7 @@ DepthScaleFactors GetDepthScaleFactors(u32 useFlags) { } } -void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, float renderHeight, int bufferWidth, int bufferHeight, ViewportAndScissor &out) { +void ConvertViewportAndScissor(const DisplayLayoutConfig &config, bool useBufferedRendering, float renderWidth, float renderHeight, int bufferWidth, int bufferHeight, ViewportAndScissor &out) { out.throughMode = gstate.isModeThrough(); float renderWidthFactor, renderHeightFactor; @@ -600,9 +600,9 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo } else { float pixelW = PSP_CoreParameter().pixelWidth; float pixelH = PSP_CoreParameter().pixelHeight; - FRect frame = GetScreenFrame(pixelW, pixelH); + FRect frame = GetScreenFrame(config.bIgnoreScreenInsets, pixelW, pixelH); FRect rc; - CalculateDisplayOutputRect(&rc, 480, 272, frame, ROTATION_LOCKED_HORIZONTAL); + CalculateDisplayOutputRect(config, &rc, 480, 272, frame, ROTATION_LOCKED_HORIZONTAL); displayOffsetX = rc.x; displayOffsetY = rc.y; renderWidth = rc.w; diff --git a/GPU/Common/GPUStateUtils.h b/GPU/Common/GPUStateUtils.h index 802d17d75c..2ace4b196e 100644 --- a/GPU/Common/GPUStateUtils.h +++ b/GPU/Common/GPUStateUtils.h @@ -87,7 +87,9 @@ struct ViewportAndScissor { bool throughMode; }; -void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, float renderHeight, int bufferWidth, int bufferHeight, ViewportAndScissor &out); +// config is only used for non-buffered rendering. +struct DisplayLayoutConfig; +void ConvertViewportAndScissor(const DisplayLayoutConfig &config, bool useBufferedRendering, float renderWidth, float renderHeight, int bufferWidth, int bufferHeight, ViewportAndScissor &out); void UpdateCachedViewportState(const ViewportAndScissor &vpAndScissor); // NOTE: See the .cpp file for detailed comment about how the use flags are interpreted. diff --git a/GPU/Common/PresentationCommon.cpp b/GPU/Common/PresentationCommon.cpp index a5d72daff9..d01df25f5f 100644 --- a/GPU/Common/PresentationCommon.cpp +++ b/GPU/Common/PresentationCommon.cpp @@ -54,7 +54,7 @@ void SetOverrideScreenFrame(const Bounds *bounds) { } } -FRect GetScreenFrame(float pixelWidth, float pixelHeight) { +FRect GetScreenFrame(bool ignoreInsets, float pixelWidth, float pixelHeight) { FRect rc = FRect{ 0.0f, 0.0f, @@ -62,7 +62,7 @@ FRect GetScreenFrame(float pixelWidth, float pixelHeight) { pixelHeight, }; - bool applyInset = !g_Config.bIgnoreScreenInsets; + const bool applyInset = !ignoreInsets; if (applyInset) { // Remove the DPI scale to get back to pixels. @@ -89,19 +89,19 @@ FRect GetScreenFrame(float pixelWidth, float pixelHeight) { return rc; } -void CalculateDisplayOutputRect(FRect *rc, float origW, float origH, const FRect &frame, int rotation) { +void CalculateDisplayOutputRect(const DisplayLayoutConfig &config, 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; - bool stretch = g_Config.bDisplayStretch && !g_Config.bDisplayIntegerScale; + bool stretch = config.bDisplayStretch && !config.bDisplayIntegerScale; - float offsetX = g_Config.fDisplayOffsetX; - float offsetY = g_Config.fDisplayOffsetY; + float offsetX = config.fDisplayOffsetX; + float offsetY = config.fDisplayOffsetY; - float scale = g_Config.fDisplayScale; - float aspectRatioAdjust = g_Config.fDisplayAspectRatio; + float scale = config.fDisplayScale; + float aspectRatioAdjust = config.fDisplayAspectRatio; float origRatio = !rotated ? origW / origH : origH / origW; float frameRatio = frame.w / frame.h; @@ -141,7 +141,7 @@ void CalculateDisplayOutputRect(FRect *rc, float origW, float origH, const FRect } } - if (g_Config.bDisplayIntegerScale) { + if (config.bDisplayIntegerScale) { float wDim = 480.0f; if (rotated) { wDim = 272.0f; @@ -151,7 +151,7 @@ void CalculateDisplayOutputRect(FRect *rc, float origW, float origH, const FRect if (zoom == 0) { // Auto (1:1) mode, not super meaningful with integer scaling, but let's do something that makes // some sense. use the longest dimension, just to have something. round down. - if (!g_Config.IsPortrait()) { + if (!config.InternalRotationIsPortrait()) { zoom = (PSP_CoreParameter().pixelWidth) / 480; } else { zoom = (PSP_CoreParameter().pixelHeight) / 480; @@ -187,22 +187,22 @@ PresentationCommon::~PresentationCommon() { DestroyDeviceObjects(); } -void PresentationCommon::GetCardboardSettings(CardboardSettings *cardboardSettings) const { - if (!g_Config.bEnableCardboardVR) { +void PresentationCommon::GetCardboardSettings(const DisplayLayoutConfig &config, CardboardSettings *cardboardSettings) const { + if (!config.bEnableCardboardVR) { cardboardSettings->enabled = false; return; } // Calculate Cardboard Settings - float cardboardScreenScale = g_Config.iCardboardScreenSize / 100.0f; + float cardboardScreenScale = config.iCardboardScreenSize / 100.0f; float cardboardScreenWidth = pixelWidth_ / 2.0f * cardboardScreenScale; float cardboardScreenHeight = pixelHeight_ * cardboardScreenScale; float cardboardMaxXShift = (pixelWidth_ / 2.0f - cardboardScreenWidth) / 2.0f; - float cardboardUserXShift = g_Config.iCardboardXShift / 100.0f * cardboardMaxXShift; + float cardboardUserXShift = config.iCardboardXShift / 100.0f * cardboardMaxXShift; float cardboardLeftEyeX = cardboardMaxXShift + cardboardUserXShift; float cardboardRightEyeX = pixelWidth_ / 2.0f + cardboardMaxXShift - cardboardUserXShift; float cardboardMaxYShift = pixelHeight_ / 2.0f - cardboardScreenHeight / 2.0f; - float cardboardUserYShift = g_Config.iCardboardYShift / 100.0f * cardboardMaxYShift; + float cardboardUserYShift = config.iCardboardYShift / 100.0f * cardboardMaxYShift; float cardboardScreenY = cardboardMaxYShift + cardboardUserYShift; cardboardSettings->enabled = true; @@ -266,7 +266,7 @@ static std::string ReadShaderSrc(const Path &filename) { // Note: called on resize and settings changes. // Also takes care of making sure the appropriate stereo shader is compiled. -bool PresentationCommon::UpdatePostShader() { +bool PresentationCommon::UpdatePostShader(const DisplayLayoutConfig &config) { DestroyStereoShader(); if (gstate_c.Use(GPU_USE_SIMPLE_STEREO_PERSPECTIVE)) { @@ -298,7 +298,7 @@ bool PresentationCommon::UpdatePostShader() { for (size_t i = 0; i < shaderInfo.size(); ++i) { const ShaderInfo *next = i + 1 < shaderInfo.size() ? shaderInfo[i + 1] : nullptr; Draw::Pipeline *postPipeline = nullptr; - if (!BuildPostShader(shaderInfo[i], next, &postPipeline)) { + if (!BuildPostShader(config, shaderInfo[i], next, &postPipeline)) { DestroyPostShader(); return false; } @@ -383,7 +383,7 @@ bool PresentationCommon::CompilePostShader(const ShaderInfo *shaderInfo, Draw::P return true; } -bool PresentationCommon::BuildPostShader(const ShaderInfo * shaderInfo, const ShaderInfo * next, Draw::Pipeline **outPipeline) { +bool PresentationCommon::BuildPostShader(const DisplayLayoutConfig &config, const ShaderInfo *shaderInfo, const ShaderInfo * next, Draw::Pipeline **outPipeline) { if (!CompilePostShader(shaderInfo, outPipeline)) { return false; } @@ -398,7 +398,7 @@ bool PresentationCommon::BuildPostShader(const ShaderInfo * shaderInfo, const Sh if (next && next->isUpscalingFilter) { // Force 1x for this shader, so the next can upscale. - const bool isPortrait = g_Config.IsPortrait(); + const bool isPortrait = config.InternalRotationIsPortrait(); nextWidth = isPortrait ? 272 : 480; nextHeight = isPortrait ? 480 : 272; } else if (next && next->SSAAFilterLevel >= 2) { @@ -408,8 +408,8 @@ bool PresentationCommon::BuildPostShader(const ShaderInfo * shaderInfo, const Sh } else if (shaderInfo->outputResolution) { // If the current shader uses output res (not next), we will use output res for it. FRect rc; - FRect frame = GetScreenFrame((float)pixelWidth_, (float)pixelHeight_); - CalculateDisplayOutputRect(&rc, 480.0f, 272.0f, frame, g_Config.iInternalScreenRotation); + FRect frame = GetScreenFrame(config.bIgnoreScreenInsets, (float)pixelWidth_, (float)pixelHeight_); + CalculateDisplayOutputRect(config, &rc, 480.0f, 272.0f, frame, config.iInternalScreenRotation); nextWidth = (int)rc.w; nextHeight = (int)rc.h; } @@ -541,8 +541,6 @@ void PresentationCommon::CreateDeviceObjects() { texColor_ = CreatePipeline({ draw_->GetVshaderPreset(VS_TEXTURE_COLOR_2D), draw_->GetFshaderPreset(FS_TEXTURE_COLOR_2D) }, false, &vsTexColBufDesc); texColorRBSwizzle_ = CreatePipeline({ draw_->GetVshaderPreset(VS_TEXTURE_COLOR_2D), draw_->GetFshaderPreset(FS_TEXTURE_COLOR_2D_RB_SWIZZLE) }, false, &vsTexColBufDesc); - if (restorePostShader_) - UpdatePostShader(); restorePostShader_ = false; } @@ -655,7 +653,7 @@ void PresentationCommon::UpdateUniforms(bool hasVideo) { hasVideo_ = hasVideo; } -void PresentationCommon::CopyToOutput(OutputFlags flags, int uvRotation, float u0, float v0, float u1, float v1) { +void PresentationCommon::CopyToOutput(const DisplayLayoutConfig &config, OutputFlags flags, int uvRotation, float u0, float v0, float u1, float v1) { draw_->Invalidate(InvalidationFlags::CACHED_RENDER_STATE); // TODO: If shader objects have been created by now, we might have received errors. @@ -675,15 +673,15 @@ void PresentationCommon::CopyToOutput(OutputFlags flags, int uvRotation, float u int pixelHeight = pixelHeight_; // These are the output coordinates. - FRect frame = GetScreenFrame((float)pixelWidth, (float)pixelHeight); + FRect frame = GetScreenFrame(config.bIgnoreScreenInsets, (float)pixelWidth, (float)pixelHeight); // Note: In cardboard mode, we halve the width here to compensate // for splitting the window in half, while still reusing normal centering. - if (g_Config.bEnableCardboardVR) { + if (config.bEnableCardboardVR) { frame.w /= 2.0; pixelWidth /= 2; } FRect rc; - CalculateDisplayOutputRect(&rc, 480.0f, 272.0f, frame, uvRotation); + CalculateDisplayOutputRect(config, &rc, 480.0f, 272.0f, frame, uvRotation); // To make buffer updates easier, we use one array of verts. int postVertsOffset = (int)sizeof(Vertex) * 4; @@ -927,7 +925,7 @@ void PresentationCommon::CopyToOutput(OutputFlags flags, int uvRotation, float u }; CardboardSettings cardboardSettings; - GetCardboardSettings(&cardboardSettings); + GetCardboardSettings(config, &cardboardSettings); if (cardboardSettings.enabled) { // TODO: This could actually support stereo now, with an appropriate shader. @@ -953,7 +951,7 @@ void PresentationCommon::CopyToOutput(OutputFlags flags, int uvRotation, float u presentedThisFrame_ = true; } -void PresentationCommon::CalculateRenderResolution(int *width, int *height, int *scaleFactor, bool *upscaling, bool *ssaa) const { +void PresentationCommon::CalculateRenderResolution(const DisplayLayoutConfig &config, int *width, int *height, int *scaleFactor, bool *upscaling, bool *ssaa) const { // Check if postprocessing shader is doing upscaling as it requires native resolution std::vector shaderInfo; if (!g_Config.vPostShaderNames.empty()) { @@ -970,7 +968,7 @@ void PresentationCommon::CalculateRenderResolution(int *width, int *height, int int zoom = g_Config.iInternalResolution; if (zoom == 0 || firstSSAAFilterLevel >= 2) { // auto mode, use the longest dimension - if (!g_Config.IsPortrait()) { + if (!config.InternalRotationIsPortrait()) { zoom = (PSP_CoreParameter().pixelWidth + 479) / 480; } else { zoom = (PSP_CoreParameter().pixelHeight + 479) / 480; diff --git a/GPU/Common/PresentationCommon.h b/GPU/Common/PresentationCommon.h index 595b2f4fa6..f4aab245d0 100644 --- a/GPU/Common/PresentationCommon.h +++ b/GPU/Common/PresentationCommon.h @@ -48,10 +48,12 @@ struct FRect { }; struct Bounds; // from geom2d +struct DisplayLayoutConfig; -FRect GetScreenFrame(float pixelWidth, float pixelHeight); +FRect GetScreenFrame(bool ignoreInsets, float pixelWidth, float pixelHeight); void SetOverrideScreenFrame(const Bounds *bounds); -void CalculateDisplayOutputRect(FRect *rc, float origW, float origH, const FRect &frame, int rotation); +struct DisplayLayoutConfig; +void CalculateDisplayOutputRect(const DisplayLayoutConfig &config, FRect *rc, float origW, float origH, const FRect &frame, int rotation); namespace Draw { class Buffer; @@ -99,9 +101,13 @@ public: return usePostShader_; } - bool UpdatePostShader(); + bool UpdatePostShader(const DisplayLayoutConfig &config); - void BeginFrame() { + void BeginFrame(const DisplayLayoutConfig &config) { + if (restorePostShader_) { + UpdatePostShader(config); + restorePostShader_ = false; + } presentedThisFrame_ = false; } bool PresentedThisFrame() const { @@ -119,9 +125,9 @@ public: void UpdateUniforms(bool hasVideo); void SourceTexture(Draw::Texture *texture, int bufferWidth, int bufferHeight); void SourceFramebuffer(Draw::Framebuffer *fb, int bufferWidth, int bufferHeight); - void CopyToOutput(OutputFlags flags, int uvRotation, float u0, float v0, float u1, float v1); + void CopyToOutput(const DisplayLayoutConfig &config, OutputFlags flags, int uvRotation, float u0, float v0, float u1, float v1); - void CalculateRenderResolution(int *width, int *height, int *scaleFactor, bool *upscaling, bool *ssaa) const; + void CalculateRenderResolution(const DisplayLayoutConfig &config, int *width, int *height, int *scaleFactor, bool *upscaling, bool *ssaa) const; protected: void CreateDeviceObjects(); @@ -135,12 +141,12 @@ protected: Draw::ShaderModule *CompileShaderModule(ShaderStage stage, ShaderLanguage lang, const std::string &src, std::string *errorString) const; Draw::Pipeline *CreatePipeline(std::vector shaders, bool postShader, const UniformBufferDesc *uniformDesc) const; bool CompilePostShader(const ShaderInfo *shaderInfo, Draw::Pipeline **outPipeline) const; - bool BuildPostShader(const ShaderInfo *shaderInfo, const ShaderInfo *next, Draw::Pipeline **outPipeline); + bool BuildPostShader(const DisplayLayoutConfig &config, const ShaderInfo *shaderInfo, const ShaderInfo *next, Draw::Pipeline **outPipeline); bool AllocateFramebuffer(int w, int h); bool BindSource(int binding, bool bindStereo); - void GetCardboardSettings(CardboardSettings *cardboardSettings) const; + void GetCardboardSettings(const DisplayLayoutConfig &config, CardboardSettings *cardboardSettings) const; void CalculatePostShaderUniforms(int bufferWidth, int bufferHeight, int targetWidth, int targetHeight, const ShaderInfo *shaderInfo, PostShaderUniforms *uniforms) const; Draw::DrawContext *draw_; diff --git a/GPU/D3D11/DrawEngineD3D11.cpp b/GPU/D3D11/DrawEngineD3D11.cpp index b459176b52..fe70779044 100644 --- a/GPU/D3D11/DrawEngineD3D11.cpp +++ b/GPU/D3D11/DrawEngineD3D11.cpp @@ -413,7 +413,9 @@ void DrawEngineD3D11::Flush() { // We need correct viewport values in gstate_c already. if (gstate_c.IsDirty(DIRTY_VIEWPORTSCISSOR_STATE)) { ViewportAndScissor vpAndScissor; - ConvertViewportAndScissor(framebufferManager_->UseBufferedRendering(), + ConvertViewportAndScissor( + framebufferManager_->GetDisplayLayoutConfigCopy(), + framebufferManager_->UseBufferedRendering(), framebufferManager_->GetRenderWidth(), framebufferManager_->GetRenderHeight(), framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(), vpAndScissor); diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index 606053044c..72f683e249 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -113,15 +113,15 @@ void GPU_D3D11::DeviceRestore(Draw::DrawContext *draw) { GPUCommonHW::DeviceRestore(draw); } -void GPU_D3D11::BeginHostFrame() { - GPUCommonHW::BeginHostFrame(); +void GPU_D3D11::BeginHostFrame(const DisplayLayoutConfig &config) { + GPUCommonHW::BeginHostFrame(config); textureCache_->StartFrame(); drawEngine_.BeginFrame(); shaderManager_->DirtyLastShader(); - framebufferManager_->BeginFrame(); + framebufferManager_->BeginFrame(config); gstate_c.Dirty(DIRTY_PROJTHROUGHMATRIX); if (gstate_c.useFlagsChanged) { diff --git a/GPU/D3D11/GPU_D3D11.h b/GPU/D3D11/GPU_D3D11.h index 23aaa9900b..511b63eb9d 100644 --- a/GPU/D3D11/GPU_D3D11.h +++ b/GPU/D3D11/GPU_D3D11.h @@ -44,7 +44,7 @@ protected: void FinishDeferred() override; private: - void BeginHostFrame() override; + void BeginHostFrame(const DisplayLayoutConfig &config) override; ID3D11Device *device_; ID3D11DeviceContext *context_; diff --git a/GPU/D3D11/StateMappingD3D11.cpp b/GPU/D3D11/StateMappingD3D11.cpp index 4f5c9be683..6e2eb6474e 100644 --- a/GPU/D3D11/StateMappingD3D11.cpp +++ b/GPU/D3D11/StateMappingD3D11.cpp @@ -325,7 +325,9 @@ void DrawEngineD3D11::ApplyDrawState(int prim) { if (gstate_c.IsDirty(DIRTY_VIEWPORTSCISSOR_STATE)) { ViewportAndScissor vpAndScissor; - ConvertViewportAndScissor(useBufferedRendering, + ConvertViewportAndScissor( + framebufferManager_->GetDisplayLayoutConfigCopy(), + useBufferedRendering, framebufferManager_->GetRenderWidth(), framebufferManager_->GetRenderHeight(), framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(), vpAndScissor); diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index 7c314ff4ee..43d0885fd0 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -356,7 +356,9 @@ void DrawEngineGLES::Flush() { // We need correct viewport values in gstate_c already. if (gstate_c.IsDirty(DIRTY_VIEWPORTSCISSOR_STATE)) { - ConvertViewportAndScissor(framebufferManager_->UseBufferedRendering(), + ConvertViewportAndScissor( + framebufferManager_->GetDisplayLayoutConfigCopy(), + framebufferManager_->UseBufferedRendering(), framebufferManager_->GetRenderWidth(), framebufferManager_->GetRenderHeight(), framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(), vpAndScissor_); diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index c1dac7fdac..34cd4cb561 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -236,8 +236,8 @@ void GPU_GLES::DeviceRestore(Draw::DrawContext *draw) { fragmentTestCache_.DeviceRestore(draw_); } -void GPU_GLES::BeginHostFrame() { - GPUCommonHW::BeginHostFrame(); +void GPU_GLES::BeginHostFrame(const DisplayLayoutConfig &config) { + GPUCommonHW::BeginHostFrame(config); drawEngine_.BeginFrame(); textureCache_->StartFrame(); @@ -253,7 +253,7 @@ void GPU_GLES::BeginHostFrame() { // Not sure if this is really needed. gstate_c.Dirty(DIRTY_ALL_UNIFORMS); - framebufferManager_->BeginFrame(); + framebufferManager_->BeginFrame(config); fragmentTestCache_.Decimate(); if (gstate_c.useFlagsChanged) { diff --git a/GPU/GLES/GPU_GLES.h b/GPU/GLES/GPU_GLES.h index 6e83b01d2b..a1c6056734 100644 --- a/GPU/GLES/GPU_GLES.h +++ b/GPU/GLES/GPU_GLES.h @@ -44,7 +44,7 @@ public: void DeviceLost() override; // Only happens on Android. Drop all textures and shaders. void DeviceRestore(Draw::DrawContext *draw) override; - void BeginHostFrame() override; + void BeginHostFrame(const DisplayLayoutConfig &config) override; void EndHostFrame() override; protected: diff --git a/GPU/GLES/StateMappingGLES.cpp b/GPU/GLES/StateMappingGLES.cpp index 7a379914b6..d234b2fe6c 100644 --- a/GPU/GLES/StateMappingGLES.cpp +++ b/GPU/GLES/StateMappingGLES.cpp @@ -274,7 +274,9 @@ void DrawEngineGLES::ApplyDrawState(int prim) { } if (gstate_c.IsDirty(DIRTY_VIEWPORTSCISSOR_STATE)) { - ConvertViewportAndScissor(useBufferedRendering, + ConvertViewportAndScissor( + framebufferManager_->GetDisplayLayoutConfigCopy(), + useBufferedRendering, framebufferManager_->GetRenderWidth(), framebufferManager_->GetRenderHeight(), framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(), vpAndScissor_); diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index f37275641c..5d3a986fda 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -61,7 +61,7 @@ GPUCommon::GPUCommon(GraphicsContext *gfxCtx, Draw::DrawContext *draw) : ResetMatrices(); } -void GPUCommon::BeginHostFrame() { +void GPUCommon::BeginHostFrame(const DisplayLayoutConfig &config) { ReapplyGfxState(); // TODO: Assume config may have changed - maybe move to resize. @@ -70,9 +70,9 @@ void GPUCommon::BeginHostFrame() { UpdateCmdInfo(); UpdateMSAALevel(draw_); - CheckConfigChanged(); + CheckConfigChanged(config); CheckDisplayResized(); - CheckRenderResized(); + CheckRenderResized(config); } void GPUCommon::EndHostFrame() { @@ -159,7 +159,7 @@ void GPUCommon::NotifyConfigChanged() { configChanged_ = true; } -void GPUCommon::NotifyRenderResized() { +void GPUCommon::NotifyRenderResized(const DisplayLayoutConfig &config) { renderResized_ = true; } diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index c75faaf4a1..05b0d8bc7e 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -199,6 +199,8 @@ inline bool IsTrianglePrim(GEPrimitiveType prim) { return prim > GE_PRIM_LINE_STRIP && prim != GE_PRIM_RECTANGLES; } +struct DisplayLayoutConfig; + class GPUCommon : public GPUDebugInterface { public: // The constructor might run on the loader thread. @@ -225,7 +227,7 @@ public: } virtual void Reinitialize(); - virtual void BeginHostFrame(); + virtual void BeginHostFrame(const DisplayLayoutConfig &config); virtual void EndHostFrame(); void InterruptStart(int listid); @@ -236,10 +238,10 @@ public: } virtual void CheckDisplayResized() = 0; - virtual void CheckConfigChanged() = 0; + virtual void CheckConfigChanged(const DisplayLayoutConfig &config) = 0; virtual void NotifyDisplayResized(); - virtual void NotifyRenderResized(); + virtual void NotifyRenderResized(const DisplayLayoutConfig &config); virtual void NotifyConfigChanged(); void DumpNextFrame(); @@ -274,7 +276,7 @@ public: uint32_t GetAddrTranslation() override; virtual void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) = 0; - virtual void CopyDisplayToOutput(bool reallyDirty) = 0; + virtual void CopyDisplayToOutput(const DisplayLayoutConfig &config, bool reallyDirty) = 0; virtual bool PresentedThisFrame() const = 0; // Invalidate any cached content sourced from the specified range. @@ -422,7 +424,7 @@ protected: virtual void ClearCacheNextFrame() {} - virtual void CheckRenderResized() {} + virtual void CheckRenderResized(const DisplayLayoutConfig &config) {} void SetDrawType(DrawType type, GEPrimitiveType prim) { if (type != lastDraw_) { diff --git a/GPU/GPUCommonHW.cpp b/GPU/GPUCommonHW.cpp index a5f6d15fe6..e1202c5c79 100644 --- a/GPU/GPUCommonHW.cpp +++ b/GPU/GPUCommonHW.cpp @@ -405,7 +405,7 @@ GPUCommonHW::~GPUCommonHW() { // Called once per frame. Might also get called during the pause screen // if "transparent". -void GPUCommonHW::CheckConfigChanged() { +void GPUCommonHW::CheckConfigChanged(const DisplayLayoutConfig &config) { if (configChanged_) { ClearCacheNextFrame(); gstate_c.SetUseFlags(CheckGPUFeatures()); @@ -418,7 +418,7 @@ void GPUCommonHW::CheckConfigChanged() { // Check needed when running tests. if (framebufferManager_) { - framebufferManager_->CheckPostShaders(); + framebufferManager_->CheckPostShaders(config); } } @@ -429,9 +429,9 @@ void GPUCommonHW::CheckDisplayResized() { } } -void GPUCommonHW::CheckRenderResized() { +void GPUCommonHW::CheckRenderResized(const DisplayLayoutConfig &config) { if (renderResized_) { - framebufferManager_->NotifyRenderResized(msaaLevel_); + framebufferManager_->NotifyRenderResized(config, msaaLevel_); renderResized_ = false; } } @@ -503,8 +503,8 @@ void GPUCommonHW::UpdateCmdInfo() { } } -void GPUCommonHW::BeginHostFrame() { - GPUCommon::BeginHostFrame(); +void GPUCommonHW::BeginHostFrame(const DisplayLayoutConfig &config) { + GPUCommon::BeginHostFrame(config); if (drawEngineCommon_->EverUsedExactEqualDepth() && !sawExactEqualDepth_) { sawExactEqualDepth_ = true; gstate_c.SetUseFlags(CheckGPUFeatures()); @@ -530,7 +530,7 @@ void GPUCommonHW::PreExecuteOp(u32 op, u32 diff) { CheckFlushOp(op >> 24, diff); } -void GPUCommonHW::CopyDisplayToOutput(bool reallyDirty) { +void GPUCommonHW::CopyDisplayToOutput(const DisplayLayoutConfig &config, bool reallyDirty) { drawEngineCommon_->FlushQueuedDepth(); // Flush anything left over. drawEngineCommon_->Flush(); @@ -538,7 +538,7 @@ void GPUCommonHW::CopyDisplayToOutput(bool reallyDirty) { shaderManager_->DirtyLastShader(); // after this, render pass is active. - framebufferManager_->CopyDisplayToOutput(reallyDirty); + framebufferManager_->CopyDisplayToOutput(config, reallyDirty); gstate_c.Dirty(DIRTY_TEXTURE_IMAGE); } diff --git a/GPU/GPUCommonHW.h b/GPU/GPUCommonHW.h index 07e4002fb2..5e62ffc826 100644 --- a/GPU/GPUCommonHW.h +++ b/GPU/GPUCommonHW.h @@ -10,12 +10,12 @@ public: ~GPUCommonHW(); // This can fail, and if so no render pass is active. - void CopyDisplayToOutput(bool reallyDirty) override; + void CopyDisplayToOutput(const DisplayLayoutConfig &config, bool reallyDirty) override; void DoState(PointerWrap &p) override; void DeviceLost() override; void DeviceRestore(Draw::DrawContext *draw) override; - void BeginHostFrame() override; + void BeginHostFrame(const DisplayLayoutConfig &config) override; u32 CheckGPUFeatures() const override; @@ -97,8 +97,8 @@ protected: void UpdateMSAALevel(Draw::DrawContext *draw) override; void CheckDisplayResized() override; - void CheckRenderResized() override; - void CheckConfigChanged() override; + void CheckRenderResized(const DisplayLayoutConfig &config) override; + void CheckConfigChanged(const DisplayLayoutConfig &config) override; u32 CheckGPUFeaturesLate(u32 features) const; diff --git a/GPU/Software/SoftGpu.cpp b/GPU/Software/SoftGpu.cpp index b95f80b21f..a7356ec746 100644 --- a/GPU/Software/SoftGpu.cpp +++ b/GPU/Software/SoftGpu.cpp @@ -451,7 +451,7 @@ SoftGPU::SoftGPU(GraphicsContext *gfxCtx, Draw::DrawContext *draw) NotifyConfigChanged(); NotifyDisplayResized(); - NotifyRenderResized(); + // NotifyRenderResized(); // hopefully not needed here. } void SoftGPU::DeviceLost() { @@ -531,7 +531,7 @@ void SoftGPU::ConvertTextureDescFrom16(Draw::TextureDesc &desc, int srcwidth, in } // Copies RGBA8 data from RAM to the currently bound render target. -void SoftGPU::CopyToCurrentFboFromDisplayRam(int srcwidth, int srcheight) { +void SoftGPU::CopyToCurrentFboFromDisplayRam(const DisplayLayoutConfig &config, int srcwidth, int srcheight) { if (!draw_ || !presentation_) return; float u0 = 0.0f; @@ -560,7 +560,7 @@ void SoftGPU::CopyToCurrentFboFromDisplayRam(int srcwidth, int srcheight) { desc.tag = "SoftGPU"; bool hasImage = true; - OutputFlags outputFlags = g_Config.iDisplayFilter == SCALE_NEAREST ? OutputFlags::NEAREST : OutputFlags::LINEAR; + OutputFlags outputFlags = config.iDisplayFilter == SCALE_NEAREST ? OutputFlags::NEAREST : OutputFlags::LINEAR; bool hasPostShader = presentation_ && presentation_->HasPostShader(); if (PSP_CoreParameter().compat.flags().DarkStalkersPresentHack && displayFormat_ == GE_FORMAT_5551 && g_DarkStalkerStretch != DSStretch::Off) { @@ -642,20 +642,20 @@ void SoftGPU::CopyToCurrentFboFromDisplayRam(int srcwidth, int srcheight) { } presentation_->SourceTexture(fbTex, desc.width, desc.height); - presentation_->CopyToOutput(outputFlags, g_Config.iInternalScreenRotation, u0, v0, u1, v1); + presentation_->CopyToOutput(config, outputFlags, config.iInternalScreenRotation, u0, v0, u1, v1); } -void SoftGPU::CopyDisplayToOutput(bool reallyDirty) { +void SoftGPU::CopyDisplayToOutput(const DisplayLayoutConfig &config, bool reallyDirty) { drawEngine_->transformUnit.Flush(this, "output"); // The display always shows 480x272. - CopyToCurrentFboFromDisplayRam(FB_WIDTH, FB_HEIGHT); + CopyToCurrentFboFromDisplayRam(config, FB_WIDTH, FB_HEIGHT); MarkDirty(displayFramebuf_, displayStride_, 272, displayFormat_, SoftGPUVRAMDirty::CLEAR); } -void SoftGPU::BeginHostFrame() { - GPUCommon::BeginHostFrame(); +void SoftGPU::BeginHostFrame(const DisplayLayoutConfig &config) { + GPUCommon::BeginHostFrame(config); if (presentation_) { - presentation_->BeginFrame(); + presentation_->BeginFrame(config); } } @@ -720,9 +720,9 @@ bool SoftGPU::ClearDirty(uint32_t addr, uint32_t bytes, SoftGPUVRAMDirty value) return result; } -void SoftGPU::NotifyRenderResized() { +void SoftGPU::NotifyRenderResized(const DisplayLayoutConfig &config) { // Force the render params to 480x272 so other things work. - if (g_Config.IsPortrait()) { + if (config.InternalRotationIsPortrait()) { PSP_CoreParameter().renderWidth = 272; PSP_CoreParameter().renderHeight = 480; } else { @@ -739,17 +739,16 @@ void SoftGPU::CheckDisplayResized() { if (displayResized_ && presentation_) { presentation_->UpdateDisplaySize(PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight); presentation_->UpdateRenderSize(PSP_CoreParameter().renderWidth, PSP_CoreParameter().renderHeight); - presentation_->UpdatePostShader(); displayResized_ = false; } } -void SoftGPU::CheckConfigChanged() { +void SoftGPU::CheckConfigChanged(const DisplayLayoutConfig &config) { if (configChanged_) { drawEngineCommon_->NotifyConfigChanged(); BuildReportingInfo(); if (presentation_) { - presentation_->UpdatePostShader(); + presentation_->UpdatePostShader(config); } configChanged_ = false; } diff --git a/GPU/Software/SoftGpu.h b/GPU/Software/SoftGpu.h index 5faaee3568..1b49f4086d 100644 --- a/GPU/Software/SoftGpu.h +++ b/GPU/Software/SoftGpu.h @@ -136,7 +136,7 @@ public: void UpdateCmdInfo() override {} void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) override; - void CopyDisplayToOutput(bool reallyDirty) override; + void CopyDisplayToOutput(const DisplayLayoutConfig &config, bool reallyDirty) override; void GetStats(char *buffer, size_t bufsize) override; std::vector GetFramebufferList() const override { return std::vector(); } void InvalidateCache(u32 addr, int size, GPUInvalidationType type) override; @@ -150,11 +150,11 @@ public: void DeviceLost() override; void DeviceRestore(Draw::DrawContext *draw) override; - void NotifyRenderResized() override; + void NotifyRenderResized(const DisplayLayoutConfig &config) override; void NotifyDisplayResized() override; void CheckDisplayResized() override; - void CheckConfigChanged() override; + void CheckConfigChanged(const DisplayLayoutConfig &config) override; void GetReportingInfo(std::string &primaryInfo, std::string &fullInfo) const override { primaryInfo = "Software"; @@ -209,12 +209,12 @@ public: typedef void (SoftGPU::*CmdFunc)(u32 op, u32 diff); - void BeginHostFrame() override; + void BeginHostFrame(const DisplayLayoutConfig &config) override; bool PresentedThisFrame() const override; protected: void FastRunLoop(DisplayList &list) override; - void CopyToCurrentFboFromDisplayRam(int srcwidth, int srcheight); + void CopyToCurrentFboFromDisplayRam(const DisplayLayoutConfig &config, int srcwidth, int srcheight); void ConvertTextureDescFrom16(Draw::TextureDesc &desc, int srcwidth, int srcheight, const uint16_t *overrideData = nullptr); void BuildReportingInfo() override {} diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index ec132cce1a..70b8f58b5e 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -427,7 +427,9 @@ void DrawEngineVulkan::Flush() { // TODO: Probably should eventually refactor this and feed the vp size into SoftwareTransform directly (Unknown's idea). if (gstate_c.IsDirty(DIRTY_VIEWPORTSCISSOR_STATE)) { ViewportAndScissor vpAndScissor; - ConvertViewportAndScissor(framebufferManager_->UseBufferedRendering(), + ConvertViewportAndScissor( + framebufferManager_->GetDisplayLayoutConfigCopy(), + framebufferManager_->UseBufferedRendering(), framebufferManager_->GetRenderWidth(), framebufferManager_->GetRenderHeight(), framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(), vpAndScissor); diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index 6c5af27345..c8b76ccc28 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -298,8 +298,8 @@ u32 GPU_Vulkan::CheckGPUFeatures() const { return CheckGPUFeaturesLate(features); } -void GPU_Vulkan::BeginHostFrame() { - GPUCommonHW::BeginHostFrame(); +void GPU_Vulkan::BeginHostFrame(const DisplayLayoutConfig &config) { + GPUCommonHW::BeginHostFrame(config); drawEngine_.BeginFrame(); textureCache_->StartFrame(); @@ -307,7 +307,7 @@ void GPU_Vulkan::BeginHostFrame() { VulkanContext *vulkan = (VulkanContext *)draw_->GetNativeObject(Draw::NativeObject::CONTEXT); int curFrame = vulkan->GetCurFrame(); - framebufferManager_->BeginFrame(); + framebufferManager_->BeginFrame(config); shaderManagerVulkan_->DirtyLastShader(); gstate_c.Dirty(DIRTY_ALL); @@ -424,9 +424,9 @@ void GPU_Vulkan::DestroyDeviceObjects() { } } -void GPU_Vulkan::CheckRenderResized() { +void GPU_Vulkan::CheckRenderResized(const DisplayLayoutConfig &config) { if (renderResized_) { - GPUCommonHW::CheckRenderResized(); + GPUCommonHW::CheckRenderResized(config); pipelineManager_->InvalidateMSAAPipelines(); framebufferManager_->ReleasePipelines(); } diff --git a/GPU/Vulkan/GPU_Vulkan.h b/GPU/Vulkan/GPU_Vulkan.h index 7e21011ef1..25475bc477 100644 --- a/GPU/Vulkan/GPU_Vulkan.h +++ b/GPU/Vulkan/GPU_Vulkan.h @@ -44,7 +44,7 @@ public: u32 CheckGPUFeatures() const override; // These are where we can reset command buffers etc. - void BeginHostFrame() override; + void BeginHostFrame(const DisplayLayoutConfig &config) override; void EndHostFrame() override; void GetStats(char *buffer, size_t bufsize) override; @@ -61,7 +61,7 @@ public: protected: void FinishDeferred() override; - void CheckRenderResized() override; + void CheckRenderResized(const DisplayLayoutConfig &config) override; private: void BuildReportingInfo() override; diff --git a/GPU/Vulkan/StateMappingVulkan.cpp b/GPU/Vulkan/StateMappingVulkan.cpp index c1fa8640e8..90059881d0 100644 --- a/GPU/Vulkan/StateMappingVulkan.cpp +++ b/GPU/Vulkan/StateMappingVulkan.cpp @@ -328,7 +328,9 @@ void DrawEngineVulkan::ConvertStateToVulkanKey(FramebufferManagerVulkan &fbManag if (gstate_c.IsDirty(DIRTY_VIEWPORTSCISSOR_STATE)) { ViewportAndScissor vpAndScissor; - ConvertViewportAndScissor(useBufferedRendering, + ConvertViewportAndScissor( + framebufferManager_->GetDisplayLayoutConfigCopy(), + useBufferedRendering, fbManager.GetRenderWidth(), fbManager.GetRenderHeight(), fbManager.GetTargetBufferWidth(), fbManager.GetTargetBufferHeight(), vpAndScissor); diff --git a/Qt/mainwindow.cpp b/Qt/mainwindow.cpp index 4636584098..5c0963cc1b 100644 --- a/Qt/mainwindow.cpp +++ b/Qt/mainwindow.cpp @@ -95,20 +95,23 @@ void MainWindow::updateMenuGroupInt(QActionGroup *group, int value) { void MainWindow::updateMenus() { + const DisplayLayoutConfig &config = g_Config.GetDisplayLayoutConfig(g_display.GetDeviceOrientation()); + updateMenuGroupInt(saveStateGroup, g_Config.iCurrentStateSlot); - updateMenuGroupInt(displayRotationGroup, g_Config.iInternalScreenRotation); + updateMenuGroupInt(displayRotationGroup, config.iInternalScreenRotation); updateMenuGroupInt(renderingResolutionGroup, g_Config.iInternalResolution); updateMenuGroupInt(frameSkippingGroup, g_Config.iFrameSkip); updateMenuGroupInt(textureFilteringGroup, g_Config.iTexFiltering); - updateMenuGroupInt(screenScalingFilterGroup, g_Config.iDisplayFilter); + updateMenuGroupInt(screenScalingFilterGroup, config.iDisplayFilter); updateMenuGroupInt(textureScalingLevelGroup, g_Config.iTexScalingLevel); updateMenuGroupInt(textureScalingTypeGroup, g_Config.iTexScalingType); + bool internalPortrait = config.InternalRotationIsPortrait(); foreach(QAction * action, windowGroup->actions()) { - int width = (g_Config.IsPortrait() ? 272 : 480) * action->data().toInt(); - int height = (g_Config.IsPortrait() ? 480 : 272) * action->data().toInt(); + int width = (internalPortrait ? 272 : 480) * action->data().toInt(); + int height = (internalPortrait ? 480 : 272) * action->data().toInt(); if (g_Config.iWindowWidth == width && g_Config.iWindowHeight == height) { - action->setChecked(true); + action->setChecked(true); break; } } @@ -457,6 +460,9 @@ void MainWindow::SetWindowScale(int zoom) { if (isFullScreen()) fullscrAct(); + const DisplayLayoutConfig &config = g_Config.GetDisplayLayoutConfig(g_display.GetDeviceOrientation()); + const bool internalPortrait = config.InternalRotationIsPortrait(); + int width, height; if (zoom == -1 && (g_Config.iWindowWidth <= 0 || g_Config.iWindowHeight <= 0)) { // Default to zoom level 2. @@ -473,8 +479,8 @@ void MainWindow::SetWindowScale(int zoom) { if (zoom > 10) zoom = 10; - width = (g_Config.IsPortrait() ? 272 : 480) * zoom; - height = (g_Config.IsPortrait() ? 480 : 272) * zoom; + width = (internalPortrait ? 272 : 480) * zoom; + height = (internalPortrait ? 480 : 272) * zoom; } g_Config.iWindowWidth = width; diff --git a/Qt/mainwindow.h b/Qt/mainwindow.h index 67982abd92..a616da89e6 100644 --- a/Qt/mainwindow.h +++ b/Qt/mainwindow.h @@ -12,6 +12,7 @@ #include "ppsspp_config.h" #include "Common/System/System.h" #include "Common/System/NativeApp.h" +#include "Common/System/Display.h" #if PPSSPP_PLATFORM(WINDOWS) #include "Common/Log/ConsoleListener.h" #endif @@ -101,7 +102,10 @@ private slots: void stopAct(); void resetAct(); void switchUMDAct(); - void displayRotationGroup_triggered(QAction *action) { g_Config.iInternalScreenRotation = action->data().toInt(); } + void displayRotationGroup_triggered(QAction *action) { + DisplayLayoutConfig &config = g_Config.GetDisplayLayoutConfig(g_display.GetDeviceOrientation()); + config.iInternalScreenRotation = action->data().toInt(); + } // Debug void breakonloadAct(); @@ -142,7 +146,10 @@ private slots: } void frameSkippingGroup_triggered(QAction *action) { g_Config.iFrameSkip = action->data().toInt(); } void textureFilteringGroup_triggered(QAction *action) { g_Config.iTexFiltering = action->data().toInt(); } - void screenScalingFilterGroup_triggered(QAction *action) { g_Config.iDisplayFilter = action->data().toInt(); } + void screenScalingFilterGroup_triggered(QAction *action) { + DisplayLayoutConfig &config = g_Config.GetDisplayLayoutConfig(g_display.GetDeviceOrientation()); + config.iDisplayFilter = action->data().toInt(); + } void textureScalingLevelGroup_triggered(QAction *action) { g_Config.iTexScalingLevel = action->data().toInt(); System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED); diff --git a/UI/ControlMappingScreen.cpp b/UI/ControlMappingScreen.cpp index de71fef87b..bcc2bc481b 100644 --- a/UI/ControlMappingScreen.cpp +++ b/UI/ControlMappingScreen.cpp @@ -510,7 +510,7 @@ AnalogCalibrationScreen::AnalogCalibrationScreen(const Path &gamePath) : UITwoPa [](int vkey, bool down) {}, [](int vkey, float analogValue) {}, [&](uint32_t bitsToSet, uint32_t bitsToClear) {}, - [&](int stick, float x, float y) { + [&](int iInternalRotation, int stick, float x, float y) { analogX_[stick] = x; analogY_[stick] = y; }, @@ -521,7 +521,7 @@ AnalogCalibrationScreen::AnalogCalibrationScreen(const Path &gamePath) : UITwoPa } void AnalogCalibrationScreen::update() { - mapper_.Update(time_now_d()); + mapper_.Update(g_Config.GetDisplayLayoutConfig(GetDeviceOrientation()), time_now_d()); // We ignore the secondary stick for now and just use the two views // for raw and psp input. if (stickView_[0]) { diff --git a/UI/DisplayLayoutScreen.cpp b/UI/DisplayLayoutScreen.cpp index 9ce8cd08cd..b58e5fba1d 100644 --- a/UI/DisplayLayoutScreen.cpp +++ b/UI/DisplayLayoutScreen.cpp @@ -60,25 +60,27 @@ static Bounds FRectToBounds(FRect rc) { class DisplayLayoutBackground : public UI::View { public: - DisplayLayoutBackground(UI::ChoiceStrip *mode, UI::LayoutParams *layoutParams) : UI::View(layoutParams), mode_(mode) {} + DisplayLayoutBackground(UI::ChoiceStrip *mode, DeviceOrientation orientation, UI::LayoutParams *layoutParams) : UI::View(layoutParams), mode_(mode), orientation_(orientation) {} bool Touch(const TouchInput &touch) override { int mode = mode_ ? mode_->GetSelection() : 0; + DisplayLayoutConfig &config = g_Config.GetDisplayLayoutConfig(orientation_); + if ((touch.flags & TOUCH_MOVE) != 0 && dragging_) { float relativeTouchX = touch.x - startX_; float relativeTouchY = touch.y - startY_; switch (mode) { case MODE_MOVE: - g_Config.fDisplayOffsetX = clamp_value(startDisplayOffsetX_ + relativeTouchX / bounds_.w, 0.0f, 1.0f); - g_Config.fDisplayOffsetY = clamp_value(startDisplayOffsetY_ + relativeTouchY / bounds_.h, 0.0f, 1.0f); + config.fDisplayOffsetX = clamp_value(startDisplayOffsetX_ + relativeTouchX / bounds_.w, 0.0f, 1.0f); + config.fDisplayOffsetY = clamp_value(startDisplayOffsetY_ + relativeTouchY / bounds_.h, 0.0f, 1.0f); break; case MODE_RESIZE: { // Resize. Vertical = scaling; Up should be bigger so let's negate in that direction float diffYProp = -relativeTouchY * 0.007f; - g_Config.fDisplayScale = clamp_value(startScale_ * powf(2.0f, diffYProp), 0.2f, 2.0f); + config.fDisplayScale = clamp_value(startScale_ * powf(2.0f, diffYProp), 0.2f, 2.0f); break; } } @@ -93,9 +95,9 @@ public: dragging_ = true; startX_ = touch.x; startY_ = touch.y; - startDisplayOffsetX_ = g_Config.fDisplayOffsetX; - startDisplayOffsetY_ = g_Config.fDisplayOffsetY; - startScale_ = g_Config.fDisplayScale; + startDisplayOffsetX_ = config.fDisplayOffsetX; + startDisplayOffsetY_ = config.fDisplayOffsetY; + startScale_ = config.fDisplayScale; } } @@ -109,7 +111,7 @@ public: private: UI::ChoiceStrip *mode_; bool dragging_ = false; - + const DeviceOrientation orientation_; // Touch down state for drag to resize etc float startX_ = 0.0f; float startY_ = 0.0f; @@ -127,11 +129,12 @@ void DisplayLayoutScreen::DrawBackground(UIContext &dc) { // But if it's not present (we're not in game, or skip buffer effects is used), // we have to draw a substitute ourselves. UIContext &dc = *screenManager()->getUIContext(); + DisplayLayoutConfig &config = g_Config.GetDisplayLayoutConfig(GetDeviceOrientation()); // TODO: Clean this up a bit, this GetScreenFrame/CenterDisplay combo is too common. - FRect screenFrame = GetScreenFrame(g_display.pixel_xres, g_display.pixel_yres); + FRect screenFrame = GetScreenFrame(config.bIgnoreScreenInsets, g_display.pixel_xres, g_display.pixel_yres); FRect rc; - CalculateDisplayOutputRect(&rc, 480.0f, 272.0f, screenFrame, g_Config.iInternalScreenRotation); + CalculateDisplayOutputRect(config, &rc, 480.0f, 272.0f, screenFrame, config.iInternalScreenRotation); dc.Flush(); ImageID bg = ImageID("I_PSP_DISPLAY"); @@ -201,7 +204,7 @@ void DisplayLayoutScreen::CreateViews() { root_ = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT)); - const bool portrait = UsePortraitLayout(); + const bool portrait = GetDeviceOrientation() == DeviceOrientation::Portrait; // Make it so that a touch can only affect one view. Makes manipulating the background through the buttons // impossible. @@ -239,31 +242,36 @@ void DisplayLayoutScreen::CreateViews() { leftColumn->SetBG(backgroundWithAlpha); rightColumn->SetBG(backgroundWithAlpha); + DisplayLayoutConfig &config = g_Config.GetDisplayLayoutConfig(GetDeviceOrientation()); if (!IsVREnabled()) { - auto stretch = new CheckBox(&g_Config.bDisplayStretch, gr->T("Stretch")); - stretch->SetDisabledPtr(&g_Config.bDisplayIntegerScale); + + auto stretch = new CheckBox(&config.bDisplayStretch, gr->T("Stretch")); + stretch->SetDisabledPtr(&config.bDisplayIntegerScale); rightColumn->Add(stretch); - PopupSliderChoiceFloat *aspectRatio = new PopupSliderChoiceFloat(&g_Config.fDisplayAspectRatio, 0.1f, 2.0f, 1.0f, gr->T("Aspect Ratio"), screenManager()); + PopupSliderChoiceFloat *aspectRatio = new PopupSliderChoiceFloat(&config.fDisplayAspectRatio, 0.1f, 2.0f, 1.0f, gr->T("Aspect Ratio"), screenManager()); rightColumn->Add(aspectRatio); - aspectRatio->SetEnabledFunc([]() { - return !g_Config.bDisplayStretch && !g_Config.bDisplayIntegerScale; + aspectRatio->SetEnabledFunc([config]() { + return !config.bDisplayStretch && !config.bDisplayIntegerScale; }); aspectRatio->SetHasDropShadow(false); aspectRatio->SetLiveUpdate(true); - rightColumn->Add(new CheckBox(&g_Config.bDisplayIntegerScale, gr->T("Integer scale factor"))); + rightColumn->Add(new CheckBox(&config.bDisplayIntegerScale, gr->T("Integer scale factor"))); + bool supportsInsets = false; #if PPSSPP_PLATFORM(ANDROID) - // Hide insets option if no insets, or OS too old. - if (System_GetPropertyInt(SYSPROP_SYSTEMVERSION) >= 28 && - (System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_LEFT) != 0.0f || - System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_TOP) != 0.0f || - System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_RIGHT) != 0.0f || - System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_BOTTOM) != 0.0f)) { - rightColumn->Add(new CheckBox(&g_Config.bIgnoreScreenInsets, gr->T("Ignore camera notch when centering"))); - } + supportsInsets = System_GetPropertyInt(SYSPROP_SYSTEMVERSION) >= 28; +#elif PPSSPP_PLATFORM(IOS) + supportsInsets = true; #endif + // Hide insets option if no insets, or OS too old. + if (supportsInsets && System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_LEFT) != 0.0f || + System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_TOP) != 0.0f || + System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_RIGHT) != 0.0f || + System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_BOTTOM) != 0.0f) { + rightColumn->Add(new CheckBox(&config.bIgnoreScreenInsets, gr->T("Ignore camera notch when centering"))); + } mode_ = new ChoiceStrip(ORIENT_HORIZONTAL, new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT)); mode_->AddChoice(di->T("Inactive")); @@ -273,7 +281,7 @@ void DisplayLayoutScreen::CreateViews() { bottomControls->Add(mode_); static const char *displayRotation[] = { "Landscape", "Portrait", "Landscape Reversed", "Portrait Reversed" }; - auto rotation = new PopupMultiChoice(&g_Config.iInternalScreenRotation, gr->T("Rotation"), displayRotation, 1, ARRAY_SIZE(displayRotation), I18NCat::CONTROLS, screenManager()); + auto rotation = new PopupMultiChoice(&config.iInternalScreenRotation, gr->T("Rotation"), displayRotation, 1, ARRAY_SIZE(displayRotation), I18NCat::CONTROLS, screenManager()); rotation->SetEnabledFunc([] { return !g_Config.bSkipBufferEffects || g_Config.bSoftwareRendering; }); @@ -281,11 +289,11 @@ void DisplayLayoutScreen::CreateViews() { rightColumn->Add(rotation); Choice *center = new Choice(di->T("Reset")); - center->OnClick.Add([&](UI::EventParams &) { - g_Config.fDisplayAspectRatio = 1.0f; - g_Config.fDisplayScale = 1.0f; - g_Config.fDisplayOffsetX = 0.5f; - g_Config.fDisplayOffsetY = 0.5f; + center->OnClick.Add([&config](UI::EventParams &) { + config.fDisplayAspectRatio = 1.0f; + config.fDisplayScale = 1.0f; + config.fDisplayOffsetX = 0.5f; + config.fDisplayOffsetY = 0.5f; }); rightColumn->Add(center); @@ -302,7 +310,7 @@ void DisplayLayoutScreen::CreateViews() { if (!IsVREnabled()) { static const char *bufFilters[] = { "Linear", "Nearest", }; - leftColumn->Add(new PopupMultiChoice(&g_Config.iDisplayFilter, gr->T("Screen Scaling Filter"), bufFilters, 1, ARRAY_SIZE(bufFilters), I18NCat::GRAPHICS, screenManager())); + leftColumn->Add(new PopupMultiChoice(&config.iDisplayFilter, gr->T("Screen Scaling Filter"), bufFilters, 1, ARRAY_SIZE(bufFilters), I18NCat::GRAPHICS, screenManager())); } Draw::DrawContext *draw = screenManager()->getDrawContext(); @@ -464,7 +472,7 @@ void DisplayLayoutScreen::CreateViews() { } } - root_->Add(new DisplayLayoutBackground(mode_, new AnchorLayoutParams(FILL_PARENT, FILL_PARENT, 0.0f, 0.0f, 0.0f, 0.0f))); + root_->Add(new DisplayLayoutBackground(mode_, GetDeviceOrientation(), new AnchorLayoutParams(FILL_PARENT, FILL_PARENT, 0.0f, 0.0f, 0.0f, 0.0f))); } void PostProcScreen::CreateViews() { diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index 867156eb6c..9fbd2c96d7 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -70,6 +70,7 @@ using namespace std::placeholders; #include "Core/HLE/sceCtrl.h" #include "Core/HLE/sceSas.h" #include "Core/HLE/sceNet.h" +#include "Core/HLE/sceDisplay.h" #include "Core/HLE/sceNetAdhoc.h" #include "Core/Debugger/SymbolMap.h" #include "Core/RetroAchievements.h" @@ -124,8 +125,8 @@ static void AssertCancelCallback(const char *message, void *userdata) { } // Handles control rotation due to internal screen rotation. -static void SetPSPAnalog(int stick, float x, float y) { - switch (g_Config.iInternalScreenRotation) { +static void SetPSPAnalog(int iInternalScreenRotation, int stick, float x, float y) { + switch (iInternalScreenRotation) { case ROTATION_LOCKED_HORIZONTAL: // Standard rotation. No change. break; @@ -917,17 +918,29 @@ void EmuScreen::ProcessVKey(VirtKey virtKey) { break; case VIRTKEY_SCREEN_ROTATION_VERTICAL: - g_Config.iInternalScreenRotation = ROTATION_LOCKED_VERTICAL; + { + DisplayLayoutConfig &config = g_Config.GetDisplayLayoutConfig(GetDeviceOrientation()); + config.iInternalScreenRotation = ROTATION_LOCKED_VERTICAL; break; + } case VIRTKEY_SCREEN_ROTATION_VERTICAL180: - g_Config.iInternalScreenRotation = ROTATION_LOCKED_VERTICAL180; + { + DisplayLayoutConfig &config = g_Config.GetDisplayLayoutConfig(GetDeviceOrientation()); + config.iInternalScreenRotation = ROTATION_LOCKED_VERTICAL180; break; + } case VIRTKEY_SCREEN_ROTATION_HORIZONTAL: - g_Config.iInternalScreenRotation = ROTATION_LOCKED_HORIZONTAL; + { + DisplayLayoutConfig &config = g_Config.GetDisplayLayoutConfig(GetDeviceOrientation()); + config.iInternalScreenRotation = ROTATION_LOCKED_HORIZONTAL; break; + } case VIRTKEY_SCREEN_ROTATION_HORIZONTAL180: - g_Config.iInternalScreenRotation = ROTATION_LOCKED_HORIZONTAL180; + { + DisplayLayoutConfig &config = g_Config.GetDisplayLayoutConfig(GetDeviceOrientation()); + config.iInternalScreenRotation = ROTATION_LOCKED_HORIZONTAL180; break; + } case VIRTKEY_TOGGLE_WLAN: // Let's not allow the user to toggle wlan while connected, could get confusing. @@ -1272,8 +1285,10 @@ void EmuScreen::CreateViews() { backButton_->SetVisibility(V_GONE); cardboardDisableButton_ = root_->Add(new Button(sc->T("Cardboard VR OFF"), new AnchorLayoutParams(bounds.centerX(), NONE, NONE, 30, true))); - cardboardDisableButton_->OnClick.Add([](UI::EventParams &) { - g_Config.bEnableCardboardVR = false; + DeviceOrientation orientation = GetDeviceOrientation(); + cardboardDisableButton_->OnClick.Add([orientation](UI::EventParams &) { + DisplayLayoutConfig &config = g_Config.GetDisplayLayoutConfig(orientation); + config.bEnableCardboardVR = false; }); cardboardDisableButton_->SetVisibility(V_GONE); cardboardDisableButton_->SetScale(0.65f); // make it smaller - this button can be in the way otherwise. @@ -1447,7 +1462,8 @@ void EmuScreen::update() { double now = time_now_d(); - controlMapper_.Update(now); + DisplayLayoutConfig &config = g_Config.GetDisplayLayoutConfig(GetDeviceOrientation()); + controlMapper_.Update(config, now); if (saveStatePreview_ && !bootPending_) { int currentSlot = SaveState::GetCurrentSlot(); @@ -1577,6 +1593,8 @@ ScreenRenderFlags EmuScreen::render(ScreenRenderMode mode) { bool framebufferBound = false; + const DeviceOrientation orientation = GetDeviceOrientation(); + if (mode & ScreenRenderMode::FIRST) { // Actually, always gonna be first when it exists (?) @@ -1607,6 +1625,9 @@ ScreenRenderFlags EmuScreen::render(ScreenRenderMode mode) { g_OSD.NudgeIngameNotifications(); + const DisplayLayoutConfig &displayLayoutConfig = g_Config.GetDisplayLayoutConfig(orientation); + __DisplaySetDisplayLayoutConfig(displayLayoutConfig); + if (mode & ScreenRenderMode::TOP) { System_Notify(SystemNotification::KEEP_SCREEN_AWAKE); } else if (!ShouldRunBehind() && strcmp(screenManager()->topScreen()->tag(), "DevMenu") != 0) { @@ -1614,8 +1635,8 @@ ScreenRenderFlags EmuScreen::render(ScreenRenderMode mode) { // Just to make sure. if (PSP_IsInited() && !skipBufferEffects) { _dbg_assert_(gpu); - gpu->BeginHostFrame(); - gpu->CopyDisplayToOutput(true); + gpu->BeginHostFrame(displayLayoutConfig); + gpu->CopyDisplayToOutput(displayLayoutConfig, true); gpu->EndHostFrame(); } if (gpu && gpu->PresentedThisFrame()) { @@ -1681,7 +1702,7 @@ ScreenRenderFlags EmuScreen::render(ScreenRenderMode mode) { uint32_t clearColor = 0; if (!blockedExecution) { if (gpu) { - gpu->BeginHostFrame(); + gpu->BeginHostFrame(displayLayoutConfig); } if (SaveState::Process()) { // We might have lost the framebuffer bind if we had one, due to a readback. @@ -1716,7 +1737,7 @@ ScreenRenderFlags EmuScreen::render(ScreenRenderMode mode) { // This won't work in non-buffered, but that's fine. if (!framebufferBound && PSP_IsInited()) { // draw->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::CLEAR, RPAction::CLEAR, clearColor }, "EmuScreen_Stepping"); - gpu->CopyDisplayToOutput(true); + gpu->CopyDisplayToOutput(displayLayoutConfig, true); framebufferBound = true; } } @@ -1801,7 +1822,7 @@ ScreenRenderFlags EmuScreen::render(ScreenRenderMode mode) { if (hasVisibleUI()) { draw->SetViewport(viewport); - cardboardDisableButton_->SetVisibility(g_Config.bEnableCardboardVR ? UI::V_VISIBLE : UI::V_GONE); + cardboardDisableButton_->SetVisibility(displayLayoutConfig.bEnableCardboardVR ? UI::V_VISIBLE : UI::V_GONE); renderUI(); } @@ -1907,7 +1928,8 @@ bool EmuScreen::hasVisibleUI() { return true; if (!g_OSD.IsEmpty() || g_Config.bShowTouchControls || g_Config.iShowStatusFlags != 0) return true; - if (g_Config.bEnableCardboardVR || g_Config.bEnableNetworkChat) + DisplayLayoutConfig &config = g_Config.GetDisplayLayoutConfig(GetDeviceOrientation()); + if (config.bEnableCardboardVR || g_Config.bEnableNetworkChat) return true; if (g_Config.bShowGPOLEDs) return true; diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index aa49f7957d..49f66e84cc 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -580,21 +580,22 @@ void GameSettingsScreen::CreateGraphicsSettings(UI::ViewGroup *graphicsSettings) CheckBox *smartFiltering = graphicsSettings->Add(new CheckBox(&g_Config.bSmart2DTexFiltering, gr->T("Smart 2D texture filtering"))); smartFiltering->SetDisabledPtr(&g_Config.bSoftwareRendering); + DisplayLayoutConfig &config = g_Config.GetDisplayLayoutConfig(GetDeviceOrientation()); #if PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(IOS) bool showCardboardSettings = deviceType != DEVICE_TYPE_VR; #else // If you enabled it through the ini, you can see this. Useful for testing. - bool showCardboardSettings = g_Config.bEnableCardboardVR; + bool showCardboardSettings = config.bEnableCardboardVR; #endif if (showCardboardSettings) { graphicsSettings->Add(new ItemHeader(gr->T("Cardboard VR Settings", "Cardboard VR Settings"))); - graphicsSettings->Add(new CheckBox(&g_Config.bEnableCardboardVR, gr->T("Enable Cardboard VR", "Enable Cardboard VR"))); - PopupSliderChoice *cardboardScreenSize = graphicsSettings->Add(new PopupSliderChoice(&g_Config.iCardboardScreenSize, 30, 150, 50, gr->T("Cardboard Screen Size", "Screen Size (in % of the viewport)"), 1, screenManager(), gr->T("% of viewport"))); - cardboardScreenSize->SetEnabledPtr(&g_Config.bEnableCardboardVR); - PopupSliderChoice *cardboardXShift = graphicsSettings->Add(new PopupSliderChoice(&g_Config.iCardboardXShift, -150, 150, 0, gr->T("Cardboard Screen X Shift", "X Shift (in % of the void)"), 1, screenManager(), gr->T("% of the void"))); - cardboardXShift->SetEnabledPtr(&g_Config.bEnableCardboardVR); - PopupSliderChoice *cardboardYShift = graphicsSettings->Add(new PopupSliderChoice(&g_Config.iCardboardYShift, -100, 100, 0, gr->T("Cardboard Screen Y Shift", "Y Shift (in % of the void)"), 1, screenManager(), gr->T("% of the void"))); - cardboardYShift->SetEnabledPtr(&g_Config.bEnableCardboardVR); + graphicsSettings->Add(new CheckBox(&config.bEnableCardboardVR, gr->T("Enable Cardboard VR", "Enable Cardboard VR"))); + PopupSliderChoice *cardboardScreenSize = graphicsSettings->Add(new PopupSliderChoice(&config.iCardboardScreenSize, 30, 150, 50, gr->T("Cardboard Screen Size", "Screen Size (in % of the viewport)"), 1, screenManager(), gr->T("% of viewport"))); + cardboardScreenSize->SetEnabledPtr(&config.bEnableCardboardVR); + PopupSliderChoice *cardboardXShift = graphicsSettings->Add(new PopupSliderChoice(&config.iCardboardXShift, -150, 150, 0, gr->T("Cardboard Screen X Shift", "X Shift (in % of the void)"), 1, screenManager(), gr->T("% of the void"))); + cardboardXShift->SetEnabledPtr(&config.bEnableCardboardVR); + PopupSliderChoice *cardboardYShift = graphicsSettings->Add(new PopupSliderChoice(&config.iCardboardYShift, -100, 100, 0, gr->T("Cardboard Screen Y Shift", "Y Shift (in % of the void)"), 1, screenManager(), gr->T("% of the void"))); + cardboardYShift->SetEnabledPtr(&config.bEnableCardboardVR); } std::vector cameraList = Camera::getDeviceList(); diff --git a/UI/IAPScreen.cpp b/UI/IAPScreen.cpp index d9ed734045..40f0d0ed66 100644 --- a/UI/IAPScreen.cpp +++ b/UI/IAPScreen.cpp @@ -15,7 +15,7 @@ void IAPScreen::CreateViews() { auto di = GetI18NCategory(I18NCat::DIALOG); auto mm = GetI18NCategory(I18NCat::MAINMENU); - const bool vertical = UsePortraitLayout(); + const bool vertical = GetDeviceOrientation() == DeviceOrientation::Portrait; root_ = new LinearLayout(vertical ? ORIENT_VERTICAL : ORIENT_HORIZONTAL, new LayoutParams(FILL_PARENT, FILL_PARENT)); diff --git a/UI/MainScreen.cpp b/UI/MainScreen.cpp index dc31c9c0d6..52d7c7e616 100644 --- a/UI/MainScreen.cpp +++ b/UI/MainScreen.cpp @@ -1213,7 +1213,7 @@ void MainScreen::CreateViews() { // Scrolling action menu to the right. using namespace UI; - const bool vertical = UsePortraitLayout(); + const bool vertical = GetDeviceOrientation() == DeviceOrientation::Portrait; auto mm = GetI18NCategory(I18NCat::MAINMENU); diff --git a/UI/MiscScreens.cpp b/UI/MiscScreens.cpp index 6dab5fbc3a..c74db93103 100644 --- a/UI/MiscScreens.cpp +++ b/UI/MiscScreens.cpp @@ -169,7 +169,7 @@ void PromptScreen::CreateViews() { // Scrolling action menu to the right. using namespace UI; - const bool portrait = UsePortraitLayout(); + const bool portrait = GetDeviceOrientation() == DeviceOrientation::Portrait; root_ = new AnchorLayout(); ViewGroup *rightColumnItems; @@ -518,7 +518,7 @@ void CreditsScreen::CreateDialogViews(UI::ViewGroup *root) { auto cr = GetI18NCategory(I18NCat::PSPCREDITS); auto mm = GetI18NCategory(I18NCat::MAINMENU); - const bool portrait = UsePortraitLayout(); + const bool portrait = GetDeviceOrientation() == DeviceOrientation::Portrait; const bool gold = System_GetPropertyBool(SYSPROP_APP_GOLD); diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index bde1e425cf..66221e4ff1 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -1293,7 +1293,8 @@ bool HandleGlobalMessage(UIMessage message, const std::string &value) { } else if (message == UIMessage::GPU_RENDER_RESIZED) { if (gpu) { - gpu->NotifyRenderResized(); + DisplayLayoutConfig &config = g_Config.GetDisplayLayoutConfig(g_display.GetDeviceOrientation()); + gpu->NotifyRenderResized(config); } return true; } @@ -1647,7 +1648,8 @@ static bool IsWindowSmall(int pixelWidth, int pixelHeight) { // Can't take this from config as it will not be set if windows is maximized. int w = (int)(pixelWidth * g_display.dpi_scale_real_x); int h = (int)(pixelHeight * g_display.dpi_scale_real_y); - return g_Config.IsPortrait() ? (h < 480 + 80) : (w < 480 + 80); + DisplayLayoutConfig &config = g_Config.GetDisplayLayoutConfig(g_display.GetDeviceOrientation()); + return config.InternalRotationIsPortrait() ? (h < 480 + 80) : (w < 480 + 80); } bool Native_UpdateScreenScale(int pixel_width, int pixel_height, float customScale) { diff --git a/UI/OnScreenDisplay.cpp b/UI/OnScreenDisplay.cpp index 84a47b7e65..b79ae0b949 100644 --- a/UI/OnScreenDisplay.cpp +++ b/UI/OnScreenDisplay.cpp @@ -563,10 +563,10 @@ void OSDOverlayScreen::DrawForeground(UIContext &ui) { void OSDOverlayScreen::update() { // Partial version of UIScreen::update() but doesn't do event processing to avoid duplicate event processing. - bool portrait = UsePortraitLayout(); - if (portrait != lastPortrait_) { + DeviceOrientation orientation = GetDeviceOrientation(); + if (orientation != lastOrientation_) { RecreateViews(); - lastPortrait_ = portrait; + lastOrientation_ = orientation; } DoRecreateViews(); diff --git a/UI/PauseScreen.cpp b/UI/PauseScreen.cpp index cacc13b79a..6e244c2638 100644 --- a/UI/PauseScreen.cpp +++ b/UI/PauseScreen.cpp @@ -403,7 +403,7 @@ UI::Margins GamePauseScreen::RootMargins() const { void GamePauseScreen::CreateViews() { using namespace UI; - bool portrait = UsePortraitLayout(); + bool portrait = GetDeviceOrientation() == DeviceOrientation::Portrait; Margins scrollMargins(0, 10, 0, 0); Margins actionMenuMargins(0, 10, 15, 0); diff --git a/UI/RemoteISOScreen.cpp b/UI/RemoteISOScreen.cpp index e81b66eb96..654fe6b24d 100644 --- a/UI/RemoteISOScreen.cpp +++ b/UI/RemoteISOScreen.cpp @@ -592,7 +592,7 @@ void RemoteISOBrowseScreen::CreateViews() { auto di = GetI18NCategory(I18NCat::DIALOG); auto ri = GetI18NCategory(I18NCat::REMOTEISO); - bool portrait = UsePortraitLayout(); + bool portrait = GetDeviceOrientation() == DeviceOrientation::Portrait; using namespace UI; diff --git a/UI/SavedataScreen.cpp b/UI/SavedataScreen.cpp index ca0316054d..f0a5970b28 100644 --- a/UI/SavedataScreen.cpp +++ b/UI/SavedataScreen.cpp @@ -674,7 +674,7 @@ void SavedataScreen::CreateExtraButtons(UI::LinearLayout *verticalLayout, int ma using namespace UI; if (System_GetPropertyBool(SYSPROP_HAS_TEXT_INPUT_DIALOG)) { auto di = GetI18NCategory(I18NCat::DIALOG); - verticalLayout->Add(new Choice(di->T("Search"), "", false, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, 0.0f, Margins(0, 0, margins, margins)))) + verticalLayout->Add(new Choice(di->T("Search"), ImageID("I_SEARCH"), new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, 0.0f, Margins(0, 0, margins, margins)))) ->OnClick.Handle(this, &SavedataScreen::OnSearch); } } diff --git a/UI/SimpleDialogScreen.cpp b/UI/SimpleDialogScreen.cpp index a019a7fec2..de99343d50 100644 --- a/UI/SimpleDialogScreen.cpp +++ b/UI/SimpleDialogScreen.cpp @@ -9,7 +9,7 @@ void UISimpleBaseDialogScreen::CreateViews() { const bool canScroll = CanScroll(); ignoreBottomInset_ = canScroll; - const bool portrait = UsePortraitLayout(); + const bool portrait = GetDeviceOrientation() == DeviceOrientation::Portrait; root_ = new LinearLayout(ORIENT_VERTICAL, new LayoutParams(FILL_PARENT, FILL_PARENT)); root_->Add(new TopBar(*screenManager()->getUIContext(), portrait, GetTitle())); @@ -29,7 +29,7 @@ void UISimpleBaseDialogScreen::CreateViews() { void UITwoPaneBaseDialogScreen::CreateViews() { using namespace UI; - const bool portrait = UsePortraitLayout(); + const bool portrait = GetDeviceOrientation() == DeviceOrientation::Portrait; auto di = GetI18NCategory(I18NCat::DIALOG); diff --git a/UI/TabbedDialogScreen.cpp b/UI/TabbedDialogScreen.cpp index f63bfb9d1e..5a30dee559 100644 --- a/UI/TabbedDialogScreen.cpp +++ b/UI/TabbedDialogScreen.cpp @@ -37,7 +37,7 @@ void UITabbedBaseDialogScreen::AddTab(const char *tag, std::string_view title, s void UITabbedBaseDialogScreen::CreateViews() { PreCreateViews(); - bool portrait = UsePortraitLayout() || ForceHorizontalTabs(); + bool portrait = GetDeviceOrientation() == DeviceOrientation::Portrait || ForceHorizontalTabs(); // Information in the top left. // Back button to the bottom left. diff --git a/UI/TouchControlVisibilityScreen.cpp b/UI/TouchControlVisibilityScreen.cpp index cbd83e322a..f9c7355364 100644 --- a/UI/TouchControlVisibilityScreen.cpp +++ b/UI/TouchControlVisibilityScreen.cpp @@ -61,7 +61,7 @@ void TouchControlVisibilityScreen::CreateVisibilityTab(UI::LinearLayout *vert) { auto di = GetI18NCategory(I18NCat::DIALOG); auto co = GetI18NCategory(I18NCat::CONTROLS); - const bool portrait = UsePortraitLayout(); + const bool portrait = GetDeviceOrientation() == DeviceOrientation::Portrait; Choice *toggleAll = new Choice(di->T("Toggle All"), "", false, new AnchorLayoutParams(leftColumnWidth - 10, WRAP_CONTENT, 10, NONE, NONE, 84)); diff --git a/UI/UIAtlas.cpp b/UI/UIAtlas.cpp index 68f0b0d761..1d53c8b9fa 100644 --- a/UI/UIAtlas.cpp +++ b/UI/UIAtlas.cpp @@ -149,6 +149,7 @@ static const ImageMeta imageIDs[] = { {"I_SHARE", false}, {"I_LOGO_PLAY_STORE", false}, {"I_LOGO_APP_STORE", false}, + {"I_SEARCH", false}, }; static std::string PNGNameFromID(std::string_view id) { diff --git a/Windows/MainWindow.cpp b/Windows/MainWindow.cpp index cd1b2f8775..deb672e8eb 100644 --- a/Windows/MainWindow.cpp +++ b/Windows/MainWindow.cpp @@ -211,7 +211,8 @@ namespace MainWindow AssertCurrentThreadName("Main"); // Actually, auto mode should be more granular... int width, height; - if (g_Config.IsPortrait()) { + const DisplayLayoutConfig &config = g_Config.GetDisplayLayoutConfig(g_display.GetDeviceOrientation()); + if (config.InternalRotationIsPortrait()) { GetWindowSizeAtResolution(272 * (int)zoom, 480 * (int)zoom, &width, &height); } else { GetWindowSizeAtResolution(480 * (int)zoom, 272 * (int)zoom, &width, &height); @@ -416,7 +417,8 @@ namespace MainWindow // First, get the w/h right. if (windowWidth <= 0 || windowHeight <= 0) { - bool portrait = g_Config.IsPortrait(); + DisplayLayoutConfig &config = g_Config.GetDisplayLayoutConfig(g_display.GetDeviceOrientation()); + const bool portrait = config.InternalRotationIsPortrait(); // We want to adjust for DPI but still get an integer pixel scaling ratio. double dpi_scale = 96.0 / System_GetPropertyFloat(SYSPROP_DISPLAY_DPI); @@ -763,7 +765,8 @@ namespace MainWindow { MINMAXINFO *minmax = reinterpret_cast(lParam); RECT rc = { 0 }; - bool portrait = g_Config.IsPortrait(); + const DisplayLayoutConfig &config = g_Config.GetDisplayLayoutConfig(g_display.GetDeviceOrientation()); + bool portrait = config.InternalRotationIsPortrait(); rc.right = portrait ? 272 : 480; rc.bottom = portrait ? 480 : 272; AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, TRUE); diff --git a/Windows/MainWindowMenu.cpp b/Windows/MainWindowMenu.cpp index 57da2d13f0..691136ceb7 100644 --- a/Windows/MainWindowMenu.cpp +++ b/Windows/MainWindowMenu.cpp @@ -17,6 +17,7 @@ #include "Common/System/OSD.h" #include "Common/System/NativeApp.h" #include "Common/System/Request.h" +#include "Common/System/Display.h" #include "Common/File/FileUtil.h" #include "Common/Log.h" #include "Common/Log/LogManager.h" @@ -510,10 +511,30 @@ namespace MainWindow { UmdSwitchAction(NON_EPHEMERAL_TOKEN); break; - case ID_EMULATION_ROTATION_H: g_Config.iInternalScreenRotation = ROTATION_LOCKED_HORIZONTAL; break; - case ID_EMULATION_ROTATION_V: g_Config.iInternalScreenRotation = ROTATION_LOCKED_VERTICAL; break; - case ID_EMULATION_ROTATION_H_R: g_Config.iInternalScreenRotation = ROTATION_LOCKED_HORIZONTAL180; break; - case ID_EMULATION_ROTATION_V_R: g_Config.iInternalScreenRotation = ROTATION_LOCKED_VERTICAL180; break; + case ID_EMULATION_ROTATION_H: + { + DisplayLayoutConfig &displayLayoutConfig = g_Config.GetDisplayLayoutConfig(g_display.GetDeviceOrientation()); + displayLayoutConfig.iInternalScreenRotation = ROTATION_LOCKED_HORIZONTAL; + break; + } + case ID_EMULATION_ROTATION_V: + { + DisplayLayoutConfig &displayLayoutConfig = g_Config.GetDisplayLayoutConfig(g_display.GetDeviceOrientation()); + displayLayoutConfig.iInternalScreenRotation = ROTATION_LOCKED_VERTICAL; + break; + } + case ID_EMULATION_ROTATION_H_R: + { + DisplayLayoutConfig &displayLayoutConfig = g_Config.GetDisplayLayoutConfig(g_display.GetDeviceOrientation()); + displayLayoutConfig.iInternalScreenRotation = ROTATION_LOCKED_HORIZONTAL180; + break; + } + case ID_EMULATION_ROTATION_V_R: + { + DisplayLayoutConfig &displayLayoutConfig = g_Config.GetDisplayLayoutConfig(g_display.GetDeviceOrientation()); + displayLayoutConfig.iInternalScreenRotation = ROTATION_LOCKED_VERTICAL180; + break; + } case ID_EMULATION_CHEATS: g_Config.bEnableCheats = !g_Config.bEnableCheats; @@ -872,8 +893,18 @@ namespace MainWindow { case ID_OPTIONS_SMART2DTEXTUREFILTERING: g_Config.bSmart2DTexFiltering = !g_Config.bSmart2DTexFiltering; break; - case ID_OPTIONS_BUFLINEARFILTER: g_Config.iDisplayFilter = SCALE_LINEAR; break; - case ID_OPTIONS_BUFNEARESTFILTER: g_Config.iDisplayFilter = SCALE_NEAREST; break; + case ID_OPTIONS_BUFLINEARFILTER: + { + DisplayLayoutConfig &displayLayoutConfig = g_Config.GetDisplayLayoutConfig(g_display.GetDeviceOrientation()); + displayLayoutConfig.iDisplayFilter = SCALE_LINEAR; + break; + } + case ID_OPTIONS_BUFNEARESTFILTER: + { + DisplayLayoutConfig &displayLayoutConfig = g_Config.GetDisplayLayoutConfig(g_display.GetDeviceOrientation()); + displayLayoutConfig.iDisplayFilter = SCALE_NEAREST; + break; + } case ID_OPTIONS_TOPMOST: g_Config.bTopMost = !g_Config.bTopMost; @@ -1021,14 +1052,17 @@ namespace MainWindow { ID_EMULATION_ROTATION_H_R, ID_EMULATION_ROTATION_V_R }; - if (g_Config.iInternalScreenRotation < ROTATION_LOCKED_HORIZONTAL) - g_Config.iInternalScreenRotation = ROTATION_LOCKED_HORIZONTAL; - else if (g_Config.iInternalScreenRotation > ROTATION_LOCKED_VERTICAL180) - g_Config.iInternalScreenRotation = ROTATION_LOCKED_VERTICAL180; + DisplayLayoutConfig &displayLayoutConfig = g_Config.GetDisplayLayoutConfig(g_display.GetDeviceOrientation()); + + if (displayLayoutConfig.iInternalScreenRotation < ROTATION_LOCKED_HORIZONTAL) + displayLayoutConfig.iInternalScreenRotation = ROTATION_LOCKED_HORIZONTAL; + + else if (displayLayoutConfig.iInternalScreenRotation > ROTATION_LOCKED_VERTICAL180) + displayLayoutConfig.iInternalScreenRotation = ROTATION_LOCKED_VERTICAL180; for (int i = 0; i < ARRAY_SIZE(displayrotationitems); i++) { - CheckMenuItem(menu, displayrotationitems[i], MF_BYCOMMAND | ((i + 1) == g_Config.iInternalScreenRotation ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, displayrotationitems[i], MF_BYCOMMAND | ((i + 1) == displayLayoutConfig.iInternalScreenRotation ? MF_CHECKED : MF_UNCHECKED)); } static const int zoomitems[11] = { @@ -1070,8 +1104,8 @@ namespace MainWindow { RECT rc; GetClientRect(GetHWND(), &rc); - int checkW = g_Config.IsPortrait() ? 272 : 480; - int checkH = g_Config.IsPortrait() ? 480 : 272; + int checkW = displayLayoutConfig.InternalRotationIsPortrait() ? 272 : 480; + int checkH = displayLayoutConfig.InternalRotationIsPortrait() ? 480 : 272; for (int i = 0; i < ARRAY_SIZE(windowSizeItems); i++) { bool check = (i + 1) * checkW == rc.right - rc.left || (i + 1) * checkH == rc.bottom - rc.top; @@ -1140,14 +1174,14 @@ namespace MainWindow { ID_OPTIONS_BUFLINEARFILTER, ID_OPTIONS_BUFNEARESTFILTER, }; - if (g_Config.iDisplayFilter < SCALE_LINEAR) - g_Config.iDisplayFilter = SCALE_LINEAR; + if (displayLayoutConfig.iDisplayFilter < SCALE_LINEAR) + displayLayoutConfig.iDisplayFilter = SCALE_LINEAR; - else if (g_Config.iDisplayFilter > SCALE_NEAREST) - g_Config.iDisplayFilter = SCALE_NEAREST; + else if (displayLayoutConfig.iDisplayFilter > SCALE_NEAREST) + displayLayoutConfig.iDisplayFilter = SCALE_NEAREST; for (int i = 0; i < ARRAY_SIZE(bufferfilteritems); i++) { - CheckMenuItem(menu, bufferfilteritems[i], MF_BYCOMMAND | ((i + 1) == g_Config.iDisplayFilter ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, bufferfilteritems[i], MF_BYCOMMAND | ((i + 1) == displayLayoutConfig.iDisplayFilter ? MF_CHECKED : MF_UNCHECKED)); } static const int frameskipping[] = { diff --git a/assets/ui_images/images.svg b/assets/ui_images/images.svg index 681ae723f1..a5dddc85b1 100644 --- a/assets/ui_images/images.svg +++ b/assets/ui_images/images.svg @@ -4193,7 +4193,7 @@ sodipodi:nodetypes="cccccssssccssssccc" />BeginHostFrame(); + gpu->BeginHostFrame(g_Config.GetDisplayLayoutConfig(DeviceOrientation::Landscape)); } Draw::DrawContext *draw = coreParameter.graphicsContext ? coreParameter.graphicsContext->GetDrawContext() : nullptr; if (draw) { @@ -268,7 +268,7 @@ bool RunAutoTest(HeadlessHost *headlessHost, CoreParameter &coreParameter, const draw->BindFramebufferAsRenderTarget(nullptr, { Draw::RPAction::CLEAR, Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE }, "Headless"); // Vulkan may get angry if we don't do a final present. if (gpu) - gpu->CopyDisplayToOutput(true); + gpu->CopyDisplayToOutput(g_Config.GetDisplayLayoutConfig(DeviceOrientation::Landscape), true); draw->EndFrame(); } diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index 7550033b38..ee175cf4da 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -1139,7 +1139,8 @@ static void check_variables(CoreParameter &coreParam) { if (gpu) { - gpu->NotifyRenderResized(); + const DisplayLayoutConfig &config = g_Config.GetDisplayLayoutConfig(g_display.GetDeviceOrientation()); + gpu->NotifyRenderResized(config); } } @@ -1359,8 +1360,10 @@ namespace Libretro ctx->GetDrawContext()->BeginFrame(Draw::DebugFlags::NONE); } - if (gpu) - gpu->BeginHostFrame(); + if (gpu) { + const DisplayLayoutConfig &config = g_Config.GetDisplayLayoutConfig(g_display.GetDeviceOrientation()); + gpu->BeginHostFrame(config); + } PSP_RunLoopWhileState(); switch (coreState) { @@ -1693,6 +1696,9 @@ void retro_run(void) // shouldn't happen. _dbg_assert_(false); return; + case BootState::Complete: + // done, continue. + break; } // BootState is BootState::Complete.