mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
More SDL3 work by AI
This commit is contained in:
1 parent
34c2218558
commit
6c85a1a4b6
11 files changed
+375
-493
No files matched your search
@@ -330,8 +330,6 @@ set(SDL_LIB_TARGET "")
|
||||
if(NOT LIBRETRO AND NOT IOS AND NOT MACOSX)
|
||||
find_package(SDL3 REQUIRED)
|
||||
set(SDL_LIB_TARGET SDL3::SDL3)
|
||||
add_compile_definitions(SDL_ENABLE_OLD_NAMES)
|
||||
add_compile_definitions(USE_SDL3)
|
||||
message(STATUS "Using SDL3")
|
||||
endif()
|
||||
|
||||
|
||||
+28
-28
@@ -7,32 +7,32 @@
|
||||
// TODO: Add any missing keys
|
||||
static const std::map<int, InputKeyCode> KeyMapRawSDLtoNative = InitConstMap<int, InputKeyCode>
|
||||
(SDLK_UNKNOWN, NKCODE_UNKNOWN)
|
||||
(SDLK_p, NKCODE_P)
|
||||
(SDLK_o, NKCODE_O)
|
||||
(SDLK_i, NKCODE_I)
|
||||
(SDLK_u, NKCODE_U)
|
||||
(SDLK_y, NKCODE_Y)
|
||||
(SDLK_t, NKCODE_T)
|
||||
(SDLK_r, NKCODE_R)
|
||||
(SDLK_e, NKCODE_E)
|
||||
(SDLK_w, NKCODE_W)
|
||||
(SDLK_q, NKCODE_Q)
|
||||
(SDLK_l, NKCODE_L)
|
||||
(SDLK_k, NKCODE_K)
|
||||
(SDLK_j, NKCODE_J)
|
||||
(SDLK_h, NKCODE_H)
|
||||
(SDLK_g, NKCODE_G)
|
||||
(SDLK_f, NKCODE_F)
|
||||
(SDLK_d, NKCODE_D)
|
||||
(SDLK_s, NKCODE_S)
|
||||
(SDLK_a, NKCODE_A)
|
||||
(SDLK_m, NKCODE_M)
|
||||
(SDLK_n, NKCODE_N)
|
||||
(SDLK_b, NKCODE_B)
|
||||
(SDLK_v, NKCODE_V)
|
||||
(SDLK_c, NKCODE_C)
|
||||
(SDLK_x, NKCODE_X)
|
||||
(SDLK_z, NKCODE_Z)
|
||||
(SDLK_P, NKCODE_P)
|
||||
(SDLK_O, NKCODE_O)
|
||||
(SDLK_I, NKCODE_I)
|
||||
(SDLK_U, NKCODE_U)
|
||||
(SDLK_Y, NKCODE_Y)
|
||||
(SDLK_T, NKCODE_T)
|
||||
(SDLK_R, NKCODE_R)
|
||||
(SDLK_E, NKCODE_E)
|
||||
(SDLK_W, NKCODE_W)
|
||||
(SDLK_Q, NKCODE_Q)
|
||||
(SDLK_L, NKCODE_L)
|
||||
(SDLK_K, NKCODE_K)
|
||||
(SDLK_J, NKCODE_J)
|
||||
(SDLK_H, NKCODE_H)
|
||||
(SDLK_G, NKCODE_G)
|
||||
(SDLK_F, NKCODE_F)
|
||||
(SDLK_D, NKCODE_D)
|
||||
(SDLK_S, NKCODE_S)
|
||||
(SDLK_A, NKCODE_A)
|
||||
(SDLK_M, NKCODE_M)
|
||||
(SDLK_N, NKCODE_N)
|
||||
(SDLK_B, NKCODE_B)
|
||||
(SDLK_V, NKCODE_V)
|
||||
(SDLK_C, NKCODE_C)
|
||||
(SDLK_X, NKCODE_X)
|
||||
(SDLK_Z, NKCODE_Z)
|
||||
(SDLK_COMMA, NKCODE_COMMA)
|
||||
(SDLK_PERIOD, NKCODE_PERIOD)
|
||||
(SDLK_LALT, NKCODE_ALT_LEFT)
|
||||
@@ -48,7 +48,7 @@ static const std::map<int, InputKeyCode> KeyMapRawSDLtoNative = InitConstMap<int
|
||||
(SDLK_RIGHTBRACKET, NKCODE_RIGHT_BRACKET)
|
||||
(SDLK_BACKSLASH, NKCODE_BACKSLASH)
|
||||
(SDLK_SEMICOLON, NKCODE_SEMICOLON)
|
||||
(SDLK_QUOTE, NKCODE_APOSTROPHE)
|
||||
(SDLK_APOSTROPHE, NKCODE_APOSTROPHE)
|
||||
(SDLK_SLASH, NKCODE_SLASH)
|
||||
(SDLK_AT, NKCODE_AT)
|
||||
(SDLK_PLUS, NKCODE_PLUS)
|
||||
@@ -80,7 +80,7 @@ static const std::map<int, InputKeyCode> KeyMapRawSDLtoNative = InitConstMap<int
|
||||
(SDLK_KP_PERIOD, NKCODE_NUMPAD_DOT)
|
||||
(SDLK_KP_ENTER, NKCODE_NUMPAD_ENTER)
|
||||
(SDLK_KP_EQUALS, NKCODE_NUMPAD_EQUALS)
|
||||
(SDLK_BACKQUOTE, NKCODE_GRAVE)
|
||||
(SDLK_GRAVE, NKCODE_GRAVE)
|
||||
(SDLK_1, NKCODE_1)
|
||||
(SDLK_2, NKCODE_2)
|
||||
(SDLK_3, NKCODE_3)
|
||||
|
||||
@@ -88,7 +88,6 @@ static int8_t EGL_Open(SDL_Window *window) {
|
||||
g_Window = (EGLNativeWindowType)nullptr;
|
||||
#else
|
||||
// Get the SDL window native handle
|
||||
#if defined(USE_SDL3)
|
||||
SDL_PropertiesID windowProps = SDL_GetWindowProperties(window);
|
||||
void *x11Display = SDL_GetPointerProperty(windowProps, SDL_PROP_WINDOW_X11_DISPLAY_POINTER, nullptr);
|
||||
if (x11Display != nullptr) {
|
||||
@@ -117,52 +116,6 @@ static int8_t EGL_Open(SDL_Window *window) {
|
||||
EGL_ERROR("Unable to get display!", false);
|
||||
g_Window = (EGLNativeWindowType)nullptr;
|
||||
}
|
||||
#else
|
||||
SDL_SysWMinfo sysInfo{};
|
||||
SDL_VERSION(&sysInfo.version);
|
||||
if (!SDL_GetWindowWMInfo(window, &sysInfo)) {
|
||||
fprintf(stderr, "ERROR: Unable to retrieve native window handle\n");
|
||||
g_Display = (EGLNativeDisplayType)XOpenDisplay(nullptr);
|
||||
g_XDisplayOpen = g_Display != nullptr;
|
||||
if (!g_XDisplayOpen)
|
||||
EGL_ERROR("Unable to get display!", false);
|
||||
g_Window = (EGLNativeWindowType)nullptr;
|
||||
} else {
|
||||
switch (sysInfo.subsystem) {
|
||||
case SDL_SYSWM_X11:
|
||||
g_Display = (EGLNativeDisplayType)sysInfo.info.x11.display;
|
||||
g_Window = (EGLNativeWindowType)sysInfo.info.x11.window;
|
||||
break;
|
||||
#if defined(SDL_VIDEO_DRIVER_DIRECTFB)
|
||||
case SDL_SYSWM_DIRECTFB:
|
||||
g_Display = (EGLNativeDisplayType)EGL_DEFAULT_DISPLAY;
|
||||
g_Window = (EGLNativeWindowType)sysInfo.info.dfb.surface;
|
||||
break;
|
||||
#endif
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 2) && defined(SDL_VIDEO_DRIVER_WAYLAND)
|
||||
case SDL_SYSWM_WAYLAND:
|
||||
g_Display = (EGLNativeDisplayType)sysInfo.info.wl.display;
|
||||
g_Window = (EGLNativeWindowType)sysInfo.info.wl.egl_window;
|
||||
break;
|
||||
#endif
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 5) && defined(SDL_VIDEO_DRIVER_VIVANTE)
|
||||
case SDL_SYSWM_VIVANTE:
|
||||
g_Display = (EGLNativeDisplayType)sysInfo.info.vivante.display;
|
||||
g_Window = (EGLNativeWindowType)sysInfo.info.vivante.window;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!EGL_OpenInit()) {
|
||||
// Let's try again with X11.
|
||||
g_Display = (EGLNativeDisplayType)XOpenDisplay(nullptr);
|
||||
g_XDisplayOpen = g_Display != nullptr;
|
||||
if (!g_XDisplayOpen)
|
||||
EGL_ERROR("Unable to get display!", false);
|
||||
g_Window = (EGLNativeWindowType)nullptr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
if (g_eglDisplay == EGL_NO_DISPLAY)
|
||||
@@ -377,7 +330,7 @@ int SDLGLGraphicsContext::Init(SDL_Window *&window, int x, int y, int w, int h,
|
||||
SetGLCoreContext(true);
|
||||
#endif
|
||||
|
||||
window = SDL_CreateWindow("PPSSPP", x, y, w, h, mode);
|
||||
window = SDL_CreateWindow("PPSSPP", w, h, (SDL_WindowFlags)mode);
|
||||
if (!window) {
|
||||
// Definitely don't shutdown here: we'll keep trying more GL versions.
|
||||
fprintf(stderr, "SDL_CreateWindow failed for GL %d.%d: %s\n", ver.major, ver.minor, SDL_GetError());
|
||||
@@ -385,6 +338,10 @@ int SDLGLGraphicsContext::Init(SDL_Window *&window, int x, int y, int w, int h,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (x != SDL_WINDOWPOS_UNDEFINED && y != SDL_WINDOWPOS_UNDEFINED) {
|
||||
SDL_SetWindowPosition(window, x, y);
|
||||
}
|
||||
|
||||
glContext = SDL_GL_CreateContext(window);
|
||||
if (glContext != nullptr) {
|
||||
// Victory, got one.
|
||||
@@ -402,7 +359,7 @@ int SDLGLGraphicsContext::Init(SDL_Window *&window, int x, int y, int w, int h,
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
||||
SetGLCoreContext(false);
|
||||
|
||||
window = SDL_CreateWindow("PPSSPP", x, y, w, h, mode);
|
||||
window = SDL_CreateWindow("PPSSPP", w, h, (SDL_WindowFlags)mode);
|
||||
if (window == nullptr) {
|
||||
NativeShutdown();
|
||||
fprintf(stderr, "SDL_CreateWindow failed: %s\n", SDL_GetError());
|
||||
@@ -410,6 +367,10 @@ int SDLGLGraphicsContext::Init(SDL_Window *&window, int x, int y, int w, int h,
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (x != SDL_WINDOWPOS_UNDEFINED && y != SDL_WINDOWPOS_UNDEFINED) {
|
||||
SDL_SetWindowPosition(window, x, y);
|
||||
}
|
||||
|
||||
glContext = SDL_GL_CreateContext(window);
|
||||
if (glContext == nullptr) {
|
||||
// OK, now we really have tried everything.
|
||||
@@ -493,7 +454,7 @@ void SDLGLGraphicsContext::ShutdownFromRenderThread() {
|
||||
#ifdef USING_EGL
|
||||
EGL_Close();
|
||||
#endif
|
||||
SDL_GL_DeleteContext(glContext);
|
||||
SDL_GL_DestroyContext(glContext);
|
||||
glContext = nullptr;
|
||||
window_ = nullptr;
|
||||
}
|
||||
@@ -1,13 +1,5 @@
|
||||
#include "ppsspp_config.h"
|
||||
#if PPSSPP_PLATFORM(MAC)
|
||||
#include "SDL2/SDL.h"
|
||||
#include "SDL2/SDL_syswm.h"
|
||||
#elif defined(USE_SDL3)
|
||||
#include <SDL3/SDL.h>
|
||||
#else
|
||||
#include "SDL.h"
|
||||
#include "SDL_syswm.h"
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
|
||||
|
||||
+94
-106
@@ -13,22 +13,15 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
#if defined(USE_SDL3)
|
||||
static bool SDLJoystickEventHandlerWrapper(void* userdata, SDL_Event* event) {
|
||||
static_cast<SDLJoystick *>(userdata)->ProcessInput(*event);
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
static int SDLJoystickEventHandlerWrapper(void* userdata, SDL_Event* event) {
|
||||
static_cast<SDLJoystick *>(userdata)->ProcessInput(*event);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
SDLJoystick::SDLJoystick(bool init_SDL ) : registeredAsEventHandler(false) {
|
||||
SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1");
|
||||
if (init_SDL) {
|
||||
SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER);
|
||||
SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO | SDL_INIT_GAMEPAD);
|
||||
}
|
||||
|
||||
const char *dbPath = "gamecontrollerdb.txt";
|
||||
@@ -37,9 +30,8 @@ SDLJoystick::SDLJoystick(bool init_SDL ) : registeredAsEventHandler(false) {
|
||||
size_t size;
|
||||
u8 *mappingData = g_VFS.ReadFile(dbPath, &size);
|
||||
if (mappingData) {
|
||||
SDL_RWops *rw = SDL_RWFromConstMem(mappingData, size);
|
||||
// 1 to free the rw after use
|
||||
if (SDL_GameControllerAddMappingsFromRW(rw, 1) == -1) {
|
||||
SDL_IOStream *io = SDL_IOFromConstMem(mappingData, size);
|
||||
if (SDL_AddGamepadMappingsFromIO(io, true) == -1) {
|
||||
ERROR_LOG(Log::System, "Failed to read mapping data - corrupt?");
|
||||
}
|
||||
delete[] mappingData;
|
||||
@@ -50,69 +42,74 @@ SDLJoystick::SDLJoystick(bool init_SDL ) : registeredAsEventHandler(false) {
|
||||
}
|
||||
|
||||
void SDLJoystick::setUpControllers() {
|
||||
int numjoys = SDL_NumJoysticks();
|
||||
for (int i = 0; i < numjoys; i++) {
|
||||
setUpController(i);
|
||||
int numjoys = 0;
|
||||
SDL_JoystickID *joysticks = SDL_GetJoysticks(&numjoys);
|
||||
for (int i = 0; joysticks && i < numjoys; i++) {
|
||||
setUpController(joysticks[i]);
|
||||
}
|
||||
if (joysticks) {
|
||||
SDL_free(joysticks);
|
||||
}
|
||||
if (controllers.size() > 0) {
|
||||
INFO_LOG(Log::System, "pad 1 has been assigned to control pad: %s", SDL_GameControllerName(controllers.front()));
|
||||
INFO_LOG(Log::System, "pad 1 has been assigned to control pad: %s", SDL_GetGamepadName(controllers.front()));
|
||||
}
|
||||
}
|
||||
|
||||
void SDLJoystick::setUpController(int deviceIndex) {
|
||||
void SDLJoystick::setUpController(SDL_JoystickID deviceID) {
|
||||
static constexpr int cbGUID = 33;
|
||||
char pszGUID[cbGUID];
|
||||
|
||||
if (!SDL_IsGameController(deviceIndex)) {
|
||||
WARN_LOG(Log::System, "Control pad device %d not supported by SDL game controller database, attempting to create default mapping...", deviceIndex);
|
||||
SDL_Joystick *joystick = SDL_JoystickOpen(deviceIndex);
|
||||
if (!SDL_IsGamepad(deviceID)) {
|
||||
WARN_LOG(Log::System, "Control pad device %d not supported by SDL game controller database, attempting to create default mapping...", deviceID);
|
||||
SDL_Joystick *joystick = SDL_OpenJoystick(deviceID);
|
||||
if (joystick) {
|
||||
SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(joystick), pszGUID, cbGUID);
|
||||
SDL_GUIDToString(SDL_GetJoystickGUID(joystick), pszGUID, cbGUID);
|
||||
// create default mapping - this is the PS3 dual shock mapping
|
||||
const std::string safeName = ReplaceAll(SDL_JoystickName(joystick), ",", "");
|
||||
const std::string safeName = ReplaceAll(SDL_GetJoystickName(joystick), ",", "");
|
||||
std::string mapping = std::string(pszGUID) + "," + safeName + ",x:b3,a:b0,b:b1,y:b2,back:b8,guide:b10,start:b9,dpleft:b15,dpdown:b14,dpright:b16,dpup:b13,leftshoulder:b4,lefttrigger:a2,rightshoulder:b6,rightshoulder:b5,righttrigger:a5,leftstick:b7,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4";
|
||||
if (SDL_GameControllerAddMapping(mapping.c_str()) == 1){
|
||||
if (SDL_AddGamepadMapping(mapping.c_str()) == 1){
|
||||
INFO_LOG(Log::System, "Added default mapping ok");
|
||||
} else {
|
||||
ERROR_LOG(Log::System, "Failed to add default mapping");
|
||||
}
|
||||
SDL_JoystickClose(joystick);
|
||||
SDL_CloseJoystick(joystick);
|
||||
} else {
|
||||
ERROR_LOG(Log::System, "Failed to get joystick identifier. Read-only device? Control pad device %d", deviceIndex);
|
||||
ERROR_LOG(Log::System, "Failed to get joystick identifier. Read-only device? Control pad device %d", deviceID);
|
||||
}
|
||||
} else {
|
||||
SDL_Joystick *joystick = SDL_JoystickOpen(deviceIndex);
|
||||
SDL_Joystick *joystick = SDL_OpenJoystick(deviceID);
|
||||
if (joystick) {
|
||||
SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(joystick), pszGUID, cbGUID);
|
||||
SDL_JoystickClose(joystick);
|
||||
SDL_GUIDToString(SDL_GetJoystickGUID(joystick), pszGUID, cbGUID);
|
||||
SDL_CloseJoystick(joystick);
|
||||
}
|
||||
}
|
||||
SDL_GameController *controller = SDL_GameControllerOpen(deviceIndex);
|
||||
SDL_Gamepad *controller = SDL_OpenGamepad(deviceID);
|
||||
if (controller) {
|
||||
if (SDL_GameControllerGetAttached(controller)) {
|
||||
if (SDL_GamepadConnected(controller)) {
|
||||
controllers.push_back(controller);
|
||||
controllerDeviceMap[SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(controller))] = deviceIndex;
|
||||
INFO_LOG(Log::System, "found control pad: %s, loading mapping", SDL_GameControllerName(controller));
|
||||
controllerDeviceMap[SDL_GetJoystickID(SDL_GetGamepadJoystick(controller))] = deviceID;
|
||||
INFO_LOG(Log::System, "found control pad: %s, loading mapping", SDL_GetGamepadName(controller));
|
||||
// NOTE: The case to InputDeviceID here is wrong, we should do some kind of lookup.
|
||||
KeyMap::NotifyPadConnected((InputDeviceID)deviceIndex, std::string(pszGUID) + ": " + SDL_GameControllerName(controller));
|
||||
const char *mapping = SDL_GameControllerMapping(controller);
|
||||
KeyMap::NotifyPadConnected((InputDeviceID)deviceID, std::string(pszGUID) + ": " + SDL_GetGamepadName(controller));
|
||||
char *mapping = SDL_GetGamepadMapping(controller);
|
||||
if (!mapping) {
|
||||
WARN_LOG(Log::System, "Could not find mapping in SDL2 controller database");
|
||||
} else {
|
||||
INFO_LOG(Log::System, "SUCCESS, mapping is: %s", mapping);
|
||||
SDL_free(mapping);
|
||||
}
|
||||
} else {
|
||||
SDL_GameControllerClose(controller);
|
||||
SDL_CloseGamepad(controller);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDLJoystick::~SDLJoystick() {
|
||||
if (registeredAsEventHandler) {
|
||||
SDL_DelEventWatch(SDLJoystickEventHandlerWrapper, this);
|
||||
SDL_RemoveEventWatch(SDLJoystickEventHandlerWrapper, this);
|
||||
}
|
||||
for (auto & controller : controllers) {
|
||||
SDL_GameControllerClose(controller);
|
||||
SDL_CloseGamepad(controller);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,59 +118,51 @@ void SDLJoystick::registerEventHandler() {
|
||||
registeredAsEventHandler = true;
|
||||
}
|
||||
|
||||
InputKeyCode SDLJoystick::getKeycodeForButton(SDL_GameControllerButton button) {
|
||||
InputKeyCode SDLJoystick::getKeycodeForButton(SDL_GamepadButton button) {
|
||||
switch (button) {
|
||||
case SDL_CONTROLLER_BUTTON_DPAD_UP:
|
||||
case SDL_GAMEPAD_BUTTON_DPAD_UP:
|
||||
return NKCODE_DPAD_UP;
|
||||
case SDL_CONTROLLER_BUTTON_DPAD_DOWN:
|
||||
case SDL_GAMEPAD_BUTTON_DPAD_DOWN:
|
||||
return NKCODE_DPAD_DOWN;
|
||||
case SDL_CONTROLLER_BUTTON_DPAD_LEFT:
|
||||
case SDL_GAMEPAD_BUTTON_DPAD_LEFT:
|
||||
return NKCODE_DPAD_LEFT;
|
||||
case SDL_CONTROLLER_BUTTON_DPAD_RIGHT:
|
||||
case SDL_GAMEPAD_BUTTON_DPAD_RIGHT:
|
||||
return NKCODE_DPAD_RIGHT;
|
||||
case SDL_CONTROLLER_BUTTON_A:
|
||||
case SDL_GAMEPAD_BUTTON_SOUTH:
|
||||
return NKCODE_BUTTON_2;
|
||||
case SDL_CONTROLLER_BUTTON_B:
|
||||
case SDL_GAMEPAD_BUTTON_EAST:
|
||||
return NKCODE_BUTTON_3;
|
||||
case SDL_CONTROLLER_BUTTON_X:
|
||||
case SDL_GAMEPAD_BUTTON_WEST:
|
||||
return NKCODE_BUTTON_4;
|
||||
case SDL_CONTROLLER_BUTTON_Y:
|
||||
case SDL_GAMEPAD_BUTTON_NORTH:
|
||||
return NKCODE_BUTTON_1;
|
||||
case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER:
|
||||
case SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER:
|
||||
return NKCODE_BUTTON_5;
|
||||
case SDL_CONTROLLER_BUTTON_LEFTSHOULDER:
|
||||
case SDL_GAMEPAD_BUTTON_LEFT_SHOULDER:
|
||||
return NKCODE_BUTTON_6;
|
||||
case SDL_CONTROLLER_BUTTON_START:
|
||||
case SDL_GAMEPAD_BUTTON_START:
|
||||
return NKCODE_BUTTON_10;
|
||||
case SDL_CONTROLLER_BUTTON_BACK:
|
||||
case SDL_GAMEPAD_BUTTON_BACK:
|
||||
return NKCODE_BUTTON_9; // select button
|
||||
case SDL_CONTROLLER_BUTTON_GUIDE:
|
||||
case SDL_GAMEPAD_BUTTON_GUIDE:
|
||||
return NKCODE_BACK; // pause menu
|
||||
case SDL_CONTROLLER_BUTTON_LEFTSTICK:
|
||||
case SDL_GAMEPAD_BUTTON_LEFT_STICK:
|
||||
return NKCODE_BUTTON_THUMBL;
|
||||
case SDL_CONTROLLER_BUTTON_RIGHTSTICK:
|
||||
case SDL_GAMEPAD_BUTTON_RIGHT_STICK:
|
||||
return NKCODE_BUTTON_THUMBR;
|
||||
|
||||
// Found these limits by checking out the SDL2 branch of the SDL repo, doing git blame, then `git tag --contains (commit)` etc.
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 16)
|
||||
case SDL_CONTROLLER_BUTTON_MISC1:
|
||||
case SDL_GAMEPAD_BUTTON_MISC1:
|
||||
return NKCODE_BUTTON_11;
|
||||
#endif
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 28)
|
||||
case SDL_CONTROLLER_BUTTON_PADDLE1:
|
||||
case SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1:
|
||||
return NKCODE_BUTTON_12;
|
||||
case SDL_CONTROLLER_BUTTON_PADDLE2:
|
||||
case SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2:
|
||||
return NKCODE_BUTTON_13;
|
||||
case SDL_CONTROLLER_BUTTON_PADDLE3:
|
||||
case SDL_GAMEPAD_BUTTON_LEFT_PADDLE1:
|
||||
return NKCODE_BUTTON_14;
|
||||
case SDL_CONTROLLER_BUTTON_PADDLE4:
|
||||
case SDL_GAMEPAD_BUTTON_LEFT_PADDLE2:
|
||||
return NKCODE_BUTTON_15;
|
||||
#endif
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 14)
|
||||
case SDL_CONTROLLER_BUTTON_TOUCHPAD:
|
||||
case SDL_GAMEPAD_BUTTON_TOUCHPAD:
|
||||
return NKCODE_BUTTON_16;
|
||||
#endif
|
||||
case SDL_CONTROLLER_BUTTON_INVALID:
|
||||
case SDL_GAMEPAD_BUTTON_INVALID:
|
||||
default:
|
||||
return NKCODE_UNKNOWN;
|
||||
}
|
||||
@@ -181,39 +170,37 @@ InputKeyCode SDLJoystick::getKeycodeForButton(SDL_GameControllerButton button) {
|
||||
|
||||
void SDLJoystick::ProcessInput(const SDL_Event &event){
|
||||
switch (event.type) {
|
||||
case SDL_CONTROLLERBUTTONDOWN:
|
||||
if (event.cbutton.state == SDL_PRESSED) {
|
||||
auto code = getKeycodeForButton((SDL_GameControllerButton)event.cbutton.button);
|
||||
if (code != NKCODE_UNKNOWN) {
|
||||
KeyInput key;
|
||||
key.flags = KeyInputFlags::DOWN;
|
||||
key.keyCode = code;
|
||||
key.deviceId = DEVICE_ID_PAD_0 + getDeviceIndex(event.cbutton.which);
|
||||
NativeKey(key);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SDL_CONTROLLERBUTTONUP:
|
||||
if (event.cbutton.state == SDL_RELEASED) {
|
||||
auto code = getKeycodeForButton((SDL_GameControllerButton)event.cbutton.button);
|
||||
if (code != NKCODE_UNKNOWN) {
|
||||
KeyInput key;
|
||||
key.flags = KeyInputFlags::UP;
|
||||
key.keyCode = code;
|
||||
key.deviceId = DEVICE_ID_PAD_0 + getDeviceIndex(event.cbutton.which);
|
||||
NativeKey(key);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SDL_CONTROLLERAXISMOTION:
|
||||
case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
|
||||
{
|
||||
InputDeviceID deviceId = DEVICE_ID_PAD_0 + getDeviceIndex(event.caxis.which);
|
||||
// TODO: Can we really cast axis IDs like that? Do they match?
|
||||
InputAxis axisId = (InputAxis)event.caxis.axis;
|
||||
float value = event.caxis.value * (1.f / 32767.f);
|
||||
auto code = getKeycodeForButton((SDL_GamepadButton)event.gbutton.button);
|
||||
if (code != NKCODE_UNKNOWN) {
|
||||
KeyInput key;
|
||||
key.flags = KeyInputFlags::DOWN;
|
||||
key.keyCode = code;
|
||||
key.deviceId = DEVICE_ID_PAD_0 + getDeviceIndex(event.gbutton.which);
|
||||
NativeKey(key);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_GAMEPAD_BUTTON_UP:
|
||||
{
|
||||
auto code = getKeycodeForButton((SDL_GamepadButton)event.gbutton.button);
|
||||
if (code != NKCODE_UNKNOWN) {
|
||||
KeyInput key;
|
||||
key.flags = KeyInputFlags::UP;
|
||||
key.keyCode = code;
|
||||
key.deviceId = DEVICE_ID_PAD_0 + getDeviceIndex(event.gbutton.which);
|
||||
NativeKey(key);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_GAMEPAD_AXIS_MOTION:
|
||||
{
|
||||
InputDeviceID deviceId = DEVICE_ID_PAD_0 + getDeviceIndex(event.gaxis.which);
|
||||
InputAxis axisId = (InputAxis)event.gaxis.axis;
|
||||
float value = event.gaxis.value * (1.f / 32767.f);
|
||||
if (value > 1.0f) value = 1.0f;
|
||||
if (value < -1.0f) value = -1.0f;
|
||||
// Filter duplicate axis values.
|
||||
auto key = std::pair<InputDeviceID, InputAxis>(deviceId, axisId);
|
||||
auto iter = prevAxisValue_.find(key);
|
||||
if (iter == prevAxisValue_.end()) {
|
||||
@@ -225,28 +212,29 @@ void SDLJoystick::ProcessInput(const SDL_Event &event){
|
||||
axis.value = value;
|
||||
axis.deviceId = deviceId;
|
||||
NativeAxis(&axis, 1);
|
||||
} // else ignore event.
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SDL_CONTROLLERDEVICEREMOVED:
|
||||
// for removal events, "which" is the instance ID for SDL_CONTROLLERDEVICEREMOVED
|
||||
case SDL_EVENT_GAMEPAD_REMOVED:
|
||||
for (auto it = controllers.begin(); it != controllers.end(); ++it) {
|
||||
if (SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(*it)) == event.cdevice.which) {
|
||||
SDL_GameControllerClose(*it);
|
||||
if (SDL_GetJoystickID(SDL_GetGamepadJoystick(*it)) == event.gdevice.which) {
|
||||
SDL_CloseGamepad(*it);
|
||||
controllerDeviceMap.erase(event.gdevice.which);
|
||||
controllers.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SDL_CONTROLLERDEVICEADDED:
|
||||
// for add events, "which" is the device index!
|
||||
case SDL_EVENT_GAMEPAD_ADDED:
|
||||
{
|
||||
int prevNumControllers = controllers.size();
|
||||
setUpController(event.cdevice.which);
|
||||
setUpController(event.gdevice.which);
|
||||
if (prevNumControllers == 0 && controllers.size() > 0) {
|
||||
INFO_LOG(Log::System, "pad 1 has been assigned to control pad: %s", SDL_GameControllerName(controllers.front()));
|
||||
INFO_LOG(Log::System, "pad 1 has been assigned to control pad: %s", SDL_GetGamepadName(controllers.front()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int SDLJoystick::getDeviceIndex(int instanceId) {
|
||||
|
||||
+4
-15
@@ -1,18 +1,7 @@
|
||||
#pragma once
|
||||
#ifdef _MSC_VER
|
||||
#include "SDL/SDL.h"
|
||||
#else
|
||||
#if PPSSPP_PLATFORM(MAC)
|
||||
#include "SDL2/SDL.h"
|
||||
#else
|
||||
#if defined(USE_SDL3)
|
||||
#include <SDL3/SDL.h>
|
||||
#else
|
||||
#include "SDL.h"
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "Common/Input/InputState.h"
|
||||
#include "Common/Input/KeyCodes.h"
|
||||
@@ -27,13 +16,13 @@ public:
|
||||
void ProcessInput(const SDL_Event &event);
|
||||
|
||||
private:
|
||||
void setUpController(int deviceIndex);
|
||||
void setUpController(SDL_JoystickID deviceID);
|
||||
void setUpControllers();
|
||||
InputKeyCode getKeycodeForButton(SDL_GameControllerButton button);
|
||||
InputKeyCode getKeycodeForButton(SDL_GamepadButton button);
|
||||
int getDeviceIndex(int instanceId);
|
||||
|
||||
bool registeredAsEventHandler;
|
||||
std::vector<SDL_GameController *> controllers;
|
||||
std::vector<SDL_Gamepad *> controllers;
|
||||
std::map<int, int> controllerDeviceMap;
|
||||
|
||||
// Deduplicate axis events. Pair is device, axis.
|
||||
|
||||
+215
-195
@@ -3,18 +3,8 @@
|
||||
#include <pwd.h>
|
||||
|
||||
#include "ppsspp_config.h"
|
||||
#if PPSSPP_PLATFORM(MAC)
|
||||
#include "SDL2/SDL.h"
|
||||
#include "SDL2/SDL_syswm.h"
|
||||
#include "SDL2/SDL_mouse.h"
|
||||
#elif defined(USE_SDL3)
|
||||
#include <SDL3/SDL.h>
|
||||
#include <SDL3/SDL_mouse.h>
|
||||
#else
|
||||
#include "SDL.h"
|
||||
#include "SDL_syswm.h"
|
||||
#include "SDL_mouse.h"
|
||||
#endif
|
||||
#include "SDL/SDLJoystick.h"
|
||||
SDLJoystick *joystick = NULL;
|
||||
|
||||
@@ -72,13 +62,7 @@ SDLJoystick *joystick = NULL;
|
||||
#include "SDLGLGraphicsContext.h"
|
||||
#include "SDLVulkanGraphicsContext.h"
|
||||
|
||||
#if PPSSPP_PLATFORM(MAC)
|
||||
#include "SDL2/SDL_vulkan.h"
|
||||
#elif defined(USE_SDL3)
|
||||
#include <SDL3/SDL_vulkan.h>
|
||||
#else
|
||||
#include "SDL_vulkan.h"
|
||||
#endif
|
||||
|
||||
#if PPSSPP_PLATFORM(MAC) || PPSSPP_PLATFORM(IOS)
|
||||
#include "Core/Util/DarwinFileSystemServices.h"
|
||||
@@ -109,6 +93,7 @@ static int g_sampleRate = 44100;
|
||||
static bool g_rebootEmuThread = false;
|
||||
|
||||
static SDL_AudioSpec g_retFmt;
|
||||
static int g_audioFramesPerBuffer = 0;
|
||||
|
||||
static bool g_textFocusChanged;
|
||||
static bool g_textFocus;
|
||||
@@ -139,78 +124,114 @@ int getDisplayNumber(void) {
|
||||
return displayNumber;
|
||||
}
|
||||
|
||||
void sdl_mixaudio_callback(void *userdata, Uint8 *stream, int len) {
|
||||
NativeMix((short *)stream, len / (2 * 2), g_sampleRate, userdata);
|
||||
void sdl_mixaudio_callback(void *userdata, SDL_AudioStream *stream, int additional_amount, int total_amount) {
|
||||
(void)total_amount;
|
||||
if (additional_amount <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const int frames = additional_amount / (int)(sizeof(int16_t) * 2);
|
||||
if (frames <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<int16_t> mixBuf(frames * 2);
|
||||
NativeMix(mixBuf.data(), frames, g_sampleRate, userdata);
|
||||
SDL_PutAudioStreamData(stream, mixBuf.data(), (int)(mixBuf.size() * sizeof(int16_t)));
|
||||
}
|
||||
|
||||
static SDL_AudioDeviceID audioDev = 0;
|
||||
static SDL_AudioStream *audioStream = nullptr;
|
||||
|
||||
// Must be called after NativeInit().
|
||||
static void InitSDLAudioDevice(const std::string &name = "") {
|
||||
SDL_AudioSpec fmt;
|
||||
memset(&fmt, 0, sizeof(fmt));
|
||||
SDL_AudioSpec fmt{};
|
||||
fmt.freq = g_sampleRate;
|
||||
fmt.format = AUDIO_S16;
|
||||
fmt.format = SDL_AUDIO_S16;
|
||||
fmt.channels = 2;
|
||||
fmt.samples = std::max(g_Config.iSDLAudioBufferSize, 128);
|
||||
fmt.callback = &sdl_mixaudio_callback;
|
||||
fmt.userdata = nullptr;
|
||||
g_audioFramesPerBuffer = std::max(g_Config.iSDLAudioBufferSize, 128);
|
||||
|
||||
std::string startDevice = name;
|
||||
if (startDevice.empty()) {
|
||||
startDevice = g_Config.sAudioDevice;
|
||||
}
|
||||
|
||||
int deviceCount = 0;
|
||||
SDL_AudioDeviceID *devices = SDL_GetAudioPlaybackDevices(&deviceCount);
|
||||
SDL_AudioDeviceID chosenDevice = SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK;
|
||||
|
||||
// List available audio devices before trying to open, for debugging purposes.
|
||||
const int deviceCount = SDL_GetNumAudioDevices(0);
|
||||
if (deviceCount > 0) {
|
||||
if (deviceCount > 0 && devices) {
|
||||
INFO_LOG(Log::Audio, "Available audio devices:");
|
||||
for (int i = 0; i < deviceCount; i++) {
|
||||
const char *deviceName = SDL_GetAudioDeviceName(i, 0);
|
||||
const char *deviceName = SDL_GetAudioDeviceName(devices[i]);
|
||||
if (!deviceName) {
|
||||
deviceName = "(unknown)";
|
||||
}
|
||||
INFO_LOG(Log::Audio, " * '%s'", deviceName);
|
||||
if (!startDevice.empty() && startDevice == deviceName) {
|
||||
chosenDevice = devices[i];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
INFO_LOG(Log::Audio, "Failed to list audio devices: retval=%d", deviceCount);
|
||||
}
|
||||
|
||||
if (!startDevice.empty() && chosenDevice == SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK) {
|
||||
WARN_LOG(Log::Audio, "Audio device '%s' not found, using default", startDevice.c_str());
|
||||
}
|
||||
|
||||
if (audioStream) {
|
||||
SDL_DestroyAudioStream(audioStream);
|
||||
audioStream = nullptr;
|
||||
}
|
||||
|
||||
audioDev = 0;
|
||||
if (!startDevice.empty()) {
|
||||
if (chosenDevice == SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK) {
|
||||
INFO_LOG(Log::Audio, "Opening default audio device");
|
||||
} else {
|
||||
INFO_LOG(Log::Audio, "Opening audio device: '%s'", startDevice.c_str());
|
||||
audioDev = SDL_OpenAudioDevice(startDevice.c_str(), 0, &fmt, &g_retFmt, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
|
||||
if (audioDev <= 0) {
|
||||
WARN_LOG(Log::Audio, "Failed to open audio device '%s'", startDevice.c_str());
|
||||
}
|
||||
}
|
||||
if (audioDev <= 0) {
|
||||
if (audioDev < 0) {
|
||||
WARN_LOG(Log::Audio, "SDL: Error: '%s'. Trying the default audio device", SDL_GetError());
|
||||
} else {
|
||||
INFO_LOG(Log::Audio, "Opening default audio device");
|
||||
}
|
||||
audioDev = SDL_OpenAudioDevice(nullptr, 0, &fmt, &g_retFmt, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
|
||||
|
||||
audioStream = SDL_OpenAudioDeviceStream(chosenDevice, &fmt, sdl_mixaudio_callback, nullptr);
|
||||
if (!audioStream && chosenDevice != SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK) {
|
||||
WARN_LOG(Log::Audio, "SDL: Error opening '%s': '%s'. Trying default.", startDevice.c_str(), SDL_GetError());
|
||||
audioStream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &fmt, sdl_mixaudio_callback, nullptr);
|
||||
}
|
||||
if (audioDev <= 0) {
|
||||
|
||||
if (!audioStream) {
|
||||
ERROR_LOG(Log::Audio, "Failed to open audio device '%s', second try. Giving up.", SDL_GetError());
|
||||
} else {
|
||||
if (g_retFmt.samples != fmt.samples) // Notify, but still use it
|
||||
ERROR_LOG(Log::Audio, "Output audio samples: %d (requested: %d)", g_retFmt.samples, fmt.samples);
|
||||
if (g_retFmt.format != fmt.format || g_retFmt.channels != fmt.channels) {
|
||||
ERROR_LOG(Log::Audio, "Sound buffer format does not match requested format.");
|
||||
ERROR_LOG(Log::Audio, "Output audio freq: %d (requested: %d)", g_retFmt.freq, fmt.freq);
|
||||
ERROR_LOG(Log::Audio, "Output audio format: %d (requested: %d)", g_retFmt.format, fmt.format);
|
||||
ERROR_LOG(Log::Audio, "Output audio channels: %d (requested: %d)", g_retFmt.channels, fmt.channels);
|
||||
ERROR_LOG(Log::Audio, "Provided output format does not match requirement, turning audio off");
|
||||
SDL_CloseAudioDevice(audioDev);
|
||||
audioDev = SDL_GetAudioStreamDevice(audioStream);
|
||||
if (!SDL_GetAudioDeviceFormat(audioDev, &g_retFmt, &g_audioFramesPerBuffer)) {
|
||||
WARN_LOG(Log::Audio, "Could not query active audio format: %s", SDL_GetError());
|
||||
g_retFmt = fmt;
|
||||
g_audioFramesPerBuffer = std::max(g_Config.iSDLAudioBufferSize, 128);
|
||||
}
|
||||
SDL_PauseAudioDevice(audioDev, 0);
|
||||
|
||||
if (g_retFmt.freq != fmt.freq || g_retFmt.format != fmt.format || g_retFmt.channels != fmt.channels) {
|
||||
WARN_LOG(Log::Audio, "Audio output format differs from requested (freq=%d/%d format=%u/%u ch=%d/%d)", g_retFmt.freq, fmt.freq, (unsigned)g_retFmt.format, (unsigned)fmt.format, g_retFmt.channels, fmt.channels);
|
||||
}
|
||||
|
||||
if (!SDL_ResumeAudioStreamDevice(audioStream)) {
|
||||
ERROR_LOG(Log::Audio, "Failed to start audio stream: %s", SDL_GetError());
|
||||
SDL_DestroyAudioStream(audioStream);
|
||||
audioStream = nullptr;
|
||||
audioDev = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (devices) {
|
||||
SDL_free(devices);
|
||||
}
|
||||
}
|
||||
|
||||
static void StopSDLAudioDevice() {
|
||||
if (audioDev > 0) {
|
||||
SDL_PauseAudioDevice(audioDev, 1);
|
||||
SDL_CloseAudioDevice(audioDev);
|
||||
if (audioStream) {
|
||||
SDL_DestroyAudioStream(audioStream);
|
||||
audioStream = nullptr;
|
||||
}
|
||||
audioDev = 0;
|
||||
}
|
||||
|
||||
static void UpdateScreenDPI(SDL_Window *window) {
|
||||
@@ -218,9 +239,9 @@ static void UpdateScreenDPI(SDL_Window *window) {
|
||||
SDL_GetWindowSize(window, &window_width, &window_height);
|
||||
|
||||
if (g_Config.iGPUBackend == (int)GPUBackend::OPENGL)
|
||||
SDL_GL_GetDrawableSize(window, &drawable_width, NULL);
|
||||
SDL_GetWindowSizeInPixels(window, &drawable_width, NULL);
|
||||
else if (g_Config.iGPUBackend == (int)GPUBackend::VULKAN)
|
||||
SDL_Vulkan_GetDrawableSize(window, &drawable_width, NULL);
|
||||
SDL_GetWindowSizeInPixels(window, &drawable_width, NULL);
|
||||
else {
|
||||
// If we add SDL support for more platforms, we'll end up here.
|
||||
g_DesktopDPI = 1.0f;
|
||||
@@ -610,8 +631,10 @@ std::string System_GetProperty(SystemProperty prop) {
|
||||
case SYSPROP_AUDIO_DEVICE_LIST:
|
||||
{
|
||||
std::string result;
|
||||
for (int i = 0; i < SDL_GetNumAudioDevices(0); ++i) {
|
||||
const char *name = SDL_GetAudioDeviceName(i, 0);
|
||||
int count = 0;
|
||||
SDL_AudioDeviceID *devices = SDL_GetAudioPlaybackDevices(&count);
|
||||
for (int i = 0; devices && i < count; ++i) {
|
||||
const char *name = SDL_GetAudioDeviceName(devices[i]);
|
||||
if (!name) {
|
||||
continue;
|
||||
}
|
||||
@@ -623,6 +646,9 @@ std::string System_GetProperty(SystemProperty prop) {
|
||||
result.append(name);
|
||||
}
|
||||
}
|
||||
if (devices) {
|
||||
SDL_free(devices);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
case SYSPROP_BUILD_VERSION:
|
||||
@@ -666,7 +692,7 @@ int64_t System_GetPropertyInt(SystemProperty prop) {
|
||||
case SYSPROP_AUDIO_SAMPLE_RATE:
|
||||
return g_retFmt.freq;
|
||||
case SYSPROP_AUDIO_FRAMES_PER_BUFFER:
|
||||
return g_retFmt.samples;
|
||||
return g_audioFramesPerBuffer;
|
||||
case SYSPROP_DEVICE_TYPE:
|
||||
#if defined(MOBILE_DEVICE)
|
||||
return DEVICE_TYPE_MOBILE;
|
||||
@@ -674,13 +700,20 @@ int64_t System_GetPropertyInt(SystemProperty prop) {
|
||||
return DEVICE_TYPE_DESKTOP;
|
||||
#endif
|
||||
case SYSPROP_DISPLAY_COUNT:
|
||||
return SDL_GetNumVideoDisplays();
|
||||
{
|
||||
int displayCount = 0;
|
||||
SDL_DisplayID *displays = SDL_GetDisplays(&displayCount);
|
||||
if (displays) {
|
||||
SDL_free(displays);
|
||||
}
|
||||
return displayCount;
|
||||
}
|
||||
case SYSPROP_KEYBOARD_LAYOUT:
|
||||
{
|
||||
char q, w, y;
|
||||
q = SDL_GetKeyFromScancode(SDL_SCANCODE_Q);
|
||||
w = SDL_GetKeyFromScancode(SDL_SCANCODE_W);
|
||||
y = SDL_GetKeyFromScancode(SDL_SCANCODE_Y);
|
||||
q = SDL_GetKeyFromScancode(SDL_SCANCODE_Q, SDL_KMOD_NONE, false);
|
||||
w = SDL_GetKeyFromScancode(SDL_SCANCODE_W, SDL_KMOD_NONE, false);
|
||||
y = SDL_GetKeyFromScancode(SDL_SCANCODE_Y, SDL_KMOD_NONE, false);
|
||||
if (q == 'a' && w == 'z' && y == 'y')
|
||||
return KEYBOARD_LAYOUT_AZERTY;
|
||||
else if (q == 'q' && w == 'w' && y == 'z')
|
||||
@@ -829,14 +862,7 @@ void UpdateWindowState(SDL_Window *window) {
|
||||
SDL_SetWindowTitle(window, g_windowState.title.c_str());
|
||||
if (g_windowState.applyFullScreenNextFrame) {
|
||||
g_windowState.applyFullScreenNextFrame = false;
|
||||
|
||||
Uint32 window_flags = SDL_GetWindowFlags(window);
|
||||
if (g_Config.bFullScreen) {
|
||||
window_flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||
} else {
|
||||
window_flags &= ~SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||
}
|
||||
SDL_SetWindowFullscreen(window, window_flags);
|
||||
SDL_SetWindowFullscreen(window, g_Config.bFullScreen);
|
||||
}
|
||||
if (g_windowState.clipboardDataAvailable) {
|
||||
SDL_SetClipboardText(g_windowState.clipboardString.c_str());
|
||||
@@ -889,14 +915,11 @@ static void EmuThreadJoin() {
|
||||
}
|
||||
|
||||
struct InputStateTracker {
|
||||
void MouseCaptureControl() {
|
||||
void MouseCaptureControl(SDL_Window *window) {
|
||||
bool captureMouseCondition = g_Config.bMouseControl && ((GetUIState() == UISTATE_INGAME && g_Config.bMouseConfine) || g_IsMappingMouseInput);
|
||||
if (mouseCaptured != captureMouseCondition) {
|
||||
mouseCaptured = captureMouseCondition;
|
||||
if (captureMouseCondition)
|
||||
SDL_SetRelativeMouseMode(SDL_TRUE);
|
||||
else
|
||||
SDL_SetRelativeMouseMode(SDL_FALSE);
|
||||
SDL_SetWindowRelativeMouseMode(window, captureMouseCondition);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -904,25 +927,25 @@ struct InputStateTracker {
|
||||
bool mouseCaptured;
|
||||
};
|
||||
|
||||
SDL_Cursor *g_builtinCursors[SDL_NUM_SYSTEM_CURSORS];
|
||||
SDL_Cursor *g_builtinCursors[SDL_SYSTEM_CURSOR_COUNT];
|
||||
|
||||
static SDL_SystemCursor GetSDLCursorFromImgui(ImGuiMouseCursor cursor) {
|
||||
switch (cursor) {
|
||||
case ImGuiMouseCursor_Arrow: return SDL_SYSTEM_CURSOR_ARROW; break;
|
||||
case ImGuiMouseCursor_TextInput: return SDL_SYSTEM_CURSOR_IBEAM; break;
|
||||
case ImGuiMouseCursor_ResizeAll: return SDL_SYSTEM_CURSOR_SIZEALL; break;
|
||||
case ImGuiMouseCursor_ResizeEW: return SDL_SYSTEM_CURSOR_SIZEWE; break;
|
||||
case ImGuiMouseCursor_ResizeNS: return SDL_SYSTEM_CURSOR_SIZENS; break;
|
||||
case ImGuiMouseCursor_ResizeNESW: return SDL_SYSTEM_CURSOR_SIZENESW; break;
|
||||
case ImGuiMouseCursor_ResizeNWSE: return SDL_SYSTEM_CURSOR_SIZENWSE; break;
|
||||
case ImGuiMouseCursor_Hand: return SDL_SYSTEM_CURSOR_HAND; break;
|
||||
case ImGuiMouseCursor_NotAllowed: return SDL_SYSTEM_CURSOR_NO; break;
|
||||
default: return SDL_SYSTEM_CURSOR_ARROW; break;
|
||||
case ImGuiMouseCursor_Arrow: return SDL_SYSTEM_CURSOR_DEFAULT; break;
|
||||
case ImGuiMouseCursor_TextInput: return SDL_SYSTEM_CURSOR_TEXT; break;
|
||||
case ImGuiMouseCursor_ResizeAll: return SDL_SYSTEM_CURSOR_MOVE; break;
|
||||
case ImGuiMouseCursor_ResizeEW: return SDL_SYSTEM_CURSOR_EW_RESIZE; break;
|
||||
case ImGuiMouseCursor_ResizeNS: return SDL_SYSTEM_CURSOR_NS_RESIZE; break;
|
||||
case ImGuiMouseCursor_ResizeNESW: return SDL_SYSTEM_CURSOR_NESW_RESIZE; break;
|
||||
case ImGuiMouseCursor_ResizeNWSE: return SDL_SYSTEM_CURSOR_NWSE_RESIZE; break;
|
||||
case ImGuiMouseCursor_Hand: return SDL_SYSTEM_CURSOR_POINTER; break;
|
||||
case ImGuiMouseCursor_NotAllowed: return SDL_SYSTEM_CURSOR_NOT_ALLOWED; break;
|
||||
default: return SDL_SYSTEM_CURSOR_DEFAULT; break;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateCursor() {
|
||||
static SDL_SystemCursor curCursor = SDL_SYSTEM_CURSOR_ARROW;
|
||||
static SDL_SystemCursor curCursor = SDL_SYSTEM_CURSOR_DEFAULT;
|
||||
auto cursor = ImGui_ImplPlatform_GetCursor();
|
||||
SDL_SystemCursor sysCursor = GetSDLCursorFromImgui(cursor);
|
||||
if (sysCursor != curCursor) {
|
||||
@@ -944,30 +967,23 @@ static void ProcessSDLEvent(SDL_Window *window, const SDL_Event &event, InputSta
|
||||
float my = event.motion.y * g_DesktopDPI * g_display.dpi_scale_x;
|
||||
|
||||
switch (event.type) {
|
||||
case SDL_QUIT:
|
||||
case SDL_EVENT_QUIT:
|
||||
g_QuitRequested = 1;
|
||||
break;
|
||||
|
||||
#if !defined(MOBILE_DEVICE)
|
||||
case SDL_WINDOWEVENT:
|
||||
switch (event.window.event) {
|
||||
case SDL_WINDOWEVENT_SIZE_CHANGED: // better than RESIZED, more general
|
||||
#if !defined(MOBILE_DEVICE)
|
||||
case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
|
||||
{
|
||||
int new_width = event.window.data1;
|
||||
int new_height = event.window.data2;
|
||||
|
||||
// The size given by SDL is in point-units, convert these to
|
||||
// pixels before passing to Native_UpdateScreenScale()
|
||||
int new_width_px = new_width * g_DesktopDPI;
|
||||
int new_height_px = new_height * g_DesktopDPI;
|
||||
|
||||
Native_NotifyWindowHidden(false);
|
||||
|
||||
Uint32 window_flags = SDL_GetWindowFlags(window);
|
||||
bool fullscreen = (window_flags & (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_FULLSCREEN_DESKTOP));
|
||||
Uint64 window_flags = SDL_GetWindowFlags(window);
|
||||
bool fullscreen = (window_flags & SDL_WINDOW_FULLSCREEN) != 0;
|
||||
|
||||
// This one calls NativeResized if the size changed.
|
||||
Native_UpdateScreenScale(new_width_px, new_height_px, UIScaleFactorToMultiplier(g_Config.iUIScaleFactor));
|
||||
Native_UpdateScreenScale(new_width, new_height, UIScaleFactorToMultiplier(g_Config.iUIScaleFactor));
|
||||
|
||||
// Set variable here in case fullscreen was toggled by hotkey
|
||||
if (g_Config.bFullScreen != fullscreen) {
|
||||
@@ -979,22 +995,24 @@ static void ProcessSDLEvent(SDL_Window *window, const SDL_Event &event, InputSta
|
||||
}
|
||||
|
||||
if (!g_Config.bFullScreen) {
|
||||
g_Config.iWindowWidth = new_width;
|
||||
g_Config.iWindowHeight = new_height;
|
||||
int windowWidth = 0;
|
||||
int windowHeight = 0;
|
||||
SDL_GetWindowSize(window, &windowWidth, &windowHeight);
|
||||
g_Config.iWindowWidth = windowWidth;
|
||||
g_Config.iWindowHeight = windowHeight;
|
||||
}
|
||||
// Hide/Show cursor correctly toggling fullscreen
|
||||
if (lastUIState == UISTATE_INGAME && fullscreen && !g_Config.bShowTouchControls) {
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
SDL_HideCursor();
|
||||
} else if (lastUIState != UISTATE_INGAME || !fullscreen) {
|
||||
SDL_ShowCursor(SDL_ENABLE);
|
||||
SDL_ShowCursor();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_WINDOWEVENT_MOVED:
|
||||
case SDL_EVENT_WINDOW_MOVED:
|
||||
{
|
||||
Uint32 window_flags = SDL_GetWindowFlags(window);
|
||||
bool fullscreen = (window_flags & (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_FULLSCREEN_DESKTOP));
|
||||
Uint64 window_flags = SDL_GetWindowFlags(window);
|
||||
bool fullscreen = (window_flags & SDL_WINDOW_FULLSCREEN) != 0;
|
||||
if (!fullscreen) {
|
||||
g_Config.iWindowX = (int)event.window.data1;
|
||||
g_Config.iWindowY = (int)event.window.data2;
|
||||
@@ -1002,7 +1020,7 @@ static void ProcessSDLEvent(SDL_Window *window, const SDL_Event &event, InputSta
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_WINDOWEVENT_FOCUS_LOST:
|
||||
case SDL_EVENT_WINDOW_FOCUS_LOST:
|
||||
{
|
||||
if (g_Config.bPauseOnLostFocus && GetUIState() == UISTATE_INGAME) {
|
||||
Core_Break(BreakReason::UIFocus, 0);
|
||||
@@ -1010,7 +1028,7 @@ static void ProcessSDLEvent(SDL_Window *window, const SDL_Event &event, InputSta
|
||||
}
|
||||
break;
|
||||
|
||||
case SDL_WINDOWEVENT_FOCUS_GAINED:
|
||||
case SDL_EVENT_WINDOW_FOCUS_GAINED:
|
||||
{
|
||||
if (Core_BreakReason() == BreakReason::UIFocus) {
|
||||
Core_Resume();
|
||||
@@ -1018,23 +1036,20 @@ static void ProcessSDLEvent(SDL_Window *window, const SDL_Event &event, InputSta
|
||||
}
|
||||
break;
|
||||
|
||||
case SDL_WINDOWEVENT_MINIMIZED:
|
||||
case SDL_WINDOWEVENT_HIDDEN:
|
||||
case SDL_EVENT_WINDOW_MINIMIZED:
|
||||
case SDL_EVENT_WINDOW_HIDDEN:
|
||||
Native_NotifyWindowHidden(true);
|
||||
break;
|
||||
case SDL_WINDOWEVENT_EXPOSED:
|
||||
case SDL_WINDOWEVENT_SHOWN:
|
||||
case SDL_EVENT_WINDOW_EXPOSED:
|
||||
case SDL_EVENT_WINDOW_SHOWN:
|
||||
Native_NotifyWindowHidden(false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case SDL_KEYDOWN:
|
||||
case SDL_EVENT_KEY_DOWN:
|
||||
{
|
||||
if (event.key.repeat > 0) { break;}
|
||||
int k = event.key.keysym.sym;
|
||||
int k = event.key.key;
|
||||
KeyInput key;
|
||||
key.flags = KeyInputFlags::DOWN;
|
||||
auto mapped = KeyMapRawSDLtoNative.find(k);
|
||||
@@ -1055,8 +1070,8 @@ static void ProcessSDLEvent(SDL_Window *window, const SDL_Event &event, InputSta
|
||||
// "Enable standard shortcut keys"
|
||||
// does on Windows.
|
||||
if (g_Config.bSystemControls) {
|
||||
bool ctrl = bool(event.key.keysym.mod & KMOD_CTRL);
|
||||
if (ctrl && (k == SDLK_w))
|
||||
bool ctrl = bool(event.key.mod & SDL_KMOD_CTRL);
|
||||
if (ctrl && (k == SDLK_W))
|
||||
{
|
||||
if (Core_IsStepping())
|
||||
Core_Resume();
|
||||
@@ -1080,10 +1095,10 @@ static void ProcessSDLEvent(SDL_Window *window, const SDL_Event &event, InputSta
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SDL_KEYUP:
|
||||
case SDL_EVENT_KEY_UP:
|
||||
{
|
||||
if (event.key.repeat > 0) { break;}
|
||||
int k = event.key.keysym.sym;
|
||||
int k = event.key.key;
|
||||
KeyInput key;
|
||||
key.flags = KeyInputFlags::UP;
|
||||
auto mapped = KeyMapRawSDLtoNative.find(k);
|
||||
@@ -1095,7 +1110,7 @@ static void ProcessSDLEvent(SDL_Window *window, const SDL_Event &event, InputSta
|
||||
NativeKey(key);
|
||||
break;
|
||||
}
|
||||
case SDL_TEXTINPUT:
|
||||
case SDL_EVENT_TEXT_INPUT:
|
||||
{
|
||||
int pos = 0;
|
||||
int c = u8_nextchar(event.text.text, &pos, strlen(event.text.text));
|
||||
@@ -1108,12 +1123,12 @@ static void ProcessSDLEvent(SDL_Window *window, const SDL_Event &event, InputSta
|
||||
}
|
||||
// This behavior doesn't feel right on a macbook with a touchpad.
|
||||
#if !PPSSPP_PLATFORM(MAC)
|
||||
case SDL_FINGERMOTION:
|
||||
case SDL_EVENT_FINGER_MOTION:
|
||||
{
|
||||
int w, h;
|
||||
SDL_GetWindowSize(window, &w, &h);
|
||||
TouchInput input{};
|
||||
input.id = event.tfinger.fingerId;
|
||||
input.id = event.tfinger.fingerID;
|
||||
input.x = event.tfinger.x * w * g_DesktopDPI * g_display.dpi_scale_x;
|
||||
input.y = event.tfinger.y * h * g_DesktopDPI * g_display.dpi_scale_x;
|
||||
input.flags = TouchInputFlags::MOVE;
|
||||
@@ -1121,12 +1136,12 @@ static void ProcessSDLEvent(SDL_Window *window, const SDL_Event &event, InputSta
|
||||
NativeTouch(input);
|
||||
break;
|
||||
}
|
||||
case SDL_FINGERDOWN:
|
||||
case SDL_EVENT_FINGER_DOWN:
|
||||
{
|
||||
int w, h;
|
||||
SDL_GetWindowSize(window, &w, &h);
|
||||
TouchInput input{};
|
||||
input.id = event.tfinger.fingerId;
|
||||
input.id = event.tfinger.fingerID;
|
||||
input.x = event.tfinger.x * w * g_DesktopDPI * g_display.dpi_scale_x;
|
||||
input.y = event.tfinger.y * h * g_DesktopDPI * g_display.dpi_scale_x;
|
||||
input.flags = TouchInputFlags::DOWN;
|
||||
@@ -1140,12 +1155,12 @@ static void ProcessSDLEvent(SDL_Window *window, const SDL_Event &event, InputSta
|
||||
NativeKey(key);
|
||||
break;
|
||||
}
|
||||
case SDL_FINGERUP:
|
||||
case SDL_EVENT_FINGER_UP:
|
||||
{
|
||||
int w, h;
|
||||
SDL_GetWindowSize(window, &w, &h);
|
||||
TouchInput input{};
|
||||
input.id = event.tfinger.fingerId;
|
||||
input.id = event.tfinger.fingerID;
|
||||
input.x = event.tfinger.x * w * g_DesktopDPI * g_display.dpi_scale_x;
|
||||
input.y = event.tfinger.y * h * g_DesktopDPI * g_display.dpi_scale_x;
|
||||
input.flags = TouchInputFlags::UP;
|
||||
@@ -1160,7 +1175,7 @@ static void ProcessSDLEvent(SDL_Window *window, const SDL_Event &event, InputSta
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
case SDL_EVENT_MOUSE_BUTTON_DOWN:
|
||||
switch (event.button.button) {
|
||||
case SDL_BUTTON_LEFT:
|
||||
{
|
||||
@@ -1210,36 +1225,34 @@ static void ProcessSDLEvent(SDL_Window *window, const SDL_Event &event, InputSta
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SDL_MOUSEWHEEL:
|
||||
case SDL_EVENT_MOUSE_WHEEL:
|
||||
{
|
||||
KeyInput key{};
|
||||
key.deviceId = DEVICE_ID_MOUSE;
|
||||
key.flags = KeyInputFlags::DOWN;
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 18)
|
||||
if (event.wheel.preciseY != 0.0f) {
|
||||
// Should the scale be DPI-driven?
|
||||
float wheelY = event.wheel.y;
|
||||
if (event.wheel.direction == SDL_MOUSEWHEEL_FLIPPED) {
|
||||
wheelY = -wheelY;
|
||||
}
|
||||
if (wheelY != 0.0f) {
|
||||
const float scale = 30.0f;
|
||||
key.keyCode = event.wheel.preciseY > 0 ? NKCODE_EXT_MOUSEWHEEL_UP : NKCODE_EXT_MOUSEWHEEL_DOWN;
|
||||
key.keyCode = wheelY > 0 ? NKCODE_EXT_MOUSEWHEEL_UP : NKCODE_EXT_MOUSEWHEEL_DOWN;
|
||||
key.flags |= KeyInputFlags::HAS_WHEEL_DELTA;
|
||||
int wheelDelta = event.wheel.preciseY * scale;
|
||||
if (event.wheel.preciseY < 0) {
|
||||
wheelDelta = -wheelDelta;
|
||||
}
|
||||
int wheelDelta = (int)(fabsf(wheelY) * scale);
|
||||
key.flags = (KeyInputFlags)((u32)key.flags | (wheelDelta << 16));
|
||||
NativeKey(key);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
if (event.wheel.y > 0) {
|
||||
if (event.wheel.integer_y > 0) {
|
||||
key.keyCode = NKCODE_EXT_MOUSEWHEEL_UP;
|
||||
NativeKey(key);
|
||||
} else if (event.wheel.y < 0) {
|
||||
} else if (event.wheel.integer_y < 0) {
|
||||
key.keyCode = NKCODE_EXT_MOUSEWHEEL_DOWN;
|
||||
NativeKey(key);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SDL_MOUSEMOTION:
|
||||
case SDL_EVENT_MOUSE_MOTION:
|
||||
{
|
||||
TouchInput input{};
|
||||
input.x = mx;
|
||||
@@ -1253,7 +1266,7 @@ static void ProcessSDLEvent(SDL_Window *window, const SDL_Event &event, InputSta
|
||||
UpdateCursor();
|
||||
break;
|
||||
}
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
case SDL_EVENT_MOUSE_BUTTON_UP:
|
||||
switch (event.button.button) {
|
||||
case SDL_BUTTON_LEFT:
|
||||
{
|
||||
@@ -1304,11 +1317,10 @@ static void ProcessSDLEvent(SDL_Window *window, const SDL_Event &event, InputSta
|
||||
}
|
||||
break;
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 4)
|
||||
case SDL_AUDIODEVICEADDED:
|
||||
case SDL_EVENT_AUDIO_DEVICE_ADDED:
|
||||
// Automatically switch to the new device.
|
||||
if (event.adevice.iscapture == 0) {
|
||||
const char *name = SDL_GetAudioDeviceName(event.adevice.which, 0);
|
||||
if (!event.adevice.recording) {
|
||||
const char *name = SDL_GetAudioDeviceName(event.adevice.which);
|
||||
if (!name) {
|
||||
INFO_LOG(Log::Audio, "Got bogus new audio device notification");
|
||||
break;
|
||||
@@ -1328,14 +1340,13 @@ static void ProcessSDLEvent(SDL_Window *window, const SDL_Event &event, InputSta
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SDL_AUDIODEVICEREMOVED:
|
||||
if (event.adevice.iscapture == 0 && event.adevice.which == audioDev) {
|
||||
case SDL_EVENT_AUDIO_DEVICE_REMOVED:
|
||||
if (!event.adevice.recording && event.adevice.which == audioDev) {
|
||||
StopSDLAudioDevice();
|
||||
INFO_LOG(Log::Audio, "Audio device removed, reselecting");
|
||||
InitSDLAudioDevice();
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
if (joystick) {
|
||||
@@ -1345,13 +1356,13 @@ static void ProcessSDLEvent(SDL_Window *window, const SDL_Event &event, InputSta
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateTextFocus() {
|
||||
void UpdateTextFocus(SDL_Window *window) {
|
||||
if (g_textFocusChanged) {
|
||||
DEBUG_LOG(Log::System, "Updating text focus: %d", g_textFocus);
|
||||
if (g_textFocus) {
|
||||
SDL_StartTextInput();
|
||||
SDL_StartTextInput(window);
|
||||
} else {
|
||||
SDL_StopTextInput();
|
||||
SDL_StopTextInput(window);
|
||||
}
|
||||
g_textFocusChanged = false;
|
||||
}
|
||||
@@ -1362,9 +1373,9 @@ void UpdateSDLCursor() {
|
||||
if (lastUIState != GetUIState()) {
|
||||
lastUIState = GetUIState();
|
||||
if (lastUIState == UISTATE_INGAME && g_Config.bFullScreen && !g_Config.bShowTouchControls)
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
SDL_HideCursor();
|
||||
if (lastUIState != UISTATE_INGAME || !g_Config.bFullScreen)
|
||||
SDL_ShowCursor(SDL_ENABLE);
|
||||
SDL_ShowCursor();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -1469,8 +1480,8 @@ int main(int argc, char *argv[]) {
|
||||
fprintf(stderr, "DEBUG: Vulkan is not available, not using Vulkan.\n");
|
||||
}
|
||||
|
||||
SDL_version compiled;
|
||||
SDL_version linked;
|
||||
const int compiled = SDL_VERSION;
|
||||
const int linked = SDL_GetVersion();
|
||||
int set_xres = -1;
|
||||
int set_yres = -1;
|
||||
bool portrait = false;
|
||||
@@ -1493,7 +1504,7 @@ int main(int argc, char *argv[]) {
|
||||
Uint32 mode = 0;
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (!strcmp(argv[i], "--fullscreen")) {
|
||||
mode |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||
mode |= SDL_WINDOW_FULLSCREEN;
|
||||
g_Config.DoNotSaveSetting(&g_Config.bFullScreen);
|
||||
} else if (set_xres == -2)
|
||||
set_xres = parseInt(argv[i]);
|
||||
@@ -1547,35 +1558,40 @@ int main(int argc, char *argv[]) {
|
||||
NativeGetAppInfo(&app_name, &app_name_nice, &landscape, &version);
|
||||
|
||||
bool joystick_enabled = true;
|
||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER | SDL_INIT_AUDIO) < 0) {
|
||||
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD | SDL_INIT_AUDIO)) {
|
||||
fprintf(stderr, "Failed to initialize SDL with joystick support. Retrying without.\n");
|
||||
joystick_enabled = false;
|
||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) {
|
||||
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO)) {
|
||||
fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError());
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_VERSION(&compiled);
|
||||
SDL_GetVersion(&linked);
|
||||
fprintf(stderr, "Info: We compiled against SDL version %d.%d.%d", compiled.major, compiled.minor, compiled.patch);
|
||||
if (compiled.minor != linked.minor || compiled.patch != linked.patch) {
|
||||
fprintf(stderr, ", but we are linking against SDL version %d.%d.%d., be aware that this can lead to unexpected behaviors\n", linked.major, linked.minor, linked.patch);
|
||||
fprintf(stderr, "Info: We compiled against SDL version %d.%d.%d", SDL_VERSIONNUM_MAJOR(compiled), SDL_VERSIONNUM_MINOR(compiled), SDL_VERSIONNUM_MICRO(compiled));
|
||||
if (compiled != linked) {
|
||||
fprintf(stderr, ", but we are linking against SDL version %d.%d.%d., be aware that this can lead to unexpected behaviors\n", SDL_VERSIONNUM_MAJOR(linked), SDL_VERSIONNUM_MINOR(linked), SDL_VERSIONNUM_MICRO(linked));
|
||||
} else {
|
||||
fprintf(stderr, " and we are linking against SDL version %d.%d.%d. :)\n", linked.major, linked.minor, linked.patch);
|
||||
fprintf(stderr, " and we are linking against SDL version %d.%d.%d. :)\n", SDL_VERSIONNUM_MAJOR(linked), SDL_VERSIONNUM_MINOR(linked), SDL_VERSIONNUM_MICRO(linked));
|
||||
}
|
||||
|
||||
// Get the video info before doing anything else, so we don't get skewed resolution results.
|
||||
// TODO: support multiple displays correctly
|
||||
SDL_DisplayMode displayMode;
|
||||
int should_be_zero = SDL_GetCurrentDisplayMode(0, &displayMode);
|
||||
if (should_be_zero != 0) {
|
||||
fprintf(stderr, "Could not get display mode: %s\n", SDL_GetError());
|
||||
int displayCount = 0;
|
||||
SDL_DisplayID *displayIDs = SDL_GetDisplays(&displayCount);
|
||||
if (!displayIDs || displayCount == 0) {
|
||||
fprintf(stderr, "Could not enumerate displays: %s\n", SDL_GetError());
|
||||
return 1;
|
||||
}
|
||||
g_DesktopWidth = displayMode.w;
|
||||
g_DesktopHeight = displayMode.h;
|
||||
g_RefreshRate = displayMode.refresh_rate;
|
||||
const SDL_DisplayMode *displayMode = SDL_GetCurrentDisplayMode(displayIDs[0]);
|
||||
if (!displayMode) {
|
||||
fprintf(stderr, "Could not get display mode: %s\n", SDL_GetError());
|
||||
SDL_free(displayIDs);
|
||||
return 1;
|
||||
}
|
||||
g_DesktopWidth = displayMode->w;
|
||||
g_DesktopHeight = displayMode->h;
|
||||
g_RefreshRate = displayMode->refresh_rate;
|
||||
SDL_free(displayIDs);
|
||||
|
||||
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
|
||||
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
|
||||
@@ -1586,19 +1602,19 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
// Force fullscreen if the resolution is too low to run windowed.
|
||||
if (g_DesktopWidth < 480 * 2 && g_DesktopHeight < 272 * 2) {
|
||||
mode |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||
mode |= SDL_WINDOW_FULLSCREEN;
|
||||
}
|
||||
|
||||
// If we're on mobile, don't try for windowed either.
|
||||
#if defined(MOBILE_DEVICE) && !PPSSPP_PLATFORM(SWITCH)
|
||||
mode |= SDL_WINDOW_FULLSCREEN;
|
||||
#elif defined(USING_FBDEV) || PPSSPP_PLATFORM(SWITCH)
|
||||
mode |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||
mode |= SDL_WINDOW_FULLSCREEN;
|
||||
#else
|
||||
mode |= SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI;
|
||||
mode |= SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY;
|
||||
#endif
|
||||
|
||||
if (mode & SDL_WINDOW_FULLSCREEN_DESKTOP) {
|
||||
if (mode & SDL_WINDOW_FULLSCREEN) {
|
||||
g_display.pixel_xres = g_DesktopWidth;
|
||||
g_display.pixel_yres = g_DesktopHeight;
|
||||
g_Config.bFullScreen = true;
|
||||
@@ -1661,7 +1677,7 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
// Use the setting from the config when initing the window.
|
||||
if (g_Config.bFullScreen) {
|
||||
mode |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||
mode |= SDL_WINDOW_FULLSCREEN;
|
||||
g_display.pixel_xres = g_DesktopWidth;
|
||||
g_display.pixel_yres = g_DesktopHeight;
|
||||
}
|
||||
@@ -1755,11 +1771,18 @@ int main(int argc, char *argv[]) {
|
||||
int width = 0, height = 0;
|
||||
unsigned char *imageData;
|
||||
if (pngLoad(iconPath, &width, &height, &imageData) == 1) {
|
||||
SDL_Surface *surface = SDL_CreateRGBSurface(0, width, height, 32,
|
||||
0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
|
||||
memcpy(surface->pixels, imageData, width*height*4);
|
||||
SDL_SetWindowIcon(window, surface);
|
||||
SDL_FreeSurface(surface);
|
||||
SDL_Surface *surface = SDL_CreateSurface(width, height, SDL_PIXELFORMAT_RGBA32);
|
||||
if (surface) {
|
||||
if (surface->pitch == width * 4) {
|
||||
memcpy(surface->pixels, imageData, width * height * 4);
|
||||
} else {
|
||||
for (int y = 0; y < height; ++y) {
|
||||
memcpy((uint8_t *)surface->pixels + y * surface->pitch, imageData + y * width * 4, width * 4);
|
||||
}
|
||||
}
|
||||
SDL_SetWindowIcon(window, surface);
|
||||
SDL_DestroySurface(surface);
|
||||
}
|
||||
free(imageData);
|
||||
imageData = NULL;
|
||||
}
|
||||
@@ -1774,13 +1797,13 @@ int main(int argc, char *argv[]) {
|
||||
g_Config.sFailedGPUBackends.clear();
|
||||
|
||||
#ifdef MOBILE_DEVICE
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
SDL_HideCursor();
|
||||
#endif
|
||||
|
||||
// Avoid the IME popup when holding keys. This doesn't affect all versions of SDL.
|
||||
// Note: We re-enable it in text input fields! This is necessary otherwise we don't receive
|
||||
// KeyInputFlags::CHAR events.
|
||||
SDL_StopTextInput();
|
||||
SDL_StopTextInput(window);
|
||||
|
||||
InitSDLAudioDevice();
|
||||
g_audioStartTime = time_now_d();
|
||||
@@ -1832,10 +1855,10 @@ int main(int argc, char *argv[]) {
|
||||
if (g_QuitRequested || g_RestartRequested)
|
||||
break;
|
||||
|
||||
UpdateTextFocus();
|
||||
UpdateTextFocus(window);
|
||||
UpdateSDLCursor();
|
||||
|
||||
inputTracker.MouseCaptureControl();
|
||||
inputTracker.MouseCaptureControl(window);
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(g_mutexWindow);
|
||||
@@ -1859,10 +1882,10 @@ int main(int argc, char *argv[]) {
|
||||
if (g_QuitRequested || g_RestartRequested)
|
||||
break;
|
||||
|
||||
UpdateTextFocus();
|
||||
UpdateTextFocus(window);
|
||||
UpdateSDLCursor();
|
||||
|
||||
inputTracker.MouseCaptureControl();
|
||||
inputTracker.MouseCaptureControl(window);
|
||||
|
||||
bool renderThreadPaused = Native_IsWindowHidden() && g_Config.bPauseWhenMinimized && emuThreadState != (int)EmuThreadState::DISABLED;
|
||||
if (emuThreadState != (int)EmuThreadState::DISABLED && !renderThreadPaused) {
|
||||
@@ -1928,10 +1951,7 @@ int main(int argc, char *argv[]) {
|
||||
graphicsContext->Shutdown();
|
||||
delete graphicsContext;
|
||||
|
||||
if (audioDev > 0) {
|
||||
SDL_PauseAudioDevice(audioDev, 1);
|
||||
SDL_CloseAudioDevice(audioDev);
|
||||
}
|
||||
StopSDLAudioDevice();
|
||||
SDL_Quit();
|
||||
#if PPSSPP_PLATFORM(RPI)
|
||||
bcm_host_deinit();
|
||||
|
||||
@@ -6,13 +6,7 @@
|
||||
*/
|
||||
|
||||
#include "ppsspp_config.h"
|
||||
#if PPSSPP_PLATFORM(MAC)
|
||||
#include "SDL2/SDL.h"
|
||||
#elif defined(USE_SDL3)
|
||||
#include <SDL3/SDL.h>
|
||||
#else
|
||||
#include "SDL.h"
|
||||
#endif
|
||||
#include "SDLMain.h"
|
||||
#include "Common/Profiler/Profiler.h"
|
||||
#include <signal.h>
|
||||
|
||||
@@ -11,15 +11,7 @@
|
||||
#include "GPU/Vulkan/VulkanUtil.h"
|
||||
|
||||
#include "Core/System.h"
|
||||
#if PPSSPP_PLATFORM(MAC)
|
||||
#include "SDL2/SDL_vulkan.h"
|
||||
#else
|
||||
#if defined(USE_SDL3)
|
||||
#include <SDL3/SDL_vulkan.h>
|
||||
#else
|
||||
#include "SDL_vulkan.h"
|
||||
#endif
|
||||
#endif
|
||||
#include "SDLVulkanGraphicsContext.h"
|
||||
|
||||
#if defined(VK_USE_PLATFORM_METAL_EXT)
|
||||
@@ -33,11 +25,14 @@ static const bool g_Validate = false;
|
||||
#endif
|
||||
|
||||
bool SDLVulkanGraphicsContext::Init(SDL_Window *&window, int x, int y, int w, int h, int mode, std::string *error_message) {
|
||||
window = SDL_CreateWindow("Initializing Vulkan...", x, y, w, h, mode);
|
||||
window = SDL_CreateWindow("Initializing Vulkan...", w, h, (SDL_WindowFlags)mode);
|
||||
if (!window) {
|
||||
fprintf(stderr, "Error creating SDL window: %s\n", SDL_GetError());
|
||||
exit(1);
|
||||
}
|
||||
if (x != SDL_WINDOWPOS_UNDEFINED && y != SDL_WINDOWPOS_UNDEFINED) {
|
||||
SDL_SetWindowPosition(window, x, y);
|
||||
}
|
||||
|
||||
init_glslang();
|
||||
|
||||
@@ -81,97 +76,56 @@ bool SDLVulkanGraphicsContext::Init(SDL_Window *&window, int x, int y, int w, in
|
||||
|
||||
vulkan_->SetCbGetDrawSize([window]() {
|
||||
int w=1,h=1;
|
||||
SDL_Vulkan_GetDrawableSize(window, &w, &h);
|
||||
SDL_GetWindowSizeInPixels(window, &w, &h);
|
||||
return VkExtent2D {(uint32_t)w, (uint32_t)h};
|
||||
});
|
||||
|
||||
#if defined(USE_SDL3)
|
||||
SDL_PropertiesID windowProps = SDL_GetWindowProperties(window);
|
||||
bool surfaceInitialized = false;
|
||||
void *x11Display = SDL_GetPointerProperty(windowProps, SDL_PROP_WINDOW_X11_DISPLAY_POINTER, nullptr);
|
||||
if (x11Display != nullptr) {
|
||||
intptr_t x11Window = (intptr_t)SDL_GetNumberProperty(windowProps, SDL_PROP_WINDOW_X11_WINDOW_NUMBER, 0);
|
||||
#if defined(VK_USE_PLATFORM_XLIB_KHR)
|
||||
vulkan_->InitSurface(WINDOWSYSTEM_XLIB, x11Display, (void *)x11Window);
|
||||
surfaceInitialized = true;
|
||||
#elif defined(VK_USE_PLATFORM_XCB_KHR)
|
||||
vulkan_->InitSurface(WINDOWSYSTEM_XCB, (void *)XGetXCBConnection((Display *)x11Display), (void *)x11Window);
|
||||
surfaceInitialized = true;
|
||||
#endif
|
||||
} else {
|
||||
}
|
||||
#if defined(VK_USE_PLATFORM_WAYLAND_KHR)
|
||||
if (!surfaceInitialized) {
|
||||
void *waylandDisplay = SDL_GetPointerProperty(windowProps, SDL_PROP_WINDOW_WAYLAND_DISPLAY_POINTER, nullptr);
|
||||
void *waylandSurface = SDL_GetPointerProperty(windowProps, SDL_PROP_WINDOW_WAYLAND_SURFACE_POINTER, nullptr);
|
||||
if (waylandDisplay != nullptr && waylandSurface != nullptr) {
|
||||
vulkan_->InitSurface(WINDOWSYSTEM_WAYLAND, waylandDisplay, waylandSurface);
|
||||
} else
|
||||
surfaceInitialized = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(VK_USE_PLATFORM_METAL_EXT)
|
||||
#if PPSSPP_PLATFORM(MAC)
|
||||
{
|
||||
if (!surfaceInitialized) {
|
||||
void *cocoaWindow = SDL_GetPointerProperty(windowProps, SDL_PROP_WINDOW_COCOA_WINDOW_POINTER, nullptr);
|
||||
if (cocoaWindow != nullptr) {
|
||||
vulkan_->InitSurface(WINDOWSYSTEM_METAL_EXT, makeWindowMetalCompatible(cocoaWindow), nullptr);
|
||||
} else
|
||||
surfaceInitialized = true;
|
||||
}
|
||||
}
|
||||
#else
|
||||
{
|
||||
if (!surfaceInitialized) {
|
||||
void *uikitWindow = SDL_GetPointerProperty(windowProps, SDL_PROP_WINDOW_UIKIT_WINDOW_POINTER, nullptr);
|
||||
if (uikitWindow != nullptr) {
|
||||
vulkan_->InitSurface(WINDOWSYSTEM_METAL_EXT, makeWindowMetalCompatible(uikitWindow), nullptr);
|
||||
} else
|
||||
surfaceInitialized = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
{
|
||||
fprintf(stderr, "Unable to determine Vulkan window system from SDL3 window properties\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
SDL_SysWMinfo sys_info{};
|
||||
SDL_VERSION(&sys_info.version); //Set SDL version
|
||||
if (!SDL_GetWindowWMInfo(window, &sys_info)) {
|
||||
fprintf(stderr, "Error getting SDL window wm info: %s\n", SDL_GetError());
|
||||
if (!surfaceInitialized) {
|
||||
fprintf(stderr, "Unable to determine Vulkan window system from SDL3 window properties\n");
|
||||
exit(1);
|
||||
}
|
||||
switch (sys_info.subsystem) {
|
||||
case SDL_SYSWM_X11:
|
||||
#if defined(VK_USE_PLATFORM_XLIB_KHR)
|
||||
vulkan_->InitSurface(WINDOWSYSTEM_XLIB, (void*)sys_info.info.x11.display,
|
||||
(void *)(intptr_t)sys_info.info.x11.window);
|
||||
#elif defined(VK_USE_PLATFORM_XCB_KHR)
|
||||
vulkan_->InitSurface(WINDOWSYSTEM_XCB, (void*)XGetXCBConnection(sys_info.info.x11.display),
|
||||
(void *)(intptr_t)sys_info.info.x11.window);
|
||||
#endif
|
||||
break;
|
||||
#if defined(VK_USE_PLATFORM_WAYLAND_KHR)
|
||||
case SDL_SYSWM_WAYLAND:
|
||||
vulkan_->InitSurface(WINDOWSYSTEM_WAYLAND, (void*)sys_info.info.wl.display, (void *)sys_info.info.wl.surface);
|
||||
break;
|
||||
#endif
|
||||
#if defined(VK_USE_PLATFORM_METAL_EXT)
|
||||
#if PPSSPP_PLATFORM(MAC)
|
||||
case SDL_SYSWM_COCOA:
|
||||
vulkan_->InitSurface(WINDOWSYSTEM_METAL_EXT, makeWindowMetalCompatible(sys_info.info.cocoa.window), nullptr);
|
||||
break;
|
||||
#else
|
||||
case SDL_SYSWM_UIKIT:
|
||||
vulkan_->InitSurface(WINDOWSYSTEM_METAL_EXT, makeWindowMetalCompatible(sys_info.info.uikit.window), nullptr);
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
#if defined(VK_USE_PLATFORM_DISPLAY_KHR)
|
||||
case SDL_SYSWM_KMSDRM:
|
||||
/*
|
||||
There is no problem passing null for the next two arguments, and reinit will be called later
|
||||
huangzihan china
|
||||
*/
|
||||
vulkan_->InitSurface(WINDOWSYSTEM_DISPLAY, nullptr, nullptr);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
fprintf(stderr, "Vulkan subsystem %d not supported\n", sys_info.subsystem);
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool useMultiThreading = g_Config.bRenderMultiThreading;
|
||||
if (g_Config.iInflightFrames == 1) {
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
#include "ppsspp_config.h"
|
||||
#if PPSSPP_PLATFORM(MAC)
|
||||
#include "SDL2/SDL.h"
|
||||
#include "SDL2/SDL_syswm.h"
|
||||
#elif defined(USE_SDL3)
|
||||
#include <SDL3/SDL.h>
|
||||
#else
|
||||
#include "SDL.h"
|
||||
#include "SDL_syswm.h"
|
||||
#endif
|
||||
|
||||
#include "Common/GraphicsContext.h"
|
||||
#include "Common/GPU/Vulkan/VulkanContext.h"
|
||||
|
||||
@@ -20,13 +20,7 @@
|
||||
#include <cstdio>
|
||||
|
||||
#include "ppsspp_config.h"
|
||||
#if PPSSPP_PLATFORM(MAC)
|
||||
#include "SDL2/SDL.h"
|
||||
#elif defined(USE_SDL3)
|
||||
#include <SDL3/SDL.h>
|
||||
#else
|
||||
#include "SDL.h"
|
||||
#endif
|
||||
|
||||
#include "headless/SDLHeadlessHost.h"
|
||||
#include "Common/GPU/OpenGL/GLCommon.h"
|
||||
|
||||
Reference in new issue
Block a user