mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 13:50:03 +00:00 
			
		
		
		
	Dependencies: Remove GLFW, Add SDL2
citra: Remove GLFW, Add SDL2 FindSDL2: Do not CACHE SDL2_* variables if library is not found EmuWindow_SDL2: Set minimal client area at initialisation time EmuWindow_SDL2: Corrections EmuWindow_SDL2: Fix no decorations on startup on OS X cmake: windows_copy_files
This commit is contained in:
		
							parent
							
								
									2b00bdec1f
								
							
						
					
					
						commit
						ba2a54a9dd
					
				
					 17 changed files with 551 additions and 304 deletions
				
			
		|  | @ -5,7 +5,7 @@ add_subdirectory(common) | |||
| add_subdirectory(core) | ||||
| add_subdirectory(video_core) | ||||
| add_subdirectory(audio_core) | ||||
| if (ENABLE_GLFW) | ||||
| if (ENABLE_SDL2) | ||||
|     add_subdirectory(citra) | ||||
| endif() | ||||
| if (ENABLE_QT) | ||||
|  |  | |||
|  | @ -1,11 +1,11 @@ | |||
| set(SRCS | ||||
|             emu_window/emu_window_glfw.cpp | ||||
|             emu_window/emu_window_sdl2.cpp | ||||
|             citra.cpp | ||||
|             config.cpp | ||||
|             citra.rc | ||||
|             ) | ||||
| set(HEADERS | ||||
|             emu_window/emu_window_glfw.h | ||||
|             emu_window/emu_window_sdl2.h | ||||
|             config.h | ||||
|             default_ini.h | ||||
|             resource.h | ||||
|  | @ -13,12 +13,11 @@ set(HEADERS | |||
| 
 | ||||
| create_directory_groups(${SRCS} ${HEADERS}) | ||||
| 
 | ||||
| include_directories(${GLFW_INCLUDE_DIRS}) | ||||
| link_directories(${GLFW_LIBRARY_DIRS}) | ||||
| include_directories(${SDL2_INCLUDE_DIR}) | ||||
| 
 | ||||
| add_executable(citra ${SRCS} ${HEADERS}) | ||||
| target_link_libraries(citra core video_core audio_core common) | ||||
| target_link_libraries(citra ${GLFW_LIBRARIES} ${OPENGL_gl_LIBRARY} inih glad) | ||||
| target_link_libraries(citra ${SDL2_LIBRARY} ${OPENGL_gl_LIBRARY} inih glad) | ||||
| if (MSVC) | ||||
|     target_link_libraries(citra getopt) | ||||
| endif() | ||||
|  | @ -27,3 +26,13 @@ target_link_libraries(citra ${PLATFORM_LIBRARIES}) | |||
| if(${CMAKE_SYSTEM_NAME} MATCHES "Linux|FreeBSD|OpenBSD|NetBSD") | ||||
|     install(TARGETS citra RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/bin") | ||||
| endif() | ||||
| 
 | ||||
| if (MSVC) | ||||
|     include(WindowsCopyFiles) | ||||
| 
 | ||||
|     set(DLL_DEST "${CMAKE_BINARY_DIR}/bin/$<CONFIG>/") | ||||
| 
 | ||||
|     windows_copy_files(citra ${SDL2_DLL_DIR} ${DLL_DEST} SDL2.dll) | ||||
| 
 | ||||
|     unset(DLL_DEST) | ||||
| endif() | ||||
|  |  | |||
|  | @ -27,7 +27,7 @@ | |||
| #include "core/loader/loader.h" | ||||
| 
 | ||||
| #include "citra/config.h" | ||||
| #include "citra/emu_window/emu_window_glfw.h" | ||||
| #include "citra/emu_window/emu_window_sdl2.h" | ||||
| 
 | ||||
| #include "video_core/video_core.h" | ||||
| 
 | ||||
|  | @ -76,7 +76,7 @@ int main(int argc, char **argv) { | |||
|     GDBStub::ToggleServer(Settings::values.use_gdbstub); | ||||
|     GDBStub::SetServerPort(static_cast<u32>(Settings::values.gdbstub_port)); | ||||
| 
 | ||||
|     EmuWindow_GLFW* emu_window = new EmuWindow_GLFW; | ||||
|     EmuWindow_SDL2* emu_window = new EmuWindow_SDL2; | ||||
| 
 | ||||
|     VideoCore::g_hw_renderer_enabled = Settings::values.use_hw_renderer; | ||||
|     VideoCore::g_shader_jit_enabled = Settings::values.use_shader_jit; | ||||
|  |  | |||
|  | @ -2,10 +2,10 @@ | |||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #define GLFW_INCLUDE_NONE | ||||
| #include <GLFW/glfw3.h> | ||||
| #include <inih/cpp/INIReader.h> | ||||
| 
 | ||||
| #include <SDL.h> | ||||
| 
 | ||||
| #include "citra/default_ini.h" | ||||
| 
 | ||||
| #include "common/file_util.h" | ||||
|  | @ -17,8 +17,8 @@ | |||
| 
 | ||||
| Config::Config() { | ||||
|     // TODO: Don't hardcode the path; let the frontend decide where to put the config files.
 | ||||
|     glfw_config_loc = FileUtil::GetUserPath(D_CONFIG_IDX) + "glfw-config.ini"; | ||||
|     glfw_config = new INIReader(glfw_config_loc); | ||||
|     sdl2_config_loc = FileUtil::GetUserPath(D_CONFIG_IDX) + "sdl2-config.ini"; | ||||
|     sdl2_config = new INIReader(sdl2_config_loc); | ||||
| 
 | ||||
|     Reload(); | ||||
| } | ||||
|  | @ -41,51 +41,51 @@ bool Config::LoadINI(INIReader* config, const char* location, const std::string& | |||
| } | ||||
| 
 | ||||
| static const std::array<int, Settings::NativeInput::NUM_INPUTS> defaults = { | ||||
|     GLFW_KEY_A, GLFW_KEY_S, GLFW_KEY_Z, GLFW_KEY_X, | ||||
|     GLFW_KEY_Q, GLFW_KEY_W, GLFW_KEY_1, GLFW_KEY_2, | ||||
|     GLFW_KEY_M, GLFW_KEY_N, GLFW_KEY_B, | ||||
|     GLFW_KEY_T, GLFW_KEY_G, GLFW_KEY_F, GLFW_KEY_H, | ||||
|     GLFW_KEY_UP, GLFW_KEY_DOWN, GLFW_KEY_LEFT, GLFW_KEY_RIGHT, | ||||
|     GLFW_KEY_I, GLFW_KEY_K, GLFW_KEY_J, GLFW_KEY_L | ||||
|     SDL_SCANCODE_A, SDL_SCANCODE_S, SDL_SCANCODE_Z, SDL_SCANCODE_X, | ||||
|     SDL_SCANCODE_Q, SDL_SCANCODE_W, SDL_SCANCODE_1, SDL_SCANCODE_2, | ||||
|     SDL_SCANCODE_M, SDL_SCANCODE_N, SDL_SCANCODE_B, | ||||
|     SDL_SCANCODE_T, SDL_SCANCODE_G, SDL_SCANCODE_F, SDL_SCANCODE_H, | ||||
|     SDL_SCANCODE_UP, SDL_SCANCODE_DOWN, SDL_SCANCODE_LEFT, SDL_SCANCODE_RIGHT, | ||||
|     SDL_SCANCODE_I, SDL_SCANCODE_K, SDL_SCANCODE_J, SDL_SCANCODE_L | ||||
| }; | ||||
| 
 | ||||
| void Config::ReadValues() { | ||||
|     // Controls
 | ||||
|     for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) { | ||||
|         Settings::values.input_mappings[Settings::NativeInput::All[i]] = | ||||
|             glfw_config->GetInteger("Controls", Settings::NativeInput::Mapping[i], defaults[i]); | ||||
|             sdl2_config->GetInteger("Controls", Settings::NativeInput::Mapping[i], defaults[i]); | ||||
|     } | ||||
| 
 | ||||
|     // Core
 | ||||
|     Settings::values.frame_skip = glfw_config->GetInteger("Core", "frame_skip", 0); | ||||
|     Settings::values.frame_skip = sdl2_config->GetInteger("Core", "frame_skip", 0); | ||||
| 
 | ||||
|     // Renderer
 | ||||
|     Settings::values.use_hw_renderer = glfw_config->GetBoolean("Renderer", "use_hw_renderer", false); | ||||
|     Settings::values.use_shader_jit = glfw_config->GetBoolean("Renderer", "use_shader_jit", true); | ||||
|     Settings::values.use_hw_renderer = sdl2_config->GetBoolean("Renderer", "use_hw_renderer", false); | ||||
|     Settings::values.use_shader_jit = sdl2_config->GetBoolean("Renderer", "use_shader_jit", true); | ||||
| 
 | ||||
|     Settings::values.bg_red   = (float)glfw_config->GetReal("Renderer", "bg_red",   1.0); | ||||
|     Settings::values.bg_green = (float)glfw_config->GetReal("Renderer", "bg_green", 1.0); | ||||
|     Settings::values.bg_blue  = (float)glfw_config->GetReal("Renderer", "bg_blue",  1.0); | ||||
|     Settings::values.bg_red   = (float)sdl2_config->GetReal("Renderer", "bg_red",   1.0); | ||||
|     Settings::values.bg_green = (float)sdl2_config->GetReal("Renderer", "bg_green", 1.0); | ||||
|     Settings::values.bg_blue  = (float)sdl2_config->GetReal("Renderer", "bg_blue",  1.0); | ||||
| 
 | ||||
|     // Data Storage
 | ||||
|     Settings::values.use_virtual_sd = glfw_config->GetBoolean("Data Storage", "use_virtual_sd", true); | ||||
|     Settings::values.use_virtual_sd = sdl2_config->GetBoolean("Data Storage", "use_virtual_sd", true); | ||||
| 
 | ||||
|     // System Region
 | ||||
|     Settings::values.region_value = glfw_config->GetInteger("System Region", "region_value", 1); | ||||
|     Settings::values.region_value = sdl2_config->GetInteger("System Region", "region_value", 1); | ||||
| 
 | ||||
|     // Miscellaneous
 | ||||
|     Settings::values.log_filter = glfw_config->Get("Miscellaneous", "log_filter", "*:Info"); | ||||
|     Settings::values.log_filter = sdl2_config->Get("Miscellaneous", "log_filter", "*:Info"); | ||||
| 
 | ||||
|     // Debugging
 | ||||
|     Settings::values.use_gdbstub = glfw_config->GetBoolean("Debugging", "use_gdbstub", false); | ||||
|     Settings::values.gdbstub_port = glfw_config->GetInteger("Debugging", "gdbstub_port", 24689); | ||||
|     Settings::values.use_gdbstub = sdl2_config->GetBoolean("Debugging", "use_gdbstub", false); | ||||
|     Settings::values.gdbstub_port = sdl2_config->GetInteger("Debugging", "gdbstub_port", 24689); | ||||
| } | ||||
| 
 | ||||
| void Config::Reload() { | ||||
|     LoadINI(glfw_config, glfw_config_loc.c_str(), DefaultINI::glfw_config_file); | ||||
|     LoadINI(sdl2_config, sdl2_config_loc.c_str(), DefaultINI::sdl2_config_file); | ||||
|     ReadValues(); | ||||
| } | ||||
| 
 | ||||
| Config::~Config() { | ||||
|     delete glfw_config; | ||||
|     delete sdl2_config; | ||||
| } | ||||
|  |  | |||
|  | @ -9,8 +9,8 @@ | |||
| class INIReader; | ||||
| 
 | ||||
| class Config { | ||||
|     INIReader* glfw_config; | ||||
|     std::string glfw_config_loc; | ||||
|     INIReader* sdl2_config; | ||||
|     std::string sdl2_config_loc; | ||||
| 
 | ||||
|     bool LoadINI(INIReader* config, const char* location, const std::string& default_contents="", bool retry=true); | ||||
|     void ReadValues(); | ||||
|  |  | |||
|  | @ -6,7 +6,7 @@ | |||
| 
 | ||||
| namespace DefaultINI { | ||||
| 
 | ||||
| const char* glfw_config_file = R"( | ||||
| const char* sdl2_config_file = R"( | ||||
| [Controls] | ||||
| pad_start = | ||||
| pad_select = | ||||
|  |  | |||
|  | @ -1,168 +0,0 @@ | |||
| // Copyright 2014 Citra Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include <algorithm> | ||||
| #include <cstdlib> | ||||
| #include <string> | ||||
| 
 | ||||
| // Let’s use our own GL header, instead of one from GLFW.
 | ||||
| #include <glad/glad.h> | ||||
| #define GLFW_INCLUDE_NONE | ||||
| #include <GLFW/glfw3.h> | ||||
| 
 | ||||
| #include "common/assert.h" | ||||
| #include "common/key_map.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "common/scm_rev.h" | ||||
| #include "common/string_util.h" | ||||
| 
 | ||||
| #include "video_core/video_core.h" | ||||
| 
 | ||||
| #include "core/settings.h" | ||||
| #include "core/hle/service/hid/hid.h" | ||||
| 
 | ||||
| #include "citra/emu_window/emu_window_glfw.h" | ||||
| 
 | ||||
| EmuWindow_GLFW* EmuWindow_GLFW::GetEmuWindow(GLFWwindow* win) { | ||||
|     return static_cast<EmuWindow_GLFW*>(glfwGetWindowUserPointer(win)); | ||||
| } | ||||
| 
 | ||||
| void EmuWindow_GLFW::OnMouseButtonEvent(GLFWwindow* win, int button, int action, int mods) { | ||||
|     if (button == GLFW_MOUSE_BUTTON_LEFT) { | ||||
|         auto emu_window = GetEmuWindow(win); | ||||
|         auto layout = emu_window->GetFramebufferLayout(); | ||||
|         double x, y; | ||||
|         glfwGetCursorPos(win, &x, &y); | ||||
| 
 | ||||
|         if (action == GLFW_PRESS) | ||||
|             emu_window->TouchPressed(static_cast<unsigned>(x), static_cast<unsigned>(y)); | ||||
|         else if (action == GLFW_RELEASE) | ||||
|             emu_window->TouchReleased(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void EmuWindow_GLFW::OnCursorPosEvent(GLFWwindow* win, double x, double y) { | ||||
|     GetEmuWindow(win)->TouchMoved(static_cast<unsigned>(std::max(x, 0.0)), static_cast<unsigned>(std::max(y, 0.0))); | ||||
| } | ||||
| 
 | ||||
| /// Called by GLFW when a key event occurs
 | ||||
| void EmuWindow_GLFW::OnKeyEvent(GLFWwindow* win, int key, int scancode, int action, int mods) { | ||||
|     auto emu_window = GetEmuWindow(win); | ||||
|     int keyboard_id = emu_window->keyboard_id; | ||||
| 
 | ||||
|     if (action == GLFW_PRESS) { | ||||
|         emu_window->KeyPressed({key, keyboard_id}); | ||||
|     } else if (action == GLFW_RELEASE) { | ||||
|         emu_window->KeyReleased({key, keyboard_id}); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /// Whether the window is still open, and a close request hasn't yet been sent
 | ||||
| const bool EmuWindow_GLFW::IsOpen() { | ||||
|     return glfwWindowShouldClose(m_render_window) == 0; | ||||
| } | ||||
| 
 | ||||
| void EmuWindow_GLFW::OnFramebufferResizeEvent(GLFWwindow* win, int width, int height) { | ||||
|     GetEmuWindow(win)->NotifyFramebufferLayoutChanged(EmuWindow::FramebufferLayout::DefaultScreenLayout(width, height)); | ||||
| } | ||||
| 
 | ||||
| void EmuWindow_GLFW::OnClientAreaResizeEvent(GLFWwindow* win, int width, int height) { | ||||
|     // NOTE: GLFW provides no proper way to set a minimal window size.
 | ||||
|     //       Hence, we just ignore the corresponding EmuWindow hint.
 | ||||
|     OnFramebufferResizeEvent(win, width, height); | ||||
| } | ||||
| 
 | ||||
| /// EmuWindow_GLFW constructor
 | ||||
| EmuWindow_GLFW::EmuWindow_GLFW() { | ||||
|     keyboard_id = KeyMap::NewDeviceId(); | ||||
| 
 | ||||
|     ReloadSetKeymaps(); | ||||
| 
 | ||||
|     glfwSetErrorCallback([](int error, const char *desc){ | ||||
|         LOG_ERROR(Frontend, "GLFW 0x%08x: %s", error, desc); | ||||
|     }); | ||||
| 
 | ||||
|     // Initialize the window
 | ||||
|     if(glfwInit() != GL_TRUE) { | ||||
|         LOG_CRITICAL(Frontend, "Failed to initialize GLFW! Exiting..."); | ||||
|         exit(1); | ||||
|     } | ||||
|     glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); | ||||
|     glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); | ||||
|     // GLFW on OSX requires these window hints to be set to create a 3.2+ GL context.
 | ||||
|     glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); | ||||
|     glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); | ||||
| 
 | ||||
|     std::string window_title = Common::StringFromFormat("Citra | %s-%s", Common::g_scm_branch, Common::g_scm_desc); | ||||
|     m_render_window = glfwCreateWindow(VideoCore::kScreenTopWidth, | ||||
|         (VideoCore::kScreenTopHeight + VideoCore::kScreenBottomHeight), | ||||
|         window_title.c_str(), nullptr, nullptr); | ||||
| 
 | ||||
|     if (m_render_window == nullptr) { | ||||
|         LOG_CRITICAL(Frontend, "Failed to create GLFW window! Exiting..."); | ||||
|         exit(1); | ||||
|     } | ||||
| 
 | ||||
|     glfwSetWindowUserPointer(m_render_window, this); | ||||
| 
 | ||||
|     // Notify base interface about window state
 | ||||
|     int width, height; | ||||
|     glfwGetFramebufferSize(m_render_window, &width, &height); | ||||
|     OnFramebufferResizeEvent(m_render_window, width, height); | ||||
| 
 | ||||
|     glfwGetWindowSize(m_render_window, &width, &height); | ||||
|     OnClientAreaResizeEvent(m_render_window, width, height); | ||||
| 
 | ||||
|     // Setup callbacks
 | ||||
|     glfwSetKeyCallback(m_render_window, OnKeyEvent); | ||||
|     glfwSetMouseButtonCallback(m_render_window, OnMouseButtonEvent); | ||||
|     glfwSetCursorPosCallback(m_render_window, OnCursorPosEvent); | ||||
|     glfwSetFramebufferSizeCallback(m_render_window, OnFramebufferResizeEvent); | ||||
|     glfwSetWindowSizeCallback(m_render_window, OnClientAreaResizeEvent); | ||||
| 
 | ||||
|     DoneCurrent(); | ||||
| } | ||||
| 
 | ||||
| /// EmuWindow_GLFW destructor
 | ||||
| EmuWindow_GLFW::~EmuWindow_GLFW() { | ||||
|     glfwTerminate(); | ||||
| } | ||||
| 
 | ||||
| /// Swap buffers to display the next frame
 | ||||
| void EmuWindow_GLFW::SwapBuffers() { | ||||
|     glfwSwapBuffers(m_render_window); | ||||
| } | ||||
| 
 | ||||
| /// Polls window events
 | ||||
| void EmuWindow_GLFW::PollEvents() { | ||||
|     glfwPollEvents(); | ||||
| } | ||||
| 
 | ||||
| /// Makes the GLFW OpenGL context current for the caller thread
 | ||||
| void EmuWindow_GLFW::MakeCurrent() { | ||||
|     glfwMakeContextCurrent(m_render_window); | ||||
| } | ||||
| 
 | ||||
| /// Releases (dunno if this is the "right" word) the GLFW context from the caller thread
 | ||||
| void EmuWindow_GLFW::DoneCurrent() { | ||||
|     glfwMakeContextCurrent(nullptr); | ||||
| } | ||||
| 
 | ||||
| void EmuWindow_GLFW::ReloadSetKeymaps() { | ||||
|     for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) { | ||||
|         KeyMap::SetKeyMapping({Settings::values.input_mappings[Settings::NativeInput::All[i]], keyboard_id}, Service::HID::pad_mapping[i]); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void EmuWindow_GLFW::OnMinimalClientAreaChangeRequest(const std::pair<unsigned,unsigned>& minimal_size) { | ||||
|     std::pair<int,int> current_size; | ||||
|     glfwGetWindowSize(m_render_window, ¤t_size.first, ¤t_size.second); | ||||
| 
 | ||||
|     DEBUG_ASSERT((int)minimal_size.first > 0 && (int)minimal_size.second > 0); | ||||
|     int new_width  = std::max(current_size.first,  (int)minimal_size.first); | ||||
|     int new_height = std::max(current_size.second, (int)minimal_size.second); | ||||
| 
 | ||||
|     if (current_size != std::make_pair(new_width, new_height)) | ||||
|         glfwSetWindowSize(m_render_window, new_width, new_height); | ||||
| } | ||||
|  | @ -1,54 +0,0 @@ | |||
| // Copyright 2014 Citra Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <utility> | ||||
| 
 | ||||
| #include "common/emu_window.h" | ||||
| 
 | ||||
| struct GLFWwindow; | ||||
| 
 | ||||
| class EmuWindow_GLFW : public EmuWindow { | ||||
| public: | ||||
|     EmuWindow_GLFW(); | ||||
|     ~EmuWindow_GLFW(); | ||||
| 
 | ||||
|     /// Swap buffers to display the next frame
 | ||||
|     void SwapBuffers() override; | ||||
| 
 | ||||
|     /// Polls window events
 | ||||
|     void PollEvents() override; | ||||
| 
 | ||||
|     /// Makes the graphics context current for the caller thread
 | ||||
|     void MakeCurrent() override; | ||||
| 
 | ||||
|     /// Releases (dunno if this is the "right" word) the GLFW context from the caller thread
 | ||||
|     void DoneCurrent() override; | ||||
| 
 | ||||
|     static void OnKeyEvent(GLFWwindow* win, int key, int scancode, int action, int mods); | ||||
| 
 | ||||
|     static void OnMouseButtonEvent(GLFWwindow* window, int button, int action, int mods); | ||||
| 
 | ||||
|     static void OnCursorPosEvent(GLFWwindow* window, double x, double y); | ||||
| 
 | ||||
|     /// Whether the window is still open, and a close request hasn't yet been sent
 | ||||
|     const bool IsOpen(); | ||||
| 
 | ||||
|     static void OnClientAreaResizeEvent(GLFWwindow* win, int width, int height); | ||||
| 
 | ||||
|     static void OnFramebufferResizeEvent(GLFWwindow* win, int width, int height); | ||||
| 
 | ||||
|     void ReloadSetKeymaps() override; | ||||
| 
 | ||||
| private: | ||||
|     void OnMinimalClientAreaChangeRequest(const std::pair<unsigned,unsigned>& minimal_size) override; | ||||
| 
 | ||||
|     static EmuWindow_GLFW* GetEmuWindow(GLFWwindow* win); | ||||
| 
 | ||||
|     GLFWwindow* m_render_window; ///< Internal GLFW render window
 | ||||
| 
 | ||||
|     /// Device id of keyboard for use with KeyMap
 | ||||
|     int keyboard_id; | ||||
| }; | ||||
							
								
								
									
										167
									
								
								src/citra/emu_window/emu_window_sdl2.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										167
									
								
								src/citra/emu_window/emu_window_sdl2.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,167 @@ | |||
| // Copyright 2016 Citra Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include <algorithm> | ||||
| #include <cstdlib> | ||||
| #include <string> | ||||
| 
 | ||||
| #define SDL_MAIN_HANDLED | ||||
| #include <SDL.h> | ||||
| 
 | ||||
| #include "common/key_map.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "common/scm_rev.h" | ||||
| #include "common/string_util.h" | ||||
| 
 | ||||
| #include "core/settings.h" | ||||
| #include "core/hle/service/hid/hid.h" | ||||
| 
 | ||||
| #include "citra/emu_window/emu_window_sdl2.h" | ||||
| 
 | ||||
| #include "video_core/video_core.h" | ||||
| 
 | ||||
| void EmuWindow_SDL2::OnMouseMotion(s32 x, s32 y) { | ||||
|     TouchMoved((unsigned)std::max(x, 0), (unsigned)std::max(y, 0)); | ||||
| } | ||||
| 
 | ||||
| void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) { | ||||
|     if (button != SDL_BUTTON_LEFT) | ||||
|         return; | ||||
| 
 | ||||
|     if (state == SDL_PRESSED) { | ||||
|         TouchPressed((unsigned)std::max(x, 0), (unsigned)std::max(y, 0)); | ||||
|     } else { | ||||
|         TouchReleased(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void EmuWindow_SDL2::OnKeyEvent(int key, u8 state) { | ||||
|     if (state == SDL_PRESSED) { | ||||
|         KeyPressed({ key, keyboard_id }); | ||||
|     } else if (state == SDL_RELEASED) { | ||||
|         KeyReleased({ key, keyboard_id }); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| bool EmuWindow_SDL2::IsOpen() const { | ||||
|     return is_open; | ||||
| } | ||||
| 
 | ||||
| void EmuWindow_SDL2::OnResize() { | ||||
|     int width, height; | ||||
| 
 | ||||
|     SDL_GetWindowSize(render_window, &width, &height); | ||||
| 
 | ||||
|     NotifyFramebufferLayoutChanged(EmuWindow::FramebufferLayout::DefaultScreenLayout(width, height)); | ||||
| } | ||||
| 
 | ||||
| EmuWindow_SDL2::EmuWindow_SDL2() { | ||||
|     keyboard_id = KeyMap::NewDeviceId(); | ||||
| 
 | ||||
|     ReloadSetKeymaps(); | ||||
| 
 | ||||
|     SDL_SetMainReady(); | ||||
| 
 | ||||
|     // Initialize the window
 | ||||
|     if (SDL_Init(SDL_INIT_VIDEO) < 0) { | ||||
|         LOG_CRITICAL(Frontend, "Failed to initialize SDL2! Exiting..."); | ||||
|         exit(1); | ||||
|     } | ||||
| 
 | ||||
|     SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); | ||||
|     SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); | ||||
|     SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); | ||||
|     SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); | ||||
| 
 | ||||
|     std::string window_title = Common::StringFromFormat("Citra | %s-%s", Common::g_scm_branch, Common::g_scm_desc); | ||||
|     render_window = SDL_CreateWindow(window_title.c_str(), | ||||
|         SDL_WINDOWPOS_UNDEFINED, // x position
 | ||||
|         SDL_WINDOWPOS_UNDEFINED, // y position
 | ||||
|         VideoCore::kScreenTopWidth, | ||||
|         VideoCore::kScreenTopHeight + VideoCore::kScreenBottomHeight, | ||||
|         SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); | ||||
| 
 | ||||
|     if (render_window == nullptr) { | ||||
|         LOG_CRITICAL(Frontend, "Failed to create SDL2 window! Exiting..."); | ||||
|         exit(1); | ||||
|     } | ||||
| 
 | ||||
|     gl_context = SDL_GL_CreateContext(render_window); | ||||
| 
 | ||||
|     if (gl_context == nullptr) { | ||||
|         LOG_CRITICAL(Frontend, "Failed to create SDL2 GL context! Exiting..."); | ||||
|         exit(1); | ||||
|     } | ||||
| 
 | ||||
|     OnResize(); | ||||
|     OnMinimalClientAreaChangeRequest(GetActiveConfig().min_client_area_size); | ||||
|     SDL_PumpEvents(); | ||||
| 
 | ||||
|     DoneCurrent(); | ||||
| } | ||||
| 
 | ||||
| EmuWindow_SDL2::~EmuWindow_SDL2() { | ||||
|     SDL_GL_DeleteContext(gl_context); | ||||
|     SDL_Quit(); | ||||
| } | ||||
| 
 | ||||
| void EmuWindow_SDL2::SwapBuffers() { | ||||
|     SDL_GL_SwapWindow(render_window); | ||||
| } | ||||
| 
 | ||||
| void EmuWindow_SDL2::PollEvents() { | ||||
|     SDL_Event event; | ||||
| 
 | ||||
|     // SDL_PollEvent returns 0 when there are no more events in the event queue
 | ||||
|     while (SDL_PollEvent(&event)) { | ||||
|         switch (event.type) { | ||||
|         case SDL_WINDOWEVENT: | ||||
|             switch (event.window.event) { | ||||
|             case SDL_WINDOWEVENT_SIZE_CHANGED: | ||||
|             case SDL_WINDOWEVENT_RESIZED: | ||||
|             case SDL_WINDOWEVENT_MAXIMIZED: | ||||
|             case SDL_WINDOWEVENT_RESTORED: | ||||
|             case SDL_WINDOWEVENT_MINIMIZED: | ||||
|                 OnResize(); | ||||
|                 break; | ||||
|             case SDL_WINDOWEVENT_CLOSE: | ||||
|                 is_open = false; | ||||
|                 break; | ||||
|             } | ||||
|             break; | ||||
|         case SDL_KEYDOWN: | ||||
|         case SDL_KEYUP: | ||||
|             OnKeyEvent(static_cast<int>(event.key.keysym.scancode), event.key.state); | ||||
|             break; | ||||
|         case SDL_MOUSEMOTION: | ||||
|             OnMouseMotion(event.motion.x, event.motion.y); | ||||
|             break; | ||||
|         case SDL_MOUSEBUTTONDOWN: | ||||
|         case SDL_MOUSEBUTTONUP: | ||||
|             OnMouseButton(event.button.button, event.button.state, event.button.x, event.button.y); | ||||
|             break; | ||||
|         case SDL_QUIT: | ||||
|             is_open = false; | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void EmuWindow_SDL2::MakeCurrent() { | ||||
|     SDL_GL_MakeCurrent(render_window, gl_context); | ||||
| } | ||||
| 
 | ||||
| void EmuWindow_SDL2::DoneCurrent() { | ||||
|     SDL_GL_MakeCurrent(render_window, nullptr); | ||||
| } | ||||
| 
 | ||||
| void EmuWindow_SDL2::ReloadSetKeymaps() { | ||||
|     for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) { | ||||
|         KeyMap::SetKeyMapping({ Settings::values.input_mappings[Settings::NativeInput::All[i]], keyboard_id }, Service::HID::pad_mapping[i]); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void EmuWindow_SDL2::OnMinimalClientAreaChangeRequest(const std::pair<unsigned, unsigned>& minimal_size) { | ||||
|     SDL_SetWindowMinimumSize(render_window, minimal_size.first, minimal_size.second); | ||||
| } | ||||
							
								
								
									
										64
									
								
								src/citra/emu_window/emu_window_sdl2.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								src/citra/emu_window/emu_window_sdl2.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,64 @@ | |||
| // Copyright 2016 Citra Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <utility> | ||||
| 
 | ||||
| #include "common/emu_window.h" | ||||
| 
 | ||||
| struct SDL_Window; | ||||
| 
 | ||||
| class EmuWindow_SDL2 : public EmuWindow { | ||||
| public: | ||||
|     EmuWindow_SDL2(); | ||||
|     ~EmuWindow_SDL2(); | ||||
| 
 | ||||
|     /// Swap buffers to display the next frame
 | ||||
|     void SwapBuffers() override; | ||||
| 
 | ||||
|     /// Polls window events
 | ||||
|     void PollEvents() override; | ||||
| 
 | ||||
|     /// Makes the graphics context current for the caller thread
 | ||||
|     void MakeCurrent() override; | ||||
| 
 | ||||
|     /// Releases the GL context from the caller thread
 | ||||
|     void DoneCurrent() override; | ||||
| 
 | ||||
|     /// Whether the window is still open, and a close request hasn't yet been sent
 | ||||
|     bool IsOpen() const; | ||||
| 
 | ||||
|     /// Load keymap from configuration
 | ||||
|     void ReloadSetKeymaps() override; | ||||
| 
 | ||||
| private: | ||||
|     /// Called by PollEvents when a key is pressed or released.
 | ||||
|     void OnKeyEvent(int key, u8 state); | ||||
| 
 | ||||
|     /// Called by PollEvents when the mouse moves.
 | ||||
|     void OnMouseMotion(s32 x, s32 y); | ||||
| 
 | ||||
|     /// Called by PollEvents when a mouse button is pressed or released
 | ||||
|     void OnMouseButton(u32 button, u8 state, s32 x, s32 y); | ||||
| 
 | ||||
|     /// Called by PollEvents when any event that may cause the window to be resized occurs
 | ||||
|     void OnResize(); | ||||
| 
 | ||||
|     /// Called when a configuration change affects the minimal size of the window
 | ||||
|     void OnMinimalClientAreaChangeRequest(const std::pair<unsigned, unsigned>& minimal_size) override; | ||||
| 
 | ||||
|     /// Is the window still open?
 | ||||
|     bool is_open = true; | ||||
| 
 | ||||
|     /// Internal SDL2 render window
 | ||||
|     SDL_Window* render_window; | ||||
| 
 | ||||
|     using SDL_GLContext = void *; | ||||
|     /// The OpenGL context associated with the window
 | ||||
|     SDL_GLContext gl_context; | ||||
| 
 | ||||
|     /// Device id of keyboard for use with KeyMap
 | ||||
|     int keyboard_id; | ||||
| }; | ||||
|  | @ -88,9 +88,14 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Linux|FreeBSD|OpenBSD|NetBSD") | |||
| endif() | ||||
| 
 | ||||
| if (Qt5_FOUND AND MSVC) | ||||
|     include(WindowsCopyFiles) | ||||
| 
 | ||||
|     set(Qt5_DLL_DIR "${Qt5_DIR}/../../../bin") | ||||
|     set(Qt5_PLATFORMS_DIR "${Qt5_DIR}/../../../plugins/platforms/") | ||||
|     set(Qt5_DLLS | ||||
|     set(DLL_DEST "${CMAKE_BINARY_DIR}/bin/$<CONFIG>/") | ||||
|     set(PLATFORMS ${DLL_DEST}platforms/) | ||||
| 
 | ||||
|     windows_copy_files(citra-qt ${Qt5_DLL_DIR} ${DLL_DEST} | ||||
|         icudt*.dll | ||||
|         icuin*.dll | ||||
|         icuuc*.dll | ||||
|  | @ -99,24 +104,8 @@ if (Qt5_FOUND AND MSVC) | |||
|         Qt5OpenGL$<$<CONFIG:Debug>:d>.* | ||||
|         Qt5Widgets$<$<CONFIG:Debug>:d>.* | ||||
|     ) | ||||
|     set(DLL_DEST "${CMAKE_BINARY_DIR}/bin/$<CONFIG>/") | ||||
|     set(PLATFORMS ${DLL_DEST}platforms/) | ||||
|     windows_copy_files(citra-qt ${Qt5_PLATFORMS_DIR} ${PLATFORMS} qwindows$<$<CONFIG:Debug>:d>.*) | ||||
| 
 | ||||
|     # windows commandline expects the / to be \ so switch them | ||||
|     string(REPLACE "/" "\\\\" Qt5_DLL_DIR ${Qt5_DLL_DIR}) | ||||
|     string(REPLACE "/" "\\\\" Qt5_PLATFORMS_DIR ${Qt5_PLATFORMS_DIR}) | ||||
|     string(REPLACE "/" "\\\\" DLL_DEST ${DLL_DEST}) | ||||
|     string(REPLACE "/" "\\\\" PLATFORMS ${PLATFORMS}) | ||||
| 
 | ||||
|     # /NJH /NJS /NDL /NFL /NC /NS /NP - Silence any output | ||||
|     # cmake adds an extra check for command success which doesn't work too well with robocopy | ||||
|     # so trick it into thinking the command was successful with the || cmd /c "exit /b 0" | ||||
|     add_custom_command(TARGET citra-qt POST_BUILD | ||||
|         COMMAND robocopy ${Qt5_DLL_DIR} ${DLL_DEST} ${Qt5_DLLS} /NJH /NJS /NDL /NFL /NC /NS /NP || cmd /c "exit /b 0" | ||||
|         COMMAND if not exist ${PLATFORMS} mkdir ${PLATFORMS} 2> nul | ||||
|         COMMAND robocopy ${Qt5_PLATFORMS_DIR} ${PLATFORMS} qwindows$<$<CONFIG:Debug>:d>.* /NJH /NJS /NDL /NFL /NC /NS /NP || cmd /c "exit /b 0" | ||||
|     ) | ||||
|     unset(Qt5_DLLS) | ||||
|     unset(Qt5_DLL_DIR) | ||||
|     unset(Qt5_PLATFORMS_DIR) | ||||
|     unset(DLL_DEST) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue