diff options
| author | 2015-03-07 18:18:40 -0500 | |
|---|---|---|
| committer | 2015-03-07 18:18:40 -0500 | |
| commit | 06bf4715810489548a9a3b5e9274dfc78bc3fc4d (patch) | |
| tree | a2722e2b7e1356d9cb9725f18f0561fcaf815ec1 /src | |
| parent | Merge pull request #637 from Subv/etc (diff) | |
| parent | Set framebuffer layout from EmuWindow. (diff) | |
| download | yuzu-06bf4715810489548a9a3b5e9274dfc78bc3fc4d.tar.gz yuzu-06bf4715810489548a9a3b5e9274dfc78bc3fc4d.tar.xz yuzu-06bf4715810489548a9a3b5e9274dfc78bc3fc4d.zip | |
Merge pull request #636 from bunnei/refactor-screen-win
Set framebuffer layout from EmuWindow.
Diffstat (limited to 'src')
| -rw-r--r-- | src/citra/emu_window/emu_window_glfw.cpp | 11 | ||||
| -rw-r--r-- | src/citra_qt/bootmanager.cpp | 3 | ||||
| -rw-r--r-- | src/common/emu_window.cpp | 50 | ||||
| -rw-r--r-- | src/common/emu_window.h | 32 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/renderer_opengl.cpp | 48 | ||||
| -rw-r--r-- | src/video_core/video_core.cpp | 3 | ||||
| -rw-r--r-- | src/video_core/video_core.h | 1 |
7 files changed, 88 insertions, 60 deletions
diff --git a/src/citra/emu_window/emu_window_glfw.cpp b/src/citra/emu_window/emu_window_glfw.cpp index ec3e8cf34..81231e1e5 100644 --- a/src/citra/emu_window/emu_window_glfw.cpp +++ b/src/citra/emu_window/emu_window_glfw.cpp | |||
| @@ -36,20 +36,13 @@ const bool EmuWindow_GLFW::IsOpen() { | |||
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | void EmuWindow_GLFW::OnFramebufferResizeEvent(GLFWwindow* win, int width, int height) { | 38 | void EmuWindow_GLFW::OnFramebufferResizeEvent(GLFWwindow* win, int width, int height) { |
| 39 | ASSERT(width > 0); | 39 | GetEmuWindow(win)->NotifyFramebufferLayoutChanged(EmuWindow::FramebufferLayout::DefaultScreenLayout(width, height)); |
| 40 | ASSERT(height > 0); | ||
| 41 | |||
| 42 | GetEmuWindow(win)->NotifyFramebufferSizeChanged(std::pair<unsigned,unsigned>(width, height)); | ||
| 43 | } | 40 | } |
| 44 | 41 | ||
| 45 | void EmuWindow_GLFW::OnClientAreaResizeEvent(GLFWwindow* win, int width, int height) { | 42 | void EmuWindow_GLFW::OnClientAreaResizeEvent(GLFWwindow* win, int width, int height) { |
| 46 | ASSERT(width > 0); | ||
| 47 | ASSERT(height > 0); | ||
| 48 | |||
| 49 | // NOTE: GLFW provides no proper way to set a minimal window size. | 43 | // NOTE: GLFW provides no proper way to set a minimal window size. |
| 50 | // Hence, we just ignore the corresponding EmuWindow hint. | 44 | // Hence, we just ignore the corresponding EmuWindow hint. |
| 51 | 45 | OnFramebufferResizeEvent(win, width, height); | |
| 52 | GetEmuWindow(win)->NotifyClientAreaSizeChanged(std::pair<unsigned,unsigned>(width, height)); | ||
| 53 | } | 46 | } |
| 54 | 47 | ||
| 55 | /// EmuWindow_GLFW constructor | 48 | /// EmuWindow_GLFW constructor |
diff --git a/src/citra_qt/bootmanager.cpp b/src/citra_qt/bootmanager.cpp index 6514288a0..a040e75c1 100644 --- a/src/citra_qt/bootmanager.cpp +++ b/src/citra_qt/bootmanager.cpp | |||
| @@ -155,6 +155,7 @@ GRenderWindow::GRenderWindow(QWidget* parent) : QWidget(parent), emu_thread(this | |||
| 155 | 155 | ||
| 156 | child = new GGLWidgetInternal(fmt, this); | 156 | child = new GGLWidgetInternal(fmt, this); |
| 157 | QBoxLayout* layout = new QHBoxLayout(this); | 157 | QBoxLayout* layout = new QHBoxLayout(this); |
| 158 | |||
| 158 | resize(VideoCore::kScreenTopWidth, VideoCore::kScreenTopHeight + VideoCore::kScreenBottomHeight); | 159 | resize(VideoCore::kScreenTopWidth, VideoCore::kScreenTopHeight + VideoCore::kScreenBottomHeight); |
| 159 | layout->addWidget(child); | 160 | layout->addWidget(child); |
| 160 | layout->setMargin(0); | 161 | layout->setMargin(0); |
| @@ -234,7 +235,7 @@ void GRenderWindow::OnFramebufferSizeChanged() | |||
| 234 | unsigned height = child->QPaintDevice::height(); | 235 | unsigned height = child->QPaintDevice::height(); |
| 235 | #endif | 236 | #endif |
| 236 | 237 | ||
| 237 | NotifyFramebufferSizeChanged(std::make_pair(width, height)); | 238 | NotifyFramebufferLayoutChanged(EmuWindow::FramebufferLayout::DefaultScreenLayout(width, height)); |
| 238 | } | 239 | } |
| 239 | 240 | ||
| 240 | void GRenderWindow::BackupGeometry() | 241 | void GRenderWindow::BackupGeometry() |
diff --git a/src/common/emu_window.cpp b/src/common/emu_window.cpp index 48bb35db5..1082ae26d 100644 --- a/src/common/emu_window.cpp +++ b/src/common/emu_window.cpp | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "emu_window.h" | 5 | #include "emu_window.h" |
| 6 | #include "video_core/video_core.h" | ||
| 6 | 7 | ||
| 7 | void EmuWindow::KeyPressed(KeyMap::HostDeviceKey key) { | 8 | void EmuWindow::KeyPressed(KeyMap::HostDeviceKey key) { |
| 8 | Service::HID::PadState mapped_key = KeyMap::GetPadKey(key); | 9 | Service::HID::PadState mapped_key = KeyMap::GetPadKey(key); |
| @@ -15,3 +16,52 @@ void EmuWindow::KeyReleased(KeyMap::HostDeviceKey key) { | |||
| 15 | 16 | ||
| 16 | Service::HID::PadButtonRelease(mapped_key); | 17 | Service::HID::PadButtonRelease(mapped_key); |
| 17 | } | 18 | } |
| 19 | |||
| 20 | EmuWindow::FramebufferLayout EmuWindow::FramebufferLayout::DefaultScreenLayout(int width, int height) { | ||
| 21 | ASSERT(width > 0); | ||
| 22 | ASSERT(height > 0); | ||
| 23 | |||
| 24 | EmuWindow::FramebufferLayout res = { width, height, {}, {} }; | ||
| 25 | |||
| 26 | float window_aspect_ratio = static_cast<float>(height) / width; | ||
| 27 | float emulation_aspect_ratio = static_cast<float>(VideoCore::kScreenTopHeight * 2) / | ||
| 28 | VideoCore::kScreenTopWidth; | ||
| 29 | |||
| 30 | if (window_aspect_ratio > emulation_aspect_ratio) { | ||
| 31 | // Window is narrower than the emulation content => apply borders to the top and bottom | ||
| 32 | int viewport_height = static_cast<int>(std::round(emulation_aspect_ratio * width)); | ||
| 33 | |||
| 34 | res.top_screen.left = 0; | ||
| 35 | res.top_screen.right = res.top_screen.left + width; | ||
| 36 | res.top_screen.top = (height - viewport_height) / 2; | ||
| 37 | res.top_screen.bottom = res.top_screen.top + viewport_height / 2; | ||
| 38 | |||
| 39 | int bottom_width = static_cast<int>((static_cast<float>(VideoCore::kScreenBottomWidth) / | ||
| 40 | VideoCore::kScreenTopWidth) * (res.top_screen.right - res.top_screen.left)); | ||
| 41 | int bottom_border = ((res.top_screen.right - res.top_screen.left) - bottom_width) / 2; | ||
| 42 | |||
| 43 | res.bottom_screen.left = bottom_border; | ||
| 44 | res.bottom_screen.right = res.bottom_screen.left + bottom_width; | ||
| 45 | res.bottom_screen.top = res.top_screen.bottom; | ||
| 46 | res.bottom_screen.bottom = res.bottom_screen.top + viewport_height / 2; | ||
| 47 | } else { | ||
| 48 | // Otherwise, apply borders to the left and right sides of the window. | ||
| 49 | int viewport_width = static_cast<int>(std::round(height / emulation_aspect_ratio)); | ||
| 50 | |||
| 51 | res.top_screen.left = (width - viewport_width) / 2; | ||
| 52 | res.top_screen.right = res.top_screen.left + viewport_width; | ||
| 53 | res.top_screen.top = 0; | ||
| 54 | res.top_screen.bottom = res.top_screen.top + height / 2; | ||
| 55 | |||
| 56 | int bottom_width = static_cast<int>((static_cast<float>(VideoCore::kScreenBottomWidth) / | ||
| 57 | VideoCore::kScreenTopWidth) * (res.top_screen.right - res.top_screen.left)); | ||
| 58 | int bottom_border = ((res.top_screen.right - res.top_screen.left) - bottom_width) / 2; | ||
| 59 | |||
| 60 | res.bottom_screen.left = res.top_screen.left + bottom_border; | ||
| 61 | res.bottom_screen.right = res.bottom_screen.left + bottom_width; | ||
| 62 | res.bottom_screen.top = res.top_screen.bottom; | ||
| 63 | res.bottom_screen.bottom = res.bottom_screen.top + height / 2; | ||
| 64 | } | ||
| 65 | |||
| 66 | return res; | ||
| 67 | } | ||
diff --git a/src/common/emu_window.h b/src/common/emu_window.h index 1ad4b82a3..b6862030e 100644 --- a/src/common/emu_window.h +++ b/src/common/emu_window.h | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include "common/scm_rev.h" | 8 | #include "common/scm_rev.h" |
| 9 | #include "common/string_util.h" | 9 | #include "common/string_util.h" |
| 10 | #include "common/key_map.h" | 10 | #include "common/key_map.h" |
| 11 | #include "common/math_util.h" | ||
| 11 | 12 | ||
| 12 | /** | 13 | /** |
| 13 | * Abstraction class used to provide an interface between emulation code and the frontend | 14 | * Abstraction class used to provide an interface between emulation code and the frontend |
| @@ -38,6 +39,23 @@ public: | |||
| 38 | std::pair<unsigned,unsigned> min_client_area_size; | 39 | std::pair<unsigned,unsigned> min_client_area_size; |
| 39 | }; | 40 | }; |
| 40 | 41 | ||
| 42 | /// Describes the layout of the window framebuffer (size and top/bottom screen positions) | ||
| 43 | struct FramebufferLayout { | ||
| 44 | |||
| 45 | /** | ||
| 46 | * Factory method for constructing a default FramebufferLayout | ||
| 47 | * @param width Window framebuffer width in pixels | ||
| 48 | * @param height Window framebuffer height in pixels | ||
| 49 | * @return Newly created FramebufferLayout object with default screen regions initialized | ||
| 50 | */ | ||
| 51 | static FramebufferLayout DefaultScreenLayout(int width, int height); | ||
| 52 | |||
| 53 | unsigned width; | ||
| 54 | unsigned height; | ||
| 55 | MathUtil::Rectangle<unsigned> top_screen; | ||
| 56 | MathUtil::Rectangle<unsigned> bottom_screen; | ||
| 57 | }; | ||
| 58 | |||
| 41 | /// Swap buffers to display the next frame | 59 | /// Swap buffers to display the next frame |
| 42 | virtual void SwapBuffers() = 0; | 60 | virtual void SwapBuffers() = 0; |
| 43 | 61 | ||
| @@ -75,11 +93,11 @@ public: | |||
| 75 | } | 93 | } |
| 76 | 94 | ||
| 77 | /** | 95 | /** |
| 78 | * Gets the framebuffer size in pixels. | 96 | * Gets the framebuffer layout (width, height, and screen regions) |
| 79 | * @note This method is thread-safe | 97 | * @note This method is thread-safe |
| 80 | */ | 98 | */ |
| 81 | const std::pair<unsigned,unsigned> GetFramebufferSize() const { | 99 | const FramebufferLayout& GetFramebufferLayout() const { |
| 82 | return framebuffer_size; | 100 | return framebuffer_layout; |
| 83 | } | 101 | } |
| 84 | 102 | ||
| 85 | /** | 103 | /** |
| @@ -118,11 +136,11 @@ protected: | |||
| 118 | } | 136 | } |
| 119 | 137 | ||
| 120 | /** | 138 | /** |
| 121 | * Update internal framebuffer size with the given parameter. | 139 | * Update framebuffer layout with the given parameter. |
| 122 | * @note EmuWindow implementations will usually use this in window resize event handlers. | 140 | * @note EmuWindow implementations will usually use this in window resize event handlers. |
| 123 | */ | 141 | */ |
| 124 | void NotifyFramebufferSizeChanged(const std::pair<unsigned,unsigned>& size) { | 142 | void NotifyFramebufferLayoutChanged(const FramebufferLayout& layout) { |
| 125 | framebuffer_size = size; | 143 | framebuffer_layout = layout; |
| 126 | } | 144 | } |
| 127 | 145 | ||
| 128 | /** | 146 | /** |
| @@ -143,7 +161,7 @@ private: | |||
| 143 | // By default, ignore this request and do nothing. | 161 | // By default, ignore this request and do nothing. |
| 144 | } | 162 | } |
| 145 | 163 | ||
| 146 | std::pair<unsigned,unsigned> framebuffer_size; | 164 | FramebufferLayout framebuffer_layout; ///< Current framebuffer layout |
| 147 | 165 | ||
| 148 | unsigned client_area_width; ///< Current client width, should be set by window impl. | 166 | unsigned client_area_width; ///< Current client width, should be set by window impl. |
| 149 | unsigned client_area_height; ///< Current client height, should be set by window impl. | 167 | unsigned client_area_height; ///< Current client height, should be set by window impl. |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index db7538ddd..95ab96340 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp | |||
| @@ -254,28 +254,26 @@ void RendererOpenGL::DrawSingleScreenRotated(const TextureInfo& texture, float x | |||
| 254 | * Draws the emulated screens to the emulator window. | 254 | * Draws the emulated screens to the emulator window. |
| 255 | */ | 255 | */ |
| 256 | void RendererOpenGL::DrawScreens() { | 256 | void RendererOpenGL::DrawScreens() { |
| 257 | auto viewport_extent = GetViewportExtent(); | 257 | auto layout = render_window->GetFramebufferLayout(); |
| 258 | glViewport(viewport_extent.left, viewport_extent.top, viewport_extent.GetWidth(), viewport_extent.GetHeight()); // TODO: Or bottom? | 258 | |
| 259 | glViewport(0, 0, layout.width, layout.height); | ||
| 259 | glClear(GL_COLOR_BUFFER_BIT); | 260 | glClear(GL_COLOR_BUFFER_BIT); |
| 260 | 261 | ||
| 261 | glUseProgram(program_id); | 262 | glUseProgram(program_id); |
| 262 | 263 | ||
| 263 | // Set projection matrix | 264 | // Set projection matrix |
| 264 | std::array<GLfloat, 3*2> ortho_matrix = MakeOrthographicMatrix((float)resolution_width, (float)resolution_height); | 265 | std::array<GLfloat, 3 * 2> ortho_matrix = MakeOrthographicMatrix((float)layout.width, |
| 266 | (float)layout.height); | ||
| 265 | glUniformMatrix3x2fv(uniform_modelview_matrix, 1, GL_FALSE, ortho_matrix.data()); | 267 | glUniformMatrix3x2fv(uniform_modelview_matrix, 1, GL_FALSE, ortho_matrix.data()); |
| 266 | 268 | ||
| 267 | // Bind texture in Texture Unit 0 | 269 | // Bind texture in Texture Unit 0 |
| 268 | glActiveTexture(GL_TEXTURE0); | 270 | glActiveTexture(GL_TEXTURE0); |
| 269 | glUniform1i(uniform_color_texture, 0); | 271 | glUniform1i(uniform_color_texture, 0); |
| 270 | 272 | ||
| 271 | const float max_width = std::max((float)VideoCore::kScreenTopWidth, (float)VideoCore::kScreenBottomWidth); | 273 | DrawSingleScreenRotated(textures[0], (float)layout.top_screen.left, (float)layout.top_screen.top, |
| 272 | const float top_x = 0.5f * (max_width - VideoCore::kScreenTopWidth); | 274 | (float)layout.top_screen.GetWidth(), (float)layout.top_screen.GetHeight()); |
| 273 | const float bottom_x = 0.5f * (max_width - VideoCore::kScreenBottomWidth); | 275 | DrawSingleScreenRotated(textures[1], (float)layout.bottom_screen.left,(float)layout.bottom_screen.top, |
| 274 | 276 | (float)layout.bottom_screen.GetWidth(), (float)layout.bottom_screen.GetHeight()); | |
| 275 | DrawSingleScreenRotated(textures[0], top_x, 0, | ||
| 276 | (float)VideoCore::kScreenTopWidth, (float)VideoCore::kScreenTopHeight); | ||
| 277 | DrawSingleScreenRotated(textures[1], bottom_x, (float)VideoCore::kScreenTopHeight, | ||
| 278 | (float)VideoCore::kScreenBottomWidth, (float)VideoCore::kScreenBottomHeight); | ||
| 279 | 277 | ||
| 280 | m_current_frame++; | 278 | m_current_frame++; |
| 281 | } | 279 | } |
| @@ -292,34 +290,6 @@ void RendererOpenGL::SetWindow(EmuWindow* window) { | |||
| 292 | render_window = window; | 290 | render_window = window; |
| 293 | } | 291 | } |
| 294 | 292 | ||
| 295 | MathUtil::Rectangle<unsigned> RendererOpenGL::GetViewportExtent() { | ||
| 296 | unsigned framebuffer_width; | ||
| 297 | unsigned framebuffer_height; | ||
| 298 | std::tie(framebuffer_width, framebuffer_height) = render_window->GetFramebufferSize(); | ||
| 299 | |||
| 300 | float window_aspect_ratio = static_cast<float>(framebuffer_height) / framebuffer_width; | ||
| 301 | float emulation_aspect_ratio = static_cast<float>(resolution_height) / resolution_width; | ||
| 302 | |||
| 303 | MathUtil::Rectangle<unsigned> viewport_extent; | ||
| 304 | if (window_aspect_ratio > emulation_aspect_ratio) { | ||
| 305 | // Window is narrower than the emulation content => apply borders to the top and bottom | ||
| 306 | unsigned viewport_height = static_cast<unsigned>(std::round(emulation_aspect_ratio * framebuffer_width)); | ||
| 307 | viewport_extent.left = 0; | ||
| 308 | viewport_extent.top = (framebuffer_height - viewport_height) / 2; | ||
| 309 | viewport_extent.right = viewport_extent.left + framebuffer_width; | ||
| 310 | viewport_extent.bottom = viewport_extent.top + viewport_height; | ||
| 311 | } else { | ||
| 312 | // Otherwise, apply borders to the left and right sides of the window. | ||
| 313 | unsigned viewport_width = static_cast<unsigned>(std::round(framebuffer_height / emulation_aspect_ratio)); | ||
| 314 | viewport_extent.left = (framebuffer_width - viewport_width) / 2; | ||
| 315 | viewport_extent.top = 0; | ||
| 316 | viewport_extent.right = viewport_extent.left + viewport_width; | ||
| 317 | viewport_extent.bottom = viewport_extent.top + framebuffer_height; | ||
| 318 | } | ||
| 319 | |||
| 320 | return viewport_extent; | ||
| 321 | } | ||
| 322 | |||
| 323 | /// Initialize the renderer | 293 | /// Initialize the renderer |
| 324 | void RendererOpenGL::Init() { | 294 | void RendererOpenGL::Init() { |
| 325 | render_window->MakeCurrent(); | 295 | render_window->MakeCurrent(); |
diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp index 0a236595c..b9d4ede3a 100644 --- a/src/video_core/video_core.cpp +++ b/src/video_core/video_core.cpp | |||
| @@ -18,7 +18,6 @@ namespace VideoCore { | |||
| 18 | 18 | ||
| 19 | EmuWindow* g_emu_window = nullptr; ///< Frontend emulator window | 19 | EmuWindow* g_emu_window = nullptr; ///< Frontend emulator window |
| 20 | RendererBase* g_renderer = nullptr; ///< Renderer plugin | 20 | RendererBase* g_renderer = nullptr; ///< Renderer plugin |
| 21 | int g_current_frame = 0; | ||
| 22 | 21 | ||
| 23 | /// Initialize the video core | 22 | /// Initialize the video core |
| 24 | void Init(EmuWindow* emu_window) { | 23 | void Init(EmuWindow* emu_window) { |
| @@ -27,8 +26,6 @@ void Init(EmuWindow* emu_window) { | |||
| 27 | g_renderer->SetWindow(g_emu_window); | 26 | g_renderer->SetWindow(g_emu_window); |
| 28 | g_renderer->Init(); | 27 | g_renderer->Init(); |
| 29 | 28 | ||
| 30 | g_current_frame = 0; | ||
| 31 | |||
| 32 | LOG_DEBUG(Render, "initialized OK"); | 29 | LOG_DEBUG(Render, "initialized OK"); |
| 33 | } | 30 | } |
| 34 | 31 | ||
diff --git a/src/video_core/video_core.h b/src/video_core/video_core.h index b782f17bd..1b51d39bf 100644 --- a/src/video_core/video_core.h +++ b/src/video_core/video_core.h | |||
| @@ -30,7 +30,6 @@ static const int kScreenBottomHeight = 240; ///< 3DS bottom screen height | |||
| 30 | // --------------------- | 30 | // --------------------- |
| 31 | 31 | ||
| 32 | extern RendererBase* g_renderer; ///< Renderer plugin | 32 | extern RendererBase* g_renderer; ///< Renderer plugin |
| 33 | extern int g_current_frame; ///< Current frame | ||
| 34 | extern EmuWindow* g_emu_window; ///< Emu window | 33 | extern EmuWindow* g_emu_window; ///< Emu window |
| 35 | 34 | ||
| 36 | /// Start the video core | 35 | /// Start the video core |