From 26b768386095de7d0dbca6186b4ff852c7172084 Mon Sep 17 00:00:00 2001 From: Starbuck5 <46412508+Starbuck5@users.noreply.github.com> Date: Sat, 25 Jan 2025 23:16:16 -0800 Subject: [PATCH 1/2] Add more pixelformat compat symbols Co-Authored-By: Ankith --- src_c/_pygame.h | 82 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/src_c/_pygame.h b/src_c/_pygame.h index 86019125f9..77fcd2cb50 100644 --- a/src_c/_pygame.h +++ b/src_c/_pygame.h @@ -108,6 +108,33 @@ PG_UnlockMutex(SDL_mutex *mutex) #define PG_FORMAT_BytesPerPixel(format) format->bytes_per_pixel #define PG_SURF_FORMATENUM(surf) surf->format +#define PG_FORMAT_R_LOSS(format) (8 - format->Rbits) +#define PG_FORMAT_G_LOSS(format) (8 - format->Gbits) +#define PG_FORMAT_B_LOSS(format) (8 - format->Bbits) +#define PG_FORMAT_A_LOSS(format) (8 - format->Abits) + +#define PG_PixelFormat const SDL_PixelFormatDetails + +static inline bool +PG_GetSurfaceDetails(SDL_Surface *surf, PG_PixelFormat **format_p, + SDL_Palette **palette_p) +{ + *palette_p = SDL_GetSurfacePalette(surf); + *format_p = SDL_GetPixelFormatDetails(surf->format); + return *format_p != NULL; +} + +static inline PG_PixelFormat * +PG_GetSurfaceFormat(SDL_Surface *surf) +{ + return SDL_GetPixelFormatDetails(surf->format); +} + +#define PG_GetRGBA SDL_GetRGBA +#define PG_GetRGB SDL_GetRGB +#define PG_MapRGBA SDL_MapRGBA +#define PG_MapRGB SDL_MapRGB + /* Mask to test if surface flags are in a fullscreen window. */ #define PG_WINDOW_FULLSCREEN_INCLUSIVE SDL_WINDOW_FULLSCREEN @@ -176,6 +203,61 @@ PG_UnlockMutex(SDL_mutex *mutex) #define PG_FORMAT_BytesPerPixel(format) format->BytesPerPixel #define PG_SURF_FORMATENUM(surf) surf->format->format +#define PG_FORMAT_R_LOSS(format) format->Rloss +#define PG_FORMAT_G_LOSS(format) format->Gloss +#define PG_FORMAT_B_LOSS(format) format->Bloss +#define PG_FORMAT_A_LOSS(format) format->Aloss + +#define PG_PixelFormat SDL_PixelFormat + +static inline bool +PG_GetSurfaceDetails(SDL_Surface *surf, PG_PixelFormat **format_p, + SDL_Palette **palette_p) +{ + *format_p = surf->format; + *palette_p = surf->format->palette; + return true; +} + +static inline PG_PixelFormat * +PG_GetSurfaceFormat(SDL_Surface *surf) +{ + return surf->format; +} + +// NOTE: +// palette is part of the format in SDL2, so these functions below have it +// as a separate parameter to be consistent with the SDL3 signature. +// They are ignoring the palette parameter, but not the palette data. + +static inline void +PG_GetRGBA(Uint32 pixel, PG_PixelFormat *format, const SDL_Palette *palette, + Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a) +{ + SDL_GetRGBA(pixel, format, r, g, b, a); +} + +static inline void +PG_GetRGB(Uint32 pixel, PG_PixelFormat *format, const SDL_Palette *palette, + Uint8 *r, Uint8 *g, Uint8 *b) +{ + SDL_GetRGB(pixel, format, r, g, b); +} + +static inline Uint32 +PG_MapRGBA(PG_PixelFormat *format, const SDL_Palette *palette, Uint8 r, + Uint8 g, Uint8 b, Uint8 a) +{ + return SDL_MapRGBA(format, r, g, b, a); +} + +static inline Uint32 +PG_MapRGB(PG_PixelFormat *format, const SDL_Palette *palette, Uint8 r, Uint8 g, + Uint8 b) +{ + return SDL_MapRGB(format, r, g, b); +} + /* Mask to test if surface flags are in a fullscreen window. * SDL_WINDOW_FULLSCREEN_DESKTOP works here because it also contains * SDL_WINDOW_FULLSCREEN. */ From ce3a190d25c876938e62894e61968f6360527b9b Mon Sep 17 00:00:00 2001 From: Starbuck5 <46412508+Starbuck5@users.noreply.github.com> Date: Sat, 25 Jan 2025 22:55:55 -0800 Subject: [PATCH 2/2] Mask SDL3 --- src_c/mask.c | 85 ++++++++++++++++++++++++++++++----------------- src_c/meson.build | 3 -- 2 files changed, 55 insertions(+), 33 deletions(-) diff --git a/src_c/mask.c b/src_c/mask.c index 0463fecdea..a40212f18f 100644 --- a/src_c/mask.c +++ b/src_c/mask.c @@ -786,11 +786,12 @@ set_pixel_color(Uint8 *pixel, Uint8 bpp, Uint32 color) * void */ static void -set_from_threshold(SDL_Surface *surf, bitmask_t *bitmask, int threshold) +set_from_threshold(SDL_Surface *surf, PG_PixelFormat *surf_format, + SDL_Palette *surf_palette, bitmask_t *bitmask, + int threshold) { /* This function expects surf to be non-zero sized. */ - SDL_PixelFormat *fmt = surf->format; - const Uint8 bpp = PG_FORMAT_BytesPerPixel(fmt); + const Uint8 bpp = PG_FORMAT_BytesPerPixel(surf_format); int x, y, n; Uint8 *srcp; const int src_skip = surf->pitch - surf->w * bpp; @@ -799,7 +800,7 @@ set_from_threshold(SDL_Surface *surf, bitmask_t *bitmask, int threshold) return; } - if (threshold < 0 || !SDL_ISPIXELFORMAT_ALPHA(fmt->format)) { + if (threshold < 0 || !SDL_ISPIXELFORMAT_ALPHA(surf_format->format)) { bitmask_fill(bitmask); return; } @@ -808,8 +809,8 @@ set_from_threshold(SDL_Surface *surf, bitmask_t *bitmask, int threshold) srcp = (Uint8 *)surf->pixels; for (y = 0; y < surf->h; ++y) { for (x = 0; x < surf->w; ++x, srcp += bpp) { - SDL_GetRGBA(bpp == 1 ? *srcp : *((Uint16 *)srcp), fmt, &r, &g, - &b, &a); + PG_GetRGBA(bpp == 1 ? *srcp : *((Uint16 *)srcp), surf_format, + surf_palette, &r, &g, &b, &a); if (a > threshold) bitmask_setbit(bitmask, x, y); } @@ -823,9 +824,9 @@ set_from_threshold(SDL_Surface *surf, bitmask_t *bitmask, int threshold) * it with the threshold. */ #if SDL_BYTEORDER == SDL_LIL_ENDIAN - const char _a_off = fmt->Ashift >> 3; + const char _a_off = surf_format->Ashift >> 3; #else - const char _a_off = 3 - (fmt->Ashift >> 3); + const char _a_off = 3 - (surf_format->Ashift >> 3); #endif srcp = (Uint8 *)surf->pixels + _a_off; @@ -902,6 +903,13 @@ mask_from_surface(PyObject *self, PyObject *args, PyObject *kwargs) "cannot create mask with negative size"); } + PG_PixelFormat *surf_format; + SDL_Palette *surf_palette; + + if (!PG_GetSurfaceDetails(surf, &surf_format, &surf_palette)) { + return RAISE(pgExc_SDLError, SDL_GetError()); + } + maskobj = CREATE_MASK_OBJ(surf->w, surf->h, 0); if (NULL == maskobj) { @@ -925,7 +933,8 @@ mask_from_surface(PyObject *self, PyObject *args, PyObject *kwargs) set_from_colorkey(surf, maskobj->mask, colorkey); } else { // use threshold - set_from_threshold(surf, maskobj->mask, threshold); + set_from_threshold(surf, surf_format, surf_palette, maskobj->mask, + threshold); } Py_END_ALLOW_THREADS; /* Obtain the GIL. */ @@ -948,56 +957,54 @@ palette_colors - this only affects surfaces with a palette */ void -bitmask_threshold(bitmask_t *m, SDL_Surface *surf, SDL_Surface *surf2, - Uint32 color, Uint32 threshold, int palette_colors) +bitmask_threshold(bitmask_t *m, SDL_Surface *surf, PG_PixelFormat *format, + SDL_Palette *palette, SDL_Surface *surf2, + PG_PixelFormat *format2, Uint32 color, Uint32 threshold, + int palette_colors) { int x, y, rshift, gshift, bshift, rshift2, gshift2, bshift2; int rloss, gloss, bloss, rloss2, gloss2, bloss2; Uint8 *pixels, *pixels2; - SDL_PixelFormat *format, *format2; Uint32 the_color, the_color2, rmask, gmask, bmask, rmask2, gmask2, bmask2; Uint8 *pix; Uint8 r, g, b, a; Uint8 tr, tg, tb, ta; int bpp1, bpp2; - format = surf->format; rmask = format->Rmask; gmask = format->Gmask; bmask = format->Bmask; rshift = format->Rshift; gshift = format->Gshift; bshift = format->Bshift; - rloss = format->Rloss; - gloss = format->Gloss; - bloss = format->Bloss; - bpp1 = PG_SURF_BytesPerPixel(surf); + rloss = PG_FORMAT_R_LOSS(format); + gloss = PG_FORMAT_G_LOSS(format); + bloss = PG_FORMAT_B_LOSS(format); + bpp1 = PG_FORMAT_BytesPerPixel(format); if (surf2) { - format2 = surf2->format; rmask2 = format2->Rmask; gmask2 = format2->Gmask; bmask2 = format2->Bmask; rshift2 = format2->Rshift; gshift2 = format2->Gshift; bshift2 = format2->Bshift; - rloss2 = format2->Rloss; - gloss2 = format2->Gloss; - bloss2 = format2->Bloss; + rloss2 = PG_FORMAT_R_LOSS(format); + gloss2 = PG_FORMAT_G_LOSS(format); + bloss2 = PG_FORMAT_B_LOSS(format); pixels2 = (Uint8 *)surf2->pixels; - bpp2 = PG_SURF_BytesPerPixel(surf); + bpp2 = PG_FORMAT_BytesPerPixel(format2); } else { /* make gcc stop complaining */ rmask2 = gmask2 = bmask2 = 0; rshift2 = gshift2 = bshift2 = 0; rloss2 = gloss2 = bloss2 = 0; - format2 = NULL; pixels2 = NULL; bpp2 = 0; } - SDL_GetRGBA(color, format, &r, &g, &b, &a); - SDL_GetRGBA(threshold, format, &tr, &tg, &tb, &ta); + PG_GetRGBA(color, format, palette, &r, &g, &b, &a); + PG_GetRGBA(threshold, format, palette, &tr, &tg, &tb, &ta); for (y = 0; y < surf->h; y++) { pixels = (Uint8 *)surf->pixels + y * surf->pitch; @@ -1110,6 +1117,8 @@ mask_from_threshold(PyObject *self, PyObject *args, PyObject *kwargs) pgSurfaceObject *surfobj2 = NULL; pgMaskObject *maskobj = NULL; SDL_Surface *surf = NULL, *surf2 = NULL; + PG_PixelFormat *surf_format, *surf2_format = NULL; + SDL_Palette *surf_palette; PyObject *rgba_obj_color, *rgba_obj_threshold = NULL; Uint8 rgba_threshold[4] = {0, 0, 0, 255}; Uint32 color; @@ -1129,6 +1138,17 @@ mask_from_threshold(PyObject *self, PyObject *args, PyObject *kwargs) surf2 = pgSurface_AsSurface(surfobj2); } + if (!PG_GetSurfaceDetails(surf, &surf_format, &surf_palette)) { + return RAISE(pgExc_SDLError, SDL_GetError()); + } + + if (surf2) { + surf2_format = PG_GetSurfaceFormat(surf2); + if (!surf2_format) { + return RAISE(pgExc_SDLError, SDL_GetError()); + } + } + if (!pg_MappedColorFromObj(rgba_obj_color, surf, &color, PG_COLOR_HANDLE_ALL)) { return NULL; @@ -1141,9 +1161,9 @@ mask_from_threshold(PyObject *self, PyObject *args, PyObject *kwargs) } } else { - color_threshold = - SDL_MapRGBA(surf->format, rgba_threshold[0], rgba_threshold[1], - rgba_threshold[2], rgba_threshold[3]); + color_threshold = PG_MapRGBA(surf_format, surf_palette, + rgba_threshold[0], rgba_threshold[1], + rgba_threshold[2], rgba_threshold[3]); } maskobj = CREATE_MASK_OBJ(surf->w, surf->h, 0); @@ -1158,8 +1178,8 @@ mask_from_threshold(PyObject *self, PyObject *args, PyObject *kwargs) } Py_BEGIN_ALLOW_THREADS; - bitmask_threshold(maskobj->mask, surf, surf2, color, color_threshold, - palette_colors); + bitmask_threshold(maskobj->mask, surf, surf_format, surf_palette, surf2, + surf2_format, color, color_threshold, palette_colors); Py_END_ALLOW_THREADS; pgSurface_Unlock(surfobj); @@ -1922,8 +1942,13 @@ extract_color(SDL_Surface *surf, PyObject *color_obj, Uint8 rgba_color[], Uint32 *color) { if (NULL == color_obj) { +#if SDL_VERSION_ATLEAST(3, 0, 0) + *color = SDL_MapSurfaceRGBA(surf, rgba_color[0], rgba_color[1], + rgba_color[2], rgba_color[3]); +#else *color = SDL_MapRGBA(surf->format, rgba_color[0], rgba_color[1], rgba_color[2], rgba_color[3]); +#endif return 1; } diff --git a/src_c/meson.build b/src_c/meson.build index 2e7b95f0d5..2d19c4a889 100644 --- a/src_c/meson.build +++ b/src_c/meson.build @@ -231,8 +231,6 @@ transform = py.extension_module( ) endif -# TODO: support SDL3 -if sdl_api != 3 mask = py.extension_module( 'mask', ['mask.c', 'bitmask.c'], @@ -241,7 +239,6 @@ mask = py.extension_module( install: true, subdir: pg, ) -endif bufferproxy = py.extension_module( 'bufferproxy',