From 4d6a8e34bf009091a15f18f02ed64058313a3b91 Mon Sep 17 00:00:00 2001 From: Starbuck5 <46412508+Starbuck5@users.noreply.github.com> Date: Sat, 12 Oct 2024 17:04:00 -0700 Subject: [PATCH 1/3] Rework SDL_INIT_TIMER for SDL3 No longer exists in SDL3, so simple compat is to mock it out to a macro that is zero in SDL3. --- src_c/_pygame.h | 4 ++++ src_c/base.c | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src_c/_pygame.h b/src_c/_pygame.h index 0cbfed872f..d5bdf7fe40 100644 --- a/src_c/_pygame.h +++ b/src_c/_pygame.h @@ -115,6 +115,8 @@ PG_UnlockMutex(SDL_mutex *mutex) #define PG_FIND_VNUM_MINOR(ver) SDL_VERSIONNUM_MINOR(ver) #define PG_FIND_VNUM_MICRO(ver) SDL_VERSIONNUM_MICRO(ver) +#define PG_INIT_TIMER 0 + #else /* ~SDL_VERSION_ATLEAST(3, 0, 0)*/ #define PG_ShowCursor() SDL_ShowCursor(SDL_ENABLE) #define PG_HideCursor() SDL_ShowCursor(SDL_DISABLE) @@ -180,6 +182,8 @@ PG_UnlockMutex(SDL_mutex *mutex) #define PG_FIND_VNUM_MINOR(ver) ver.minor #define PG_FIND_VNUM_MICRO(ver) ver.patch +#define PG_INIT_TIMER SDL_INIT_TIMER + #if SDL_VERSION_ATLEAST(2, 0, 14) #define PG_SurfaceHasRLE SDL_HasSurfaceRLE #else diff --git a/src_c/base.c b/src_c/base.c index 573bca3aa2..d4f33c813c 100644 --- a/src_c/base.c +++ b/src_c/base.c @@ -341,10 +341,10 @@ pg_init(PyObject *self, PyObject *_null) /*nice to initialize timer, so startup time will reflec pg_init() time*/ #if defined(WITH_THREAD) && !defined(MS_WIN32) && defined(SDL_INIT_EVENTTHREAD) - pg_sdl_was_init = SDL_Init(SDL_INIT_EVENTTHREAD | SDL_INIT_TIMER | + pg_sdl_was_init = SDL_Init(SDL_INIT_EVENTTHREAD | PG_INIT_TIMER | PG_INIT_NOPARACHUTE) == 0; #else - pg_sdl_was_init = SDL_Init(SDL_INIT_TIMER | PG_INIT_NOPARACHUTE) == 0; + pg_sdl_was_init = SDL_Init(PG_INIT_TIMER | PG_INIT_NOPARACHUTE) == 0; #endif pg_env_blend_alpha_SDL2 = SDL_getenv("PYGAME_BLEND_ALPHA_SDL2"); From 582792472e9a224e6d4c089937399443053cdcf1 Mon Sep 17 00:00:00 2001 From: Starbuck5 <46412508+Starbuck5@users.noreply.github.com> Date: Sat, 12 Oct 2024 17:07:03 -0700 Subject: [PATCH 2/3] Rework pg_EnvShouldBlendAlphaSDL2 for SDL3 SDL_getenv now returns a const char* instead of a char*, so rather than worry about propagating that through or casting it away, lets just have pg_EnvShouldBlendAlphaSDL2 return an int, and have the callers evaluate that instead of evaluating whether a char* is NULL or not. This requires no changes to the callers. --- src_c/base.c | 8 ++++---- src_c/include/_pygame.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src_c/base.c b/src_c/base.c index d4f33c813c..04379ba0f2 100644 --- a/src_c/base.c +++ b/src_c/base.c @@ -81,7 +81,7 @@ static int pg_is_init = 0; static int pg_sdl_was_init = 0; SDL_Window *pg_default_window = NULL; pgSurfaceObject *pg_default_screen = NULL; -static char *pg_env_blend_alpha_SDL2 = NULL; +static int pg_env_blend_alpha_SDL2 = 0; static void pg_install_parachute(void); @@ -170,7 +170,7 @@ static pgSurfaceObject * pg_GetDefaultWindowSurface(void); static void pg_SetDefaultWindowSurface(pgSurfaceObject *); -static char * +static int pg_EnvShouldBlendAlphaSDL2(void); /* compare compiled to linked, raise python error on incompatibility */ @@ -347,7 +347,7 @@ pg_init(PyObject *self, PyObject *_null) pg_sdl_was_init = SDL_Init(PG_INIT_TIMER | PG_INIT_NOPARACHUTE) == 0; #endif - pg_env_blend_alpha_SDL2 = SDL_getenv("PYGAME_BLEND_ALPHA_SDL2"); + pg_env_blend_alpha_SDL2 = SDL_getenv("PYGAME_BLEND_ALPHA_SDL2") != NULL; /* initialize all pygame modules */ for (i = 0; modnames[i]; i++) { @@ -2096,7 +2096,7 @@ pg_SetDefaultConvertFormat(Uint32 format) return pg_default_convert_format; // returns for NULL error checking } -static char * +static int pg_EnvShouldBlendAlphaSDL2(void) { return pg_env_blend_alpha_SDL2; diff --git a/src_c/include/_pygame.h b/src_c/include/_pygame.h index bcfb0fdc8c..8158fe68df 100644 --- a/src_c/include/_pygame.h +++ b/src_c/include/_pygame.h @@ -181,7 +181,7 @@ typedef struct pg_bufferinfo_s { (*(void (*)(pgSurfaceObject *))PYGAMEAPI_GET_SLOT(base, 22)) #define pg_EnvShouldBlendAlphaSDL2 \ - (*(char *(*)(void))PYGAMEAPI_GET_SLOT(base, 23)) + (*(int (*)(void))PYGAMEAPI_GET_SLOT(base, 23)) #define pg_GetDefaultConvertFormat \ (*(SDL_PixelFormat * (*)(void)) PYGAMEAPI_GET_SLOT(base, 27)) From cc260b3908be71e765e04b961eed230214a2b282 Mon Sep 17 00:00:00 2001 From: Starbuck5 <46412508+Starbuck5@users.noreply.github.com> Date: Thu, 31 Oct 2024 00:51:51 -0700 Subject: [PATCH 3/3] Adjust pg_(Get/Set)DefaultConvertFormat for SDL3 This reworks the functions to work on pixel format enums instead of structs, because in SDL3 the enums are much easier to get than the structs. This required involved changes to surface.c, but I think the previous mask logic is much clearer now that it is expressed using format enums. --- src_c/_pygame.h | 6 +++- src_c/base.c | 18 ++++++------ src_c/include/_pygame.h | 4 +-- src_c/meson.build | 3 -- src_c/surface.c | 64 +++++++++++++++++------------------------ src_c/window.c | 8 ++---- 6 files changed, 44 insertions(+), 59 deletions(-) diff --git a/src_c/_pygame.h b/src_c/_pygame.h index d5bdf7fe40..46fe2d966d 100644 --- a/src_c/_pygame.h +++ b/src_c/_pygame.h @@ -75,7 +75,9 @@ #define PG_CreateSurface SDL_CreateSurface #define PG_CreateSurfaceFrom SDL_CreateSurfaceFrom #define PG_ConvertSurface SDL_ConvertSurface -#define PG_ConvertSurfaceFormat SDL_ConvertSurfaceFormat +#define PG_ConvertSurfaceFormat SDL_ConvertSurface + +#define PG_PixelFormatEnum SDL_PixelFormat #define PG_SurfaceHasRLE SDL_SurfaceHasRLE @@ -146,6 +148,8 @@ PG_UnlockMutex(SDL_mutex *mutex) #define PG_ConvertSurfaceFormat(src, pixel_format) \ SDL_ConvertSurfaceFormat(src, pixel_format, 0) +#define PG_PixelFormatEnum SDL_PixelFormatEnum + #define PG_SoftStretchNearest(src, srcrect, dst, dstrect) \ SDL_SoftStretch(src, srcrect, dst, dstrect) diff --git a/src_c/base.c b/src_c/base.c index 04379ba0f2..f42b045783 100644 --- a/src_c/base.c +++ b/src_c/base.c @@ -2075,25 +2075,25 @@ pg_SetDefaultWindowSurface(pgSurfaceObject *screen) pg_default_screen = screen; } -SDL_PixelFormat *pg_default_convert_format = NULL; +PG_PixelFormatEnum pg_default_convert_format = 0; -static SDL_PixelFormat * +static PG_PixelFormatEnum pg_GetDefaultConvertFormat(void) { if (pg_default_screen) { +#if SDL_VERSION_ATLEAST(3, 0, 0) return pg_default_screen->surf->format; +#else + return pg_default_screen->surf->format->format; +#endif } return pg_default_convert_format; } -static SDL_PixelFormat * -pg_SetDefaultConvertFormat(Uint32 format) +static void +pg_SetDefaultConvertFormat(PG_PixelFormatEnum format) { - if (pg_default_convert_format != NULL) { - SDL_FreeFormat(pg_default_convert_format); - } - pg_default_convert_format = SDL_AllocFormat(format); - return pg_default_convert_format; // returns for NULL error checking + pg_default_convert_format = format; } static int diff --git a/src_c/include/_pygame.h b/src_c/include/_pygame.h index 8158fe68df..b3548a66ee 100644 --- a/src_c/include/_pygame.h +++ b/src_c/include/_pygame.h @@ -184,10 +184,10 @@ typedef struct pg_bufferinfo_s { (*(int (*)(void))PYGAMEAPI_GET_SLOT(base, 23)) #define pg_GetDefaultConvertFormat \ - (*(SDL_PixelFormat * (*)(void)) PYGAMEAPI_GET_SLOT(base, 27)) + (*(PG_PixelFormatEnum(*)(void))PYGAMEAPI_GET_SLOT(base, 27)) #define pg_SetDefaultConvertFormat \ - (*(SDL_PixelFormat * (*)(Uint32)) PYGAMEAPI_GET_SLOT(base, 28)) + (*(void (*)(Uint32))PYGAMEAPI_GET_SLOT(base, 28)) #define import_pygame_base() IMPORT_PYGAME_MODULE(base) #endif /* ~PYGAMEAPI_BASE_INTERNAL */ diff --git a/src_c/meson.build b/src_c/meson.build index ca10cca737..fb43a584eb 100644 --- a/src_c/meson.build +++ b/src_c/meson.build @@ -1,7 +1,5 @@ # first the "required" modules -# TODO: support SDL3 -if sdl_api != 3 base = py.extension_module( 'base', 'base.c', @@ -10,7 +8,6 @@ base = py.extension_module( install: true, subdir: pg, ) -endif color = py.extension_module( 'color', diff --git a/src_c/surface.c b/src_c/surface.c index b9e3008ae3..d4a8eae2e9 100644 --- a/src_c/surface.c +++ b/src_c/surface.c @@ -1582,27 +1582,21 @@ surf_convert(pgSurfaceObject *self, PyObject *args) static SDL_Surface * pg_DisplayFormat(SDL_Surface *surface) { - SDL_PixelFormat *default_format = pg_GetDefaultConvertFormat(); + PG_PixelFormatEnum default_format = pg_GetDefaultConvertFormat(); if (!default_format) { SDL_SetError( "No convert format has been set, try display.set_mode()" " or Window.get_surface()."); return NULL; } - return PG_ConvertSurface(surface, default_format); + return PG_ConvertSurfaceFormat(surface, default_format); } static SDL_Surface * pg_DisplayFormatAlpha(SDL_Surface *surface) { - SDL_PixelFormat *dformat; - Uint32 pfe; - Uint32 amask = 0xff000000; - Uint32 rmask = 0x00ff0000; - Uint32 gmask = 0x0000ff00; - Uint32 bmask = 0x000000ff; - - dformat = pg_GetDefaultConvertFormat(); + PG_PixelFormatEnum pfe = SDL_PIXELFORMAT_ARGB8888; + PG_PixelFormatEnum dformat = pg_GetDefaultConvertFormat(); if (!dformat) { SDL_SetError( "No convert format has been set, try display.set_mode()" @@ -1610,38 +1604,32 @@ pg_DisplayFormatAlpha(SDL_Surface *surface) return NULL; } - switch (PG_FORMAT_BytesPerPixel(dformat)) { - case 2: - /* same behavior as SDL1 */ - if ((dformat->Rmask == 0x1f) && - (dformat->Bmask == 0xf800 || dformat->Bmask == 0x7c00)) { - rmask = 0xff; - bmask = 0xff0000; - } + switch (dformat) { +#if SDL_VERSION_ATLEAST(3, 0, 0) + case SDL_PIXELFORMAT_XBGR1555: +#else + case SDL_PIXELFORMAT_BGR555: +#endif + case SDL_PIXELFORMAT_ABGR1555: + case SDL_PIXELFORMAT_BGR565: + case PG_PIXELFORMAT_XBGR8888: + case SDL_PIXELFORMAT_ABGR8888: + pfe = SDL_PIXELFORMAT_ABGR8888; break; - case 3: - case 4: - /* keep the format if the high bits are free */ - if ((dformat->Rmask == 0xff) && (dformat->Bmask == 0xff0000)) { - rmask = 0xff; - bmask = 0xff0000; - } - else if (dformat->Rmask == 0xff00 && - (dformat->Bmask == 0xff000000)) { - amask = 0x000000ff; - rmask = 0x0000ff00; - gmask = 0x00ff0000; - bmask = 0xff000000; - } + + case SDL_PIXELFORMAT_BGRX8888: + case SDL_PIXELFORMAT_BGRA8888: +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + case SDL_PIXELFORMAT_BGR24: +#else + case SDL_PIXELFORMAT_RGB24: +#endif + pfe = SDL_PIXELFORMAT_BGRA8888; break; - default: /* ARGB8888 */ + + default: break; } - pfe = SDL_MasksToPixelFormatEnum(32, rmask, gmask, bmask, amask); - if (pfe == SDL_PIXELFORMAT_UNKNOWN) { - SDL_SetError("unknown pixel format"); - return NULL; - } return PG_ConvertSurfaceFormat(surface, pfe); } diff --git a/src_c/window.c b/src_c/window.c index f2217cd20c..63b7270d06 100644 --- a/src_c/window.c +++ b/src_c/window.c @@ -157,12 +157,8 @@ window_get_surface(pgWindowObject *self, PyObject *_null) return RAISE(pgExc_SDLError, SDL_GetError()); } - if (pg_GetDefaultConvertFormat() == NULL) { - if (pg_SetDefaultConvertFormat(_surf->format->format) == NULL) { - /* This is very unlikely, I think only would happen if SDL runs - * out of memory when allocating the format. */ - return RAISE(pgExc_SDLError, SDL_GetError()); - } + if (pg_GetDefaultConvertFormat() == 0) { + pg_SetDefaultConvertFormat(_surf->format->format); } if (self->surf == NULL) {