From aa02bc6e9e5eecfd64bdf0ac09661d765fcbeeac Mon Sep 17 00:00:00 2001 From: Ankith Date: Thu, 21 Aug 2025 14:18:11 +0530 Subject: [PATCH] SDL3 runtime fixes --- docs/reST/c_api/surface.rst | 2 +- src_c/_pygame.h | 8 ++ src_c/display.c | 137 +++++++++++++++++----------------- src_c/font.c | 6 +- src_c/pixelcopy.c | 6 +- src_c/surface.c | 144 ++++++++++++++++++++++++------------ src_c/surface_fill.c | 3 +- src_c/window.c | 8 +- test/surface_test.py | 10 +++ 9 files changed, 197 insertions(+), 127 deletions(-) diff --git a/docs/reST/c_api/surface.rst b/docs/reST/c_api/surface.rst index a394d629f0..6cbc91f0e3 100644 --- a/docs/reST/c_api/surface.rst +++ b/docs/reST/c_api/surface.rst @@ -56,4 +56,4 @@ Header file: src_c/include/pygame.h by the blit. The C version of the :py:meth:`pygame.Surface.blit` method. - Return ``1`` on success, ``0`` on an exception. + Return ``0`` on success, ``1`` on an exception. diff --git a/src_c/_pygame.h b/src_c/_pygame.h index 3a57f01be4..2c701c0edb 100644 --- a/src_c/_pygame.h +++ b/src_c/_pygame.h @@ -192,6 +192,8 @@ PG_GetSurfaceFormat(SDL_Surface *surf) #define PG_GetSurfaceClipRect SDL_GetSurfaceClipRect +#define PG_GL_SetSwapInterval SDL_GL_SetSwapInterval + #else /* ~SDL_VERSION_ATLEAST(3, 0, 0)*/ #define PG_ShowCursor() SDL_ShowCursor(SDL_ENABLE) #define PG_HideCursor() SDL_ShowCursor(SDL_DISABLE) @@ -400,6 +402,12 @@ PG_GetSurfaceClipRect(SDL_Surface *surface, SDL_Rect *rect) *rect = surface->clip_rect; return true; } + +static inline bool +PG_GL_SetSwapInterval(int interval) +{ + return SDL_GL_SetSwapInterval(interval) == 0; +} #endif /* DictProxy is useful for event posting with an arbitrary dict. Maintains diff --git a/src_c/display.c b/src_c/display.c index e7d0f3f933..b2c380abcb 100644 --- a/src_c/display.c +++ b/src_c/display.c @@ -279,7 +279,11 @@ pg_get_init(PyObject *self, PyObject *_null) static PyObject * pg_get_active(PyObject *self, PyObject *_null) { - SDL_WindowFlags flags = SDL_GetWindowFlags(pg_GetDefaultWindow()); + SDL_Window *win = pg_GetDefaultWindow(); + if (!win) { + Py_RETURN_FALSE; + } + SDL_WindowFlags flags = SDL_GetWindowFlags(win); #if SDL_VERSION_ATLEAST(3, 0, 0) return PyBool_FromLong(!(flags & SDL_WINDOW_HIDDEN) && @@ -793,7 +797,7 @@ pg_get_surface(PyObject *self, PyObject *_null) static PyObject * pg_gl_set_attribute(PyObject *self, PyObject *arg) { - int flag, value, result; + int flag, value; VIDEO_INIT_CHECK(); if (!PyArg_ParseTuple(arg, "ii", &flag, &value)) { return NULL; @@ -801,25 +805,35 @@ pg_gl_set_attribute(PyObject *self, PyObject *arg) if (flag == -1) { /*an undefined/unsupported val, ignore*/ Py_RETURN_NONE; } - result = SDL_GL_SetAttribute(flag, value); - if (result == -1) { +#if SDL_VERSION_ATLEAST(3, 0, 0) + if (!SDL_GL_SetAttribute(flag, value)) { return RAISE(pgExc_SDLError, SDL_GetError()); } +#else + if (SDL_GL_SetAttribute(flag, value) == -1) { + return RAISE(pgExc_SDLError, SDL_GetError()); + } +#endif Py_RETURN_NONE; } static PyObject * pg_gl_get_attribute(PyObject *self, PyObject *arg) { - int flag, value, result; + int flag, value; VIDEO_INIT_CHECK(); if (!PyArg_ParseTuple(arg, "i", &flag)) { return NULL; } - result = SDL_GL_GetAttribute(flag, &value); - if (result == -1) { +#if SDL_VERSION_ATLEAST(3, 0, 0) + if (!SDL_GL_GetAttribute(flag, &value)) { + return RAISE(pgExc_SDLError, SDL_GetError()); + } +#else + if (SDL_GL_GetAttribute(flag, &value) == -1) { return RAISE(pgExc_SDLError, SDL_GetError()); } +#endif return PyLong_FromLong(value); } @@ -1118,12 +1132,12 @@ PG_CreateWindowCompat(const char *title, int x, int y, int w, int h, } #if SDL_VERSION_ATLEAST(3, 0, 0) -/* Returns 0 on success, negative on failure. */ -static int +/* Returns true on success, false on failure. */ +static bool PG_SetWindowFullscreen(SDL_Window *window, bool fullscreen, bool non_desktop_fullscreen) { - int ret = -1; + bool ret = false; SDL_DisplayMode **modes = NULL; SDL_DisplayMode *chosen_mode = NULL; if (!SDL_SetWindowFullscreen(window, fullscreen)) { @@ -1152,11 +1166,23 @@ PG_SetWindowFullscreen(SDL_Window *window, bool fullscreen, } } - ret = 0; + ret = true; end: SDL_free(modes); return ret; } +#else +static bool +PG_SetWindowFullscreen(SDL_Window *window, bool fullscreen, + bool non_desktop_fullscreen) +{ + int flags = 0; + if (fullscreen) { + flags = non_desktop_fullscreen ? SDL_WINDOW_FULLSCREEN + : SDL_WINDOW_FULLSCREEN_DESKTOP; + } + return (SDL_SetWindowFullscreen(window, flags) == 0); +} #endif static PyObject * @@ -1183,7 +1209,7 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) char *title = state->title; const char *scale_env, *winid_env; #if SDL_VERSION_ATLEAST(3, 0, 0) - int non_desktop_fullscreen = 0; + int non_desktop_fullscreen = 1; #endif char *keywords[] = {"size", "flags", "depth", "display", "vsync", NULL}; @@ -1308,7 +1334,7 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) if (flags & PGS_SCALED) { #if SDL_VERSION_ATLEAST(3, 0, 0) sdl_flags |= SDL_WINDOW_FULLSCREEN; - non_desktop_fullscreen = 1; + non_desktop_fullscreen = 0; #else sdl_flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; #endif @@ -1318,7 +1344,7 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) Borderless fullscreen is preferred when possible */ #if SDL_VERSION_ATLEAST(3, 0, 0) sdl_flags |= SDL_WINDOW_FULLSCREEN; - non_desktop_fullscreen = 1; + non_desktop_fullscreen = 0; #else sdl_flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; #endif @@ -1437,11 +1463,16 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) if (flags & PGS_SCALED && !(flags & PGS_FULLSCREEN)) { SDL_Rect display_bounds; int fractional_scaling = SDL_FALSE; - +#if SDL_VERSION_ATLEAST(3, 0, 0) + if (!SDL_GetDisplayUsableBounds(display, &display_bounds)) { + return RAISE(pgExc_SDLError, SDL_GetError()); + } +#else if (0 != SDL_GetDisplayUsableBounds(display, &display_bounds)) { return RAISE(pgExc_SDLError, SDL_GetError()); } +#endif if (SDL_GetHintBoolean("SDL_HINT_RENDER_SCALE_QUALITY", SDL_FALSE)) { @@ -1530,9 +1561,9 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) * changes if the window is fullscreen * See https://github.com/pygame/pygame/issues/2711 */ #if SDL_VERSION_ATLEAST(3, 0, 0) - if (0 != PG_SetWindowFullscreen( - win, sdl_flags & SDL_WINDOW_FULLSCREEN, - non_desktop_fullscreen)) { + if (!PG_SetWindowFullscreen(win, + sdl_flags & SDL_WINDOW_FULLSCREEN, + non_desktop_fullscreen)) { return RAISE(pgExc_SDLError, SDL_GetError()); } #else @@ -1592,7 +1623,7 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) vsync to be always on or always off, or vsync is on by default for the whole desktop because of wayland GL compositing. */ if (vsync == -1) { - if (SDL_GL_SetSwapInterval(-1) != 0) { + if (!PG_GL_SetSwapInterval(-1)) { PyErr_SetString(pgExc_SDLError, "adaptive vsync for OpenGL not " "available"); @@ -1602,7 +1633,7 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) } } else if (vsync == 1) { - if (SDL_GL_SetSwapInterval(1) != 0) { + if (!PG_GL_SetSwapInterval(1)) { PyErr_SetString(pgExc_SDLError, "regular vsync for OpenGL not " "available"); @@ -1611,7 +1642,7 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) } } else { - SDL_GL_SetSwapInterval(0); + PG_GL_SetSwapInterval(0); } } else { @@ -1686,7 +1717,7 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) #if SDL_VERSION_ATLEAST(3, 0, 0) int has_vsync = 0; SDL_GetRenderVSync(pg_renderer, &has_vsync); - if (vsync && has_vsync) { + if (vsync && !has_vsync) { PyErr_SetString(pgExc_SDLError, "could not enable vsync"); _display_state_cleanup(state); @@ -3030,7 +3061,6 @@ static PyObject * pg_toggle_fullscreen(PyObject *self, PyObject *_null) { SDL_Window *win = pg_GetDefaultWindow(); - int result; SDL_WindowFlags flags; int window_w, window_h, w, h, window_display, x, y; pgSurfaceObject *display_surface; @@ -3159,8 +3189,7 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) /* TOGGLE FULLSCREEN OFF */ if (state->unscaled_render) { - result = SDL_SetWindowFullscreen(win, 0); - if (result != 0) { + if (!PG_SetWindowFullscreen(win, false, false)) { return RAISE(pgExc_SDLError, SDL_GetError()); } } @@ -3174,8 +3203,7 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) if (scale < 1) { scale = 1; } - result = SDL_SetWindowFullscreen(win, 0); - if (result != 0) { + if (!PG_SetWindowFullscreen(win, false, false)) { return RAISE(pgExc_SDLError, SDL_GetError()); } SDL_SetWindowSize(win, w * scale, h * scale); @@ -3215,8 +3243,7 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) /* this is literally the only place where state->toggle_windowed_w * should ever be read. We only use it because with GL, there is no * display surface we can query for dimensions. */ - result = SDL_SetWindowFullscreen(win, 0); - if (result != 0) { + if (!PG_SetWindowFullscreen(win, false, false)) { return RAISE(pgExc_SDLError, SDL_GetError()); } SDL_GL_MakeCurrent(win, state->gl_context); @@ -3252,8 +3279,7 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) else if ((flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP) { #endif - result = SDL_SetWindowFullscreen(win, 0); - if (result != 0) { + if (!PG_SetWindowFullscreen(win, false, false)) { return RAISE(pgExc_SDLError, SDL_GetError()); } display_surface->surf = SDL_GetWindowSurface(win); @@ -3282,15 +3308,11 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) if (win == NULL) { return RAISE(pgExc_SDLError, SDL_GetError()); } - else { - result = 0; - } display_surface->surf = SDL_GetWindowSurface(win); pg_SetDefaultWindow(win); } else { - result = SDL_SetWindowFullscreen(win, 0); - if (result != 0) { + if (!PG_SetWindowFullscreen(win, false, false)) { return RAISE(pgExc_SDLError, SDL_GetError()); } display_surface->surf = SDL_GetWindowSurface(win); @@ -3325,24 +3347,12 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) state->fullscreen_backup_y = y; if (state->unscaled_render) { -#if SDL_VERSION_ATLEAST(3, 0, 0) - result = PG_SetWindowFullscreen(win, 1, 0); -#else - result = - SDL_SetWindowFullscreen(win, SDL_WINDOW_FULLSCREEN_DESKTOP); -#endif - if (result != 0) { + if (!PG_SetWindowFullscreen(win, true, false)) { return RAISE(pgExc_SDLError, SDL_GetError()); } } else if (pg_renderer != NULL) { -#if SDL_VERSION_ATLEAST(3, 0, 0) - result = PG_SetWindowFullscreen(win, 1, 0); -#else - result = - SDL_SetWindowFullscreen(win, SDL_WINDOW_FULLSCREEN_DESKTOP); -#endif - if (result != 0) { + if (!PG_SetWindowFullscreen(win, true, false)) { return RAISE(pgExc_SDLError, SDL_GetError()); } if (is_renderer_software && subsystem == SDL_SYSWM_X11) { @@ -3375,13 +3385,7 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) #endif } else if (state->using_gl) { -#if SDL_VERSION_ATLEAST(3, 0, 0) - result = PG_SetWindowFullscreen(win, 1, 0); -#else - result = - SDL_SetWindowFullscreen(win, SDL_WINDOW_FULLSCREEN_DESKTOP); -#endif - if (result != 0) { + if (!PG_SetWindowFullscreen(win, true, false)) { return RAISE(pgExc_SDLError, SDL_GetError()); } SDL_GL_MakeCurrent(win, state->gl_context); @@ -3406,13 +3410,7 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) } } else if (w == display_mode->w && h == display_mode->h) { -#if SDL_VERSION_ATLEAST(3, 0, 0) - result = PG_SetWindowFullscreen(win, 1, 0); -#else - result = - SDL_SetWindowFullscreen(win, SDL_WINDOW_FULLSCREEN_DESKTOP); -#endif - if (result != 0) { + if (!PG_SetWindowFullscreen(win, true, false)) { return RAISE(pgExc_SDLError, SDL_GetError()); } display_surface->surf = SDL_GetWindowSurface(win); @@ -3429,8 +3427,7 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) return PyLong_FromLong(-1); } else { - result = SDL_SetWindowFullscreen(win, SDL_WINDOW_FULLSCREEN); - if (result != 0) { + if (!PG_SetWindowFullscreen(win, true, true)) { return RAISE(pgExc_SDLError, SDL_GetError()); } display_surface->surf = SDL_GetWindowSurface(win); @@ -3442,7 +3439,7 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) if (win == NULL) { return RAISE(pgExc_SDLError, SDL_GetError()); } - if (0 != SDL_SetWindowFullscreen(win, SDL_WINDOW_FULLSCREEN)) { + if (!PG_SetWindowFullscreen(win, true, true)) { return RAISE(pgExc_SDLError, SDL_GetError()); } display_surface->surf = SDL_GetWindowSurface(win); @@ -3456,7 +3453,7 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) } } } - return PyLong_FromLong(result != 0); + return PyLong_FromLong(1); } /* This API is provisional, and, not finalised, and should not be documented @@ -3766,7 +3763,11 @@ pg_message_box(PyObject *self, PyObject *arg, PyObject *kwargs) int clicked_button_id; +#if SDL_VERSION_ATLEAST(3, 0, 0) + if (!SDL_ShowMessageBox(&msgbox_data, &clicked_button_id)) { +#else if (SDL_ShowMessageBox(&msgbox_data, &clicked_button_id)) { +#endif PyErr_SetString(pgExc_SDLError, SDL_GetError()); goto error; } diff --git a/src_c/font.c b/src_c/font.c index c28cb0d94a..117cb6b58a 100644 --- a/src_c/font.c +++ b/src_c/font.c @@ -717,11 +717,7 @@ font_render(PyObject *self, PyObject *args, PyObject *kwds) resolve to Render_Solid, that needs to be explicitly handled. */ if (surf != NULL && bg_rgba_obj != Py_None) { SDL_SetColorKey(surf, 0, 0); -#if SDL_TTF_VERSION_ATLEAST(3, 0, 0) - SDL_Palette *palette = SDL_GetSurfacePalette(surf); -#else - SDL_Palette *palette = surf->format->palette; -#endif + SDL_Palette *palette = PG_GetSurfacePalette(surf); if (palette) { palette->colors[0].r = backg.r; palette->colors[0].g = backg.g; diff --git a/src_c/pixelcopy.c b/src_c/pixelcopy.c index e9f1a327c9..1e59752f07 100644 --- a/src_c/pixelcopy.c +++ b/src_c/pixelcopy.c @@ -1197,11 +1197,7 @@ make_surface(PyObject *self, PyObject *arg) pgBuffer_Release(&pg_view); return RAISE(pgExc_SDLError, SDL_GetError()); } -#if SDL_VERSION_ATLEAST(3, 0, 0) - SDL_Palette *palette = SDL_GetSurfacePalette(surf); -#else - SDL_Palette *palette = surf->format->palette; -#endif + SDL_Palette *palette = PG_GetSurfacePalette(surf); if (SDL_ISPIXELFORMAT_INDEXED(PG_SURF_FORMATENUM(surf))) { /* Give the surface something other than an all white palette. * */ diff --git a/src_c/surface.c b/src_c/surface.c index 3a5440cb3c..59bb6b9a9f 100644 --- a/src_c/surface.c +++ b/src_c/surface.c @@ -1544,16 +1544,14 @@ surf_set_alpha(pgSurfaceObject *self, PyObject *args) bool success = PG_SetSurfaceRLE(surf, (flags & PGS_RLEACCEL) ? SDL_TRUE : SDL_FALSE); /* HACK HACK HACK */ - // TODO SDL3: figure out how to port this or if it's relevant to SDL3. -#if !SDL_VERSION_ATLEAST(3, 0, 0) - if ((surf->flags & SDL_RLEACCEL) && (!(flags & PGS_RLEACCEL))) { + if (SDL_MUSTLOCK(surf) && (!(flags & PGS_RLEACCEL))) { /* hack to strip SDL_RLEACCEL flag off surface immediately when it is not requested */ SDL_Rect sdlrect; sdlrect.x = 0; sdlrect.y = 0; - sdlrect.h = 0; - sdlrect.w = 0; + sdlrect.h = 1; + sdlrect.w = 1; SDL_Surface *surface = PG_CreateSurface(1, 1, PG_SURF_FORMATENUM(surf)); @@ -1561,7 +1559,6 @@ surf_set_alpha(pgSurfaceObject *self, PyObject *args) SDL_LowerBlit(surf, &sdlrect, surface, &sdlrect); SDL_FreeSurface(surface); } -#endif /* HACK HACK HACK */ if (success) { success = PG_SetSurfaceAlphaMod(surf, alpha); @@ -3010,20 +3007,15 @@ surf_get_flags(PyObject *self, PyObject *_null) if (sdl_flags & SDL_PREALLOC) { flags |= PGS_PREALLOC; } + /* This checks if RLE was requested on the surface */ if (PG_SurfaceHasRLE(surf)) { flags |= PGS_RLEACCELOK; } - // TODO SDL3: figure out how to properly emulate SDL2 check/relevance - // Current implementation is just a placeholder. -#if SDL_VERSION_ATLEAST(3, 0, 0) - if (SDL_SurfaceHasRLE(surf)) { - flags |= PGS_RLEACCEL; - } -#else - if ((sdl_flags & SDL_RLEACCEL)) { + /* this checks if the surface actually has RLE. + * On SDL2: SDL_MUSTLOCK is (flags & SDL_RLEACCEL) */ + if (SDL_MUSTLOCK(surf)) { flags |= PGS_RLEACCEL; } -#endif if (is_window_surf) { if (window_flags & PG_WINDOW_FULLSCREEN_INCLUSIVE) { flags |= PGS_FULLSCREEN; @@ -4455,6 +4447,76 @@ surface_do_overlap(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, return dstoffset < span || dstoffset > src->pitch - span; } +int +PG_BlitSurface(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, + SDL_Rect *dstrect) +{ +#if SDL_VERSION_ATLEAST(3, 0, 0) + /* SDL3 doesn't modify dstrect, so compat for that. + * Below logic taken from SDL2 source with slight modifications */ + SDL_Rect r_src, r_dst; + + r_src.x = 0; + r_src.y = 0; + r_src.w = src->w; + r_src.h = src->h; + + if (dstrect) { + r_dst.x = dstrect->x; + r_dst.y = dstrect->y; + } + else { + r_dst.x = 0; + r_dst.y = 0; + } + + /* clip the source rectangle to the source surface */ + if (srcrect) { + SDL_Rect tmp; + if (SDL_IntersectRect(srcrect, &r_src, &tmp) == SDL_FALSE) { + goto end; + } + + /* Shift dstrect, if srcrect origin has changed */ + r_dst.x += tmp.x - srcrect->x; + r_dst.y += tmp.y - srcrect->y; + + /* Update srcrect */ + r_src = tmp; + } + + /* There're no dstrect.w/h parameters. It's the same as srcrect */ + r_dst.w = r_src.w; + r_dst.h = r_src.h; + + /* clip the destination rectangle against the clip rectangle */ + { + SDL_Rect tmp, clip_rect; + SDL_GetSurfaceClipRect(dst, &clip_rect); + if (SDL_IntersectRect(&r_dst, &clip_rect, &tmp) == SDL_FALSE) { + goto end; + } + + /* Update dstrect */ + r_dst = tmp; + } + + if (r_dst.w > 0 && r_dst.h > 0) { + if (dstrect) { /* update output parameter */ + *dstrect = r_dst; + } + return SDL_BlitSurface(src, srcrect, dst, dstrect) ? 0 : -1; + } +end: + if (dstrect) { + dstrect->w = dstrect->h = 0; + } + return 0; +#else + return SDL_BlitSurface(src, srcrect, dst, dstrect); +#endif +} + /*this internal blit function is accessible through the C api*/ int pgSurface_Blit(pgSurfaceObject *dstobj, pgSurfaceObject *srcobj, @@ -4465,13 +4527,11 @@ pgSurface_Blit(pgSurfaceObject *dstobj, pgSurfaceObject *srcobj, SDL_Surface *subsurface = NULL; int result, suboffsetx = 0, suboffsety = 0; SDL_Rect orig_clip, sub_clip, dstclip; -#if !SDL_VERSION_ATLEAST(3, 0, 0) Uint8 alpha; -#endif if (!PG_GetSurfaceClipRect(dst, &dstclip)) { PyErr_SetString(pgExc_SDLError, SDL_GetError()); - return 0; + return 1; } /* passthrough blits to the real surface */ @@ -4522,8 +4582,6 @@ pgSurface_Blit(pgSurfaceObject *dstobj, pgSurfaceObject *srcobj, result = pygame_Blit(src, srcrect, dst, dstrect, blend_flags); /* Py_END_ALLOW_THREADS */ } -// TODO SDL3: port the below bit of code. Skipping for initial surface port. -#if !SDL_VERSION_ATLEAST(3, 0, 0) /* can't blit alpha to 8bit, crashes SDL */ else if (PG_SURF_BytesPerPixel(dst) == 1 && (SDL_ISPIXELFORMAT_ALPHA(PG_SURF_FORMATENUM(src)) || @@ -4533,34 +4591,37 @@ pgSurface_Blit(pgSurfaceObject *dstobj, pgSurfaceObject *srcobj, result = pygame_Blit(src, srcrect, dst, dstrect, 0); } else { +#if SDL_VERSION_ATLEAST(3, 0, 0) + const SDL_PixelFormatDetails *fmt = + SDL_GetPixelFormatDetails(src->format); + src = fmt ? SDL_ConvertSurface(src, + SDL_GetPixelFormatForMasks( + fmt->bits_per_pixel, fmt->Rmask, + fmt->Gmask, fmt->Bmask, 0)) + : NULL; +#else SDL_PixelFormat *fmt = src->format; SDL_PixelFormat *newfmt = SDL_AllocFormat(SDL_MasksToPixelFormatEnum( fmt->BitsPerPixel, fmt->Rmask, fmt->Gmask, fmt->Bmask, 0)); if (!newfmt) { - result = -1; + src = NULL; } else { - src = PG_ConvertSurface(src, newfmt); - + src = SDL_ConvertSurface(src, newfmt, 0); SDL_FreeFormat(newfmt); - if (src) { -#if SDL_VERSION_ATLEAST(3, 0, 0) - result = - SDL_BlitSurface(src, srcrect, dst, dstrect) ? 0 : -1; -#else - result = SDL_BlitSurface(src, srcrect, dst, dstrect); + } #endif - SDL_FreeSurface(src); - } - else { - result = -1; - } + if (src) { + result = PG_BlitSurface(src, srcrect, dst, dstrect); + SDL_FreeSurface(src); + } + else { + result = -1; } } /* Py_END_ALLOW_THREADS */ } -#endif else if (blend_flags != PYGAME_BLEND_ALPHA_SDL2 && !(pg_EnvShouldBlendAlphaSDL2()) && !SDL_HasColorKey(src) && (PG_SURF_BytesPerPixel(dst) == 4 || @@ -4568,12 +4629,7 @@ pgSurface_Blit(pgSurfaceObject *dstobj, pgSurfaceObject *srcobj, _PgSurface_SrcAlpha(src) && (SDL_ISPIXELFORMAT_ALPHA(PG_SURF_FORMATENUM(src))) && !PG_SurfaceHasRLE(src) && !PG_SurfaceHasRLE(dst) && -#if SDL_VERSION_ATLEAST(3, 0, 0) - 1 -#else - !(src->flags & SDL_RLEACCEL) && !(dst->flags & SDL_RLEACCEL) -#endif - ) { + !SDL_MUSTLOCK(src) && !SDL_MUSTLOCK(dst)) { /* If we have a 32bit source surface with per pixel alpha and no RLE we'll use pygame_Blit so we can mimic how SDL1 behaved */ @@ -4581,11 +4637,7 @@ pgSurface_Blit(pgSurfaceObject *dstobj, pgSurfaceObject *srcobj, } else { /* Py_BEGIN_ALLOW_THREADS */ -#if SDL_VERSION_ATLEAST(3, 0, 0) - result = SDL_BlitSurface(src, srcrect, dst, dstrect) ? 0 : -1; -#else - result = SDL_BlitSurface(src, srcrect, dst, dstrect); -#endif + result = PG_BlitSurface(src, srcrect, dst, dstrect); /* Py_END_ALLOW_THREADS */ } diff --git a/src_c/surface_fill.c b/src_c/surface_fill.c index 5f3873b2be..e03d67948d 100644 --- a/src_c/surface_fill.c +++ b/src_c/surface_fill.c @@ -1143,7 +1143,8 @@ surface_fill_blend(SDL_Surface *surface, SDL_Rect *rect, Uint32 color, } default: { - result = SDL_SetError("invalid blend flag for this operation"); + SDL_SetError("invalid blend flag for this operation"); + result = -1; break; } } diff --git a/src_c/window.c b/src_c/window.c index 15a3cbca03..a928a215c0 100644 --- a/src_c/window.c +++ b/src_c/window.c @@ -301,9 +301,15 @@ _resize_event_watch(void *userdata, SDL_Event *event) static PyObject * window_set_windowed(pgWindowObject *self, PyObject *_null) { +#if SDL_VERSION_ATLEAST(3, 0, 0) + if (!SDL_SetWindowFullscreen(self->_win, 0)) { + return RAISE(pgExc_SDLError, SDL_GetError()); + } +#else if (SDL_SetWindowFullscreen(self->_win, 0)) { return RAISE(pgExc_SDLError, SDL_GetError()); } +#endif Py_RETURN_NONE; } @@ -371,7 +377,7 @@ window_set_fullscreen(pgWindowObject *self, PyObject *args, PyObject *kwargs) static PyObject * window_focus(pgWindowObject *self, PyObject *args, PyObject *kwargs) { - SDL_bool input_only = SDL_FALSE; + int input_only = SDL_FALSE; char *kwids[] = {"input_only", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|p", kwids, &input_only)) { return NULL; diff --git a/test/surface_test.py b/test/surface_test.py index c2c91f4f5b..1e1d16da97 100644 --- a/test/surface_test.py +++ b/test/surface_test.py @@ -376,6 +376,11 @@ def test_subsurface_rle2(self): self.assertTrue(s1.get_flags() & pygame.RLEACCELOK) self.assertTrue(not s2.get_flags() & pygame.RLEACCELOK) + @unittest.skipIf( + (2, 32, 50) <= pygame.version.SDL <= (2, 32, 56) + or (3, 0, 0) <= pygame.version.SDL <= (3, 2, 22), + "This test was briefly broken on SDL3 (and sdl2-compat) but got fixed.", + ) def test_solarwolf_rle_usage(self): """Test for error/crash when calling set_colorkey() followed by convert twice in succession. Code originally taken @@ -404,6 +409,11 @@ def optimize(img): finally: pygame.display.quit() + @unittest.skipIf( + (2, 32, 50) <= pygame.version.SDL <= (2, 32, 56) + or (3, 0, 0) <= pygame.version.SDL <= (3, 2, 22), + "This test was briefly broken on SDL3 (and sdl2-compat) but got fixed.", + ) def test_solarwolf_rle_usage_2(self): """Test for RLE status after setting alpha"""