summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Kevin Hartman2014-08-29 22:23:12 -0700
committerGravatar Tony Wasserka2014-11-18 13:06:05 +0100
commit221a9b023d8c9ca55c093823e9efd6d13d0a54a2 (patch)
tree57a26a0e11416b366688d00c4a2c9216fa0cde78 /src
parentAdd a GUI logging channel. (diff)
downloadyuzu-221a9b023d8c9ca55c093823e9efd6d13d0a54a2.tar.gz
yuzu-221a9b023d8c9ca55c093823e9efd6d13d0a54a2.tar.xz
yuzu-221a9b023d8c9ca55c093823e9efd6d13d0a54a2.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/citra/emu_window/emu_window_glfw.cpp5
-rw-r--r--src/citra/emu_window/emu_window_glfw.h5
-rw-r--r--src/citra_qt/bootmanager.cpp24
-rw-r--r--src/citra_qt/bootmanager.hxx1
-rw-r--r--src/common/emu_window.h7
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp36
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.h15
7 files changed, 89 insertions, 4 deletions
diff --git a/src/citra/emu_window/emu_window_glfw.cpp b/src/citra/emu_window/emu_window_glfw.cpp
index 0c774bbc5..d0f6e9a9e 100644
--- a/src/citra/emu_window/emu_window_glfw.cpp
+++ b/src/citra/emu_window/emu_window_glfw.cpp
@@ -34,6 +34,10 @@ const bool EmuWindow_GLFW::IsOpen() {
34 return glfwWindowShouldClose(m_render_window) == 0; 34 return glfwWindowShouldClose(m_render_window) == 0;
35} 35}
36 36
37void EmuWindow_GLFW::GetFramebufferSize(int* fbWidth, int* fbHeight) {
38 glfwGetFramebufferSize(m_render_window, fbWidth, fbHeight);
39}
40
37/// EmuWindow_GLFW constructor 41/// EmuWindow_GLFW constructor
38EmuWindow_GLFW::EmuWindow_GLFW() { 42EmuWindow_GLFW::EmuWindow_GLFW() {
39 keyboard_id = KeyMap::NewDeviceId(); 43 keyboard_id = KeyMap::NewDeviceId();
@@ -64,6 +68,7 @@ EmuWindow_GLFW::EmuWindow_GLFW() {
64 glfwSetWindowUserPointer(m_render_window, this); 68 glfwSetWindowUserPointer(m_render_window, this);
65 glfwSetKeyCallback(m_render_window, OnKeyEvent); 69 glfwSetKeyCallback(m_render_window, OnKeyEvent);
66 70
71
67 DoneCurrent(); 72 DoneCurrent();
68} 73}
69 74
diff --git a/src/citra/emu_window/emu_window_glfw.h b/src/citra/emu_window/emu_window_glfw.h
index 7c3072145..e96228765 100644
--- a/src/citra/emu_window/emu_window_glfw.h
+++ b/src/citra/emu_window/emu_window_glfw.h
@@ -21,7 +21,7 @@ public:
21 21
22 /// Makes the graphics context current for the caller thread 22 /// Makes the graphics context current for the caller thread
23 void MakeCurrent() override; 23 void MakeCurrent() override;
24 24
25 /// Releases (dunno if this is the "right" word) the GLFW context from the caller thread 25 /// Releases (dunno if this is the "right" word) the GLFW context from the caller thread
26 void DoneCurrent() override; 26 void DoneCurrent() override;
27 27
@@ -32,6 +32,9 @@ public:
32 32
33 void ReloadSetKeymaps() override; 33 void ReloadSetKeymaps() override;
34 34
35 /// Gets the size of the window in pixels
36 void GetFramebufferSize(int* fbWidth, int* fbHeight);
37
35private: 38private:
36 GLFWwindow* m_render_window; ///< Internal GLFW render window 39 GLFWwindow* m_render_window; ///< Internal GLFW render window
37 40
diff --git a/src/citra_qt/bootmanager.cpp b/src/citra_qt/bootmanager.cpp
index 20824692d..516e115fd 100644
--- a/src/citra_qt/bootmanager.cpp
+++ b/src/citra_qt/bootmanager.cpp
@@ -2,6 +2,12 @@
2#include <QKeyEvent> 2#include <QKeyEvent>
3#include <QApplication> 3#include <QApplication>
4 4
5#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
6// Required for screen DPI information
7#include <QScreen>
8#include <QWindow>
9#endif
10
5#include "common/common.h" 11#include "common/common.h"
6#include "bootmanager.hxx" 12#include "bootmanager.hxx"
7 13
@@ -176,6 +182,24 @@ void GRenderWindow::PollEvents() {
176 */ 182 */
177} 183}
178 184
185// On Qt 5.1+, this correctly gets the size of the framebuffer (pixels).
186//
187// Older versions get the window size (density independent pixels),
188// and hence, do not support DPI scaling ("retina" displays).
189// The result will be a viewport that is smaller than the extent of the window.
190void GRenderWindow::GetFramebufferSize(int* fbWidth, int* fbHeight)
191{
192#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
193 int pixelRatio = child->QPaintDevice::devicePixelRatio();
194
195 *fbWidth = child->QPaintDevice::width() * pixelRatio;
196 *fbHeight = child->QPaintDevice::height() * pixelRatio;
197#else
198 *fbWidth = child->QPaintDevice::width();
199 *fbHeight = child->QPaintDevice::height();
200#endif
201}
202
179void GRenderWindow::BackupGeometry() 203void GRenderWindow::BackupGeometry()
180{ 204{
181 geometry = ((QGLWidget*)this)->saveGeometry(); 205 geometry = ((QGLWidget*)this)->saveGeometry();
diff --git a/src/citra_qt/bootmanager.hxx b/src/citra_qt/bootmanager.hxx
index f8afc403e..ec3e1fe71 100644
--- a/src/citra_qt/bootmanager.hxx
+++ b/src/citra_qt/bootmanager.hxx
@@ -96,6 +96,7 @@ public:
96 void MakeCurrent() override; 96 void MakeCurrent() override;
97 void DoneCurrent() override; 97 void DoneCurrent() override;
98 void PollEvents() override; 98 void PollEvents() override;
99 void GetFramebufferSize(int* fbWidth, int* fbHeight) override;
99 100
100 void BackupGeometry(); 101 void BackupGeometry();
101 void RestoreGeometry(); 102 void RestoreGeometry();
diff --git a/src/common/emu_window.h b/src/common/emu_window.h
index 6c2b598f6..ba9d4fa76 100644
--- a/src/common/emu_window.h
+++ b/src/common/emu_window.h
@@ -49,8 +49,11 @@ public:
49 void SetConfig(const WindowConfig& val) { 49 void SetConfig(const WindowConfig& val) {
50 m_config = val; 50 m_config = val;
51 } 51 }
52 52
53 int GetClientAreaWidth() const { 53 /// Gets the size of the window in pixels
54 virtual void GetFramebufferSize(int* fbWidth, int* fbHeight) = 0;
55
56 int GetClientAreaWidth() const {
54 return m_client_area_width; 57 return m_client_area_width;
55 } 58 }
56 59
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
191 * Draws the emulated screens to the emulator window. 191 * Draws the emulated screens to the emulator window.
192 */ 192 */
193void RendererOpenGL::DrawScreens() { 193void RendererOpenGL::DrawScreens() {
194 glViewport(0, 0, resolution_width, resolution_height); 194 UpdateViewportExtent();
195 glViewport(viewport_extent.x, viewport_extent.y, viewport_extent.width, viewport_extent.height);
195 glClear(GL_COLOR_BUFFER_BIT); 196 glClear(GL_COLOR_BUFFER_BIT);
196 197
197 glUseProgram(program_id); 198 glUseProgram(program_id);
@@ -228,6 +229,39 @@ void RendererOpenGL::SetWindow(EmuWindow* window) {
228 render_window = window; 229 render_window = window;
229} 230}
230 231
232void RendererOpenGL::UpdateViewportExtent() {
233 int width_in_pixels;
234 int height_in_pixels;
235
236 render_window->GetFramebufferSize(&width_in_pixels, &height_in_pixels);
237
238 // No update needed if framebuffer size hasn't changed
239 if (width_in_pixels == framebuffer_size.width && height_in_pixels == framebuffer_size.height) {
240 return;
241 }
242
243 framebuffer_size.width = width_in_pixels;
244 framebuffer_size.height = height_in_pixels;
245
246 float window_aspect_ratio = static_cast<float>(height_in_pixels) / width_in_pixels;
247 float emulation_aspect_ratio = static_cast<float>(resolution_height) / resolution_width;
248
249 if (window_aspect_ratio > emulation_aspect_ratio) {
250 // If the window is more narrow than the emulation content, borders are applied on the
251 // top and bottom of the window.
252 viewport_extent.width = width_in_pixels;
253 viewport_extent.height = emulation_aspect_ratio * viewport_extent.width;
254 viewport_extent.x = 0;
255 viewport_extent.y = (height_in_pixels - viewport_extent.height) / 2;
256 } else {
257 // Otherwise, borders are applied on the left and right sides of the window.
258 viewport_extent.height = height_in_pixels;
259 viewport_extent.width = (1 / emulation_aspect_ratio) * viewport_extent.height;
260 viewport_extent.x = (width_in_pixels - viewport_extent.width) / 2;
261 viewport_extent.y = 0;
262 }
263}
264
231/// Initialize the renderer 265/// Initialize the renderer
232void RendererOpenGL::Init() { 266void RendererOpenGL::Init() {
233 render_window->MakeCurrent(); 267 render_window->MakeCurrent();
diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h
index eed201a95..d440e2bc7 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.h
+++ b/src/video_core/renderer_opengl/renderer_opengl.h
@@ -52,12 +52,27 @@ private:
52 static void LoadFBToActiveGLTexture(const GPU::Regs::FramebufferConfig& framebuffer, 52 static void LoadFBToActiveGLTexture(const GPU::Regs::FramebufferConfig& framebuffer,
53 const TextureInfo& texture); 53 const TextureInfo& texture);
54 54
55 /// Updates the viewport rectangle
56 void UpdateViewportExtent();
57
55 EmuWindow* render_window; ///< Handle to render window 58 EmuWindow* render_window; ///< Handle to render window
56 u32 last_mode; ///< Last render mode 59 u32 last_mode; ///< Last render mode
57 60
58 int resolution_width; ///< Current resolution width 61 int resolution_width; ///< Current resolution width
59 int resolution_height; ///< Current resolution height 62 int resolution_height; ///< Current resolution height
60 63
64 struct {
65 int width;
66 int height;
67 } framebuffer_size; ///< Current framebuffer size
68
69 struct {
70 int x;
71 int y;
72 int width;
73 int height;
74 } viewport_extent; ///< Current viewport rectangle
75
61 // OpenGL object IDs 76 // OpenGL object IDs
62 GLuint vertex_array_handle; 77 GLuint vertex_array_handle;
63 GLuint vertex_buffer_handle; 78 GLuint vertex_buffer_handle;