From 6813ed3185ca1f8778802243054a5bd987453d00 Mon Sep 17 00:00:00 2001 From: damusss Date: Sun, 11 May 2025 19:36:19 +0200 Subject: [PATCH] Start compiling _sdl2 with SDL3 --- src_c/_sdl2/controller.c | 57 +++++++++++++++++++++++++----- src_c/_sdl2/meson.build | 13 ++++++- src_c/cython/pygame/_sdl2/sdl2.pxd | 12 ++++++- src_c/meson.build | 3 -- src_py/_sdl2/__init__.py | 10 ++++-- 5 files changed, 80 insertions(+), 15 deletions(-) diff --git a/src_c/_sdl2/controller.c b/src_c/_sdl2/controller.c index 648af64a09..9db0cfa29d 100644 --- a/src_c/_sdl2/controller.c +++ b/src_c/_sdl2/controller.c @@ -26,11 +26,19 @@ static PyObject * controller_module_init(PyObject *module, PyObject *_null) { if (!SDL_WasInit(SDL_INIT_GAMECONTROLLER)) { +#if SDL_VERSION_ATLEAST(3, 0, 0) + if (SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) == SDL_FALSE) { +#else if (SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER)) { +#endif return RAISE(pgExc_SDLError, SDL_GetError()); } } +#if SDL_VERSION_ATLEAST(3, 0, 0) + SDL_SetGamepadEventsEnabled(SDL_TRUE); +#else SDL_GameControllerEventState(SDL_ENABLE); +#endif Py_RETURN_NONE; } @@ -87,7 +95,16 @@ controller_module_get_count(PyObject *module, PyObject *_null) { CONTROLLER_INIT_CHECK(); +#if SDL_VERSION_ATLEAST(3, 0, 0) + int count; + SDL_JoystickID *joysticks = SDL_GetJoysticks(&count); + if (!joysticks) { + return RAISE(pgExc_SDLError, SDL_GetError()); + } + SDL_free(joysticks); +#else int count = SDL_NumJoysticks(); +#endif if (count < 0) { return RAISE(pgExc_SDLError, SDL_GetError()); } @@ -290,7 +307,11 @@ controller_set_mapping(pgControllerObject *self, PyObject *args, char guid_str[64]; SDL_Joystick *joy = SDL_GameControllerGetJoystick(self->controller); +#if SDL_VERSION_ATLEAST(3, 0, 0) + SDL_GUIDToString(SDL_JoystickGetGUID(joy), guid_str, 63); +#else SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(joy), guid_str, 63); +#endif PyObject *key, *value; const char *key_str, *value_str; @@ -371,10 +392,17 @@ controller_rumble(pgControllerObject *self, PyObject *args, PyObject *kwargs) low_freq = MAX(MIN(low_freq, 1.0f), 0.0f) * 65535; high_freq = MAX(MIN(high_freq, 1.0f), 0.0f) * 65535; +#if SDL_VERSION_ATLEAST(3, 0, 0) + SDL_bool success = SDL_GameControllerRumble( + self->controller, (Uint16)low_freq, (Uint16)high_freq, duration); + + return PyBool_FromLong(success == SDL_TRUE); +#else int success = SDL_GameControllerRumble(self->controller, (Uint16)low_freq, (Uint16)high_freq, duration); - return PyBool_FromLong(success == 0); + +#endif } static PyObject * @@ -384,7 +412,9 @@ controller_stop_rumble(pgControllerObject *self, PyObject *_null) if (!self->controller) { return RAISE(pgExc_SDLError, "Controller is not initialized"); } - SDL_GameControllerRumble(self->controller, 0, 0, 1); + if (SDL_GameControllerRumble(self->controller, 0, 0, 1) == SDL_FALSE) { + return RAISE(pgExc_SDLError, SDL_GetError()); + } Py_RETURN_NONE; } @@ -437,7 +467,18 @@ controller_new(PyTypeObject *subtype, PyObject *args, PyObject *kwargs) CONTROLLER_INIT_CHECK(); - if (id >= SDL_NumJoysticks() || !SDL_IsGameController(id)) { +#if SDL_VERSION_ATLEAST(3, 0, 0) + int joycount; + SDL_JoystickID *joysticks = SDL_GetJoysticks(&joycount); + if (!joysticks) { + return RAISE(pgExc_SDLError, SDL_GetError()); + } + SDL_free(joysticks); +#else + int joycount = SDL_NumJoysticks(); +#endif + + if (id >= joycount || !SDL_IsGameController(id)) { return RAISE(pgExc_SDLError, "Invalid index"); } @@ -557,11 +598,11 @@ MODINIT_DEFINE(controller) .m_doc = DOC_SDL2_CONTROLLER, .m_size = -1, .m_methods = _controller_module_methods, -/* -#if PY_VERSION_HEX >= 0x030D0000 - .m_slots = mod_controller_slots, -#endif -*/ + /* + #if PY_VERSION_HEX >= 0x030D0000 + .m_slots = mod_controller_slots, + #endif + */ }; import_pygame_base(); diff --git a/src_c/_sdl2/meson.build b/src_c/_sdl2/meson.build index 2ad443e993..9fbf6e6a8b 100644 --- a/src_c/_sdl2/meson.build +++ b/src_c/_sdl2/meson.build @@ -1,5 +1,10 @@ cython_base = '../cython/pygame/_sdl2' +sdl_cargs = [] +if sdl_api == 3 +sdl_cargs += ['-DUSE_SDL3'] +endif +if sdl_api != 3 _sdl2_audio = py.extension_module( 'audio', fs.is_file('audio.c') ? 'audio.c' : cython_base / 'audio.pyx', @@ -8,7 +13,9 @@ _sdl2_audio = py.extension_module( install: true, subdir: pg / '_sdl2', ) +endif +if sdl_api != 3 _sdl2_video = py.extension_module( 'video', fs.is_file('video.c') ? 'video.c' : cython_base / 'video.pyx', @@ -37,6 +44,7 @@ if sdl_mixer_dep.found() subdir: pg / '_sdl2', ) endif +endif _sdl2_sdl2 = py.extension_module( 'sdl2', @@ -45,9 +53,11 @@ _sdl2_sdl2 = py.extension_module( include_directories: '..', install: true, subdir: pg / '_sdl2', + c_args: sdl_cargs, ) -# This is not a cython file +# These are not a cython files +if sdl_api != 3 _sdl2_touch = py.extension_module( 'touch', 'touch.c', @@ -56,6 +66,7 @@ _sdl2_touch = py.extension_module( install: true, subdir: pg / '_sdl2', ) +endif _sdl2_controller = py.extension_module( 'controller', diff --git a/src_c/cython/pygame/_sdl2/sdl2.pxd b/src_c/cython/pygame/_sdl2/sdl2.pxd index a7cca25180..674a14f325 100644 --- a/src_c/cython/pygame/_sdl2/sdl2.pxd +++ b/src_c/cython/pygame/_sdl2/sdl2.pxd @@ -4,7 +4,17 @@ from libc.string cimport memset from libc.stdio cimport * -cdef extern from "SDL.h" nogil: +cdef extern from * nogil: + """ + #ifdef USE_SDL3 + #include + #define SDL_INIT_TIMER 0 + #define SDL_INIT_EVERYTHING 0 + #define SDL_INIT_NOPARACHUTE 0 + #else + #include + #endif + """ # SDL_stdinc.h provides the real ones based on platform. ctypedef char Sint8 ctypedef unsigned char Uint8 diff --git a/src_c/meson.build b/src_c/meson.build index 0c1479a812..377fdf517a 100644 --- a/src_c/meson.build +++ b/src_c/meson.build @@ -327,10 +327,7 @@ gfxdraw = py.extension_module( endif # pygame._sdl2 -# TODO: support SDL3 -if sdl_api != 3 subdir('_sdl2') -endif # pygame._camera pg_camera_sources = ['_camera.c'] diff --git a/src_py/_sdl2/__init__.py b/src_py/_sdl2/__init__.py index 6ad3b1b047..da67676fa3 100644 --- a/src_py/_sdl2/__init__.py +++ b/src_py/_sdl2/__init__.py @@ -1,4 +1,10 @@ +from pygame.version import SDL + +print(SDL) if __import__("sys").platform not in ("wasi", "emscripten"): - from .audio import * # pylint: disable=wildcard-import; lgtm[py/polluting-import] + if SDL < (3, 0, 0): + from .audio import * # pylint: disable=wildcard-import; lgtm[py/polluting-import] from .sdl2 import * # pylint: disable=wildcard-import; lgtm[py/polluting-import] - from .video import * # pylint: disable=wildcard-import; lgtm[py/polluting-import] + + if SDL < (3, 0, 0): + from .video import * # pylint: disable=wildcard-import; lgtm[py/polluting-import]