1 // Copyright 2014 Citra Emulator Project
2 // Licensed under GPLv2 or any later version
3 // Refer to the license.txt file included.
4 
5 #pragma once
6 
7 #include <array>
8 #include <glad/glad.h>
9 #include "common/common_types.h"
10 #include "common/math_util.h"
11 #include "core/hw/gpu.h"
12 #include "video_core/renderer_base.h"
13 #include "video_core/renderer_opengl/frame_dumper_opengl.h"
14 #include "video_core/renderer_opengl/gl_resource_manager.h"
15 #include "video_core/renderer_opengl/gl_state.h"
16 
17 namespace Layout {
18 struct FramebufferLayout;
19 }
20 
21 namespace Frontend {
22 
23 struct Frame {
24     u32 width{};                      /// Width of the frame (to detect resize)
25     u32 height{};                     /// Height of the frame
26     bool color_reloaded = false;      /// Texture attachment was recreated (ie: resized)
27     OpenGL::OGLRenderbuffer color{};  /// Buffer shared between the render/present FBO
28     OpenGL::OGLFramebuffer render{};  /// FBO created on the render thread
29     OpenGL::OGLFramebuffer present{}; /// FBO created on the present thread
30     GLsync render_fence{};            /// Fence created on the render thread
31     GLsync present_fence{};           /// Fence created on the presentation thread
32 };
33 } // namespace Frontend
34 
35 namespace OpenGL {
36 
37 /// Structure used for storing information about the textures for each 3DS screen
38 struct TextureInfo {
39     OGLTexture resource;
40     GLsizei width;
41     GLsizei height;
42     GPU::Regs::PixelFormat format;
43     GLenum gl_format;
44     GLenum gl_type;
45 };
46 
47 /// Structure used for storing information about the display target for each 3DS screen
48 struct ScreenInfo {
49     GLuint display_texture;
50     Common::Rectangle<float> display_texcoords;
51     TextureInfo texture;
52 };
53 
54 struct PresentationTexture {
55     u32 width = 0;
56     u32 height = 0;
57     OGLTexture texture;
58 };
59 
60 class RendererOpenGL : public RendererBase {
61 public:
62     explicit RendererOpenGL(Frontend::EmuWindow& window);
63     ~RendererOpenGL() override;
64 
65     /// Initialize the renderer
66     VideoCore::ResultStatus Init() override;
67 
68     /// Shutdown the renderer
69     void ShutDown() override;
70 
71     /// Finalizes rendering the guest frame
72     void SwapBuffers() override;
73 
74     /// Draws the latest frame from texture mailbox to the currently bound draw framebuffer in this
75     /// context
76     void TryPresent(int timeout_ms) override;
77 
78     /// Prepares for video dumping (e.g. create necessary buffers, etc)
79     void PrepareVideoDumping() override;
80 
81     /// Cleans up after video dumping is ended
82     void CleanupVideoDumping() override;
83 
84 private:
85     void InitOpenGLObjects();
86     void ReloadSampler();
87     void ReloadShader();
88     void PrepareRendertarget();
89     void RenderScreenshot();
90     void RenderToMailbox(const Layout::FramebufferLayout& layout,
91                          std::unique_ptr<Frontend::TextureMailbox>& mailbox, bool flipped);
92     void ConfigureFramebufferTexture(TextureInfo& texture,
93                                      const GPU::Regs::FramebufferConfig& framebuffer);
94     void DrawScreens(const Layout::FramebufferLayout& layout, bool flipped);
95     void DrawSingleScreenRotated(const ScreenInfo& screen_info, float x, float y, float w, float h);
96     void DrawSingleScreen(const ScreenInfo& screen_info, float x, float y, float w, float h);
97     void DrawSingleScreenStereoRotated(const ScreenInfo& screen_info_l,
98                                        const ScreenInfo& screen_info_r, float x, float y, float w,
99                                        float h);
100     void DrawSingleScreenStereo(const ScreenInfo& screen_info_l, const ScreenInfo& screen_info_r,
101                                 float x, float y, float w, float h);
102     void UpdateFramerate();
103 
104     // Loads framebuffer from emulated memory into the display information structure
105     void LoadFBToScreenInfo(const GPU::Regs::FramebufferConfig& framebuffer,
106                             ScreenInfo& screen_info, bool right_eye);
107     // Fills active OpenGL texture with the given RGB color.
108     void LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, const TextureInfo& texture);
109 
110     OpenGLState state;
111 
112     // OpenGL object IDs
113     OGLVertexArray vertex_array;
114     OGLBuffer vertex_buffer;
115     OGLProgram shader;
116     OGLFramebuffer screenshot_framebuffer;
117     OGLSampler filter_sampler;
118 
119     /// Display information for top and bottom screens respectively
120     std::array<ScreenInfo, 3> screen_infos;
121 
122     // Shader uniform location indices
123     GLuint uniform_modelview_matrix;
124     GLuint uniform_color_texture;
125     GLuint uniform_color_texture_r;
126 
127     // Shader uniform for Dolphin compatibility
128     GLuint uniform_i_resolution;
129     GLuint uniform_o_resolution;
130     GLuint uniform_layer;
131 
132     // Shader attribute input indices
133     GLuint attrib_position;
134     GLuint attrib_tex_coord;
135 
136     FrameDumperOpenGL frame_dumper;
137 };
138 
139 } // namespace OpenGL
140