From 34e779a654ce1f85a46a88accbb94023aaf2d657 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Sat, 24 Jul 2021 22:19:50 +1000 Subject: [PATCH] GS: Manage draw rectangle in GS instead of wx --- pcsx2/GS/GS.cpp | 20 ++++-- pcsx2/GS/GS.h | 3 +- pcsx2/GS/Renderers/Common/GSRenderer.cpp | 83 +++++++++++++++++++++--- pcsx2/GS/Renderers/Common/GSRenderer.h | 8 ++- pcsx2/gui/AppMain.cpp | 22 +------ pcsx2/gui/FrameForGS.cpp | 79 ++-------------------- pcsx2/gui/GSFrame.h | 1 - pcsx2/gui/GlobalCommands.cpp | 24 ++----- 8 files changed, 107 insertions(+), 133 deletions(-) diff --git a/pcsx2/GS/GS.cpp b/pcsx2/GS/GS.cpp index a728052b00..307b72b370 100644 --- a/pcsx2/GS/GS.cpp +++ b/pcsx2/GS/GS.cpp @@ -419,9 +419,6 @@ int GSopen2(void** dsp, uint32 flags) int retval = _GSopen(dsp, "", current_renderer); - if (s_gs != NULL) - s_gs->SetAspectRatio(0); // PCSX2 manages the aspect ratios - gsopen_done = true; return retval; @@ -866,6 +863,19 @@ void GSsetExclusive(int enabled) } } +bool GSGetFMVSwitch() +{ + return s_gs ? s_gs->GetFMVSwitch() : false; +} + +void GSSetFMVSwitch(bool enabled) +{ + if (s_gs) + { + s_gs->SetFMVSwitch(enabled); + } +} + #if defined(__unix__) || defined(__APPLE__) inline unsigned long timeGetTime() @@ -1511,10 +1521,6 @@ void GSApp::Init() m_gs_interlace.push_back(GSSetting(6, "Blend bff", "slight blur, 1/2 fps")); m_gs_interlace.push_back(GSSetting(7, "Automatic", "Default")); - m_gs_aspectratio.push_back(GSSetting(0, "Stretch", "")); - m_gs_aspectratio.push_back(GSSetting(1, "4:3", "")); - m_gs_aspectratio.push_back(GSSetting(2, "16:9", "")); - m_gs_upscale_multiplier.push_back(GSSetting(1, "Native", "PS2")); m_gs_upscale_multiplier.push_back(GSSetting(2, "2x Native", "~720p")); m_gs_upscale_multiplier.push_back(GSSetting(3, "3x Native", "~1080p")); diff --git a/pcsx2/GS/GS.h b/pcsx2/GS/GS.h index 7abda193d2..53d39b46cd 100644 --- a/pcsx2/GS/GS.h +++ b/pcsx2/GS/GS.h @@ -1817,6 +1817,8 @@ void GSgetTitleInfo2(char* dest, size_t length); void GSsetFrameSkip(int frameskip); void GSsetVsync(int vsync); void GSsetExclusive(int enabled); +bool GSGetFMVSwitch(); +void GSSetFMVSwitch(bool enabled); class GSApp { @@ -1871,7 +1873,6 @@ public: std::vector m_gs_renderers; std::vector m_gs_interlace; - std::vector m_gs_aspectratio; std::vector m_gs_upscale_multiplier; std::vector m_gs_max_anisotropy; std::vector m_gs_dithering; diff --git a/pcsx2/GS/Renderers/Common/GSRenderer.cpp b/pcsx2/GS/Renderers/Common/GSRenderer.cpp index ca9f9f3d71..7b05030095 100644 --- a/pcsx2/GS/Renderers/Common/GSRenderer.cpp +++ b/pcsx2/GS/Renderers/Common/GSRenderer.cpp @@ -15,13 +15,13 @@ #include "PrecompiledHeader.h" #include "GSRenderer.h" +#include "gui/AppConfig.h" #if defined(__unix__) #include #endif const unsigned int s_interlace_nb = 8; const unsigned int s_post_shader_nb = 5; -const unsigned int s_aspect_ratio_nb = 3; const unsigned int s_mipmap_nb = 3; GSRenderer::GSRenderer() @@ -29,6 +29,7 @@ GSRenderer::GSRenderer() , m_shift_key(false) , m_control_key(false) , m_texture_shuffle(false) + , m_fmv_switch(false) , m_real_size(0, 0) , m_wnd() , m_dev(NULL) @@ -36,7 +37,6 @@ GSRenderer::GSRenderer() m_GStitleInfoBuffer[0] = 0; m_interlace = theApp.GetConfigI("interlace") % s_interlace_nb; - m_aspectratio = theApp.GetConfigI("AspectRatio") % s_aspect_ratio_nb; m_shader = theApp.GetConfigI("TVShader") % s_post_shader_nb; m_vsync = theApp.GetConfigI("vsync"); m_aa1 = theApp.GetConfigB("aa1"); @@ -304,6 +304,73 @@ GSVector2i GSRenderer::GetInternalResolution() return m_real_size; } +GSVector4i GSRenderer::ComputeDrawRectangle(int width, int height) const +{ + const double f_width = static_cast(width); + const double f_height = static_cast(height); + const double clientAr = f_width / f_height; + + double targetAr = clientAr; + + if (m_fmv_switch) + { + if (g_Conf->GSWindow.FMVAspectRatioSwitch == FMV_AspectRatio_Switch_4_3) + { + targetAr = 4.0 / 3.0; + } + else if (g_Conf->GSWindow.FMVAspectRatioSwitch == FMV_AspectRatio_Switch_16_9) + { + targetAr = 16.0 / 9.0; + } + } + else + { + if (g_Conf->GSWindow.AspectRatio == AspectRatio_4_3) + { + targetAr = 4.0 / 3.0; + } + else if (g_Conf->GSWindow.AspectRatio == AspectRatio_16_9) + { + targetAr = 16.0 / 9.0; + } + } + + const double arr = targetAr / clientAr; + double target_width = f_width; + double target_height = f_height; + if (arr < 1) + target_width = std::floor(f_width * arr + 0.5); + else if (arr > 1) + target_height = std::floor(f_height / arr + 0.5); + + float zoom = g_Conf->GSWindow.Zoom.ToFloat() / 100.0; + if (zoom == 0) //auto zoom in untill black-bars are gone (while keeping the aspect ratio). + zoom = std::max((float)arr, (float)(1.0 / arr)); + + target_width *= zoom; + target_height *= zoom * g_Conf->GSWindow.StretchY.ToFloat() / 100.0; + + double target_x, target_y; + if (target_width > f_width) + target_x = -((target_width - f_width) * 0.5); + else + target_x = (f_width - target_width) * 0.5; + if (target_height > f_height) + target_y = -((target_height - f_height) * 0.5); + else + target_y = (f_height - target_height) * 0.5; + + const double unit = .01 * std::min(target_x, target_y); + target_x += unit * g_Conf->GSWindow.OffsetX.ToFloat(); + target_y += unit * g_Conf->GSWindow.OffsetY.ToFloat(); + + return GSVector4i( + static_cast(std::floor(target_x)), + static_cast(std::floor(target_y)), + static_cast(std::round(target_x + target_width)), + static_cast(std::round(target_y + target_height))); +} + void GSRenderer::SetVSync(int vsync) { m_vsync = vsync; @@ -356,6 +423,7 @@ void GSRenderer::VSync(int field) #endif { //GS owns the window's title, be verbose. + static const char* aspect_ratio_names[AspectRatio_MaxCount] = { "Stretch", "4:3", "16:9" }; std::string s2 = m_regs->SMODE2.INT ? (std::string("Interlaced ") + (m_regs->SMODE2.FFMD ? "(frame)" : "(field)")) : "Progressive"; @@ -364,7 +432,7 @@ void GSRenderer::VSync(int field) m_perfmon.GetFrame(), GetInternalResolution().x, GetInternalResolution().y, fps, (int)(100.0 * fps / GetTvRefreshRate()), s2.c_str(), theApp.m_gs_interlace[m_interlace].name.c_str(), - theApp.m_gs_aspectratio[m_aspectratio].name.c_str(), + aspect_ratio_names[g_Conf->GSWindow.AspectRatio], (int)m_perfmon.Get(GSPerfMon::SyncPoint), (int)m_perfmon.Get(GSPerfMon::Prim), (int)m_perfmon.Get(GSPerfMon::Draw), @@ -438,7 +506,7 @@ void GSRenderer::VSync(int field) m_dev->m_osd.m_real_size.x = window_size.v[2]; m_dev->m_osd.m_real_size.y = window_size.v[3]; - m_dev->Present(m_wnd->GetClientRect().fit(m_aspectratio), m_shader); + m_dev->Present(ComputeDrawRectangle(window_size.z, window_size.w), m_shader); // snapshot @@ -534,7 +602,8 @@ bool GSRenderer::MakeSnapshot(const std::string& path) bool GSRenderer::BeginCapture(std::string& filename) { - GSVector4i disp = m_wnd->GetClientRect().fit(m_aspectratio); + const GSVector4i crect(m_wnd->GetClientRect()); + GSVector4i disp = ComputeDrawRectangle(crect.z, crect.w); float aspect = (float)disp.width() / std::max(1, disp.height()); return m_capture.BeginCapture(GetTvRefreshRate(), GetInternalResolution(), aspect, filename); @@ -587,10 +656,6 @@ void GSRenderer::KeyEvent(GSKeyEventData* e) theApp.SetConfig("interlace", m_interlace); printf("GS: Set deinterlace mode to %d (%s).\n", m_interlace, theApp.m_gs_interlace.at(m_interlace).name.c_str()); return; - case VK_F6: - if (m_wnd->IsManaged()) - m_aspectratio = (m_aspectratio + s_aspect_ratio_nb + step) % s_aspect_ratio_nb; - return; case VK_DELETE: m_aa1 = !m_aa1; theApp.SetConfig("aa1", m_aa1); diff --git a/pcsx2/GS/Renderers/Common/GSRenderer.h b/pcsx2/GS/Renderers/Common/GSRenderer.h index e12853e659..a2ecc5b6a1 100644 --- a/pcsx2/GS/Renderers/Common/GSRenderer.h +++ b/pcsx2/GS/Renderers/Common/GSRenderer.h @@ -34,13 +34,13 @@ class GSRenderer : public GSState protected: int m_dithering; int m_interlace; - int m_aspectratio; int m_vsync; bool m_aa1; bool m_shaderfx; bool m_fxaa; bool m_shadeboost; bool m_texture_shuffle; + bool m_fmv_switch; GSVector2i m_real_size; virtual GSTexture* GetOutput(int i, int& y_offset) = 0; @@ -63,14 +63,18 @@ public: virtual int GetUpscaleMultiplier() { return 1; } virtual GSVector2i GetCustomResolution() { return GSVector2i(0, 0); } GSVector2i GetInternalResolution(); - void SetAspectRatio(int aspect) { m_aspectratio = aspect; } void SetVSync(int vsync); + __fi bool GetFMVSwitch() const { return m_fmv_switch; } + __fi void SetFMVSwitch(bool enabled) { m_fmv_switch = enabled; } + virtual bool BeginCapture(std::string& filename); virtual void EndCapture(); void PurgePool(); + GSVector4i ComputeDrawRectangle(int width, int height) const; + public: std::mutex m_pGSsetTitle_Crit; diff --git a/pcsx2/gui/AppMain.cpp b/pcsx2/gui/AppMain.cpp index 0c6f2945bd..bc8896e875 100644 --- a/pcsx2/gui/AppMain.cpp +++ b/pcsx2/gui/AppMain.cpp @@ -71,9 +71,6 @@ wxIMPLEMENT_APP(Pcsx2App); std::unique_ptr g_Conf; -AspectRatioType iniAR; -bool switchAR; - uptr pDsp[2]; // Returns a string message telling the user to consult guides for obtaining a legal BIOS. @@ -451,21 +448,6 @@ extern bool FMVstarted; extern bool EnableFMV; extern bool renderswitch; -void DoFmvSwitch(bool on) -{ - if (g_Conf->GSWindow.FMVAspectRatioSwitch != FMV_AspectRatio_Switch_Off) { - if (on) { - switchAR = true; - iniAR = g_Conf->GSWindow.AspectRatio; - } else { - switchAR = false; - } - if (GSFrame* gsFrame = wxGetApp().GetGsFramePtr()) - if (GSPanel* viewport = gsFrame->GetViewport()) - viewport->DoResize(); - } -} - void Pcsx2App::LogicalVsync() { if( AppRpc_TryInvokeAsync( &Pcsx2App::LogicalVsync ) ) return; @@ -479,7 +461,7 @@ void Pcsx2App::LogicalVsync() if (g_Conf->GSWindow.FMVAspectRatioSwitch != FMV_AspectRatio_Switch_Off) { if (EnableFMV) { DevCon.Warning("FMV on"); - DoFmvSwitch(true); + GSSetFMVSwitch(true); EnableFMV = false; } @@ -487,7 +469,7 @@ void Pcsx2App::LogicalVsync() int diff = cpuRegs.cycle - eecount_on_last_vdec; if (diff > 60000000 ) { DevCon.Warning("FMV off"); - DoFmvSwitch(false); + GSSetFMVSwitch(false); FMVstarted = false; } } diff --git a/pcsx2/gui/FrameForGS.cpp b/pcsx2/gui/FrameForGS.cpp index 3a01ab417b..21012c0a29 100644 --- a/pcsx2/gui/FrameForGS.cpp +++ b/pcsx2/gui/FrameForGS.cpp @@ -243,72 +243,11 @@ void GSPanel::DoShowMouse() m_HideMouseTimer.Start( 1750, true ); } -void GSPanel::DoResize() -{ - if( GetParent() == NULL ) return; - wxSize client = GetParent()->GetClientSize(); - wxSize viewport = client; - - if ( !client.GetHeight() || !client.GetWidth() ) - return; - - double clientAr = (double)client.GetWidth()/(double)client.GetHeight(); - - extern AspectRatioType iniAR; - extern bool switchAR; - double targetAr = clientAr; - - if (g_Conf->GSWindow.AspectRatio != iniAR) { - switchAR = false; - } - - if (switchAR) { - if (g_Conf->GSWindow.FMVAspectRatioSwitch == FMV_AspectRatio_Switch_4_3) { - targetAr = 4.0 / 3.0; - } else if (g_Conf->GSWindow.FMVAspectRatioSwitch == FMV_AspectRatio_Switch_16_9) { - targetAr = 16.0 / 9.0; - } else { - // Allows for better real time toggling, returns to the non fmv override aspect ratio. - switchAR = false; - } - } else { - if (g_Conf->GSWindow.AspectRatio == AspectRatio_4_3) { - targetAr = 4.0 / 3.0; - } else if (g_Conf->GSWindow.AspectRatio == AspectRatio_16_9) { - targetAr = 16.0 / 9.0; - } - } - - double arr = targetAr / clientAr; - - if( arr < 1 ) - viewport.x = (int)( (double)viewport.x*arr + 0.5); - else if( arr > 1 ) - viewport.y = (int)( (double)viewport.y/arr + 0.5); - - float zoom = g_Conf->GSWindow.Zoom.ToFloat()/100.0; - if( zoom == 0 )//auto zoom in untill black-bars are gone (while keeping the aspect ratio). - zoom = std::max( (float)arr, (float)(1.0/arr) ); - - viewport.Scale(zoom, zoom*g_Conf->GSWindow.StretchY.ToFloat()/100.0 ); - SetSize( viewport ); - CenterOnParent(); - - int cx, cy; - GetPosition(&cx, &cy); - float unit = .01*(float)std::min(viewport.x, viewport.y); - SetPosition( wxPoint( cx + unit*g_Conf->GSWindow.OffsetX.ToFloat(), cy + unit*g_Conf->GSWindow.OffsetY.ToFloat() ) ); -#ifdef GSWindowScaleDebug - Console.WriteLn(Color_Yellow, "GSWindowScaleDebug: zoom %f, viewport.x %d, viewport.y %d", zoom, viewport.GetX(), viewport.GetY()); -#endif -} void GSPanel::OnResize(wxSizeEvent& event) { if( IsBeingDeleted() ) return; - DoResize(); - //Console.Error( "Size? %d x %d", GetSize().x, GetSize().y ); - //event. + event.Skip(); } void GSPanel::OnCloseWindow(wxCloseEvent& evt) @@ -524,7 +463,6 @@ void GSPanel::CoreThread_OnSuspended() void GSPanel::AppStatusEvent_OnSettingsApplied() { if( IsBeingDeleted() ) return; - DoResize(); DoShowMouse(); } @@ -557,6 +495,8 @@ GSFrame::GSFrame( const wxString& title) GSPanel* gsPanel = new GSPanel( this ); m_id_gspanel = gsPanel->GetId(); + gsPanel->SetPosition(wxPoint(0, 0)); + gsPanel->SetSize(GetClientSize()); // TODO -- Implement this GS window status window! Whee. // (main concern is retaining proper client window sizes when closing/re-opening the window). @@ -653,7 +593,6 @@ bool GSFrame::Show( bool shown ) m_id_gspanel = gsPanel->GetId(); } - gsPanel->DoResize(); gsPanel->SetFocus(); if (!m_timer_UpdateTitle.IsRunning()) @@ -844,15 +783,9 @@ void GSFrame::OnResize( wxSizeEvent& evt ) g_Conf->GSWindow.WindowSize = GetClientSize(); } + // Ensure we're always in sync with the parent size. if( GSPanel* gsPanel = GetViewport() ) - { - gsPanel->DoResize(); - gsPanel->SetFocus(); - } + gsPanel->SetSize(evt.GetSize()); - //wxPoint hudpos = wxPoint(-10,-10) + (GetClientSize() - m_hud->GetSize()); - //m_hud->SetPosition( hudpos ); //+ GetScreenPosition() + GetClientAreaOrigin() ); - - // if we skip, the panel is auto-sized to fit our window anyway, which we do not want! - //evt.Skip(); + evt.Skip(); } diff --git a/pcsx2/gui/GSFrame.h b/pcsx2/gui/GSFrame.h index 2e7bed6f24..0b2ce3424c 100644 --- a/pcsx2/gui/GSFrame.h +++ b/pcsx2/gui/GSFrame.h @@ -51,7 +51,6 @@ public: GSPanel( wxWindow* parent ); virtual ~GSPanel(); - void DoResize(); void DoShowMouse(); void DirectKeyCommand( wxKeyEvent& evt ); void DirectKeyCommand( const KeyAcceleratorCode& kac ); diff --git a/pcsx2/gui/GlobalCommands.cpp b/pcsx2/gui/GlobalCommands.cpp index 8f007f43c3..39c09cf587 100644 --- a/pcsx2/gui/GlobalCommands.cpp +++ b/pcsx2/gui/GlobalCommands.cpp @@ -38,8 +38,6 @@ // renderswitch - tells GS to go into dx9 sw if "renderswitch" is set. bool renderswitch = false; -extern bool switchAR; - static bool g_Pcsx2Recording = false; // true if recording video and sound @@ -174,21 +172,11 @@ namespace Implementations pauser.AllowResume(); } - void UpdateImagePosition() - { - //AppApplySettings() would have been nicer, since it also immidiately affects the GUI (if open). - //However, the events sequence it generates also "depresses" Shift/CTRL/etc, so consecutive zoom with CTRL down breaks. - //Since zoom only affects the window viewport anyway, we can live with directly calling it. - if (GSFrame* gsFrame = wxGetApp().GetGsFramePtr()) - if (GSPanel* woot = gsFrame->GetViewport()) - woot->DoResize(); - } - void GSwindow_CycleAspectRatio() { AspectRatioType& art = g_Conf->GSWindow.AspectRatio; const char* arts = "Not modified"; - if (art == AspectRatio_Stretch && switchAR) //avoids a double 4:3 when coming from FMV aspect ratio switch + if (art == AspectRatio_Stretch && GSGetFMVSwitch()) //avoids a double 4:3 when coming from FMV aspect ratio switch art = AspectRatio_4_3; switch (art) { @@ -209,7 +197,9 @@ namespace Implementations } OSDlog(Color_StrongBlue, true, "(GSwindow) Aspect ratio: %s", arts); - UpdateImagePosition(); + + // Disable FMV mode if we were previously in it, so the user can override the AR. + GSSetFMVSwitch(false); } void SetOffset(float x, float y) @@ -217,8 +207,6 @@ namespace Implementations g_Conf->GSWindow.OffsetX = x; g_Conf->GSWindow.OffsetY = y; OSDlog(Color_StrongBlue, true, "(GSwindow) Offset: x=%f, y=%f", x, y); - - UpdateImagePosition(); } void GSwindow_OffsetYplus() @@ -252,8 +240,6 @@ namespace Implementations return; g_Conf->GSWindow.StretchY = zoom; OSDlog(Color_StrongBlue, true, "(GSwindow) Vertical stretch: %f", zoom); - - UpdateImagePosition(); } void GSwindow_ZoomInY() @@ -279,8 +265,6 @@ namespace Implementations OSDlog(Color_StrongBlue, true, "(GSwindow) Zoom: 0 (auto, no black bars)"); else OSDlog(Color_StrongBlue, true, "(GSwindow) Zoom: %f", zoom); - - UpdateImagePosition(); }