From ce553ab995d036688df4b39c60641cfd45bfbb10 Mon Sep 17 00:00:00 2001 From: SachinVin <26602104+SachinVin@users.noreply.github.com> Date: Mon, 1 May 2023 19:57:42 +0530 Subject: [PATCH] renderer_opengl: DrawSingleScreen*: remove duplicate code (#6426) Co-authored-by: Tobias --- src/core/frontend/framebuffer_layout.h | 8 + .../renderer_opengl/renderer_opengl.cpp | 385 ++++++++---------- .../renderer_opengl/renderer_opengl.h | 10 +- 3 files changed, 172 insertions(+), 231 deletions(-) diff --git a/src/core/frontend/framebuffer_layout.h b/src/core/frontend/framebuffer_layout.h index 192e79b4a..8dcb6354d 100644 --- a/src/core/frontend/framebuffer_layout.h +++ b/src/core/frontend/framebuffer_layout.h @@ -9,6 +9,14 @@ namespace Layout { +/// Orientation of the 3DS displays +enum class DisplayOrientation { + Landscape, // Default orientation of the 3DS + Portrait, // 3DS rotated 90 degrees counter-clockwise + LandscapeFlipped, // 3DS rotated 180 degrees counter-clockwise + PortraitFlipped, // 3DS rotated 270 degrees counter-clockwise +}; + /// Describes the horizontal coordinates for the right eye screen when using Cardboard VR struct CardboardSettings { u32 top_screen_right_eye; diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 47c581bfe..89ac5fc49 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -261,6 +261,7 @@ public: * Vertex structure that the drawn screen rectangles are composed of. */ struct ScreenRectVertex { + ScreenRectVertex() = default; ScreenRectVertex(GLfloat x, GLfloat y, GLfloat u, GLfloat v) { position[0] = x; position[1] = y; @@ -268,8 +269,8 @@ struct ScreenRectVertex { tex_coord[1] = v; } - GLfloat position[2]; - GLfloat tex_coord[2]; + std::array position{}; + std::array tex_coord{}; }; /** @@ -746,20 +747,51 @@ void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture, * Draws a single texture to the emulator window, rotating the texture to correct for the 3DS's LCD * rotation. */ -void RendererOpenGL::DrawSingleScreenRotated(const ScreenInfo& screen_info, float x, float y, - float w, float h) { +void RendererOpenGL::DrawSingleScreen(const ScreenInfo& screen_info, float x, float y, float w, + float h, Layout::DisplayOrientation orientation) { const auto& texcoords = screen_info.display_texcoords; - const std::array vertices = {{ - ScreenRectVertex(x, y, texcoords.bottom, texcoords.left), - ScreenRectVertex(x + w, y, texcoords.bottom, texcoords.right), - ScreenRectVertex(x, y + h, texcoords.top, texcoords.left), - ScreenRectVertex(x + w, y + h, texcoords.top, texcoords.right), - }}; + std::array vertices; + switch (orientation) { + case Layout::DisplayOrientation::Landscape: + vertices = {{ + ScreenRectVertex(x, y, texcoords.bottom, texcoords.left), + ScreenRectVertex(x + w, y, texcoords.bottom, texcoords.right), + ScreenRectVertex(x, y + h, texcoords.top, texcoords.left), + ScreenRectVertex(x + w, y + h, texcoords.top, texcoords.right), + }}; + break; + case Layout::DisplayOrientation::Portrait: + vertices = {{ + ScreenRectVertex(x, y, texcoords.bottom, texcoords.right), + ScreenRectVertex(x + w, y, texcoords.top, texcoords.right), + ScreenRectVertex(x, y + h, texcoords.bottom, texcoords.left), + ScreenRectVertex(x + w, y + h, texcoords.top, texcoords.left), + }}; + std::swap(h, w); + break; + case Layout::DisplayOrientation::LandscapeFlipped: + vertices = {{ + ScreenRectVertex(x, y, texcoords.top, texcoords.right), + ScreenRectVertex(x + w, y, texcoords.top, texcoords.left), + ScreenRectVertex(x, y + h, texcoords.bottom, texcoords.right), + ScreenRectVertex(x + w, y + h, texcoords.bottom, texcoords.left), + }}; + break; + case Layout::DisplayOrientation::PortraitFlipped: + vertices = {{ + ScreenRectVertex(x, y, texcoords.top, texcoords.left), + ScreenRectVertex(x + w, y, texcoords.bottom, texcoords.left), + ScreenRectVertex(x, y + h, texcoords.top, texcoords.right), + ScreenRectVertex(x + w, y + h, texcoords.bottom, texcoords.right), + }}; + std::swap(h, w); + break; + default: + LOG_ERROR(Render_OpenGL, "Unknown DisplayOrientation: {}", orientation); + break; + } - // As this is the "DrawSingleScreenRotated" function, the output resolution dimensions have been - // swapped. If a non-rotated draw-screen function were to be added for book-mode games, those - // should probably be set to the standard (w, h, 1.0 / w, 1.0 / h) ordering. const u32 scale_factor = GetResolutionScaleFactor(); glUniform4f(uniform_i_resolution, static_cast(screen_info.texture.width * scale_factor), static_cast(screen_info.texture.height * scale_factor), @@ -778,50 +810,56 @@ void RendererOpenGL::DrawSingleScreenRotated(const ScreenInfo& screen_info, floa state.Apply(); } -void RendererOpenGL::DrawSingleScreen(const ScreenInfo& screen_info, float x, float y, float w, - float h) { - const auto& texcoords = screen_info.display_texcoords; - - const std::array vertices = {{ - ScreenRectVertex(x, y, texcoords.bottom, texcoords.right), - ScreenRectVertex(x + w, y, texcoords.top, texcoords.right), - ScreenRectVertex(x, y + h, texcoords.bottom, texcoords.left), - ScreenRectVertex(x + w, y + h, texcoords.top, texcoords.left), - }}; - - const u32 scale_factor = GetResolutionScaleFactor(); - glUniform4f(uniform_i_resolution, static_cast(screen_info.texture.width * scale_factor), - static_cast(screen_info.texture.height * scale_factor), - 1.0f / static_cast(screen_info.texture.width * scale_factor), - 1.0f / static_cast(screen_info.texture.height * scale_factor)); - glUniform4f(uniform_o_resolution, w, h, 1.0f / w, 1.0f / h); - state.texture_units[0].texture_2d = screen_info.display_texture; - state.texture_units[0].sampler = filter_sampler.handle; - state.Apply(); - - glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices.data()); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - state.texture_units[0].texture_2d = 0; - state.texture_units[0].sampler = 0; - state.Apply(); -} - /** * Draws a single texture to the emulator window, rotating the texture to correct for the 3DS's LCD * rotation. */ -void RendererOpenGL::DrawSingleScreenStereoRotated(const ScreenInfo& screen_info_l, - const ScreenInfo& screen_info_r, float x, - float y, float w, float h) { +void RendererOpenGL::DrawSingleScreenStereo(const ScreenInfo& screen_info_l, + const ScreenInfo& screen_info_r, float x, float y, + float w, float h, + Layout::DisplayOrientation orientation) { const auto& texcoords = screen_info_l.display_texcoords; - const std::array vertices = {{ - ScreenRectVertex(x, y, texcoords.bottom, texcoords.left), - ScreenRectVertex(x + w, y, texcoords.bottom, texcoords.right), - ScreenRectVertex(x, y + h, texcoords.top, texcoords.left), - ScreenRectVertex(x + w, y + h, texcoords.top, texcoords.right), - }}; + std::array vertices; + switch (orientation) { + case Layout::DisplayOrientation::Landscape: + vertices = {{ + ScreenRectVertex(x, y, texcoords.bottom, texcoords.left), + ScreenRectVertex(x + w, y, texcoords.bottom, texcoords.right), + ScreenRectVertex(x, y + h, texcoords.top, texcoords.left), + ScreenRectVertex(x + w, y + h, texcoords.top, texcoords.right), + }}; + break; + case Layout::DisplayOrientation::Portrait: + vertices = {{ + ScreenRectVertex(x, y, texcoords.bottom, texcoords.right), + ScreenRectVertex(x + w, y, texcoords.top, texcoords.right), + ScreenRectVertex(x, y + h, texcoords.bottom, texcoords.left), + ScreenRectVertex(x + w, y + h, texcoords.top, texcoords.left), + }}; + std::swap(h, w); + break; + case Layout::DisplayOrientation::LandscapeFlipped: + vertices = {{ + ScreenRectVertex(x, y, texcoords.top, texcoords.right), + ScreenRectVertex(x + w, y, texcoords.top, texcoords.left), + ScreenRectVertex(x, y + h, texcoords.bottom, texcoords.right), + ScreenRectVertex(x + w, y + h, texcoords.bottom, texcoords.left), + }}; + break; + case Layout::DisplayOrientation::PortraitFlipped: + vertices = {{ + ScreenRectVertex(x, y, texcoords.top, texcoords.left), + ScreenRectVertex(x + w, y, texcoords.bottom, texcoords.left), + ScreenRectVertex(x, y + h, texcoords.top, texcoords.right), + ScreenRectVertex(x + w, y + h, texcoords.bottom, texcoords.right), + }}; + std::swap(h, w); + break; + default: + LOG_ERROR(Render_OpenGL, "Unknown DisplayOrientation: {}", orientation); + break; + } const u32 scale_factor = GetResolutionScaleFactor(); glUniform4f(uniform_i_resolution, @@ -846,41 +884,6 @@ void RendererOpenGL::DrawSingleScreenStereoRotated(const ScreenInfo& screen_info state.Apply(); } -void RendererOpenGL::DrawSingleScreenStereo(const ScreenInfo& screen_info_l, - const ScreenInfo& screen_info_r, float x, float y, - float w, float h) { - const auto& texcoords = screen_info_l.display_texcoords; - - const std::array vertices = {{ - ScreenRectVertex(x, y, texcoords.bottom, texcoords.right), - ScreenRectVertex(x + w, y, texcoords.top, texcoords.right), - ScreenRectVertex(x, y + h, texcoords.bottom, texcoords.left), - ScreenRectVertex(x + w, y + h, texcoords.top, texcoords.left), - }}; - - const u32 scale_factor = GetResolutionScaleFactor(); - glUniform4f(uniform_i_resolution, - static_cast(screen_info_l.texture.width * scale_factor), - static_cast(screen_info_l.texture.height * scale_factor), - 1.0f / static_cast(screen_info_l.texture.width * scale_factor), - 1.0f / static_cast(screen_info_l.texture.height * scale_factor)); - glUniform4f(uniform_o_resolution, w, h, 1.0f / w, 1.0f / h); - state.texture_units[0].texture_2d = screen_info_l.display_texture; - state.texture_units[1].texture_2d = screen_info_r.display_texture; - state.texture_units[0].sampler = filter_sampler.handle; - state.texture_units[1].sampler = filter_sampler.handle; - state.Apply(); - - glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices.data()); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - state.texture_units[0].texture_2d = 0; - state.texture_units[1].texture_2d = 0; - state.texture_units[0].sampler = 0; - state.texture_units[1].sampler = 0; - state.Apply(); -} - /** * Draws the emulated screens to the emulator window. */ @@ -975,76 +978,41 @@ void RendererOpenGL::DrawTopScreen(const Layout::FramebufferLayout& layout, const float top_screen_width = static_cast(top_screen.GetWidth()); const float top_screen_height = static_cast(top_screen.GetHeight()); - if (layout.is_rotated) { - switch (Settings::values.render_3d.GetValue()) { - case Settings::StereoRenderOption::Off: { - int eye = static_cast(Settings::values.mono_render_option.GetValue()); - DrawSingleScreenRotated(screen_infos[eye], top_screen_left, top_screen_top, - top_screen_width, top_screen_height); - break; - } - case Settings::StereoRenderOption::SideBySide: { - DrawSingleScreenRotated(screen_infos[0], top_screen_left / 2, top_screen_top, - top_screen_width / 2, top_screen_height); - glUniform1i(uniform_layer, 1); - DrawSingleScreenRotated(screen_infos[1], - static_cast((top_screen_left / 2) + (layout.width / 2)), - top_screen_top, top_screen_width / 2, top_screen_height); - break; - } - case Settings::StereoRenderOption::CardboardVR: { - DrawSingleScreenRotated(screen_infos[0], top_screen_left, top_screen_top, - top_screen_width, top_screen_height); - glUniform1i(uniform_layer, 1); - DrawSingleScreenRotated( - screen_infos[1], - static_cast(layout.cardboard.top_screen_right_eye + (layout.width / 2)), - top_screen_top, top_screen_width, top_screen_height); - break; - } - case Settings::StereoRenderOption::Anaglyph: - case Settings::StereoRenderOption::Interlaced: - case Settings::StereoRenderOption::ReverseInterlaced: { - DrawSingleScreenStereoRotated(screen_infos[0], screen_infos[1], top_screen_left, - top_screen_top, top_screen_width, top_screen_height); - break; - } - } - } else { - switch (Settings::values.render_3d.GetValue()) { - case Settings::StereoRenderOption::Off: { - int eye = static_cast(Settings::values.mono_render_option.GetValue()); - DrawSingleScreen(screen_infos[eye], top_screen_left, top_screen_top, top_screen_width, - top_screen_height); - break; - } - case Settings::StereoRenderOption::SideBySide: { - DrawSingleScreen(screen_infos[0], top_screen_left / 2, top_screen_top, - top_screen_width / 2, top_screen_height); - glUniform1i(uniform_layer, 1); - DrawSingleScreen(screen_infos[1], - static_cast((top_screen_left / 2) + (layout.width / 2)), - top_screen_top, top_screen_width / 2, top_screen_height); - break; - } - case Settings::StereoRenderOption::CardboardVR: { - DrawSingleScreen(screen_infos[0], (float)top_screen.left, top_screen_top, - top_screen_width, top_screen_height); - glUniform1i(uniform_layer, 1); - DrawSingleScreen( - screen_infos[1], - static_cast(layout.cardboard.top_screen_right_eye + (layout.width / 2)), - top_screen_top, top_screen_width, top_screen_height); - break; - } - case Settings::StereoRenderOption::Anaglyph: - case Settings::StereoRenderOption::Interlaced: - case Settings::StereoRenderOption::ReverseInterlaced: { - DrawSingleScreenStereo(screen_infos[0], screen_infos[1], top_screen_left, - top_screen_top, top_screen_width, top_screen_height); - break; - } - } + const auto orientation = layout.is_rotated ? Layout::DisplayOrientation::Landscape + : Layout::DisplayOrientation::Portrait; + switch (Settings::values.render_3d.GetValue()) { + case Settings::StereoRenderOption::Off: { + const int eye = static_cast(Settings::values.mono_render_option.GetValue()); + DrawSingleScreen(screen_infos[eye], top_screen_left, top_screen_top, top_screen_width, + top_screen_height, orientation); + break; + } + case Settings::StereoRenderOption::SideBySide: { + DrawSingleScreen(screen_infos[0], top_screen_left / 2, top_screen_top, top_screen_width / 2, + top_screen_height, orientation); + glUniform1i(uniform_layer, 1); + DrawSingleScreen(screen_infos[1], + static_cast((top_screen_left / 2) + (layout.width / 2)), + top_screen_top, top_screen_width / 2, top_screen_height, orientation); + break; + } + case Settings::StereoRenderOption::CardboardVR: { + DrawSingleScreen(screen_infos[0], top_screen_left, top_screen_top, top_screen_width, + top_screen_height, orientation); + glUniform1i(uniform_layer, 1); + DrawSingleScreen( + screen_infos[1], + static_cast(layout.cardboard.top_screen_right_eye + (layout.width / 2)), + top_screen_top, top_screen_width, top_screen_height, orientation); + break; + } + case Settings::StereoRenderOption::Anaglyph: + case Settings::StereoRenderOption::Interlaced: + case Settings::StereoRenderOption::ReverseInterlaced: { + DrawSingleScreenStereo(screen_infos[0], screen_infos[1], top_screen_left, top_screen_top, + top_screen_width, top_screen_height, orientation); + break; + } } } @@ -1059,75 +1027,42 @@ void RendererOpenGL::DrawBottomScreen(const Layout::FramebufferLayout& layout, const float bottom_screen_width = static_cast(bottom_screen.GetWidth()); const float bottom_screen_height = static_cast(bottom_screen.GetHeight()); - if (layout.is_rotated) { - switch (Settings::values.render_3d.GetValue()) { - case Settings::StereoRenderOption::Off: { - DrawSingleScreenRotated(screen_infos[2], bottom_screen_left, bottom_screen_top, - bottom_screen_width, bottom_screen_height); - break; - } - case Settings::StereoRenderOption::SideBySide: { - DrawSingleScreenRotated(screen_infos[2], bottom_screen_left / 2, bottom_screen_top, - bottom_screen_width / 2, bottom_screen_height); - glUniform1i(uniform_layer, 1); - DrawSingleScreenRotated( - screen_infos[2], static_cast((bottom_screen_left / 2) + (layout.width / 2)), - bottom_screen_top, bottom_screen_width / 2, bottom_screen_height); - break; - } - case Settings::StereoRenderOption::CardboardVR: { - DrawSingleScreenRotated(screen_infos[2], bottom_screen_left, bottom_screen_top, - bottom_screen_width, bottom_screen_height); - glUniform1i(uniform_layer, 1); - DrawSingleScreenRotated( - screen_infos[2], - static_cast(layout.cardboard.bottom_screen_right_eye + (layout.width / 2)), - bottom_screen_top, bottom_screen_width, bottom_screen_height); - break; - } - case Settings::StereoRenderOption::Anaglyph: - case Settings::StereoRenderOption::Interlaced: - case Settings::StereoRenderOption::ReverseInterlaced: { - DrawSingleScreenStereoRotated(screen_infos[2], screen_infos[2], bottom_screen_left, - bottom_screen_top, bottom_screen_width, - bottom_screen_height); - break; - } - } - } else { - switch (Settings::values.render_3d.GetValue()) { - case Settings::StereoRenderOption::Off: { - DrawSingleScreen(screen_infos[2], bottom_screen_left, bottom_screen_top, - bottom_screen_width, bottom_screen_height); - break; - } - case Settings::StereoRenderOption::SideBySide: { - DrawSingleScreen(screen_infos[2], bottom_screen_left / 2, bottom_screen_top, - bottom_screen_width / 2, bottom_screen_height); - glUniform1i(uniform_layer, 1); - DrawSingleScreen(screen_infos[2], - static_cast((bottom_screen_left / 2) + (layout.width / 2)), - bottom_screen_top, bottom_screen_width / 2, bottom_screen_height); - break; - } - case Settings::StereoRenderOption::CardboardVR: { - DrawSingleScreen(screen_infos[2], (float)layout.bottom_screen.left, bottom_screen_top, - bottom_screen_width, bottom_screen_height); - glUniform1i(uniform_layer, 1); - DrawSingleScreen( - screen_infos[2], - static_cast(layout.cardboard.bottom_screen_right_eye + (layout.width / 2)), - bottom_screen_top, bottom_screen_width, bottom_screen_height); - break; - } - case Settings::StereoRenderOption::Anaglyph: - case Settings::StereoRenderOption::Interlaced: - case Settings::StereoRenderOption::ReverseInterlaced: { - DrawSingleScreenStereo(screen_infos[2], screen_infos[2], bottom_screen_left, - bottom_screen_top, bottom_screen_width, bottom_screen_height); - break; - } - } + const auto orientation = layout.is_rotated ? Layout::DisplayOrientation::Landscape + : Layout::DisplayOrientation::Portrait; + + switch (Settings::values.render_3d.GetValue()) { + case Settings::StereoRenderOption::Off: { + DrawSingleScreen(screen_infos[2], bottom_screen_left, bottom_screen_top, + bottom_screen_width, bottom_screen_height, orientation); + break; + } + case Settings::StereoRenderOption::SideBySide: { + DrawSingleScreen(screen_infos[2], bottom_screen_left / 2, bottom_screen_top, + bottom_screen_width / 2, bottom_screen_height, orientation); + glUniform1i(uniform_layer, 1); + DrawSingleScreen( + screen_infos[2], static_cast((bottom_screen_left / 2) + (layout.width / 2)), + bottom_screen_top, bottom_screen_width / 2, bottom_screen_height, orientation); + break; + } + case Settings::StereoRenderOption::CardboardVR: { + DrawSingleScreen(screen_infos[2], bottom_screen_left, bottom_screen_top, + bottom_screen_width, bottom_screen_height, orientation); + glUniform1i(uniform_layer, 1); + DrawSingleScreen( + screen_infos[2], + static_cast(layout.cardboard.bottom_screen_right_eye + (layout.width / 2)), + bottom_screen_top, bottom_screen_width, bottom_screen_height, orientation); + break; + } + case Settings::StereoRenderOption::Anaglyph: + case Settings::StereoRenderOption::Interlaced: + case Settings::StereoRenderOption::ReverseInterlaced: { + DrawSingleScreenStereo(screen_infos[2], screen_infos[2], bottom_screen_left, + bottom_screen_top, bottom_screen_width, bottom_screen_height, + orientation); + break; + } } } diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h index 0b7464ad3..088a817f2 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h @@ -87,13 +87,11 @@ private: const Common::Rectangle& bottom_screen); void DrawTopScreen(const Layout::FramebufferLayout& layout, const Common::Rectangle& top_screen); - void DrawSingleScreenRotated(const ScreenInfo& screen_info, float x, float y, float w, float h); - void DrawSingleScreen(const ScreenInfo& screen_info, float x, float y, float w, float h); - void DrawSingleScreenStereoRotated(const ScreenInfo& screen_info_l, - const ScreenInfo& screen_info_r, float x, float y, float w, - float h); + void DrawSingleScreen(const ScreenInfo& screen_info, float x, float y, float w, float h, + Layout::DisplayOrientation orientation); void DrawSingleScreenStereo(const ScreenInfo& screen_info_l, const ScreenInfo& screen_info_r, - float x, float y, float w, float h); + float x, float y, float w, float h, + Layout::DisplayOrientation orientation); // Loads framebuffer from emulated memory into the display information structure void LoadFBToScreenInfo(const GPU::Regs::FramebufferConfig& framebuffer,