Skip to content

Commit

Permalink
Adjust pg_(Get/Set)DefaultConvertFormat for SDL3
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Starbuck5 committed Nov 2, 2024
1 parent 5827924 commit cc260b3
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 59 deletions.
6 changes: 5 additions & 1 deletion src_c/_pygame.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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)

Expand Down
18 changes: 9 additions & 9 deletions src_c/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions src_c/include/_pygame.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
3 changes: 0 additions & 3 deletions src_c/meson.build
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# first the "required" modules

# TODO: support SDL3
if sdl_api != 3
base = py.extension_module(
'base',
'base.c',
Expand All @@ -10,7 +8,6 @@ base = py.extension_module(
install: true,
subdir: pg,
)
endif

color = py.extension_module(
'color',
Expand Down
64 changes: 26 additions & 38 deletions src_c/surface.c
Original file line number Diff line number Diff line change
Expand Up @@ -1582,66 +1582,54 @@ 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()"
" or Window.get_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);
}

Expand Down
8 changes: 2 additions & 6 deletions src_c/window.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down

0 comments on commit cc260b3

Please sign in to comment.