diff --git a/src/citra/emu_window/emu_window_sdl2.cpp b/src/citra/emu_window/emu_window_sdl2.cpp index 851303987a..5586cda29b 100644 --- a/src/citra/emu_window/emu_window_sdl2.cpp +++ b/src/citra/emu_window/emu_window_sdl2.cpp @@ -227,6 +227,7 @@ void EmuWindow_SDL2::Present() { while (IsOpen()) { VideoCore::g_renderer->Present(); SDL_GL_SwapWindow(render_window); + VideoCore::g_renderer->PresentComplete(); } SDL_GL_MakeCurrent(render_window, nullptr); } diff --git a/src/citra_qt/bootmanager.cpp b/src/citra_qt/bootmanager.cpp index d8b5db284c..9d732d463e 100644 --- a/src/citra_qt/bootmanager.cpp +++ b/src/citra_qt/bootmanager.cpp @@ -86,7 +86,7 @@ GRenderWindow::GRenderWindow(QWidget* parent, EmuThread* emu_thread) setWindowTitle(QStringLiteral("Citra %1 | %2-%3") .arg(Common::g_build_name, Common::g_scm_branch, Common::g_scm_desc)); setAttribute(Qt::WA_AcceptTouchEvents); - + connect(this, &QOpenGLWidget::frameSwapped, this, &GRenderWindow::OnFrameSwapped); InputCommon::Init(); } @@ -104,6 +104,10 @@ void GRenderWindow::DoneCurrent() { void GRenderWindow::PollEvents() {} +void OnFrameSwapped() { + VideoCore::g_renderer->PresentComplete(); +} + // On Qt 5.0+, this correctly gets the size of the framebuffer (pixels). // // Older versions get the window size (density independent pixels), @@ -294,6 +298,10 @@ void GRenderWindow::paintGL() { update(); } +void GRenderWindow::OnFrameSwapped() { + VideoCore::g_renderer->PresentComplete(); +} + void GRenderWindow::showEvent(QShowEvent* event) { QWidget::showEvent(event); } diff --git a/src/citra_qt/bootmanager.h b/src/citra_qt/bootmanager.h index bd01d78384..51188b209f 100644 --- a/src/citra_qt/bootmanager.h +++ b/src/citra_qt/bootmanager.h @@ -163,6 +163,7 @@ public slots: void OnEmulationStarting(EmuThread* emu_thread); void OnEmulationStopping(); void OnFramebufferSizeChanged(); + void OnFrameSwapped(); signals: /// Emitted when the window is closed diff --git a/src/video_core/renderer_base.h b/src/video_core/renderer_base.h index 871ff40cbf..1558ba1734 100644 --- a/src/video_core/renderer_base.h +++ b/src/video_core/renderer_base.h @@ -34,6 +34,9 @@ public: /// Draws the latest frame to the window (Renderer specific implementation) virtual void Present() = 0; + /// Marks the presentation buffer as complete and swaps it back into the pool + virtual void PresentComplete() = 0; + /// Prepares for video dumping (e.g. create necessary buffers, etc) virtual void PrepareVideoDumping() = 0; diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 34d64c757a..08065ea0bb 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -794,6 +794,9 @@ void RendererOpenGL::Present() { /* insert fence for the main thread to block on */ frame.present_sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); glFlush(); +} + +void RendererOpenGL::PresentComplete() { render_window.mailbox->PresentationComplete(); } diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h index 1d3345f226..d8ed30d733 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h @@ -60,6 +60,9 @@ public: /// context void Present() override; + /// Finializes the presentation and sets up the presentation frame to go back into the mailbox + void PresentComplete() override; + /// Prepares for video dumping (e.g. create necessary buffers, etc) void PrepareVideoDumping() override;