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/common/emu_window.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/common/emu_window.h') 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: void SetConfig(const WindowConfig& val) { m_config = val; } - - int GetClientAreaWidth() const { + + /// Gets the size of the window in pixels + virtual void GetFramebufferSize(int* fbWidth, int* fbHeight) = 0; + + int GetClientAreaWidth() const { return m_client_area_width; } -- 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/common/emu_window.h | 61 ++++++++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 28 deletions(-) (limited to 'src/common/emu_window.h') diff --git a/src/common/emu_window.h b/src/common/emu_window.h index ba9d4fa76..72c40c6a4 100644 --- a/src/common/emu_window.h +++ b/src/common/emu_window.h @@ -43,54 +43,59 @@ public: static void KeyReleased(KeyMap::HostDeviceKey key); WindowConfig GetConfig() const { - return m_config; + return config; } void SetConfig(const WindowConfig& val) { - m_config = val; + config = val; } - /// Gets the size of the window in pixels - virtual void GetFramebufferSize(int* fbWidth, int* fbHeight) = 0; - - int GetClientAreaWidth() const { - return m_client_area_width; - } - - void SetClientAreaWidth(const int val) { - m_client_area_width = val; + /** + * Gets the size of the framebuffer in pixels + */ + const std::pair GetFramebufferSize() const { + return framebuffer_size; } - int GetClientAreaHeight() const { - return m_client_area_height; + /** + * Gets window client area width in logical coordinates + */ + std::pair GetClientAreaSize() const { + return std::make_pair(client_area_width, client_area_height); } - void SetClientAreaHeight(const int val) { - m_client_area_height = val; + std::string GetWindowTitle() const { + return window_title; } - std::string GetWindowTitle() const { - return m_window_title; - } - - void SetWindowTitle(std::string val) { - m_window_title = val; + void SetWindowTitle(const std::string& val) { + window_title = val; } protected: - EmuWindow(): - m_window_title(Common::StringFromFormat("Citra | %s-%s", Common::g_scm_branch, Common::g_scm_desc)), + EmuWindow() : // TODO: What the hell... -.- - don't hardcode dimensions here without applying them in a sensible manner... + window_title(Common::StringFromFormat("Citra | %s-%s", Common::g_scm_branch, Common::g_scm_desc)) m_client_area_width(640), - m_client_area_height(480) + m_client_area_height(480), {} virtual ~EmuWindow() {} - std::string m_window_title; ///< Current window title, should be used by window impl. + std::pair NotifyFramebufferSizeChanged(const std::pair& size) { + framebuffer_size = size; + } - int m_client_area_width; ///< Current client width, should be set by window impl. - int m_client_area_height; ///< Current client height, should be set by window impl. + void NotifyClientAreaSizeChanged(std::pair size) { + client_area_width = size.first; + client_area_height = size.second; + } private: - WindowConfig m_config; ///< Internal configuration + std::string window_title; ///< Current window title, should be used by window impl. + + std::pair framebuffer_size; + + unsigned client_area_width; ///< Current client width, should be set by window impl. + unsigned client_area_height; ///< Current client height, should be set by window impl. + WindowConfig config; ///< Internal configuration }; -- cgit v1.2.3 From 722ce2258949c5edf81c946faedfd040efeb38a6 Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Sun, 12 Oct 2014 22:46:33 +0200 Subject: EmuWindow: Add support for specifying minimal client area sizes. --- src/common/emu_window.h | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) (limited to 'src/common/emu_window.h') diff --git a/src/common/emu_window.h b/src/common/emu_window.h index 72c40c6a4..baacc6da2 100644 --- a/src/common/emu_window.h +++ b/src/common/emu_window.h @@ -20,6 +20,7 @@ public: bool fullscreen; int res_width; int res_height; + std::pair min_client_area_size; }; /// Swap buffers to display the next frame @@ -42,8 +43,8 @@ public: /// Signals a key release action to the HID module static void KeyReleased(KeyMap::HostDeviceKey key); - WindowConfig GetConfig() const { - return config; + const WindowConfig& GetActiveConfig() const { + return active_config; } void SetConfig(const WindowConfig& val) { @@ -72,24 +73,40 @@ public: window_title = val; } + // Only call this from the GUI thread! + void ProcessConfigurationChanges() { + // TODO: For proper thread safety, we should eventually implement a proper + // multiple-writer/single-reader queue... + + if (config.min_client_area_size != active_config.min_client_area_size) { + OnMinimalClientAreaChangeRequest(config.min_client_area_size); + config.min_client_area_size = active_config.min_client_area_size; + } + } + protected: - EmuWindow() : // TODO: What the hell... -.- - don't hardcode dimensions here without applying them in a sensible manner... + EmuWindow() : window_title(Common::StringFromFormat("Citra | %s-%s", Common::g_scm_branch, Common::g_scm_desc)) - m_client_area_width(640), - m_client_area_height(480), - {} + { + // TODO + config.min_client_area_size = std::make_pair(300u, 500u); + active_config = config; + } virtual ~EmuWindow() {} std::pair NotifyFramebufferSizeChanged(const std::pair& size) { framebuffer_size = size; } - void NotifyClientAreaSizeChanged(std::pair size) { + void NotifyClientAreaSizeChanged(const std::pair& size) { client_area_width = size.first; client_area_height = size.second; } private: + virtual void OnMinimalClientAreaChangeRequest(const std::pair& minimal_size) { + } + std::string window_title; ///< Current window title, should be used by window impl. std::pair framebuffer_size; @@ -97,5 +114,6 @@ private: unsigned client_area_width; ///< Current client width, should be set by window impl. unsigned client_area_height; ///< Current client height, should be set by window impl. - WindowConfig config; ///< Internal configuration + WindowConfig config; ///< Internal configuration (changes pending for being applied in ProcessConfigurationChanges) + WindowConfig active_config; ///< Internal active configuration }; -- cgit v1.2.3 From ded9c8a826b2b69b4c7a63bf4cea9805b5244788 Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Thu, 13 Nov 2014 18:12:27 +0100 Subject: EmuWindow: Add documentation. --- src/common/emu_window.h | 75 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 57 insertions(+), 18 deletions(-) (limited to 'src/common/emu_window.h') diff --git a/src/common/emu_window.h b/src/common/emu_window.h index baacc6da2..1465743f2 100644 --- a/src/common/emu_window.h +++ b/src/common/emu_window.h @@ -9,13 +9,26 @@ #include "common/string_util.h" #include "common/key_map.h" -// Abstraction class used to provide an interface between emulation code and the frontend (e.g. SDL, -// QGLWidget, GLFW, etc...) +/** + * Abstraction class used to provide an interface between emulation code and the frontend + * (e.g. SDL, QGLWidget, GLFW, etc...). + * + * Design notes on the interaction between EmuWindow and the emulation core: + * - Generally, decisions on anything visible to the user should be left up to the GUI. + * For example, the emulation core should not try to dictate some window title or size. + * This stuff is not the core's business and only causes problems with regards to thread-safety + * anyway. + * - Under certain circumstances, it may be desirable for the core to politely request the GUI + * to set e.g. a minimum window size. However, the GUI should always be free to ignore any + * such hints. + * - EmuWindow may expose some of its state as read-only to the emulation core, however care + * should be taken to make sure the provided information is self-consistent. This requires + * some sort of synchronization (most of this is still a TODO). + */ class EmuWindow { - public: - /// Data structure to store an emuwindow configuration + /// Data structure to store emuwindow configuration struct WindowConfig { bool fullscreen; int res_width; @@ -43,48 +56,51 @@ public: /// Signals a key release action to the HID module static void KeyReleased(KeyMap::HostDeviceKey key); + /** + * Returns currently active configuration. + * @note Accesses to the returned object need not be consistent because it may be modified in another thread + */ const WindowConfig& GetActiveConfig() const { return active_config; } + /** + * Requests the internal configuration to be replaced by the specified argument at some point in the future. + * @note This method is thread-safe, because it delays configuration changes to the GUI event loop. Hence there is no guarantee on when the requested configuration will be active. + */ void SetConfig(const WindowConfig& val) { config = val; } /** - * Gets the size of the framebuffer in pixels + * Gets the framebuffer size in pixels. + * @note This method is thread-safe */ const std::pair GetFramebufferSize() const { return framebuffer_size; } /** - * Gets window client area width in logical coordinates + * Gets window client area width in logical coordinates. + * @note For high-DPI systems, this is smaller than the framebuffer size. + * @note This method is thread-safe */ std::pair GetClientAreaSize() const { return std::make_pair(client_area_width, client_area_height); } + // TODO: Remove std::string GetWindowTitle() const { return window_title; } + // TODO: Remove void SetWindowTitle(const std::string& val) { window_title = val; } - // Only call this from the GUI thread! - void ProcessConfigurationChanges() { - // TODO: For proper thread safety, we should eventually implement a proper - // multiple-writer/single-reader queue... - - if (config.min_client_area_size != active_config.min_client_area_size) { - OnMinimalClientAreaChangeRequest(config.min_client_area_size); - config.min_client_area_size = active_config.min_client_area_size; - } - } - protected: + // TODO: Remove window title initialization EmuWindow() : window_title(Common::StringFromFormat("Citra | %s-%s", Common::g_scm_branch, Common::g_scm_desc)) { @@ -94,10 +110,32 @@ protected: } virtual ~EmuWindow() {} - std::pair NotifyFramebufferSizeChanged(const std::pair& size) { + /** + * Processes any pending configuration changes from the last SetConfig call. + * @note Implementations will usually want to call this from the GUI thread. + */ + void ProcessConfigurationChanges() { + // TODO: For proper thread safety, we should eventually implement a proper + // multiple-writer/single-reader queue... + + if (config.min_client_area_size != active_config.min_client_area_size) { + OnMinimalClientAreaChangeRequest(config.min_client_area_size); + config.min_client_area_size = active_config.min_client_area_size; + } + } + + /** + * Update internal framebuffer size with the given parameter. + * @note EmuWindow implementations will usually use this in window resize event handlers. + */ + void NotifyFramebufferSizeChanged(const std::pair& size) { framebuffer_size = size; } + /** + * Update internal client area size with the given parameter. + * @note EmuWindow implementations will usually use this in window resize event handlers. + */ void NotifyClientAreaSizeChanged(const std::pair& size) { client_area_width = size.first; client_area_height = size.second; @@ -107,6 +145,7 @@ private: virtual void OnMinimalClientAreaChangeRequest(const std::pair& minimal_size) { } + // TODO: Remove std::string window_title; ///< Current window title, should be used by window impl. std::pair framebuffer_size; -- cgit v1.2.3 From 182476c96a6c75e90a90cbb52048bf754fdd786d Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Thu, 13 Nov 2014 18:17:39 +0100 Subject: EmuWindow: Remove window title getters/setters. The window title is none of the emulation core's business. The GUI code is free to put whatever it wants there. Providing properly thread-safe window title getters and setters is a mess anyway. --- src/common/emu_window.h | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) (limited to 'src/common/emu_window.h') diff --git a/src/common/emu_window.h b/src/common/emu_window.h index 1465743f2..3817a7734 100644 --- a/src/common/emu_window.h +++ b/src/common/emu_window.h @@ -89,20 +89,8 @@ public: return std::make_pair(client_area_width, client_area_height); } - // TODO: Remove - std::string GetWindowTitle() const { - return window_title; - } - - // TODO: Remove - void SetWindowTitle(const std::string& val) { - window_title = val; - } - protected: - // TODO: Remove window title initialization - EmuWindow() : - window_title(Common::StringFromFormat("Citra | %s-%s", Common::g_scm_branch, Common::g_scm_desc)) + EmuWindow() { // TODO config.min_client_area_size = std::make_pair(300u, 500u); @@ -145,9 +133,6 @@ private: virtual void OnMinimalClientAreaChangeRequest(const std::pair& minimal_size) { } - // TODO: Remove - std::string window_title; ///< Current window title, should be used by window impl. - std::pair framebuffer_size; unsigned client_area_width; ///< Current client width, should be set by window impl. -- cgit v1.2.3 From 19bb01c223a36b7c02253cfedeb9e07c0d5a692b Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Thu, 13 Nov 2014 18:24:15 +0100 Subject: EmuWindow: Better document the purpose of OnMinimalClientAreaChangeRequest. --- src/common/emu_window.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/common/emu_window.h') diff --git a/src/common/emu_window.h b/src/common/emu_window.h index 3817a7734..a9cf71690 100644 --- a/src/common/emu_window.h +++ b/src/common/emu_window.h @@ -100,6 +100,8 @@ protected: /** * Processes any pending configuration changes from the last SetConfig call. + * This method invokes OnMinimalClientAreaChangeRequest if the corresponding configuration + * field changed. * @note Implementations will usually want to call this from the GUI thread. */ void ProcessConfigurationChanges() { @@ -130,7 +132,12 @@ protected: } private: + /** + * Handler called when the minimal client area was requested to be changed via SetConfig. + * For the request to be honored, EmuWindow implementations will usually reimplement this function. + */ virtual void OnMinimalClientAreaChangeRequest(const std::pair& minimal_size) { + // By default, ignore this request and do nothing. } std::pair framebuffer_size; -- cgit v1.2.3 From 6a6464807ab5ba804e7b0dd4bfe1629cd5457278 Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Thu, 13 Nov 2014 20:31:34 +0100 Subject: EmuWindow: Add a TODO. Implementing this function currently is not critical, as we don't perform any configuration changes, yet. However, the interface is a good starting point for adding this functionality. --- src/common/emu_window.h | 1 + 1 file changed, 1 insertion(+) (limited to 'src/common/emu_window.h') diff --git a/src/common/emu_window.h b/src/common/emu_window.h index a9cf71690..52c870036 100644 --- a/src/common/emu_window.h +++ b/src/common/emu_window.h @@ -103,6 +103,7 @@ protected: * This method invokes OnMinimalClientAreaChangeRequest if the corresponding configuration * field changed. * @note Implementations will usually want to call this from the GUI thread. + * @todo Actually call this in existing implementations. */ void ProcessConfigurationChanges() { // TODO: For proper thread safety, we should eventually implement a proper -- cgit v1.2.3 From 5785f764aba431967881df01acc08a3405c97097 Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Thu, 13 Nov 2014 20:45:37 +0100 Subject: EmuWindow: Add some explicit documentation and set proper minimal client area size. --- src/common/emu_window.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/common/emu_window.h') diff --git a/src/common/emu_window.h b/src/common/emu_window.h index 52c870036..4cb94fed1 100644 --- a/src/common/emu_window.h +++ b/src/common/emu_window.h @@ -24,6 +24,8 @@ * - EmuWindow may expose some of its state as read-only to the emulation core, however care * should be taken to make sure the provided information is self-consistent. This requires * some sort of synchronization (most of this is still a TODO). + * - DO NOT TREAT THIS CLASS AS A GUI TOOLKIT ABSTRACTION LAYER. That's not what it is. Please + * re-read the upper points again and think about it if you don't see this. */ class EmuWindow { @@ -92,8 +94,8 @@ public: protected: EmuWindow() { - // TODO - config.min_client_area_size = std::make_pair(300u, 500u); + // TODO: Find a better place to set this. + config.min_client_area_size = std::make_pair(400u, 480u); active_config = config; } virtual ~EmuWindow() {} -- cgit v1.2.3