From 221a9b023d8c9ca55c093823e9efd6d13d0a54a2 Mon Sep 17 00:00:00 2001 From: Kevin Hartman Date: Fri, 29 Aug 2014 22:23:12 -0700 Subject: Viewport scaling and display density independence The view is scaled to be as large as possible, without changing the aspect, within the bounds of the window. On "retina" displays, or other displays where window units != pixels, the view should no longer draw incorrectly. --- src/video_core/renderer_opengl/renderer_opengl.cpp | 36 +++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) (limited to 'src/video_core/renderer_opengl/renderer_opengl.cpp') diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 8483f79be..3757482db 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -191,7 +191,8 @@ void RendererOpenGL::DrawSingleScreenRotated(const TextureInfo& texture, float x * Draws the emulated screens to the emulator window. */ void RendererOpenGL::DrawScreens() { - glViewport(0, 0, resolution_width, resolution_height); + UpdateViewportExtent(); + glViewport(viewport_extent.x, viewport_extent.y, viewport_extent.width, viewport_extent.height); glClear(GL_COLOR_BUFFER_BIT); glUseProgram(program_id); @@ -228,6 +229,39 @@ void RendererOpenGL::SetWindow(EmuWindow* window) { render_window = window; } +void RendererOpenGL::UpdateViewportExtent() { + int width_in_pixels; + int height_in_pixels; + + render_window->GetFramebufferSize(&width_in_pixels, &height_in_pixels); + + // No update needed if framebuffer size hasn't changed + if (width_in_pixels == framebuffer_size.width && height_in_pixels == framebuffer_size.height) { + return; + } + + framebuffer_size.width = width_in_pixels; + framebuffer_size.height = height_in_pixels; + + float window_aspect_ratio = static_cast(height_in_pixels) / width_in_pixels; + float emulation_aspect_ratio = static_cast(resolution_height) / resolution_width; + + if (window_aspect_ratio > emulation_aspect_ratio) { + // If the window is more narrow than the emulation content, borders are applied on the + // top and bottom of the window. + viewport_extent.width = width_in_pixels; + viewport_extent.height = emulation_aspect_ratio * viewport_extent.width; + viewport_extent.x = 0; + viewport_extent.y = (height_in_pixels - viewport_extent.height) / 2; + } else { + // Otherwise, borders are applied on the left and right sides of the window. + viewport_extent.height = height_in_pixels; + viewport_extent.width = (1 / emulation_aspect_ratio) * viewport_extent.height; + viewport_extent.x = (width_in_pixels - viewport_extent.width) / 2; + viewport_extent.y = 0; + } +} + /// Initialize the renderer void RendererOpenGL::Init() { render_window->MakeCurrent(); -- cgit v1.2.3 From bd8f491e4c08e9b9a7b852de0b50c144da8ac8c8 Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Sun, 12 Oct 2014 18:14:57 +0200 Subject: Fixup EmuWindow interface and implementations thereof. --- src/video_core/renderer_opengl/renderer_opengl.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/video_core/renderer_opengl/renderer_opengl.cpp') diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 3757482db..082a464b3 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -230,10 +230,10 @@ void RendererOpenGL::SetWindow(EmuWindow* window) { } void RendererOpenGL::UpdateViewportExtent() { - int width_in_pixels; - int height_in_pixels; + unsigned width_in_pixels; + unsigned height_in_pixels; - render_window->GetFramebufferSize(&width_in_pixels, &height_in_pixels); + std::tie(width_in_pixels, height_in_pixels) = render_window->GetFramebufferSize(); // No update needed if framebuffer size hasn't changed if (width_in_pixels == framebuffer_size.width && height_in_pixels == framebuffer_size.height) { -- cgit v1.2.3 From c5c6e095f037a0128de156103f5b98d5bf2b417c Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Thu, 13 Nov 2014 19:33:29 +0100 Subject: OpenGL Renderer: Cleanup viewport extent calculation. --- src/video_core/renderer_opengl/renderer_opengl.cpp | 49 ++++++++++------------ 1 file changed, 22 insertions(+), 27 deletions(-) (limited to 'src/video_core/renderer_opengl/renderer_opengl.cpp') diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 082a464b3..729e8e73d 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -191,8 +191,8 @@ void RendererOpenGL::DrawSingleScreenRotated(const TextureInfo& texture, float x * Draws the emulated screens to the emulator window. */ void RendererOpenGL::DrawScreens() { - UpdateViewportExtent(); - glViewport(viewport_extent.x, viewport_extent.y, viewport_extent.width, viewport_extent.height); + auto viewport_extent = GetViewportExtent(); + glViewport(viewport_extent.left, viewport_extent.top, viewport_extent.GetWidth(), viewport_extent.GetHeight()); // TODO: Or bottom? glClear(GL_COLOR_BUFFER_BIT); glUseProgram(program_id); @@ -229,37 +229,32 @@ void RendererOpenGL::SetWindow(EmuWindow* window) { render_window = window; } -void RendererOpenGL::UpdateViewportExtent() { - unsigned width_in_pixels; - unsigned height_in_pixels; +MathUtil::Rectangle RendererOpenGL::GetViewportExtent() { + unsigned framebuffer_width; + unsigned framebuffer_height; + std::tie(framebuffer_width, framebuffer_height) = render_window->GetFramebufferSize(); - std::tie(width_in_pixels, height_in_pixels) = render_window->GetFramebufferSize(); - - // No update needed if framebuffer size hasn't changed - if (width_in_pixels == framebuffer_size.width && height_in_pixels == framebuffer_size.height) { - return; - } - - framebuffer_size.width = width_in_pixels; - framebuffer_size.height = height_in_pixels; - - float window_aspect_ratio = static_cast(height_in_pixels) / width_in_pixels; + float window_aspect_ratio = static_cast(framebuffer_height) / framebuffer_width; float emulation_aspect_ratio = static_cast(resolution_height) / resolution_width; + MathUtil::Rectangle viewport_extent; if (window_aspect_ratio > emulation_aspect_ratio) { - // If the window is more narrow than the emulation content, borders are applied on the - // top and bottom of the window. - viewport_extent.width = width_in_pixels; - viewport_extent.height = emulation_aspect_ratio * viewport_extent.width; - viewport_extent.x = 0; - viewport_extent.y = (height_in_pixels - viewport_extent.height) / 2; + // Window is narrower than the emulation content => apply borders to the top and bottom + unsigned viewport_height = emulation_aspect_ratio * framebuffer_width; + viewport_extent.left = 0; + viewport_extent.top = (framebuffer_height - viewport_height) / 2; + viewport_extent.right = viewport_extent.left + framebuffer_width; + viewport_extent.bottom = viewport_extent.top + viewport_height; } else { - // Otherwise, borders are applied on the left and right sides of the window. - viewport_extent.height = height_in_pixels; - viewport_extent.width = (1 / emulation_aspect_ratio) * viewport_extent.height; - viewport_extent.x = (width_in_pixels - viewport_extent.width) / 2; - viewport_extent.y = 0; + // Otherwise, apply borders to the left and right sides of the window. + unsigned viewport_width = framebuffer_height / emulation_aspect_ratio; + viewport_extent.left = (framebuffer_width - viewport_width) / 2; + viewport_extent.top = 0; + viewport_extent.right = viewport_extent.left + viewport_width; + viewport_extent.bottom = viewport_extent.top + framebuffer_height; } + + return viewport_extent; } /// Initialize the renderer -- cgit v1.2.3