From bfe45774f16e958bf34ed0d58a1d31e2325df47d Mon Sep 17 00:00:00 2001
From: bunnei <bunneidev@gmail.com>
Date: Thu, 22 Mar 2018 21:04:30 -0400
Subject: [PATCH] video_core: Move FramebufferInfo to FramebufferConfig in GPU.

---
 .../service/nvdrv/devices/nvdisp_disp0.cpp    |  6 +-
 src/video_core/gpu.h                          | 29 ++++++++++
 src/video_core/rasterizer_interface.h         |  4 +-
 src/video_core/renderer_base.h                | 33 +----------
 .../renderer_opengl/gl_rasterizer.cpp         |  5 +-
 .../renderer_opengl/gl_rasterizer.h           |  4 +-
 .../renderer_opengl/renderer_opengl.cpp       | 56 ++++++++++---------
 .../renderer_opengl/renderer_opengl.h         |  9 +--
 8 files changed, 77 insertions(+), 69 deletions(-)

diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
index 94530724e9..7cd1d93062 100644
--- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
@@ -26,14 +26,14 @@ void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u3
                 "Drawing from address %lx offset %08X Width %u Height %u Stride %u Format %u", addr,
                 offset, width, height, stride, format);
 
-    using PixelFormat = RendererBase::FramebufferInfo::PixelFormat;
+    using PixelFormat = Tegra::FramebufferConfig::PixelFormat;
     using Flags = NVFlinger::BufferQueue::BufferTransformFlags;
     const bool flip_vertical = static_cast<u32>(transform) & static_cast<u32>(Flags::FlipV);
-    const RendererBase::FramebufferInfo framebuffer_info{
+    const Tegra::FramebufferConfig framebuffer{
         addr, offset, width, height, stride, static_cast<PixelFormat>(format), flip_vertical};
 
     Core::System::GetInstance().perf_stats.EndGameFrame();
-    VideoCore::g_renderer->SwapBuffers(framebuffer_info);
+    VideoCore::g_renderer->SwapBuffers(framebuffer);
 }
 
 } // namespace Devices
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h
index f9a725dee0..f3c5e366a7 100644
--- a/src/video_core/gpu.h
+++ b/src/video_core/gpu.h
@@ -12,6 +12,35 @@
 
 namespace Tegra {
 
+/**
+ * Struct describing framebuffer configuration
+ */
+struct FramebufferConfig {
+    enum class PixelFormat : u32 {
+        ABGR8 = 1,
+    };
+
+    /**
+     * Returns the number of bytes per pixel.
+     */
+    static u32 BytesPerPixel(PixelFormat format) {
+        switch (format) {
+        case PixelFormat::ABGR8:
+            return 4;
+        }
+
+        UNREACHABLE();
+    }
+
+    VAddr address;
+    u32 offset;
+    u32 width;
+    u32 height;
+    u32 stride;
+    PixelFormat pixel_format;
+    bool flip_vertical;
+};
+
 namespace Engines {
 class Fermi2D;
 class Maxwell3D;
diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h
index 6c7bd08268..966e25f347 100644
--- a/src/video_core/rasterizer_interface.h
+++ b/src/video_core/rasterizer_interface.h
@@ -5,6 +5,7 @@
 #pragma once
 
 #include "common/common_types.h"
+#include "video_core/gpu.h"
 
 struct ScreenInfo;
 
@@ -49,7 +50,8 @@ public:
     }
 
     /// Attempt to use a faster method to display the framebuffer to screen
-    virtual bool AccelerateDisplay(const void* config, PAddr framebuffer_addr, u32 pixel_stride,
+    virtual bool AccelerateDisplay(const Tegra::FramebufferConfig& framebuffer,
+                                   PAddr framebuffer_addr, u32 pixel_stride,
                                    ScreenInfo& screen_info) {
         return false;
     }
diff --git a/src/video_core/renderer_base.h b/src/video_core/renderer_base.h
index 532e5b37c8..89a960eaf8 100644
--- a/src/video_core/renderer_base.h
+++ b/src/video_core/renderer_base.h
@@ -8,6 +8,7 @@
 #include <boost/optional.hpp>
 #include "common/assert.h"
 #include "common/common_types.h"
+#include "video_core/gpu.h"
 #include "video_core/rasterizer_interface.h"
 
 class EmuWindow;
@@ -17,40 +18,10 @@ public:
     /// Used to reference a framebuffer
     enum kFramebuffer { kFramebuffer_VirtualXFB = 0, kFramebuffer_EFB, kFramebuffer_Texture };
 
-    /**
-     * Struct describing framebuffer metadata
-     * TODO(bunnei): This struct belongs in the GPU code, but we don't have a good place for it yet.
-     */
-    struct FramebufferInfo {
-        enum class PixelFormat : u32 {
-            ABGR8 = 1,
-        };
-
-        /**
-         * Returns the number of bytes per pixel.
-         */
-        static u32 BytesPerPixel(PixelFormat format) {
-            switch (format) {
-            case PixelFormat::ABGR8:
-                return 4;
-            }
-
-            UNREACHABLE();
-        }
-
-        VAddr address;
-        u32 offset;
-        u32 width;
-        u32 height;
-        u32 stride;
-        PixelFormat pixel_format;
-        bool flip_vertical;
-    };
-
     virtual ~RendererBase() {}
 
     /// Swap buffers (render frame)
-    virtual void SwapBuffers(boost::optional<const FramebufferInfo&> framebuffer_info) = 0;
+    virtual void SwapBuffers(boost::optional<const Tegra::FramebufferConfig&> framebuffer) = 0;
 
     /**
      * Set the emulator window to use for renderer
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 0aed4b0486..abc6607b0d 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -226,8 +226,9 @@ bool RasterizerOpenGL::AccelerateFill(const void* config) {
     return true;
 }
 
-bool RasterizerOpenGL::AccelerateDisplay(const void* config, PAddr framebuffer_addr,
-                                         u32 pixel_stride, ScreenInfo& screen_info) {
+bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& framebuffer,
+                                         PAddr framebuffer_addr, u32 pixel_stride,
+                                         ScreenInfo& screen_info) {
     ASSERT_MSG(false, "Unimplemented");
     return true;
 }
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index 7a68480d96..8f213404d0 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -38,8 +38,8 @@ public:
     bool AccelerateDisplayTransfer(const void* config) override;
     bool AccelerateTextureCopy(const void* config) override;
     bool AccelerateFill(const void* config) override;
-    bool AccelerateDisplay(const void* config, PAddr framebuffer_addr, u32 pixel_stride,
-                           ScreenInfo& screen_info) override;
+    bool AccelerateDisplay(const Tegra::FramebufferConfig& framebuffer, PAddr framebuffer_addr,
+                           u32 pixel_stride, ScreenInfo& screen_info) override;
     bool AccelerateDrawBatch(bool is_indexed) override;
 
     /// OpenGL shader generated for a given Maxwell register state
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index 65d38ade58..2ea5e91e36 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -98,22 +98,22 @@ RendererOpenGL::RendererOpenGL() = default;
 RendererOpenGL::~RendererOpenGL() = default;
 
 /// Swap buffers (render frame)
-void RendererOpenGL::SwapBuffers(boost::optional<const FramebufferInfo&> framebuffer_info) {
+void RendererOpenGL::SwapBuffers(boost::optional<const Tegra::FramebufferConfig&> framebuffer) {
     // Maintain the rasterizer's state as a priority
     OpenGLState prev_state = OpenGLState::GetCurState();
     state.Apply();
 
-    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) {
+    if (framebuffer != boost::none) {
+        // If framebuffer is provided, reload it from memory to a texture
+        if (screen_info.texture.width != (GLsizei)framebuffer->width ||
+            screen_info.texture.height != (GLsizei)framebuffer->height ||
+            screen_info.texture.pixel_format != framebuffer->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);
+            ConfigureFramebufferTexture(screen_info.texture, *framebuffer);
         }
-        LoadFBToScreenInfo(*framebuffer_info, screen_info);
+        LoadFBToScreenInfo(*framebuffer, screen_info);
     }
 
     DrawScreens();
@@ -245,43 +245,47 @@ static void MortonCopyPixels128(u32 width, u32 height, u32 bytes_per_pixel, u32
 /**
  * Loads framebuffer from emulated memory into the active OpenGL texture.
  */
-void RendererOpenGL::LoadFBToScreenInfo(const FramebufferInfo& framebuffer_info,
+void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuffer,
                                         ScreenInfo& screen_info) {
-    const u32 bpp{FramebufferInfo::BytesPerPixel(framebuffer_info.pixel_format)};
-    const u32 size_in_bytes{framebuffer_info.stride * framebuffer_info.height * bpp};
+    const u32 bpp{Tegra::FramebufferConfig::BytesPerPixel(framebuffer.pixel_format)};
+    const u32 size_in_bytes{framebuffer.stride * framebuffer.height * bpp};
+    const VAddr framebuffer_addr{framebuffer.address};
+    const size_t pixel_stride{framebuffer.stride / bpp};
 
-    MortonCopyPixels128(framebuffer_info.width, framebuffer_info.height, bpp, 4,
-                        Memory::GetPointer(framebuffer_info.address), gl_framebuffer_data.data(),
-                        true);
+    // OpenGL only supports specifying a stride in units of pixels, not bytes, unfortunately
+    ASSERT(pixel_stride * bpp == framebuffer.stride);
+
+    MortonCopyPixels128(framebuffer.width, framebuffer.height, bpp, 4,
+                        Memory::GetPointer(framebuffer.address), gl_framebuffer_data.data(), true);
 
     LOG_TRACE(Render_OpenGL, "0x%08x bytes from 0x%llx(%dx%d), fmt %x", size_in_bytes,
-              framebuffer_info.address, framebuffer_info.width, framebuffer_info.height,
-              (int)framebuffer_info.pixel_format);
+              framebuffer.address, framebuffer.width, framebuffer.height,
+              (int)framebuffer.pixel_format);
 
     // Ensure no bad interactions with GL_UNPACK_ALIGNMENT, which by default
     // only allows rows to have a memory alignement of 4.
-    ASSERT(framebuffer_info.stride % 4 == 0);
+    ASSERT(framebuffer.stride % 4 == 0);
 
-    framebuffer_flip_vertical = framebuffer_info.flip_vertical;
+    framebuffer_flip_vertical = framebuffer.flip_vertical;
 
     // Reset the screen info's display texture to its own permanent texture
     screen_info.display_texture = screen_info.texture.resource.handle;
     screen_info.display_texcoords = MathUtil::Rectangle<float>(0.f, 0.f, 1.f, 1.f);
 
-    // Memory::RasterizerFlushRegion(framebuffer_info.address, size_in_bytes);
+    Rasterizer()->FlushRegion(framebuffer.address, size_in_bytes);
 
     state.texture_units[0].texture_2d = screen_info.texture.resource.handle;
     state.Apply();
 
     glActiveTexture(GL_TEXTURE0);
-    glPixelStorei(GL_UNPACK_ROW_LENGTH, (GLint)framebuffer_info.stride);
+    glPixelStorei(GL_UNPACK_ROW_LENGTH, (GLint)framebuffer.stride);
 
     // Update existing texture
     // TODO: Test what happens on hardware when you change the framebuffer dimensions so that
     //       they differ from the LCD resolution.
     // TODO: Applications could theoretically crash Citra here by specifying too large
     //       framebuffer sizes. We should make sure that this cannot happen.
-    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, framebuffer_info.width, framebuffer_info.height,
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, framebuffer.width, framebuffer.height,
                     screen_info.texture.gl_format, screen_info.texture.gl_type,
                     gl_framebuffer_data.data());
 
@@ -372,14 +376,14 @@ void RendererOpenGL::InitOpenGLObjects() {
 }
 
 void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture,
-                                                 const FramebufferInfo& framebuffer_info) {
+                                                 const Tegra::FramebufferConfig& framebuffer) {
 
-    texture.width = framebuffer_info.width;
-    texture.height = framebuffer_info.height;
+    texture.width = framebuffer.width;
+    texture.height = framebuffer.height;
 
     GLint internal_format;
-    switch (framebuffer_info.pixel_format) {
-    case FramebufferInfo::PixelFormat::ABGR8:
+    switch (framebuffer.pixel_format) {
+    case Tegra::FramebufferConfig::PixelFormat::ABGR8:
         // Use RGBA8 and swap in the fragment shader
         internal_format = GL_RGBA;
         texture.gl_format = GL_RGBA;
diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h
index 05bb3c5cf1..bd7c2510fc 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.h
+++ b/src/video_core/renderer_opengl/renderer_opengl.h
@@ -21,7 +21,7 @@ struct TextureInfo {
     GLsizei height;
     GLenum gl_format;
     GLenum gl_type;
-    RendererBase::FramebufferInfo::PixelFormat pixel_format;
+    Tegra::FramebufferConfig::PixelFormat pixel_format;
 };
 
 /// Structure used for storing information about the display target for each 3DS screen
@@ -37,7 +37,7 @@ public:
     ~RendererOpenGL() override;
 
     /// Swap buffers (render frame)
-    void SwapBuffers(boost::optional<const FramebufferInfo&> framebuffer_info) override;
+    void SwapBuffers(boost::optional<const Tegra::FramebufferConfig&> framebuffer) override;
 
     /**
      * Set the emulator window to use for renderer
@@ -53,13 +53,14 @@ public:
 
 private:
     void InitOpenGLObjects();
-    void ConfigureFramebufferTexture(TextureInfo& texture, const FramebufferInfo& framebuffer_info);
+    void ConfigureFramebufferTexture(TextureInfo& texture,
+                                     const Tegra::FramebufferConfig& framebuffer);
     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 Tegra::FramebufferConfig& framebuffer, ScreenInfo& screen_info);
     // Fills active OpenGL texture with the given RGBA color.
     void LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, u8 color_a,
                                     const TextureInfo& texture);