More SDL3 work by AI

This commit is contained in:
Henrik Rydgård committed 2026-06-16 11:39:24 +02:00
1 parent 34c2218558
commit 6c85a1a4b6
11 files changed
+375 -493

No files matched your search

-2
View File
@@ -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
View File
@@ -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)
+11 -50
View File
@@ -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;
}
-8
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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>
+23 -69
View File
@@ -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) {
-8
View File
@@ -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"
-6
View File
@@ -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"