From 28795e549b5fed37452846a04fd7ca699e32f7aa Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Fri, 20 May 2022 23:09:24 +1000 Subject: [PATCH] GS/Qt: Represent the current frame on resize when paused Stops the frame displayed with incorrect proportions. --- pcsx2-qt/EmuThread.cpp | 8 ++++++++ pcsx2/Frontend/ImGuiManager.cpp | 4 ++++ pcsx2/GS.h | 4 ++++ pcsx2/GS/GS.cpp | 5 +++++ pcsx2/GS/GS.h | 1 + pcsx2/GS/Renderers/Common/GSRenderer.cpp | 24 ++++++++++++++++++++++++ pcsx2/GS/Renderers/Common/GSRenderer.h | 1 + pcsx2/MTGS.cpp | 8 ++++++++ 8 files changed, 55 insertions(+) diff --git a/pcsx2-qt/EmuThread.cpp b/pcsx2-qt/EmuThread.cpp index 96de15b6c3..0ed8f39bd8 100644 --- a/pcsx2-qt/EmuThread.cpp +++ b/pcsx2-qt/EmuThread.cpp @@ -744,6 +744,10 @@ void Host::ResizeHostDisplay(u32 new_window_width, u32 new_window_height, float { s_host_display->ResizeRenderWindow(new_window_width, new_window_height, new_window_scale); ImGuiManager::WindowResized(); + + // if we're paused, re-present the current frame at the new window size. + if (VMManager::GetState() == VMState::Paused) + GetMTGS().PresentCurrentFrame(); } void Host::RequestResizeHostDisplay(s32 width, s32 height) @@ -755,6 +759,10 @@ void Host::UpdateHostDisplay() { g_emu_thread->updateDisplay(); ImGuiManager::WindowResized(); + + // if we're paused, re-present the current frame at the new window size. + if (VMManager::GetState() == VMState::Paused) + GetMTGS().PresentCurrentFrame(); } void Host::OnVMStarting() diff --git a/pcsx2/Frontend/ImGuiManager.cpp b/pcsx2/Frontend/ImGuiManager.cpp index 0c0905c4f8..7c76c46e5a 100644 --- a/pcsx2/Frontend/ImGuiManager.cpp +++ b/pcsx2/Frontend/ImGuiManager.cpp @@ -117,6 +117,10 @@ void ImGuiManager::WindowResized() ImGui::GetIO().DisplaySize = ImVec2(static_cast(new_width), static_cast(new_height)); UpdateScale(); + + // restart imgui frame on the new window size to pick it up, otherwise we draw to the old size + ImGui::EndFrame(); + NewFrame(); } void ImGuiManager::UpdateScale() diff --git a/pcsx2/GS.h b/pcsx2/GS.h index d0db251126..8f937fec42 100644 --- a/pcsx2/GS.h +++ b/pcsx2/GS.h @@ -383,6 +383,10 @@ public: /// Fully stops the thread, closing in the process if needed. void ShutdownThread(); + /// Re-presents the current frame. Call when things like window resizes happen to re-display + /// the current frame with the correct proportions. Should only be called on the GS thread. + void PresentCurrentFrame(); + // Waits for the GS to empty out the entire ring buffer contents. void WaitGS(bool syncRegs=true, bool weakWait=false, bool isMTVU=false); void ResetGS(bool hardware_reset); diff --git a/pcsx2/GS/GS.cpp b/pcsx2/GS/GS.cpp index 06101ff85b..fc0eefeecf 100644 --- a/pcsx2/GS/GS.cpp +++ b/pcsx2/GS/GS.cpp @@ -527,6 +527,11 @@ void GSStopGSDump() g_gs_renderer->StopGSDump(); } +void GSPresentCurrentFrame() +{ + g_gs_renderer->PresentCurrentFrame(); +} + #ifndef PCSX2_CORE void GSkeyEvent(const HostKeyEvent& e) diff --git a/pcsx2/GS/GS.h b/pcsx2/GS/GS.h index 43830ae9d3..e7cb80c89b 100644 --- a/pcsx2/GS/GS.h +++ b/pcsx2/GS/GS.h @@ -71,6 +71,7 @@ void GSvsync(u32 field, bool registers_written); int GSfreeze(FreezeAction mode, freezeData* data); void GSQueueSnapshot(const std::string& path, u32 gsdump_frames = 0); void GSStopGSDump(); +void GSPresentCurrentFrame(); #ifndef PCSX2_CORE void GSkeyEvent(const HostKeyEvent& e); void GSconfigure(); diff --git a/pcsx2/GS/Renderers/Common/GSRenderer.cpp b/pcsx2/GS/Renderers/Common/GSRenderer.cpp index 6e6d173c68..6fed0eb8ad 100644 --- a/pcsx2/GS/Renderers/Common/GSRenderer.cpp +++ b/pcsx2/GS/Renderers/Common/GSRenderer.cpp @@ -745,6 +745,30 @@ void GSRenderer::StopGSDump() m_dump_frames = 0; } +void GSRenderer::PresentCurrentFrame() +{ + g_gs_device->ResetAPIState(); + if (Host::BeginPresentFrame(false)) + { + GSTexture* current = g_gs_device->GetCurrent(); + if (current) + { + HostDisplay* const display = g_gs_device->GetDisplay(); + const GSVector4 draw_rect(CalculateDrawRect(display->GetWindowWidth(), display->GetWindowHeight(), + current->GetWidth(), current->GetHeight(), display->GetDisplayAlignment(), display->UsesLowerLeftOrigin(), GetVideoMode() == GSVideoMode::SDTV_480P)); + + static constexpr ShaderConvert s_shader[5] = { ShaderConvert::COPY, ShaderConvert::SCANLINE, + ShaderConvert::DIAGONAL_FILTER, ShaderConvert::TRIANGULAR_FILTER, + ShaderConvert::COMPLEX_FILTER }; // FIXME + + g_gs_device->StretchRect(current, nullptr, draw_rect, s_shader[GSConfig.TVShader], GSConfig.LinearPresent); + } + + Host::EndPresentFrame(); + } + g_gs_device->RestoreAPIState(); +} + #ifndef PCSX2_CORE bool GSRenderer::BeginCapture(std::string& filename) diff --git a/pcsx2/GS/Renderers/Common/GSRenderer.h b/pcsx2/GS/Renderers/Common/GSRenderer.h index 30c0148cdc..68740d7e57 100644 --- a/pcsx2/GS/Renderers/Common/GSRenderer.h +++ b/pcsx2/GS/Renderers/Common/GSRenderer.h @@ -68,6 +68,7 @@ public: void QueueSnapshot(const std::string& path, u32 gsdump_frames); void StopGSDump(); + void PresentCurrentFrame(); #ifndef PCSX2_CORE bool BeginCapture(std::string& filename); diff --git a/pcsx2/MTGS.cpp b/pcsx2/MTGS.cpp index 7a40f8683a..d11e65bb6c 100644 --- a/pcsx2/MTGS.cpp +++ b/pcsx2/MTGS.cpp @@ -911,6 +911,9 @@ void SysMtgsThread::Freeze(FreezeAction mode, MTGS_FreezeData& data) void SysMtgsThread::RunOnGSThread(AsyncCallType func) { SendPointerPacket(GS_RINGTYPE_ASYNC_CALL, 0, new AsyncCallType(std::move(func))); + + // wake the gs thread in case it's sleeping + SetEvent(); } void SysMtgsThread::ApplySettings() @@ -993,3 +996,8 @@ bool SysMtgsThread::SaveMemorySnapshot(u32 width, u32 height, std::vector* WaitGS(false, false, false); return result; } + +void SysMtgsThread::PresentCurrentFrame() +{ + GSPresentCurrentFrame(); +}