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 Oct 31, 2024
1 parent 5827924 commit de257d7
Show file tree
Hide file tree
Showing 6 changed files with 48 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
20 changes: 11 additions & 9 deletions src_c/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -2075,25 +2075,27 @@ 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 SDL_VERSION_ATLEAST(3, 0, 0)
if (pg_default_screen) {
return pg_default_screen->surf->format;
}
#else
if (pg_default_screen) {
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
66 changes: 28 additions & 38 deletions src_c/surface.c
Original file line number Diff line number Diff line change
Expand Up @@ -1582,65 +1582,55 @@ 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);
#if SDL_VERSION_ATLEAST(3, 0, 0)
return SDL_ConvertSurface(surface, default_format);
#else
return SDL_ConvertSurfaceFormat(surface, default_format, 0);
#endif
}

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:
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 PG_PIXELFORMAT_XBGR8888:
case SDL_PIXELFORMAT_ABGR8888:
pfe = SDL_PIXELFORMAT_ABGR8888;
break;
default: /* ARGB8888 */

case SDL_PIXELFORMAT_BGRX8888:
case SDL_PIXELFORMAT_BGRA8888:
pfe = SDL_PIXELFORMAT_BGRA8888;
break;

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 de257d7

Please sign in to comment.