diff options
Diffstat (limited to '')
| -rwxr-xr-x | .travis-deps.sh | 13 | ||||
| -rw-r--r-- | .travis.yml | 2 | ||||
| -rw-r--r-- | CMakeLists.txt | 29 | ||||
| -rw-r--r-- | appveyor.yml | 2 | ||||
| -rw-r--r-- | externals/cmake-modules/FindSDL2.cmake | 224 | ||||
| -rw-r--r-- | externals/cmake-modules/WindowsCopyFiles.cmake | 28 | ||||
| -rw-r--r-- | src/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/citra/CMakeLists.txt | 19 | ||||
| -rw-r--r-- | src/citra/citra.cpp | 4 | ||||
| -rw-r--r-- | src/citra/config.cpp | 60 | ||||
| -rw-r--r-- | src/citra/config.h | 10 | ||||
| -rw-r--r-- | src/citra/default_ini.h | 2 | ||||
| -rw-r--r-- | src/citra/emu_window/emu_window_glfw.cpp | 168 | ||||
| -rw-r--r-- | src/citra/emu_window/emu_window_glfw.h | 54 | ||||
| -rw-r--r-- | src/citra/emu_window/emu_window_sdl2.cpp | 167 | ||||
| -rw-r--r-- | src/citra/emu_window/emu_window_sdl2.h | 64 | ||||
| -rw-r--r-- | src/citra_qt/CMakeLists.txt | 25 |
17 files changed, 559 insertions, 314 deletions
diff --git a/.travis-deps.sh b/.travis-deps.sh index 4b907abb3..bab90d307 100755 --- a/.travis-deps.sh +++ b/.travis-deps.sh | |||
| @@ -13,18 +13,13 @@ if [ "$TRAVIS_OS_NAME" = "linux" -o -z "$TRAVIS_OS_NAME" ]; then | |||
| 13 | | tar -xz -C $HOME/.local --strip-components=1 | 13 | | tar -xz -C $HOME/.local --strip-components=1 |
| 14 | 14 | ||
| 15 | ( | 15 | ( |
| 16 | git clone https://github.com/glfw/glfw.git --branch 3.1.1 --depth 1 | 16 | wget http://libsdl.org/release/SDL2-2.0.4.tar.gz -O - | tar xz |
| 17 | mkdir glfw/build && cd glfw/build | 17 | cd SDL2-2.0.4 |
| 18 | cmake -DBUILD_SHARED_LIBS=ON \ | 18 | ./configure --prefix=$HOME/.local |
| 19 | -DGLFW_BUILD_EXAMPLES=OFF \ | ||
| 20 | -DGLFW_BUILD_TESTS=OFF \ | ||
| 21 | -DCMAKE_INSTALL_PREFIX=$HOME/.local \ | ||
| 22 | .. | ||
| 23 | make -j4 && make install | 19 | make -j4 && make install |
| 24 | ) | 20 | ) |
| 25 | |||
| 26 | elif [ "$TRAVIS_OS_NAME" = "osx" ]; then | 21 | elif [ "$TRAVIS_OS_NAME" = "osx" ]; then |
| 27 | brew update > /dev/null # silence the very verbose output | 22 | brew update > /dev/null # silence the very verbose output |
| 28 | brew install qt5 glfw3 | 23 | brew install qt5 sdl2 |
| 29 | gem install xcpretty | 24 | gem install xcpretty |
| 30 | fi | 25 | fi |
diff --git a/.travis.yml b/.travis.yml index 4d21257bc..2e875cccf 100644 --- a/.travis.yml +++ b/.travis.yml | |||
| @@ -18,8 +18,6 @@ addons: | |||
| 18 | - gcc-4.9 | 18 | - gcc-4.9 |
| 19 | - g++-4.9 | 19 | - g++-4.9 |
| 20 | - xorg-dev | 20 | - xorg-dev |
| 21 | - libglu1-mesa-dev | ||
| 22 | - libxcursor-dev | ||
| 23 | - lib32stdc++6 # For CMake | 21 | - lib32stdc++6 # For CMake |
| 24 | - lftp # To upload builds | 22 | - lftp # To upload builds |
| 25 | 23 | ||
diff --git a/CMakeLists.txt b/CMakeLists.txt index b8a981711..d6a4a915a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt | |||
| @@ -35,8 +35,8 @@ endfunction() | |||
| 35 | 35 | ||
| 36 | project(citra) | 36 | project(citra) |
| 37 | 37 | ||
| 38 | option(ENABLE_GLFW "Enable the GLFW frontend" ON) | 38 | option(ENABLE_SDL2 "Enable the SDL2 frontend" ON) |
| 39 | option(CITRA_USE_BUNDLED_GLFW "Download bundled GLFW binaries" OFF) | 39 | option(CITRA_USE_BUNDLED_SDL2 "Download bundled SDL2 binaries" OFF) |
| 40 | 40 | ||
| 41 | option(ENABLE_QT "Enable the Qt frontend" ON) | 41 | option(ENABLE_QT "Enable the Qt frontend" ON) |
| 42 | option(CITRA_USE_BUNDLED_QT "Download bundled Qt binaries" OFF) | 42 | option(CITRA_USE_BUNDLED_QT "Download bundled Qt binaries" OFF) |
| @@ -135,34 +135,29 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/externals/cmake-modules") | |||
| 135 | find_package(OpenGL REQUIRED) | 135 | find_package(OpenGL REQUIRED) |
| 136 | include_directories(${OPENGL_INCLUDE_DIR}) | 136 | include_directories(${OPENGL_INCLUDE_DIR}) |
| 137 | 137 | ||
| 138 | if (ENABLE_GLFW) | 138 | if (ENABLE_SDL2) |
| 139 | if (CITRA_USE_BUNDLED_GLFW) | 139 | if (CITRA_USE_BUNDLED_SDL2) |
| 140 | # Detect toolchain and platform | 140 | # Detect toolchain and platform |
| 141 | if (MSVC14 AND ARCHITECTURE_x86_64) | 141 | if (MSVC14 AND ARCHITECTURE_x86_64) |
| 142 | set(GLFW_VER "glfw-3.1.1-msvc2015_64") | 142 | set(SDL2_VER "SDL2-2.0.4") |
| 143 | elseif (MSVC12 AND ARCHITECTURE_x86_64) | ||
| 144 | set(GLFW_VER "glfw-3.1.1-msvc2013_64") | ||
| 145 | else() | 143 | else() |
| 146 | message(FATAL_ERROR "No bundled GLFW binaries for your toolchain. Disable CITRA_USE_BUNDLED_GLFW and provide your own.") | 144 | message(FATAL_ERROR "No bundled SDL2 binaries for your toolchain. Disable CITRA_USE_BUNDLED_SDL2 and provide your own.") |
| 147 | endif() | 145 | endif() |
| 148 | 146 | ||
| 149 | if (DEFINED GLFW_VER) | 147 | if (DEFINED SDL2_VER) |
| 150 | download_bundled_external("glfw/" ${GLFW_VER} GLFW_PREFIX) | 148 | download_bundled_external("sdl2/" ${SDL2_VER} SDL2_PREFIX) |
| 151 | endif() | 149 | endif() |
| 152 | 150 | ||
| 153 | set(GLFW_INCLUDE_DIRS "${GLFW_PREFIX}/include" CACHE PATH "Path to GLFW3 headers") | 151 | set(SDL2_INCLUDE_DIR "${SDL2_PREFIX}/include" CACHE PATH "Path to SDL2 headers") |
| 154 | set(GLFW_LIBRARY_DIRS "${GLFW_PREFIX}/lib" CACHE PATH "Path to GLFW3 libraries") | 152 | set(SDL2_LIBRARY "${SDL2_PREFIX}/lib/x64/SDL2.lib" CACHE PATH "Path to SDL2 library") |
| 155 | set(GLFW_LIBRARIES glfw3) | 153 | set(SDL2_DLL_DIR "${SDL2_PREFIX}/lib/x64/" CACHE PATH "Path to SDL2.dll") |
| 156 | else() | 154 | else() |
| 157 | find_package(PkgConfig REQUIRED) | 155 | find_package(SDL2 REQUIRED) |
| 158 | pkg_search_module(GLFW REQUIRED glfw3) | ||
| 159 | endif() | 156 | endif() |
| 160 | endif() | 157 | endif() |
| 161 | 158 | ||
| 162 | IF (APPLE) | 159 | IF (APPLE) |
| 163 | FIND_LIBRARY(COCOA_LIBRARY Cocoa) # Umbrella framework for everything GUI-related | 160 | FIND_LIBRARY(COCOA_LIBRARY Cocoa) # Umbrella framework for everything GUI-related |
| 164 | FIND_LIBRARY(IOKIT_LIBRARY IOKit) # GLFW dependency | ||
| 165 | FIND_LIBRARY(COREVIDEO_LIBRARY CoreVideo) # GLFW dependency | ||
| 166 | set(PLATFORM_LIBRARIES iconv ${COCOA_LIBRARY} ${IOKIT_LIBRARY} ${COREVIDEO_LIBRARY}) | 161 | set(PLATFORM_LIBRARIES iconv ${COCOA_LIBRARY} ${IOKIT_LIBRARY} ${COREVIDEO_LIBRARY}) |
| 167 | 162 | ||
| 168 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") | 163 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") |
diff --git a/appveyor.yml b/appveyor.yml index a5ed35392..1edd7041f 100644 --- a/appveyor.yml +++ b/appveyor.yml | |||
| @@ -19,7 +19,7 @@ install: | |||
| 19 | before_build: | 19 | before_build: |
| 20 | - mkdir build | 20 | - mkdir build |
| 21 | - cd build | 21 | - cd build |
| 22 | - cmake -G "Visual Studio 14 2015 Win64" -DCITRA_USE_BUNDLED_GLFW=1 -DCITRA_USE_BUNDLED_QT=1 .. | 22 | - cmake -G "Visual Studio 14 2015 Win64" -DCITRA_USE_BUNDLED_QT=1 -DCITRA_USE_BUNDLED_SDL2=1 .. |
| 23 | - cd .. | 23 | - cd .. |
| 24 | 24 | ||
| 25 | after_build: | 25 | after_build: |
diff --git a/externals/cmake-modules/FindSDL2.cmake b/externals/cmake-modules/FindSDL2.cmake new file mode 100644 index 000000000..0af86840a --- /dev/null +++ b/externals/cmake-modules/FindSDL2.cmake | |||
| @@ -0,0 +1,224 @@ | |||
| 1 | |||
| 2 | # This module defines | ||
| 3 | # SDL2_LIBRARY, the name of the library to link against | ||
| 4 | # SDL2_FOUND, if false, do not try to link to SDL2 | ||
| 5 | # SDL2_INCLUDE_DIR, where to find SDL.h | ||
| 6 | # | ||
| 7 | # This module responds to the the flag: | ||
| 8 | # SDL2_BUILDING_LIBRARY | ||
| 9 | # If this is defined, then no SDL2main will be linked in because | ||
| 10 | # only applications need main(). | ||
| 11 | # Otherwise, it is assumed you are building an application and this | ||
| 12 | # module will attempt to locate and set the the proper link flags | ||
| 13 | # as part of the returned SDL2_LIBRARY variable. | ||
| 14 | # | ||
| 15 | # Don't forget to include SDLmain.h and SDLmain.m your project for the | ||
| 16 | # OS X framework based version. (Other versions link to -lSDL2main which | ||
| 17 | # this module will try to find on your behalf.) Also for OS X, this | ||
| 18 | # module will automatically add the -framework Cocoa on your behalf. | ||
| 19 | # | ||
| 20 | # | ||
| 21 | # Additional Note: If you see an empty SDL2_LIBRARY_TEMP in your configuration | ||
| 22 | # and no SDL2_LIBRARY, it means CMake did not find your SDL2 library | ||
| 23 | # (SDL2.dll, libsdl2.so, SDL2.framework, etc). | ||
| 24 | # Set SDL2_LIBRARY_TEMP to point to your SDL2 library, and configure again. | ||
| 25 | # Similarly, if you see an empty SDL2MAIN_LIBRARY, you should set this value | ||
| 26 | # as appropriate. These values are used to generate the final SDL2_LIBRARY | ||
| 27 | # variable, but when these values are unset, SDL2_LIBRARY does not get created. | ||
| 28 | # | ||
| 29 | # | ||
| 30 | # $SDL2DIR is an environment variable that would | ||
| 31 | # correspond to the ./configure --prefix=$SDL2DIR | ||
| 32 | # used in building SDL2. | ||
| 33 | # l.e.galup 9-20-02 | ||
| 34 | # | ||
| 35 | # Modified by Eric Wing. | ||
| 36 | # Added code to assist with automated building by using environmental variables | ||
| 37 | # and providing a more controlled/consistent search behavior. | ||
| 38 | # Added new modifications to recognize OS X frameworks and | ||
| 39 | # additional Unix paths (FreeBSD, etc). | ||
| 40 | # Also corrected the header search path to follow "proper" SDL guidelines. | ||
| 41 | # Added a search for SDL2main which is needed by some platforms. | ||
| 42 | # Added a search for threads which is needed by some platforms. | ||
| 43 | # Added needed compile switches for MinGW. | ||
| 44 | # | ||
| 45 | # On OSX, this will prefer the Framework version (if found) over others. | ||
| 46 | # People will have to manually change the cache values of | ||
| 47 | # SDL2_LIBRARY to override this selection or set the CMake environment | ||
| 48 | # CMAKE_INCLUDE_PATH to modify the search paths. | ||
| 49 | # | ||
| 50 | # Note that the header path has changed from SDL2/SDL.h to just SDL.h | ||
| 51 | # This needed to change because "proper" SDL convention | ||
| 52 | # is #include "SDL.h", not <SDL2/SDL.h>. This is done for portability | ||
| 53 | # reasons because not all systems place things in SDL2/ (see FreeBSD). | ||
| 54 | |||
| 55 | #============================================================================= | ||
| 56 | # Copyright 2003-2009 Kitware, Inc. | ||
| 57 | # | ||
| 58 | # Distributed under the OSI-approved BSD License (the "License"). | ||
| 59 | # | ||
| 60 | # This software is distributed WITHOUT ANY WARRANTY; without even the | ||
| 61 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
| 62 | # See the License for more information. | ||
| 63 | #============================================================================= | ||
| 64 | # CMake - Cross Platform Makefile Generator | ||
| 65 | # Copyright 2000-2016 Kitware, Inc. | ||
| 66 | # Copyright 2000-2011 Insight Software Consortium | ||
| 67 | # All rights reserved. | ||
| 68 | # | ||
| 69 | # Redistribution and use in source and binary forms, with or without | ||
| 70 | # modification, are permitted provided that the following conditions | ||
| 71 | # are met: | ||
| 72 | # | ||
| 73 | # * Redistributions of source code must retain the above copyright | ||
| 74 | # notice, this list of conditions and the following disclaimer. | ||
| 75 | # | ||
| 76 | # * Redistributions in binary form must reproduce the above copyright | ||
| 77 | # notice, this list of conditions and the following disclaimer in the | ||
| 78 | # documentation and/or other materials provided with the distribution. | ||
| 79 | # | ||
| 80 | # * Neither the names of Kitware, Inc., the Insight Software Consortium, | ||
| 81 | # nor the names of their contributors may be used to endorse or promote | ||
| 82 | # products derived from this software without specific prior written | ||
| 83 | # permission. | ||
| 84 | # | ||
| 85 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
| 86 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
| 87 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
| 88 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
| 89 | # HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
| 90 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
| 91 | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
| 92 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
| 93 | # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| 94 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
| 95 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 96 | # | ||
| 97 | # ------------------------------------------------------------------------------ | ||
| 98 | # | ||
| 99 | # The above copyright and license notice applies to distributions of | ||
| 100 | # CMake in source and binary form. Some source files contain additional | ||
| 101 | # notices of original copyright by their contributors; see each source | ||
| 102 | # for details. Third-party software packages supplied with CMake under | ||
| 103 | # compatible licenses provide their own copyright notices documented in | ||
| 104 | # corresponding subdirectories. | ||
| 105 | # | ||
| 106 | # ------------------------------------------------------------------------------ | ||
| 107 | # | ||
| 108 | # CMake was initially developed by Kitware with the following sponsorship: | ||
| 109 | # | ||
| 110 | # * National Library of Medicine at the National Institutes of Health | ||
| 111 | # as part of the Insight Segmentation and Registration Toolkit (ITK). | ||
| 112 | # | ||
| 113 | # * US National Labs (Los Alamos, Livermore, Sandia) ASC Parallel | ||
| 114 | # Visualization Initiative. | ||
| 115 | # | ||
| 116 | # * National Alliance for Medical Image Computing (NAMIC) is funded by the | ||
| 117 | # National Institutes of Health through the NIH Roadmap for Medical Research, | ||
| 118 | # Grant U54 EB005149. | ||
| 119 | # | ||
| 120 | # * Kitware, Inc. | ||
| 121 | # | ||
| 122 | |||
| 123 | message("<FindSDL2.cmake>") | ||
| 124 | |||
| 125 | SET(SDL2_SEARCH_PATHS | ||
| 126 | ~/Library/Frameworks | ||
| 127 | /Library/Frameworks | ||
| 128 | /usr/local | ||
| 129 | /usr | ||
| 130 | /sw # Fink | ||
| 131 | /opt/local # DarwinPorts | ||
| 132 | /opt/csw # Blastwave | ||
| 133 | /opt | ||
| 134 | ${SDL2_PATH} | ||
| 135 | ) | ||
| 136 | |||
| 137 | FIND_LIBRARY(SDL2_LIBRARY_TEMP | ||
| 138 | NAMES SDL2 | ||
| 139 | HINTS | ||
| 140 | $ENV{SDL2DIR} | ||
| 141 | PATH_SUFFIXES lib64 lib | ||
| 142 | PATHS ${SDL2_SEARCH_PATHS} | ||
| 143 | ) | ||
| 144 | |||
| 145 | IF(SDL2_LIBRARY_TEMP) | ||
| 146 | FIND_PATH(SDL2_INCLUDE_DIR SDL.h | ||
| 147 | HINTS | ||
| 148 | $ENV{SDL2DIR} | ||
| 149 | PATH_SUFFIXES include/SDL2 include | ||
| 150 | PATHS ${SDL2_SEARCH_PATHS} | ||
| 151 | ) | ||
| 152 | |||
| 153 | IF(NOT SDL2_BUILDING_LIBRARY) | ||
| 154 | IF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework") | ||
| 155 | # Non-OS X framework versions expect you to also dynamically link to | ||
| 156 | # SDL2main. This is mainly for Windows and OS X. Other (Unix) platforms | ||
| 157 | # seem to provide SDL2main for compatibility even though they don't | ||
| 158 | # necessarily need it. | ||
| 159 | FIND_LIBRARY(SDL2MAIN_LIBRARY | ||
| 160 | NAMES SDL2main | ||
| 161 | HINTS | ||
| 162 | $ENV{SDL2DIR} | ||
| 163 | PATH_SUFFIXES lib64 lib | ||
| 164 | PATHS ${SDL2_SEARCH_PATHS} | ||
| 165 | ) | ||
| 166 | ENDIF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework") | ||
| 167 | ENDIF(NOT SDL2_BUILDING_LIBRARY) | ||
| 168 | |||
| 169 | # SDL2 may require threads on your system. | ||
| 170 | # The Apple build may not need an explicit flag because one of the | ||
| 171 | # frameworks may already provide it. | ||
| 172 | # But for non-OSX systems, I will use the CMake Threads package. | ||
| 173 | IF(NOT APPLE) | ||
| 174 | FIND_PACKAGE(Threads) | ||
| 175 | ENDIF(NOT APPLE) | ||
| 176 | |||
| 177 | # MinGW needs an additional library, mwindows | ||
| 178 | # It's total link flags should look like -lmingw32 -lSDL2main -lSDL2 -lmwindows | ||
| 179 | # (Actually on second look, I think it only needs one of the m* libraries.) | ||
| 180 | IF(MINGW) | ||
| 181 | SET(MINGW32_LIBRARY mingw32 CACHE STRING "mwindows for MinGW") | ||
| 182 | ENDIF(MINGW) | ||
| 183 | |||
| 184 | # For SDL2main | ||
| 185 | IF(NOT SDL2_BUILDING_LIBRARY) | ||
| 186 | IF(SDL2MAIN_LIBRARY) | ||
| 187 | SET(SDL2_LIBRARY_TEMP ${SDL2MAIN_LIBRARY} ${SDL2_LIBRARY_TEMP}) | ||
| 188 | ENDIF(SDL2MAIN_LIBRARY) | ||
| 189 | ENDIF(NOT SDL2_BUILDING_LIBRARY) | ||
| 190 | |||
| 191 | # For OS X, SDL2 uses Cocoa as a backend so it must link to Cocoa. | ||
| 192 | # CMake doesn't display the -framework Cocoa string in the UI even | ||
| 193 | # though it actually is there if I modify a pre-used variable. | ||
| 194 | # I think it has something to do with the CACHE STRING. | ||
| 195 | # So I use a temporary variable until the end so I can set the | ||
| 196 | # "real" variable in one-shot. | ||
| 197 | IF(APPLE) | ||
| 198 | SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} "-framework Cocoa") | ||
| 199 | ENDIF(APPLE) | ||
| 200 | |||
| 201 | # For threads, as mentioned Apple doesn't need this. | ||
| 202 | # In fact, there seems to be a problem if I used the Threads package | ||
| 203 | # and try using this line, so I'm just skipping it entirely for OS X. | ||
| 204 | IF(NOT APPLE) | ||
| 205 | SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} ${CMAKE_THREAD_LIBS_INIT}) | ||
| 206 | ENDIF(NOT APPLE) | ||
| 207 | |||
| 208 | # For MinGW library | ||
| 209 | IF(MINGW) | ||
| 210 | SET(SDL2_LIBRARY_TEMP ${MINGW32_LIBRARY} ${SDL2_LIBRARY_TEMP}) | ||
| 211 | ENDIF(MINGW) | ||
| 212 | |||
| 213 | # Set the final string here so the GUI reflects the final state. | ||
| 214 | SET(SDL2_LIBRARY ${SDL2_LIBRARY_TEMP} CACHE STRING "Where the SDL2 Library can be found") | ||
| 215 | |||
| 216 | # Unset the temp variable to INTERNAL so it is not seen in the CMake GUI | ||
| 217 | UNSET(SDL2_LIBRARY_TEMP) | ||
| 218 | ENDIF(SDL2_LIBRARY_TEMP) | ||
| 219 | |||
| 220 | message("</FindSDL2.cmake>") | ||
| 221 | |||
| 222 | INCLUDE(FindPackageHandleStandardArgs) | ||
| 223 | |||
| 224 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2 REQUIRED_VARS SDL2_LIBRARY SDL2_INCLUDE_DIR) | ||
diff --git a/externals/cmake-modules/WindowsCopyFiles.cmake b/externals/cmake-modules/WindowsCopyFiles.cmake new file mode 100644 index 000000000..cd0c2ce47 --- /dev/null +++ b/externals/cmake-modules/WindowsCopyFiles.cmake | |||
| @@ -0,0 +1,28 @@ | |||
| 1 | # Copyright 2016 Citra Emulator Project | ||
| 2 | # Licensed under GPLv2 or any later version | ||
| 3 | # Refer to the license.txt file included. | ||
| 4 | |||
| 5 | # This file provides the function windows_copy_files. | ||
| 6 | # This is only valid on Windows. | ||
| 7 | |||
| 8 | # Include guard | ||
| 9 | if(__windows_copy_files) | ||
| 10 | return() | ||
| 11 | endif() | ||
| 12 | set(__windows_copy_files YES) | ||
| 13 | |||
| 14 | # Any number of files to copy from SOURCE_DIR to DEST_DIR can be specified after DEST_DIR. | ||
| 15 | # This copying happens post-build. | ||
| 16 | function(windows_copy_files TARGET SOURCE_DIR DEST_DIR) | ||
| 17 | # windows commandline expects the / to be \ so switch them | ||
| 18 | string(REPLACE "/" "\\\\" SOURCE_DIR ${SOURCE_DIR}) | ||
| 19 | string(REPLACE "/" "\\\\" DEST_DIR ${DEST_DIR}) | ||
| 20 | |||
| 21 | # /NJH /NJS /NDL /NFL /NC /NS /NP - Silence any output | ||
| 22 | # cmake adds an extra check for command success which doesn't work too well with robocopy | ||
| 23 | # so trick it into thinking the command was successful with the || cmd /c "exit /b 0" | ||
| 24 | add_custom_command(TARGET ${TARGET} POST_BUILD | ||
| 25 | COMMAND if not exist ${DEST_DIR} mkdir ${DEST_DIR} 2> nul | ||
| 26 | COMMAND robocopy ${SOURCE_DIR} ${DEST_DIR} ${ARGN} /NJH /NJS /NDL /NFL /NC /NS /NP || cmd /c "exit /b 0" | ||
| 27 | ) | ||
| 28 | endfunction() \ No newline at end of file | ||
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2bb411492..de4fe716a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt | |||
| @@ -5,7 +5,7 @@ add_subdirectory(common) | |||
| 5 | add_subdirectory(core) | 5 | add_subdirectory(core) |
| 6 | add_subdirectory(video_core) | 6 | add_subdirectory(video_core) |
| 7 | add_subdirectory(audio_core) | 7 | add_subdirectory(audio_core) |
| 8 | if (ENABLE_GLFW) | 8 | if (ENABLE_SDL2) |
| 9 | add_subdirectory(citra) | 9 | add_subdirectory(citra) |
| 10 | endif() | 10 | endif() |
| 11 | if (ENABLE_QT) | 11 | if (ENABLE_QT) |
diff --git a/src/citra/CMakeLists.txt b/src/citra/CMakeLists.txt index b9abb818e..fa615deb9 100644 --- a/src/citra/CMakeLists.txt +++ b/src/citra/CMakeLists.txt | |||
| @@ -1,11 +1,11 @@ | |||
| 1 | set(SRCS | 1 | set(SRCS |
| 2 | emu_window/emu_window_glfw.cpp | 2 | emu_window/emu_window_sdl2.cpp |
| 3 | citra.cpp | 3 | citra.cpp |
| 4 | config.cpp | 4 | config.cpp |
| 5 | citra.rc | 5 | citra.rc |
| 6 | ) | 6 | ) |
| 7 | set(HEADERS | 7 | set(HEADERS |
| 8 | emu_window/emu_window_glfw.h | 8 | emu_window/emu_window_sdl2.h |
| 9 | config.h | 9 | config.h |
| 10 | default_ini.h | 10 | default_ini.h |
| 11 | resource.h | 11 | resource.h |
| @@ -13,12 +13,11 @@ set(HEADERS | |||
| 13 | 13 | ||
| 14 | create_directory_groups(${SRCS} ${HEADERS}) | 14 | create_directory_groups(${SRCS} ${HEADERS}) |
| 15 | 15 | ||
| 16 | include_directories(${GLFW_INCLUDE_DIRS}) | 16 | include_directories(${SDL2_INCLUDE_DIR}) |
| 17 | link_directories(${GLFW_LIBRARY_DIRS}) | ||
| 18 | 17 | ||
| 19 | add_executable(citra ${SRCS} ${HEADERS}) | 18 | add_executable(citra ${SRCS} ${HEADERS}) |
| 20 | target_link_libraries(citra core video_core audio_core common) | 19 | target_link_libraries(citra core video_core audio_core common) |
| 21 | target_link_libraries(citra ${GLFW_LIBRARIES} ${OPENGL_gl_LIBRARY} inih glad) | 20 | target_link_libraries(citra ${SDL2_LIBRARY} ${OPENGL_gl_LIBRARY} inih glad) |
| 22 | if (MSVC) | 21 | if (MSVC) |
| 23 | target_link_libraries(citra getopt) | 22 | target_link_libraries(citra getopt) |
| 24 | endif() | 23 | endif() |
| @@ -27,3 +26,13 @@ target_link_libraries(citra ${PLATFORM_LIBRARIES}) | |||
| 27 | if(${CMAKE_SYSTEM_NAME} MATCHES "Linux|FreeBSD|OpenBSD|NetBSD") | 26 | if(${CMAKE_SYSTEM_NAME} MATCHES "Linux|FreeBSD|OpenBSD|NetBSD") |
| 28 | install(TARGETS citra RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/bin") | 27 | install(TARGETS citra RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/bin") |
| 29 | endif() | 28 | endif() |
| 29 | |||
| 30 | if (MSVC) | ||
| 31 | include(WindowsCopyFiles) | ||
| 32 | |||
| 33 | set(DLL_DEST "${CMAKE_BINARY_DIR}/bin/$<CONFIG>/") | ||
| 34 | |||
| 35 | windows_copy_files(citra ${SDL2_DLL_DIR} ${DLL_DEST} SDL2.dll) | ||
| 36 | |||
| 37 | unset(DLL_DEST) | ||
| 38 | endif() | ||
diff --git a/src/citra/citra.cpp b/src/citra/citra.cpp index c96fc1374..415b98a05 100644 --- a/src/citra/citra.cpp +++ b/src/citra/citra.cpp | |||
| @@ -27,7 +27,7 @@ | |||
| 27 | #include "core/loader/loader.h" | 27 | #include "core/loader/loader.h" |
| 28 | 28 | ||
| 29 | #include "citra/config.h" | 29 | #include "citra/config.h" |
| 30 | #include "citra/emu_window/emu_window_glfw.h" | 30 | #include "citra/emu_window/emu_window_sdl2.h" |
| 31 | 31 | ||
| 32 | #include "video_core/video_core.h" | 32 | #include "video_core/video_core.h" |
| 33 | 33 | ||
| @@ -76,7 +76,7 @@ int main(int argc, char **argv) { | |||
| 76 | GDBStub::ToggleServer(Settings::values.use_gdbstub); | 76 | GDBStub::ToggleServer(Settings::values.use_gdbstub); |
| 77 | GDBStub::SetServerPort(static_cast<u32>(Settings::values.gdbstub_port)); | 77 | GDBStub::SetServerPort(static_cast<u32>(Settings::values.gdbstub_port)); |
| 78 | 78 | ||
| 79 | EmuWindow_GLFW* emu_window = new EmuWindow_GLFW; | 79 | EmuWindow_SDL2* emu_window = new EmuWindow_SDL2; |
| 80 | 80 | ||
| 81 | VideoCore::g_hw_renderer_enabled = Settings::values.use_hw_renderer; | 81 | VideoCore::g_hw_renderer_enabled = Settings::values.use_hw_renderer; |
| 82 | VideoCore::g_shader_jit_enabled = Settings::values.use_shader_jit; | 82 | VideoCore::g_shader_jit_enabled = Settings::values.use_shader_jit; |
diff --git a/src/citra/config.cpp b/src/citra/config.cpp index 2f13c29a2..9034b188e 100644 --- a/src/citra/config.cpp +++ b/src/citra/config.cpp | |||
| @@ -2,14 +2,15 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #define GLFW_INCLUDE_NONE | ||
| 6 | #include <GLFW/glfw3.h> | ||
| 7 | #include <inih/cpp/INIReader.h> | 5 | #include <inih/cpp/INIReader.h> |
| 8 | 6 | ||
| 7 | #include <SDL.h> | ||
| 8 | |||
| 9 | #include "citra/default_ini.h" | 9 | #include "citra/default_ini.h" |
| 10 | 10 | ||
| 11 | #include "common/file_util.h" | 11 | #include "common/file_util.h" |
| 12 | #include "common/logging/log.h" | 12 | #include "common/logging/log.h" |
| 13 | #include "common/make_unique.h" | ||
| 13 | 14 | ||
| 14 | #include "core/settings.h" | 15 | #include "core/settings.h" |
| 15 | 16 | ||
| @@ -17,21 +18,22 @@ | |||
| 17 | 18 | ||
| 18 | Config::Config() { | 19 | Config::Config() { |
| 19 | // TODO: Don't hardcode the path; let the frontend decide where to put the config files. | 20 | // TODO: Don't hardcode the path; let the frontend decide where to put the config files. |
| 20 | glfw_config_loc = FileUtil::GetUserPath(D_CONFIG_IDX) + "glfw-config.ini"; | 21 | sdl2_config_loc = FileUtil::GetUserPath(D_CONFIG_IDX) + "sdl2-config.ini"; |
| 21 | glfw_config = new INIReader(glfw_config_loc); | 22 | sdl2_config = Common::make_unique<INIReader>(sdl2_config_loc); |
| 22 | 23 | ||
| 23 | Reload(); | 24 | Reload(); |
| 24 | } | 25 | } |
| 25 | 26 | ||
| 26 | bool Config::LoadINI(INIReader* config, const char* location, const std::string& default_contents, bool retry) { | 27 | bool Config::LoadINI(const std::string& default_contents, bool retry) { |
| 27 | if (config->ParseError() < 0) { | 28 | const char* location = this->sdl2_config_loc.c_str(); |
| 29 | if (sdl2_config->ParseError() < 0) { | ||
| 28 | if (retry) { | 30 | if (retry) { |
| 29 | LOG_WARNING(Config, "Failed to load %s. Creating file from defaults...", location); | 31 | LOG_WARNING(Config, "Failed to load %s. Creating file from defaults...", location); |
| 30 | FileUtil::CreateFullPath(location); | 32 | FileUtil::CreateFullPath(location); |
| 31 | FileUtil::WriteStringToFile(true, default_contents, location); | 33 | FileUtil::WriteStringToFile(true, default_contents, location); |
| 32 | *config = INIReader(location); // Reopen file | 34 | sdl2_config = Common::make_unique<INIReader>(location); // Reopen file |
| 33 | 35 | ||
| 34 | return LoadINI(config, location, default_contents, false); | 36 | return LoadINI(default_contents, false); |
| 35 | } | 37 | } |
| 36 | LOG_ERROR(Config, "Failed."); | 38 | LOG_ERROR(Config, "Failed."); |
| 37 | return false; | 39 | return false; |
| @@ -41,51 +43,47 @@ bool Config::LoadINI(INIReader* config, const char* location, const std::string& | |||
| 41 | } | 43 | } |
| 42 | 44 | ||
| 43 | static const std::array<int, Settings::NativeInput::NUM_INPUTS> defaults = { | 45 | static const std::array<int, Settings::NativeInput::NUM_INPUTS> defaults = { |
| 44 | GLFW_KEY_A, GLFW_KEY_S, GLFW_KEY_Z, GLFW_KEY_X, | 46 | SDL_SCANCODE_A, SDL_SCANCODE_S, SDL_SCANCODE_Z, SDL_SCANCODE_X, |
| 45 | GLFW_KEY_Q, GLFW_KEY_W, GLFW_KEY_1, GLFW_KEY_2, | 47 | SDL_SCANCODE_Q, SDL_SCANCODE_W, SDL_SCANCODE_1, SDL_SCANCODE_2, |
| 46 | GLFW_KEY_M, GLFW_KEY_N, GLFW_KEY_B, | 48 | SDL_SCANCODE_M, SDL_SCANCODE_N, SDL_SCANCODE_B, |
| 47 | GLFW_KEY_T, GLFW_KEY_G, GLFW_KEY_F, GLFW_KEY_H, | 49 | SDL_SCANCODE_T, SDL_SCANCODE_G, SDL_SCANCODE_F, SDL_SCANCODE_H, |
| 48 | GLFW_KEY_UP, GLFW_KEY_DOWN, GLFW_KEY_LEFT, GLFW_KEY_RIGHT, | 50 | SDL_SCANCODE_UP, SDL_SCANCODE_DOWN, SDL_SCANCODE_LEFT, SDL_SCANCODE_RIGHT, |
| 49 | GLFW_KEY_I, GLFW_KEY_K, GLFW_KEY_J, GLFW_KEY_L | 51 | SDL_SCANCODE_I, SDL_SCANCODE_K, SDL_SCANCODE_J, SDL_SCANCODE_L |
| 50 | }; | 52 | }; |
| 51 | 53 | ||
| 52 | void Config::ReadValues() { | 54 | void Config::ReadValues() { |
| 53 | // Controls | 55 | // Controls |
| 54 | for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) { | 56 | for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) { |
| 55 | Settings::values.input_mappings[Settings::NativeInput::All[i]] = | 57 | Settings::values.input_mappings[Settings::NativeInput::All[i]] = |
| 56 | glfw_config->GetInteger("Controls", Settings::NativeInput::Mapping[i], defaults[i]); | 58 | sdl2_config->GetInteger("Controls", Settings::NativeInput::Mapping[i], defaults[i]); |
| 57 | } | 59 | } |
| 58 | 60 | ||
| 59 | // Core | 61 | // Core |
| 60 | Settings::values.frame_skip = glfw_config->GetInteger("Core", "frame_skip", 0); | 62 | Settings::values.frame_skip = sdl2_config->GetInteger("Core", "frame_skip", 0); |
| 61 | 63 | ||
| 62 | // Renderer | 64 | // Renderer |
| 63 | Settings::values.use_hw_renderer = glfw_config->GetBoolean("Renderer", "use_hw_renderer", false); | 65 | Settings::values.use_hw_renderer = sdl2_config->GetBoolean("Renderer", "use_hw_renderer", false); |
| 64 | Settings::values.use_shader_jit = glfw_config->GetBoolean("Renderer", "use_shader_jit", true); | 66 | Settings::values.use_shader_jit = sdl2_config->GetBoolean("Renderer", "use_shader_jit", true); |
| 65 | 67 | ||
| 66 | Settings::values.bg_red = (float)glfw_config->GetReal("Renderer", "bg_red", 1.0); | 68 | Settings::values.bg_red = (float)sdl2_config->GetReal("Renderer", "bg_red", 1.0); |
| 67 | Settings::values.bg_green = (float)glfw_config->GetReal("Renderer", "bg_green", 1.0); | 69 | Settings::values.bg_green = (float)sdl2_config->GetReal("Renderer", "bg_green", 1.0); |
| 68 | Settings::values.bg_blue = (float)glfw_config->GetReal("Renderer", "bg_blue", 1.0); | 70 | Settings::values.bg_blue = (float)sdl2_config->GetReal("Renderer", "bg_blue", 1.0); |
| 69 | 71 | ||
| 70 | // Data Storage | 72 | // Data Storage |
| 71 | Settings::values.use_virtual_sd = glfw_config->GetBoolean("Data Storage", "use_virtual_sd", true); | 73 | Settings::values.use_virtual_sd = sdl2_config->GetBoolean("Data Storage", "use_virtual_sd", true); |
| 72 | 74 | ||
| 73 | // System Region | 75 | // System Region |
| 74 | Settings::values.region_value = glfw_config->GetInteger("System Region", "region_value", 1); | 76 | Settings::values.region_value = sdl2_config->GetInteger("System Region", "region_value", 1); |
| 75 | 77 | ||
| 76 | // Miscellaneous | 78 | // Miscellaneous |
| 77 | Settings::values.log_filter = glfw_config->Get("Miscellaneous", "log_filter", "*:Info"); | 79 | Settings::values.log_filter = sdl2_config->Get("Miscellaneous", "log_filter", "*:Info"); |
| 78 | 80 | ||
| 79 | // Debugging | 81 | // Debugging |
| 80 | Settings::values.use_gdbstub = glfw_config->GetBoolean("Debugging", "use_gdbstub", false); | 82 | Settings::values.use_gdbstub = sdl2_config->GetBoolean("Debugging", "use_gdbstub", false); |
| 81 | Settings::values.gdbstub_port = glfw_config->GetInteger("Debugging", "gdbstub_port", 24689); | 83 | Settings::values.gdbstub_port = sdl2_config->GetInteger("Debugging", "gdbstub_port", 24689); |
| 82 | } | 84 | } |
| 83 | 85 | ||
| 84 | void Config::Reload() { | 86 | void Config::Reload() { |
| 85 | LoadINI(glfw_config, glfw_config_loc.c_str(), DefaultINI::glfw_config_file); | 87 | LoadINI(DefaultINI::sdl2_config_file); |
| 86 | ReadValues(); | 88 | ReadValues(); |
| 87 | } | 89 | } |
| 88 | |||
| 89 | Config::~Config() { | ||
| 90 | delete glfw_config; | ||
| 91 | } | ||
diff --git a/src/citra/config.h b/src/citra/config.h index c326ec669..52a478146 100644 --- a/src/citra/config.h +++ b/src/citra/config.h | |||
| @@ -4,19 +4,19 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <memory> | ||
| 7 | #include <string> | 8 | #include <string> |
| 8 | 9 | ||
| 9 | class INIReader; | 10 | #include <inih/cpp/INIReader.h> |
| 10 | 11 | ||
| 11 | class Config { | 12 | class Config { |
| 12 | INIReader* glfw_config; | 13 | std::unique_ptr<INIReader> sdl2_config; |
| 13 | std::string glfw_config_loc; | 14 | std::string sdl2_config_loc; |
| 14 | 15 | ||
| 15 | bool LoadINI(INIReader* config, const char* location, const std::string& default_contents="", bool retry=true); | 16 | bool LoadINI(const std::string& default_contents="", bool retry=true); |
| 16 | void ReadValues(); | 17 | void ReadValues(); |
| 17 | public: | 18 | public: |
| 18 | Config(); | 19 | Config(); |
| 19 | ~Config(); | ||
| 20 | 20 | ||
| 21 | void Reload(); | 21 | void Reload(); |
| 22 | }; | 22 | }; |
diff --git a/src/citra/default_ini.h b/src/citra/default_ini.h index 5ba40a8ed..c9b490a00 100644 --- a/src/citra/default_ini.h +++ b/src/citra/default_ini.h | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | namespace DefaultINI { | 7 | namespace DefaultINI { |
| 8 | 8 | ||
| 9 | const char* glfw_config_file = R"( | 9 | const char* sdl2_config_file = R"( |
| 10 | [Controls] | 10 | [Controls] |
| 11 | pad_start = | 11 | pad_start = |
| 12 | pad_select = | 12 | pad_select = |
diff --git a/src/citra/emu_window/emu_window_glfw.cpp b/src/citra/emu_window/emu_window_glfw.cpp deleted file mode 100644 index 9453b1f48..000000000 --- a/src/citra/emu_window/emu_window_glfw.cpp +++ /dev/null | |||
| @@ -1,168 +0,0 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <algorithm> | ||
| 6 | #include <cstdlib> | ||
| 7 | #include <string> | ||
| 8 | |||
| 9 | // Let’s use our own GL header, instead of one from GLFW. | ||
| 10 | #include <glad/glad.h> | ||
| 11 | #define GLFW_INCLUDE_NONE | ||
| 12 | #include <GLFW/glfw3.h> | ||
| 13 | |||
| 14 | #include "common/assert.h" | ||
| 15 | #include "common/key_map.h" | ||
| 16 | #include "common/logging/log.h" | ||
| 17 | #include "common/scm_rev.h" | ||
| 18 | #include "common/string_util.h" | ||
| 19 | |||
| 20 | #include "video_core/video_core.h" | ||
| 21 | |||
| 22 | #include "core/settings.h" | ||
| 23 | #include "core/hle/service/hid/hid.h" | ||
| 24 | |||
| 25 | #include "citra/emu_window/emu_window_glfw.h" | ||
| 26 | |||
| 27 | EmuWindow_GLFW* EmuWindow_GLFW::GetEmuWindow(GLFWwindow* win) { | ||
| 28 | return static_cast<EmuWindow_GLFW*>(glfwGetWindowUserPointer(win)); | ||
| 29 | } | ||
| 30 | |||
| 31 | void EmuWindow_GLFW::OnMouseButtonEvent(GLFWwindow* win, int button, int action, int mods) { | ||
| 32 | if (button == GLFW_MOUSE_BUTTON_LEFT) { | ||
| 33 | auto emu_window = GetEmuWindow(win); | ||
| 34 | auto layout = emu_window->GetFramebufferLayout(); | ||
| 35 | double x, y; | ||
| 36 | glfwGetCursorPos(win, &x, &y); | ||
| 37 | |||
| 38 | if (action == GLFW_PRESS) | ||
| 39 | emu_window->TouchPressed(static_cast<unsigned>(x), static_cast<unsigned>(y)); | ||
| 40 | else if (action == GLFW_RELEASE) | ||
| 41 | emu_window->TouchReleased(); | ||
| 42 | } | ||
| 43 | } | ||
| 44 | |||
| 45 | void EmuWindow_GLFW::OnCursorPosEvent(GLFWwindow* win, double x, double y) { | ||
| 46 | GetEmuWindow(win)->TouchMoved(static_cast<unsigned>(std::max(x, 0.0)), static_cast<unsigned>(std::max(y, 0.0))); | ||
| 47 | } | ||
| 48 | |||
| 49 | /// Called by GLFW when a key event occurs | ||
| 50 | void EmuWindow_GLFW::OnKeyEvent(GLFWwindow* win, int key, int scancode, int action, int mods) { | ||
| 51 | auto emu_window = GetEmuWindow(win); | ||
| 52 | int keyboard_id = emu_window->keyboard_id; | ||
| 53 | |||
| 54 | if (action == GLFW_PRESS) { | ||
| 55 | emu_window->KeyPressed({key, keyboard_id}); | ||
| 56 | } else if (action == GLFW_RELEASE) { | ||
| 57 | emu_window->KeyReleased({key, keyboard_id}); | ||
| 58 | } | ||
| 59 | } | ||
| 60 | |||
| 61 | /// Whether the window is still open, and a close request hasn't yet been sent | ||
| 62 | const bool EmuWindow_GLFW::IsOpen() { | ||
| 63 | return glfwWindowShouldClose(m_render_window) == 0; | ||
| 64 | } | ||
| 65 | |||
| 66 | void EmuWindow_GLFW::OnFramebufferResizeEvent(GLFWwindow* win, int width, int height) { | ||
| 67 | GetEmuWindow(win)->NotifyFramebufferLayoutChanged(EmuWindow::FramebufferLayout::DefaultScreenLayout(width, height)); | ||
| 68 | } | ||
| 69 | |||
| 70 | void EmuWindow_GLFW::OnClientAreaResizeEvent(GLFWwindow* win, int width, int height) { | ||
| 71 | // NOTE: GLFW provides no proper way to set a minimal window size. | ||
| 72 | // Hence, we just ignore the corresponding EmuWindow hint. | ||
| 73 | OnFramebufferResizeEvent(win, width, height); | ||
| 74 | } | ||
| 75 | |||
| 76 | /// EmuWindow_GLFW constructor | ||
| 77 | EmuWindow_GLFW::EmuWindow_GLFW() { | ||
| 78 | keyboard_id = KeyMap::NewDeviceId(); | ||
| 79 | |||
| 80 | ReloadSetKeymaps(); | ||
| 81 | |||
| 82 | glfwSetErrorCallback([](int error, const char *desc){ | ||
| 83 | LOG_ERROR(Frontend, "GLFW 0x%08x: %s", error, desc); | ||
| 84 | }); | ||
| 85 | |||
| 86 | // Initialize the window | ||
| 87 | if(glfwInit() != GL_TRUE) { | ||
| 88 | LOG_CRITICAL(Frontend, "Failed to initialize GLFW! Exiting..."); | ||
| 89 | exit(1); | ||
| 90 | } | ||
| 91 | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); | ||
| 92 | glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); | ||
| 93 | // GLFW on OSX requires these window hints to be set to create a 3.2+ GL context. | ||
| 94 | glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); | ||
| 95 | glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); | ||
| 96 | |||
| 97 | std::string window_title = Common::StringFromFormat("Citra | %s-%s", Common::g_scm_branch, Common::g_scm_desc); | ||
| 98 | m_render_window = glfwCreateWindow(VideoCore::kScreenTopWidth, | ||
| 99 | (VideoCore::kScreenTopHeight + VideoCore::kScreenBottomHeight), | ||
| 100 | window_title.c_str(), nullptr, nullptr); | ||
| 101 | |||
| 102 | if (m_render_window == nullptr) { | ||
| 103 | LOG_CRITICAL(Frontend, "Failed to create GLFW window! Exiting..."); | ||
| 104 | exit(1); | ||
| 105 | } | ||
| 106 | |||
| 107 | glfwSetWindowUserPointer(m_render_window, this); | ||
| 108 | |||
| 109 | // Notify base interface about window state | ||
| 110 | int width, height; | ||
| 111 | glfwGetFramebufferSize(m_render_window, &width, &height); | ||
| 112 | OnFramebufferResizeEvent(m_render_window, width, height); | ||
| 113 | |||
| 114 | glfwGetWindowSize(m_render_window, &width, &height); | ||
| 115 | OnClientAreaResizeEvent(m_render_window, width, height); | ||
| 116 | |||
| 117 | // Setup callbacks | ||
| 118 | glfwSetKeyCallback(m_render_window, OnKeyEvent); | ||
| 119 | glfwSetMouseButtonCallback(m_render_window, OnMouseButtonEvent); | ||
| 120 | glfwSetCursorPosCallback(m_render_window, OnCursorPosEvent); | ||
| 121 | glfwSetFramebufferSizeCallback(m_render_window, OnFramebufferResizeEvent); | ||
| 122 | glfwSetWindowSizeCallback(m_render_window, OnClientAreaResizeEvent); | ||
| 123 | |||
| 124 | DoneCurrent(); | ||
| 125 | } | ||
| 126 | |||
| 127 | /// EmuWindow_GLFW destructor | ||
| 128 | EmuWindow_GLFW::~EmuWindow_GLFW() { | ||
| 129 | glfwTerminate(); | ||
| 130 | } | ||
| 131 | |||
| 132 | /// Swap buffers to display the next frame | ||
| 133 | void EmuWindow_GLFW::SwapBuffers() { | ||
| 134 | glfwSwapBuffers(m_render_window); | ||
| 135 | } | ||
| 136 | |||
| 137 | /// Polls window events | ||
| 138 | void EmuWindow_GLFW::PollEvents() { | ||
| 139 | glfwPollEvents(); | ||
| 140 | } | ||
| 141 | |||
| 142 | /// Makes the GLFW OpenGL context current for the caller thread | ||
| 143 | void EmuWindow_GLFW::MakeCurrent() { | ||
| 144 | glfwMakeContextCurrent(m_render_window); | ||
| 145 | } | ||
| 146 | |||
| 147 | /// Releases (dunno if this is the "right" word) the GLFW context from the caller thread | ||
| 148 | void EmuWindow_GLFW::DoneCurrent() { | ||
| 149 | glfwMakeContextCurrent(nullptr); | ||
| 150 | } | ||
| 151 | |||
| 152 | void EmuWindow_GLFW::ReloadSetKeymaps() { | ||
| 153 | for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) { | ||
| 154 | KeyMap::SetKeyMapping({Settings::values.input_mappings[Settings::NativeInput::All[i]], keyboard_id}, Service::HID::pad_mapping[i]); | ||
| 155 | } | ||
| 156 | } | ||
| 157 | |||
| 158 | void EmuWindow_GLFW::OnMinimalClientAreaChangeRequest(const std::pair<unsigned,unsigned>& minimal_size) { | ||
| 159 | std::pair<int,int> current_size; | ||
| 160 | glfwGetWindowSize(m_render_window, ¤t_size.first, ¤t_size.second); | ||
| 161 | |||
| 162 | DEBUG_ASSERT((int)minimal_size.first > 0 && (int)minimal_size.second > 0); | ||
| 163 | int new_width = std::max(current_size.first, (int)minimal_size.first); | ||
| 164 | int new_height = std::max(current_size.second, (int)minimal_size.second); | ||
| 165 | |||
| 166 | if (current_size != std::make_pair(new_width, new_height)) | ||
| 167 | glfwSetWindowSize(m_render_window, new_width, new_height); | ||
| 168 | } | ||
diff --git a/src/citra/emu_window/emu_window_glfw.h b/src/citra/emu_window/emu_window_glfw.h deleted file mode 100644 index 7ccd5e6aa..000000000 --- a/src/citra/emu_window/emu_window_glfw.h +++ /dev/null | |||
| @@ -1,54 +0,0 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <utility> | ||
| 8 | |||
| 9 | #include "common/emu_window.h" | ||
| 10 | |||
| 11 | struct GLFWwindow; | ||
| 12 | |||
| 13 | class EmuWindow_GLFW : public EmuWindow { | ||
| 14 | public: | ||
| 15 | EmuWindow_GLFW(); | ||
| 16 | ~EmuWindow_GLFW(); | ||
| 17 | |||
| 18 | /// Swap buffers to display the next frame | ||
| 19 | void SwapBuffers() override; | ||
| 20 | |||
| 21 | /// Polls window events | ||
| 22 | void PollEvents() override; | ||
| 23 | |||
| 24 | /// Makes the graphics context current for the caller thread | ||
| 25 | void MakeCurrent() override; | ||
| 26 | |||
| 27 | /// Releases (dunno if this is the "right" word) the GLFW context from the caller thread | ||
| 28 | void DoneCurrent() override; | ||
| 29 | |||
| 30 | static void OnKeyEvent(GLFWwindow* win, int key, int scancode, int action, int mods); | ||
| 31 | |||
| 32 | static void OnMouseButtonEvent(GLFWwindow* window, int button, int action, int mods); | ||
| 33 | |||
| 34 | static void OnCursorPosEvent(GLFWwindow* window, double x, double y); | ||
| 35 | |||
| 36 | /// Whether the window is still open, and a close request hasn't yet been sent | ||
| 37 | const bool IsOpen(); | ||
| 38 | |||
| 39 | static void OnClientAreaResizeEvent(GLFWwindow* win, int width, int height); | ||
| 40 | |||
| 41 | static void OnFramebufferResizeEvent(GLFWwindow* win, int width, int height); | ||
| 42 | |||
| 43 | void ReloadSetKeymaps() override; | ||
| 44 | |||
| 45 | private: | ||
| 46 | void OnMinimalClientAreaChangeRequest(const std::pair<unsigned,unsigned>& minimal_size) override; | ||
| 47 | |||
| 48 | static EmuWindow_GLFW* GetEmuWindow(GLFWwindow* win); | ||
| 49 | |||
| 50 | GLFWwindow* m_render_window; ///< Internal GLFW render window | ||
| 51 | |||
| 52 | /// Device id of keyboard for use with KeyMap | ||
| 53 | int keyboard_id; | ||
| 54 | }; | ||
diff --git a/src/citra/emu_window/emu_window_sdl2.cpp b/src/citra/emu_window/emu_window_sdl2.cpp new file mode 100644 index 000000000..1fed82e78 --- /dev/null +++ b/src/citra/emu_window/emu_window_sdl2.cpp | |||
| @@ -0,0 +1,167 @@ | |||
| 1 | // Copyright 2016 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <algorithm> | ||
| 6 | #include <cstdlib> | ||
| 7 | #include <string> | ||
| 8 | |||
| 9 | #define SDL_MAIN_HANDLED | ||
| 10 | #include <SDL.h> | ||
| 11 | |||
| 12 | #include "common/key_map.h" | ||
| 13 | #include "common/logging/log.h" | ||
| 14 | #include "common/scm_rev.h" | ||
| 15 | #include "common/string_util.h" | ||
| 16 | |||
| 17 | #include "core/settings.h" | ||
| 18 | #include "core/hle/service/hid/hid.h" | ||
| 19 | |||
| 20 | #include "citra/emu_window/emu_window_sdl2.h" | ||
| 21 | |||
| 22 | #include "video_core/video_core.h" | ||
| 23 | |||
| 24 | void EmuWindow_SDL2::OnMouseMotion(s32 x, s32 y) { | ||
| 25 | TouchMoved((unsigned)std::max(x, 0), (unsigned)std::max(y, 0)); | ||
| 26 | } | ||
| 27 | |||
| 28 | void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) { | ||
| 29 | if (button != SDL_BUTTON_LEFT) | ||
| 30 | return; | ||
| 31 | |||
| 32 | if (state == SDL_PRESSED) { | ||
| 33 | TouchPressed((unsigned)std::max(x, 0), (unsigned)std::max(y, 0)); | ||
| 34 | } else { | ||
| 35 | TouchReleased(); | ||
| 36 | } | ||
| 37 | } | ||
| 38 | |||
| 39 | void EmuWindow_SDL2::OnKeyEvent(int key, u8 state) { | ||
| 40 | if (state == SDL_PRESSED) { | ||
| 41 | KeyPressed({ key, keyboard_id }); | ||
| 42 | } else if (state == SDL_RELEASED) { | ||
| 43 | KeyReleased({ key, keyboard_id }); | ||
| 44 | } | ||
| 45 | } | ||
| 46 | |||
| 47 | bool EmuWindow_SDL2::IsOpen() const { | ||
| 48 | return is_open; | ||
| 49 | } | ||
| 50 | |||
| 51 | void EmuWindow_SDL2::OnResize() { | ||
| 52 | int width, height; | ||
| 53 | |||
| 54 | SDL_GetWindowSize(render_window, &width, &height); | ||
| 55 | |||
| 56 | NotifyFramebufferLayoutChanged(EmuWindow::FramebufferLayout::DefaultScreenLayout(width, height)); | ||
| 57 | } | ||
| 58 | |||
| 59 | EmuWindow_SDL2::EmuWindow_SDL2() { | ||
| 60 | keyboard_id = KeyMap::NewDeviceId(); | ||
| 61 | |||
| 62 | ReloadSetKeymaps(); | ||
| 63 | |||
| 64 | SDL_SetMainReady(); | ||
| 65 | |||
| 66 | // Initialize the window | ||
| 67 | if (SDL_Init(SDL_INIT_VIDEO) < 0) { | ||
| 68 | LOG_CRITICAL(Frontend, "Failed to initialize SDL2! Exiting..."); | ||
| 69 | exit(1); | ||
| 70 | } | ||
| 71 | |||
| 72 | SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); | ||
| 73 | SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); | ||
| 74 | SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); | ||
| 75 | SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); | ||
| 76 | |||
| 77 | std::string window_title = Common::StringFromFormat("Citra | %s-%s", Common::g_scm_branch, Common::g_scm_desc); | ||
| 78 | render_window = SDL_CreateWindow(window_title.c_str(), | ||
| 79 | SDL_WINDOWPOS_UNDEFINED, // x position | ||
| 80 | SDL_WINDOWPOS_UNDEFINED, // y position | ||
| 81 | VideoCore::kScreenTopWidth, | ||
| 82 | VideoCore::kScreenTopHeight + VideoCore::kScreenBottomHeight, | ||
| 83 | SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); | ||
| 84 | |||
| 85 | if (render_window == nullptr) { | ||
| 86 | LOG_CRITICAL(Frontend, "Failed to create SDL2 window! Exiting..."); | ||
| 87 | exit(1); | ||
| 88 | } | ||
| 89 | |||
| 90 | gl_context = SDL_GL_CreateContext(render_window); | ||
| 91 | |||
| 92 | if (gl_context == nullptr) { | ||
| 93 | LOG_CRITICAL(Frontend, "Failed to create SDL2 GL context! Exiting..."); | ||
| 94 | exit(1); | ||
| 95 | } | ||
| 96 | |||
| 97 | OnResize(); | ||
| 98 | OnMinimalClientAreaChangeRequest(GetActiveConfig().min_client_area_size); | ||
| 99 | SDL_PumpEvents(); | ||
| 100 | |||
| 101 | DoneCurrent(); | ||
| 102 | } | ||
| 103 | |||
| 104 | EmuWindow_SDL2::~EmuWindow_SDL2() { | ||
| 105 | SDL_GL_DeleteContext(gl_context); | ||
| 106 | SDL_Quit(); | ||
| 107 | } | ||
| 108 | |||
| 109 | void EmuWindow_SDL2::SwapBuffers() { | ||
| 110 | SDL_GL_SwapWindow(render_window); | ||
| 111 | } | ||
| 112 | |||
| 113 | void EmuWindow_SDL2::PollEvents() { | ||
| 114 | SDL_Event event; | ||
| 115 | |||
| 116 | // SDL_PollEvent returns 0 when there are no more events in the event queue | ||
| 117 | while (SDL_PollEvent(&event)) { | ||
| 118 | switch (event.type) { | ||
| 119 | case SDL_WINDOWEVENT: | ||
| 120 | switch (event.window.event) { | ||
| 121 | case SDL_WINDOWEVENT_SIZE_CHANGED: | ||
| 122 | case SDL_WINDOWEVENT_RESIZED: | ||
| 123 | case SDL_WINDOWEVENT_MAXIMIZED: | ||
| 124 | case SDL_WINDOWEVENT_RESTORED: | ||
| 125 | case SDL_WINDOWEVENT_MINIMIZED: | ||
| 126 | OnResize(); | ||
| 127 | break; | ||
| 128 | case SDL_WINDOWEVENT_CLOSE: | ||
| 129 | is_open = false; | ||
| 130 | break; | ||
| 131 | } | ||
| 132 | break; | ||
| 133 | case SDL_KEYDOWN: | ||
| 134 | case SDL_KEYUP: | ||
| 135 | OnKeyEvent(static_cast<int>(event.key.keysym.scancode), event.key.state); | ||
| 136 | break; | ||
| 137 | case SDL_MOUSEMOTION: | ||
| 138 | OnMouseMotion(event.motion.x, event.motion.y); | ||
| 139 | break; | ||
| 140 | case SDL_MOUSEBUTTONDOWN: | ||
| 141 | case SDL_MOUSEBUTTONUP: | ||
| 142 | OnMouseButton(event.button.button, event.button.state, event.button.x, event.button.y); | ||
| 143 | break; | ||
| 144 | case SDL_QUIT: | ||
| 145 | is_open = false; | ||
| 146 | break; | ||
| 147 | } | ||
| 148 | } | ||
| 149 | } | ||
| 150 | |||
| 151 | void EmuWindow_SDL2::MakeCurrent() { | ||
| 152 | SDL_GL_MakeCurrent(render_window, gl_context); | ||
| 153 | } | ||
| 154 | |||
| 155 | void EmuWindow_SDL2::DoneCurrent() { | ||
| 156 | SDL_GL_MakeCurrent(render_window, nullptr); | ||
| 157 | } | ||
| 158 | |||
| 159 | void EmuWindow_SDL2::ReloadSetKeymaps() { | ||
| 160 | for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) { | ||
| 161 | KeyMap::SetKeyMapping({ Settings::values.input_mappings[Settings::NativeInput::All[i]], keyboard_id }, Service::HID::pad_mapping[i]); | ||
| 162 | } | ||
| 163 | } | ||
| 164 | |||
| 165 | void EmuWindow_SDL2::OnMinimalClientAreaChangeRequest(const std::pair<unsigned, unsigned>& minimal_size) { | ||
| 166 | SDL_SetWindowMinimumSize(render_window, minimal_size.first, minimal_size.second); | ||
| 167 | } | ||
diff --git a/src/citra/emu_window/emu_window_sdl2.h b/src/citra/emu_window/emu_window_sdl2.h new file mode 100644 index 000000000..77279f022 --- /dev/null +++ b/src/citra/emu_window/emu_window_sdl2.h | |||
| @@ -0,0 +1,64 @@ | |||
| 1 | // Copyright 2016 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <utility> | ||
| 8 | |||
| 9 | #include "common/emu_window.h" | ||
| 10 | |||
| 11 | struct SDL_Window; | ||
| 12 | |||
| 13 | class EmuWindow_SDL2 : public EmuWindow { | ||
| 14 | public: | ||
| 15 | EmuWindow_SDL2(); | ||
| 16 | ~EmuWindow_SDL2(); | ||
| 17 | |||
| 18 | /// Swap buffers to display the next frame | ||
| 19 | void SwapBuffers() override; | ||
| 20 | |||
| 21 | /// Polls window events | ||
| 22 | void PollEvents() override; | ||
| 23 | |||
| 24 | /// Makes the graphics context current for the caller thread | ||
| 25 | void MakeCurrent() override; | ||
| 26 | |||
| 27 | /// Releases the GL context from the caller thread | ||
| 28 | void DoneCurrent() override; | ||
| 29 | |||
| 30 | /// Whether the window is still open, and a close request hasn't yet been sent | ||
| 31 | bool IsOpen() const; | ||
| 32 | |||
| 33 | /// Load keymap from configuration | ||
| 34 | void ReloadSetKeymaps() override; | ||
| 35 | |||
| 36 | private: | ||
| 37 | /// Called by PollEvents when a key is pressed or released. | ||
| 38 | void OnKeyEvent(int key, u8 state); | ||
| 39 | |||
| 40 | /// Called by PollEvents when the mouse moves. | ||
| 41 | void OnMouseMotion(s32 x, s32 y); | ||
| 42 | |||
| 43 | /// Called by PollEvents when a mouse button is pressed or released | ||
| 44 | void OnMouseButton(u32 button, u8 state, s32 x, s32 y); | ||
| 45 | |||
| 46 | /// Called by PollEvents when any event that may cause the window to be resized occurs | ||
| 47 | void OnResize(); | ||
| 48 | |||
| 49 | /// Called when a configuration change affects the minimal size of the window | ||
| 50 | void OnMinimalClientAreaChangeRequest(const std::pair<unsigned, unsigned>& minimal_size) override; | ||
| 51 | |||
| 52 | /// Is the window still open? | ||
| 53 | bool is_open = true; | ||
| 54 | |||
| 55 | /// Internal SDL2 render window | ||
| 56 | SDL_Window* render_window; | ||
| 57 | |||
| 58 | using SDL_GLContext = void *; | ||
| 59 | /// The OpenGL context associated with the window | ||
| 60 | SDL_GLContext gl_context; | ||
| 61 | |||
| 62 | /// Device id of keyboard for use with KeyMap | ||
| 63 | int keyboard_id; | ||
| 64 | }; | ||
diff --git a/src/citra_qt/CMakeLists.txt b/src/citra_qt/CMakeLists.txt index b3d1205a4..9b3eb2cd6 100644 --- a/src/citra_qt/CMakeLists.txt +++ b/src/citra_qt/CMakeLists.txt | |||
| @@ -88,9 +88,14 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Linux|FreeBSD|OpenBSD|NetBSD") | |||
| 88 | endif() | 88 | endif() |
| 89 | 89 | ||
| 90 | if (Qt5_FOUND AND MSVC) | 90 | if (Qt5_FOUND AND MSVC) |
| 91 | include(WindowsCopyFiles) | ||
| 92 | |||
| 91 | set(Qt5_DLL_DIR "${Qt5_DIR}/../../../bin") | 93 | set(Qt5_DLL_DIR "${Qt5_DIR}/../../../bin") |
| 92 | set(Qt5_PLATFORMS_DIR "${Qt5_DIR}/../../../plugins/platforms/") | 94 | set(Qt5_PLATFORMS_DIR "${Qt5_DIR}/../../../plugins/platforms/") |
| 93 | set(Qt5_DLLS | 95 | set(DLL_DEST "${CMAKE_BINARY_DIR}/bin/$<CONFIG>/") |
| 96 | set(PLATFORMS ${DLL_DEST}platforms/) | ||
| 97 | |||
| 98 | windows_copy_files(citra-qt ${Qt5_DLL_DIR} ${DLL_DEST} | ||
| 94 | icudt*.dll | 99 | icudt*.dll |
| 95 | icuin*.dll | 100 | icuin*.dll |
| 96 | icuuc*.dll | 101 | icuuc*.dll |
| @@ -99,24 +104,8 @@ if (Qt5_FOUND AND MSVC) | |||
| 99 | Qt5OpenGL$<$<CONFIG:Debug>:d>.* | 104 | Qt5OpenGL$<$<CONFIG:Debug>:d>.* |
| 100 | Qt5Widgets$<$<CONFIG:Debug>:d>.* | 105 | Qt5Widgets$<$<CONFIG:Debug>:d>.* |
| 101 | ) | 106 | ) |
| 102 | set(DLL_DEST "${CMAKE_BINARY_DIR}/bin/$<CONFIG>/") | 107 | windows_copy_files(citra-qt ${Qt5_PLATFORMS_DIR} ${PLATFORMS} qwindows$<$<CONFIG:Debug>:d>.*) |
| 103 | set(PLATFORMS ${DLL_DEST}platforms/) | ||
| 104 | 108 | ||
| 105 | # windows commandline expects the / to be \ so switch them | ||
| 106 | string(REPLACE "/" "\\\\" Qt5_DLL_DIR ${Qt5_DLL_DIR}) | ||
| 107 | string(REPLACE "/" "\\\\" Qt5_PLATFORMS_DIR ${Qt5_PLATFORMS_DIR}) | ||
| 108 | string(REPLACE "/" "\\\\" DLL_DEST ${DLL_DEST}) | ||
| 109 | string(REPLACE "/" "\\\\" PLATFORMS ${PLATFORMS}) | ||
| 110 | |||
| 111 | # /NJH /NJS /NDL /NFL /NC /NS /NP - Silence any output | ||
| 112 | # cmake adds an extra check for command success which doesn't work too well with robocopy | ||
| 113 | # so trick it into thinking the command was successful with the || cmd /c "exit /b 0" | ||
| 114 | add_custom_command(TARGET citra-qt POST_BUILD | ||
| 115 | COMMAND robocopy ${Qt5_DLL_DIR} ${DLL_DEST} ${Qt5_DLLS} /NJH /NJS /NDL /NFL /NC /NS /NP || cmd /c "exit /b 0" | ||
| 116 | COMMAND if not exist ${PLATFORMS} mkdir ${PLATFORMS} 2> nul | ||
| 117 | COMMAND robocopy ${Qt5_PLATFORMS_DIR} ${PLATFORMS} qwindows$<$<CONFIG:Debug>:d>.* /NJH /NJS /NDL /NFL /NC /NS /NP || cmd /c "exit /b 0" | ||
| 118 | ) | ||
| 119 | unset(Qt5_DLLS) | ||
| 120 | unset(Qt5_DLL_DIR) | 109 | unset(Qt5_DLL_DIR) |
| 121 | unset(Qt5_PLATFORMS_DIR) | 110 | unset(Qt5_PLATFORMS_DIR) |
| 122 | unset(DLL_DEST) | 111 | unset(DLL_DEST) |