mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	Merge pull request #165 from neobrain/viewport-scaling
Stretch emulation output to render window and be display density independent
This commit is contained in:
		
						commit
						40acd63631
					
				
					 11 changed files with 284 additions and 86 deletions
				
			
		|  | @ -9,17 +9,33 @@ | |||
| #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). | ||||
|  * - 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 | ||||
| { | ||||
| 
 | ||||
| public: | ||||
|     /// Data structure to store an emuwindow configuration
 | ||||
|     /// Data structure to store emuwindow configuration
 | ||||
|     struct WindowConfig { | ||||
|         bool    fullscreen; | ||||
|         int     res_width; | ||||
|         int     res_height; | ||||
|         std::pair<unsigned,unsigned> min_client_area_size; | ||||
|     }; | ||||
| 
 | ||||
|     /// Swap buffers to display the next frame
 | ||||
|  | @ -42,52 +58,96 @@ public: | |||
|     /// Signals a key release action to the HID module
 | ||||
|     static void KeyReleased(KeyMap::HostDeviceKey key); | ||||
| 
 | ||||
|     WindowConfig GetConfig() const { | ||||
|         return m_config; | ||||
|     /**
 | ||||
|      * 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) { | ||||
|         m_config = val; | ||||
|     } | ||||
|      | ||||
|     int GetClientAreaWidth() const {  | ||||
|         return m_client_area_width; | ||||
|         config = val; | ||||
|     } | ||||
| 
 | ||||
|     void SetClientAreaWidth(const int val) { | ||||
|         m_client_area_width = val; | ||||
|     /**
 | ||||
|       * Gets the framebuffer size in pixels. | ||||
|       * @note This method is thread-safe | ||||
|       */ | ||||
|     const std::pair<unsigned,unsigned> GetFramebufferSize() const { | ||||
|         return framebuffer_size; | ||||
|     } | ||||
| 
 | ||||
|     int GetClientAreaHeight() const { | ||||
|         return m_client_area_height; | ||||
|     } | ||||
| 
 | ||||
|     void SetClientAreaHeight(const int val) { | ||||
|         m_client_area_height = val; | ||||
|     } | ||||
| 
 | ||||
|     std::string GetWindowTitle() const {  | ||||
|         return m_window_title; | ||||
|     } | ||||
|      | ||||
|     void SetWindowTitle(std::string val) { | ||||
|         m_window_title = val; | ||||
|     /**
 | ||||
|      * 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<unsigned,unsigned> GetClientAreaSize() const { | ||||
|         return std::make_pair(client_area_width, client_area_height); | ||||
|     } | ||||
| 
 | ||||
| protected: | ||||
|     EmuWindow(): | ||||
|         m_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) | ||||
|     {} | ||||
|     EmuWindow() | ||||
|     { | ||||
|         // TODO: Find a better place to set this.
 | ||||
|         config.min_client_area_size = std::make_pair(400u, 480u); | ||||
|         active_config = config; | ||||
|     } | ||||
|     virtual ~EmuWindow() {} | ||||
| 
 | ||||
|     std::string m_window_title;     ///< Current window title, should be used by window impl.
 | ||||
|     /**
 | ||||
|      * 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. | ||||
|      * @todo Actually call this in existing implementations. | ||||
|      */ | ||||
|     void ProcessConfigurationChanges() { | ||||
|         // TODO: For proper thread safety, we should eventually implement a proper
 | ||||
|         // multiple-writer/single-reader queue...
 | ||||
| 
 | ||||
|     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.
 | ||||
|         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<unsigned,unsigned>& 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<unsigned,unsigned>& size) { | ||||
|         client_area_width = size.first; | ||||
|         client_area_height = size.second; | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     WindowConfig m_config;                ///< Internal configuration
 | ||||
|     /**
 | ||||
|      * 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<unsigned,unsigned>& minimal_size) { | ||||
|         // By default, ignore this request and do nothing.
 | ||||
|     } | ||||
| 
 | ||||
|     std::pair<unsigned,unsigned> 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 (changes pending for being applied in ProcessConfigurationChanges)
 | ||||
|     WindowConfig active_config;  ///< Internal active configuration
 | ||||
| }; | ||||
|  |  | |||
|  | @ -69,6 +69,7 @@ enum LOG_TYPE { | |||
|     HW, | ||||
|     TIME, | ||||
|     NETPLAY, | ||||
|     GUI, | ||||
| 
 | ||||
|     NUMBER_OF_LOGS // Must be last
 | ||||
| }; | ||||
|  |  | |||
|  | @ -75,6 +75,7 @@ LogManager::LogManager() | |||
|     m_Log[LogTypes::ACTIONREPLAY]       = new LogContainer("ActionReplay",      "ActionReplay"); | ||||
|     m_Log[LogTypes::MEMCARD_MANAGER]    = new LogContainer("MemCard Manager",   "MemCard Manager"); | ||||
|     m_Log[LogTypes::NETPLAY]            = new LogContainer("NETPLAY",           "Netplay"); | ||||
|     m_Log[LogTypes::GUI]                = new LogContainer("GUI",               "GUI"); | ||||
| 
 | ||||
|     m_fileLog = new FileLogListener(FileUtil::GetUserPath(F_MAINLOG_IDX).c_str()); | ||||
|     m_consoleLog = new ConsoleListener(); | ||||
|  |  | |||
|  | @ -7,6 +7,7 @@ | |||
| #include "common/common.h" | ||||
| 
 | ||||
| #include <algorithm> | ||||
| #include <type_traits> | ||||
| #include <vector> | ||||
| 
 | ||||
| namespace MathUtil | ||||
|  | @ -109,11 +110,11 @@ struct Rectangle | |||
|     Rectangle(T theLeft, T theTop, T theRight, T theBottom) | ||||
|         : left(theLeft), top(theTop), right(theRight), bottom(theBottom) | ||||
|     { } | ||||
|      | ||||
| 
 | ||||
|     bool operator==(const Rectangle& r) { return left==r.left && top==r.top && right==r.right && bottom==r.bottom; } | ||||
| 
 | ||||
|     T GetWidth() const { return abs(right - left); } | ||||
|     T GetHeight() const { return abs(bottom - top); } | ||||
|     T GetWidth() const { return std::abs(static_cast<typename std::make_signed<T>::type>(right - left)); } | ||||
|     T GetHeight() const { return std::abs(static_cast<typename std::make_signed<T>::type>(bottom - top)); } | ||||
| 
 | ||||
|     // If the rectangle is in a coordinate system with a lower-left origin, use
 | ||||
|     // this Clamp.
 | ||||
|  | @ -127,7 +128,7 @@ struct Rectangle | |||
| 
 | ||||
|     // If the rectangle is in a coordinate system with an upper-left origin,
 | ||||
|     // use this Clamp.
 | ||||
|     void ClampUL(T x1, T y1, T x2, T y2)  | ||||
|     void ClampUL(T x1, T y1, T x2, T y2) | ||||
|     { | ||||
|         if (left < x1) left = x1; | ||||
|         if (right > x2) right = x2; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue