From ebd613c2ccfa770caa55bff9e6ca67eee7bca754 Mon Sep 17 00:00:00 2001
From: bunnei <bunneidev@gmail.com>
Date: Sun, 14 Jan 2018 23:51:54 -0500
Subject: [PATCH] renderer: Render previous frame when no new one is available.

---
 src/core/hle/service/vi/vi.cpp                |  5 +++-
 src/video_core/renderer_base.h                |  3 ++-
 .../renderer_opengl/renderer_opengl.cpp       | 23 +++++++++++--------
 .../renderer_opengl/renderer_opengl.h         |  8 +++----
 4 files changed, 22 insertions(+), 17 deletions(-)

diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index d3b63949e..b35a7a377 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -12,6 +12,8 @@
 #include "core/hle/service/nvdrv/nvdrv_a.h"
 #include "core/hle/service/vi/vi.h"
 #include "core/hle/service/vi/vi_m.h"
+#include "video_core/renderer_base.h"
+#include "video_core/video_core.h"
 
 namespace Service {
 namespace VI {
@@ -743,7 +745,8 @@ void NVFlinger::Compose() {
         auto buffer = buffer_queue->AcquireBuffer();
 
         if (buffer == boost::none) {
-            // There was no queued buffer to draw.
+            // There was no queued buffer to draw, render previous frame
+            VideoCore::g_renderer->SwapBuffers({});
             continue;
         }
 
diff --git a/src/video_core/renderer_base.h b/src/video_core/renderer_base.h
index d15db6c8c..28893b181 100644
--- a/src/video_core/renderer_base.h
+++ b/src/video_core/renderer_base.h
@@ -5,6 +5,7 @@
 #pragma once
 
 #include <memory>
+#include <boost/optional.hpp>
 #include "common/assert.h"
 #include "common/common_types.h"
 
@@ -47,7 +48,7 @@ public:
     virtual ~RendererBase() {}
 
     /// Swap buffers (render frame)
-    virtual void SwapBuffers(const FramebufferInfo& framebuffer_info) = 0;
+    virtual void SwapBuffers(boost::optional<const FramebufferInfo&> framebuffer_info) = 0;
 
     /**
      * Set the emulator window to use for renderer
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index a5df91604..f1c3ff948 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -4,8 +4,8 @@
 
 #include <algorithm>
 #include <cstddef>
-#include <cstring>
 #include <cstdlib>
+#include <cstring>
 #include <memory>
 #include <glad/glad.h>
 #include "common/assert.h"
@@ -98,20 +98,23 @@ RendererOpenGL::RendererOpenGL() = default;
 RendererOpenGL::~RendererOpenGL() = default;
 
 /// Swap buffers (render frame)
-void RendererOpenGL::SwapBuffers(const FramebufferInfo& framebuffer_info) {
+void RendererOpenGL::SwapBuffers(boost::optional<const FramebufferInfo&> framebuffer_info) {
     // Maintain the rasterizer's state as a priority
     OpenGLState prev_state = OpenGLState::GetCurState();
     state.Apply();
 
-    if (screen_info.texture.width != (GLsizei)framebuffer_info.width ||
-        screen_info.texture.height != (GLsizei)framebuffer_info.height ||
-        screen_info.texture.pixel_format != framebuffer_info.pixel_format) {
-        // Reallocate texture if the framebuffer size has changed.
-        // This is expected to not happen very often and hence should not be a
-        // performance problem.
-        ConfigureFramebufferTexture(screen_info.texture, framebuffer_info);
+    if (framebuffer_info != boost::none) {
+        // If framebuffer_info is provided, reload it from memory to a texture
+        if (screen_info.texture.width != (GLsizei)framebuffer_info->width ||
+            screen_info.texture.height != (GLsizei)framebuffer_info->height ||
+            screen_info.texture.pixel_format != framebuffer_info->pixel_format) {
+            // Reallocate texture if the framebuffer size has changed.
+            // This is expected to not happen very often and hence should not be a
+            // performance problem.
+            ConfigureFramebufferTexture(screen_info.texture, *framebuffer_info);
+        }
+        LoadFBToScreenInfo(*framebuffer_info, screen_info);
     }
-    LoadFBToScreenInfo(framebuffer_info, screen_info);
 
     DrawScreens();
 
diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h
index dc21d7a38..2f5e35787 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.h
+++ b/src/video_core/renderer_opengl/renderer_opengl.h
@@ -37,7 +37,7 @@ public:
     ~RendererOpenGL() override;
 
     /// Swap buffers (render frame)
-    void SwapBuffers(const FramebufferInfo& framebuffer_info) override;
+    void SwapBuffers(boost::optional<const FramebufferInfo&> framebuffer_info) override;
 
     /**
      * Set the emulator window to use for renderer
@@ -53,15 +53,13 @@ public:
 
 private:
     void InitOpenGLObjects();
-    void ConfigureFramebufferTexture(TextureInfo& texture,
-                                     const FramebufferInfo& framebuffer_info);
+    void ConfigureFramebufferTexture(TextureInfo& texture, const FramebufferInfo& framebuffer_info);
     void DrawScreens();
     void DrawSingleScreen(const ScreenInfo& screen_info, float x, float y, float w, float h);
     void UpdateFramerate();
 
     // Loads framebuffer from emulated memory into the display information structure
-    void LoadFBToScreenInfo(const FramebufferInfo& framebuffer_info,
-                            ScreenInfo& screen_info);
+    void LoadFBToScreenInfo(const FramebufferInfo& framebuffer_info, ScreenInfo& screen_info);
     // Fills active OpenGL texture with the given RGB color.
     void LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, const TextureInfo& texture);