From 70ff5c3789d81506b304512812ff181b6d94000c Mon Sep 17 00:00:00 2001 From: Ankith Date: Sun, 18 May 2025 19:24:35 +0530 Subject: [PATCH 01/11] sdl3(display): remove all gamma ramp related code --- src_c/display.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src_c/display.c b/src_c/display.c index 6934ca808d..a1ae793cb1 100644 --- a/src_c/display.c +++ b/src_c/display.c @@ -44,7 +44,9 @@ static SDL_Texture *pg_texture = NULL; typedef struct _display_state_s { char *title; PyObject *icon; +#if !SDL_VERSION_ATLEAST(3, 0, 0) Uint16 *gamma_ramp; +#endif SDL_GLContext gl_context; int toggle_windowed_w; int toggle_windowed_h; @@ -87,10 +89,12 @@ _display_state_cleanup(_DisplayState *state) SDL_GL_DeleteContext(state->gl_context); state->gl_context = NULL; } +#if !SDL_VERSION_ATLEAST(3, 0, 0) if (state->gamma_ramp) { free(state->gamma_ramp); state->gamma_ramp = NULL; } +#endif } // prevent this code block from being linked twice @@ -1342,6 +1346,8 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) surf = SDL_GetWindowSurface(win); } } + +#if !SDL_VERSION_ATLEAST(3, 0, 0) if (state->gamma_ramp) { int result = SDL_SetWindowGammaRamp(win, state->gamma_ramp, state->gamma_ramp + 256, @@ -1356,6 +1362,7 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) goto DESTROY_WINDOW; } } +#endif if (state->using_gl && pg_renderer != NULL) { _display_state_cleanup(state); @@ -2011,6 +2018,24 @@ pg_set_palette(PyObject *self, PyObject *args) Py_RETURN_NONE; } +#if SDL_VERSION_ATLEAST(3, 0, 0) +static PyObject * +pg_set_gamma(PyObject *self, PyObject *arg) +{ + return RAISE(pgExc_SDLError, + "set_gamma not supported with SDL3, this functionality has " + "been removed."); +} + +static PyObject * +pg_set_gamma_ramp(PyObject *self, PyObject *arg) +{ + return RAISE( + pgExc_SDLError, + "pg_set_gamma_ramp not supported with SDL3, this functionality has " + "been removed."); +} +#else static PyObject * pg_set_gamma(PyObject *self, PyObject *arg) { @@ -2150,6 +2175,7 @@ pg_set_gamma_ramp(PyObject *self, PyObject *arg) } return PyBool_FromLong(result == 0); } +#endif static PyObject * pg_set_caption(PyObject *self, PyObject *arg) @@ -3207,7 +3233,9 @@ MODINIT_DEFINE(display) state = DISPLAY_MOD_STATE(module); state->title = NULL; state->icon = NULL; +#if !SDL_VERSION_ATLEAST(3, 0, 0) state->gamma_ramp = NULL; +#endif state->using_gl = 0; state->auto_resize = SDL_TRUE; From a0b67667adfe919148d4e50639f26a2059365e16 Mon Sep 17 00:00:00 2001 From: Ankith Date: Sun, 18 May 2025 20:01:12 +0530 Subject: [PATCH 02/11] sdl3(display): handle SDL_GL_* updates --- src_c/display.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src_c/display.c b/src_c/display.c index a1ae793cb1..76fa9c2224 100644 --- a/src_c/display.c +++ b/src_c/display.c @@ -2370,12 +2370,25 @@ pg_is_vsync(PyObject *self, PyObject *_null) } if (state->using_gl) { +#if SDL_VERSION_ATLEAST(3, 0, 0) + int interval; + if (!SDL_GL_GetSwapInterval(&interval)) { + return RAISE(pgExc_SDLError, SDL_GetError()); + } + if (interval != 0) { + Py_RETURN_TRUE; + } + else { + Py_RETURN_FALSE; + } +#else if (SDL_GL_GetSwapInterval() != 0) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } +#endif } Py_RETURN_FALSE; @@ -2534,7 +2547,11 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) */ if (state->using_gl) { p_glViewport = (GL_glViewport_Func)SDL_GL_GetProcAddress("glViewport"); +#if SDL_VERSION_ATLEAST(3, 0, 0) + SDL_GetWindowSizeInPixels(win, &w, &h); +#else SDL_GL_GetDrawableSize(win, &w, &h); +#endif } else { w = display_surface->surf->w; From a27892d3fd470fdbc45c9959d55eb378779b0066 Mon Sep 17 00:00:00 2001 From: Ankith Date: Sun, 18 May 2025 20:02:41 +0530 Subject: [PATCH 03/11] sdl3(display): handle SDL_RendererInfo changes --- src_c/display.c | 71 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 64 insertions(+), 7 deletions(-) diff --git a/src_c/display.c b/src_c/display.c index 76fa9c2224..9f4e5363b8 100644 --- a/src_c/display.c +++ b/src_c/display.c @@ -1279,8 +1279,6 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) if (flags & PGS_SCALED || state->unscaled_render) { if (pg_renderer == NULL) { - SDL_RendererInfo info; - SDL_SetHintWithPriority(SDL_HINT_RENDER_SCALE_QUALITY, "nearest", SDL_HINT_DEFAULT); @@ -1319,6 +1317,26 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) SDL_SetWindowMinimumSize(win, w, h); } +#if SDL_VERSION_ATLEAST(3, 0, 0) + int has_vsync = 0; + SDL_GetRenderVSync(pg_renderer, &has_vsync); + if (vsync && has_vsync) { + PyErr_SetString(pgExc_SDLError, + "could not enable vsync"); + _display_state_cleanup(state); + goto DESTROY_WINDOW; + } + const char *name = SDL_GetRendererName(pg_renderer); + if (name && !strcmp(name, SDL_SOFTWARE_RENDERER)) { + if (PyErr_WarnEx(PyExc_Warning, + "no fast renderer available", + 1) != 0) { + _display_state_cleanup(state); + goto DESTROY_WINDOW; + } + } +#else + SDL_RendererInfo info; SDL_GetRendererInfo(pg_renderer, &info); if (vsync && !(info.flags & SDL_RENDERER_PRESENTVSYNC)) { PyErr_SetString(pgExc_SDLError, @@ -1334,6 +1352,7 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) goto DESTROY_WINDOW; } } +#endif pg_texture = SDL_CreateTexture( pg_renderer, SDL_PIXELFORMAT_ARGB8888, @@ -2272,6 +2291,21 @@ pg_iconify(PyObject *self, PyObject *_null) static PyObject * pg_get_scaled_renderer_info(PyObject *self, PyObject *_null) { +#if SDL_VERSION_ATLEAST(3, 0, 0) + VIDEO_INIT_CHECK(); + if (!pg_renderer) { + Py_RETURN_NONE; + } + + const char *name = SDL_GetRendererName(pg_renderer); + if (!name) { + return RAISE(pgExc_SDLError, SDL_GetError()); + } + + /* flags are not being handled here but it shouldn't matter as this is + * undocumented API */ + return Py_BuildValue("(si)", name, 0); +#else SDL_RendererInfo r_info; VIDEO_INIT_CHECK(); @@ -2284,6 +2318,7 @@ pg_get_scaled_renderer_info(PyObject *self, PyObject *_null) } return Py_BuildValue("(si)", r_info.name, r_info.flags); +#endif } static PyObject * @@ -2355,6 +2390,19 @@ pg_is_vsync(PyObject *self, PyObject *_null) } if (pg_renderer != NULL) { +#if SDL_VERSION_ATLEAST(3, 0, 0) + int has_vsync = 0; + if (!SDL_GetRenderVSync(pg_renderer, &has_vsync)) { + return RAISE(pgExc_SDLError, SDL_GetError()); + } + + if (has_vsync) { + Py_RETURN_TRUE; + } + else { + Py_RETURN_FALSE; + } +#else SDL_RendererInfo info; if (SDL_GetRendererInfo(pg_renderer, &info) != 0) { @@ -2367,6 +2415,7 @@ pg_is_vsync(PyObject *self, PyObject *_null) else { Py_RETURN_FALSE; } +#endif } if (state->using_gl) { @@ -2465,7 +2514,7 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) _DisplayState *state = DISPLAY_MOD_STATE(self); GL_glViewport_Func p_glViewport = NULL; SDL_SysWMinfo wm_info; - SDL_RendererInfo r_info; + int is_renderer_software = 0; VIDEO_INIT_CHECK(); if (!win) { @@ -2485,9 +2534,19 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) } if (pg_renderer != NULL) { +#if SDL_VERSION_ATLEAST(3, 0, 0) + const char *r_name; + if (!(r_name = SDL_GetRendererName(pg_renderer))) { + return RAISE(pgExc_SDLError, SDL_GetError()); + } + is_renderer_software = !strcmp(r_name, SDL_SOFTWARE_RENDERER); +#else + SDL_RendererInfo r_info; if (SDL_GetRendererInfo(pg_renderer, &r_info) != 0) { return RAISE(pgExc_SDLError, SDL_GetError()); } + is_renderer_software = r_info.flags & SDL_RENDERER_SOFTWARE; +#endif } switch (wm_info.subsystem) { @@ -2583,8 +2642,7 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) } SDL_SetWindowSize(win, w * scale, h * scale); - if (r_info.flags & SDL_RENDERER_SOFTWARE && - wm_info.subsystem == SDL_SYSWM_X11) { + if (is_renderer_software && wm_info.subsystem == SDL_SYSWM_X11) { /* display surface lost? */ SDL_DestroyTexture(pg_texture); SDL_DestroyRenderer(pg_renderer); @@ -2720,8 +2778,7 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) if (result != 0) { return RAISE(pgExc_SDLError, SDL_GetError()); } - if (r_info.flags & SDL_RENDERER_SOFTWARE && - wm_info.subsystem == SDL_SYSWM_X11) { + if (is_renderer_software && wm_info.subsystem == SDL_SYSWM_X11) { if (PyErr_WarnEx( PyExc_Warning, "recreating software renderer in toggle_fullscreen", From c20a3a2a26343ab9994e24a5a4eb526c626d84f7 Mon Sep 17 00:00:00 2001 From: Ankith Date: Sun, 18 May 2025 20:07:44 +0530 Subject: [PATCH 04/11] sdl3(display): handle MessageBox changes --- src_c/display.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src_c/display.c b/src_c/display.c index 9f4e5363b8..0f98c3fd86 100644 --- a/src_c/display.c +++ b/src_c/display.c @@ -718,7 +718,13 @@ pg_ResizeEventWatch(void *userdata, SDL_Event *event) _DisplayState *state; SDL_Window *window; - if (event->type != SDL_WINDOWEVENT) { +#if SDL_VERSION_ATLEAST(3, 0, 0) + if (event->type >= SDL_EVENT_WINDOW_FIRST && + event->type <= SDL_EVENT_WINDOW_LAST) +#else + if (event->type == SDL_WINDOWEVENT) +#endif + { return 0; } @@ -3067,7 +3073,11 @@ pg_message_box(PyObject *self, PyObject *arg, PyObject *kwargs) if (buttons == NULL) { buttons_data = malloc(sizeof(SDL_MessageBoxButtonData)); buttons_data->flags = 0; +#if SDL_VERSION_ATLEAST(3, 0, 0) + buttons_data->buttonID = 0; +#else buttons_data->buttonid = 0; +#endif buttons_data->text = "OK"; msgbox_data.numbuttons = 1; @@ -3141,6 +3151,19 @@ pg_message_box(PyObject *self, PyObject *arg, PyObject *kwargs) } buttons_data[i].text = btn_name; +#if SDL_VERSION_ATLEAST(3, 0, 0) + buttons_data[i].buttonID = (int)i; + buttons_data[i].flags = 0; + if (return_button_index == buttons_data[i].buttonID) { + buttons_data[i].flags |= + SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT; + } + if (escape_button_used && + escape_button_index == buttons_data[i].buttonID) { + buttons_data[i].flags |= + SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT; + } +#else buttons_data[i].buttonid = (int)i; buttons_data[i].flags = 0; if (return_button_index == buttons_data[i].buttonid) { @@ -3152,6 +3175,7 @@ pg_message_box(PyObject *self, PyObject *arg, PyObject *kwargs) buttons_data[i].flags |= SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT; } +#endif } } From 8a34ee3cd0ae255aea2727453b667c5ad10b808f Mon Sep 17 00:00:00 2001 From: Ankith Date: Sun, 18 May 2025 20:11:27 +0530 Subject: [PATCH 05/11] sdl3(display): handle pixelformat/surface changes --- src_c/display.c | 28 +++++++++++++++++++++------- src_c/include/_pygame.h | 6 ++++++ 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src_c/display.c b/src_c/display.c index 0f98c3fd86..3a918b7fdf 100644 --- a/src_c/display.c +++ b/src_c/display.c @@ -335,8 +335,10 @@ pg_vidinfo_getattr(PyObject *self, char *name) info->vfmt->Bshift, info->vfmt->Ashift); } else if (!strcmp(name, "losses")) { - return Py_BuildValue("(iiii)", info->vfmt->Rloss, info->vfmt->Gloss, - info->vfmt->Bloss, info->vfmt->Aloss); + return Py_BuildValue("(iiii)", PG_FORMAT_R_LOSS(info->vfmt), + PG_FORMAT_G_LOSS(info->vfmt), + PG_FORMAT_B_LOSS(info->vfmt), + PG_FORMAT_A_LOSS(info->vfmt)); } else if (!strcmp(name, "current_h")) { return PyLong_FromLong(info->current_h); @@ -382,8 +384,9 @@ pg_vidinfo_str(PyObject *self) PG_FORMAT_BytesPerPixel(info->vfmt), info->vfmt->Rmask, info->vfmt->Gmask, info->vfmt->Bmask, info->vfmt->Amask, info->vfmt->Rshift, info->vfmt->Gshift, info->vfmt->Bshift, - info->vfmt->Ashift, info->vfmt->Rloss, info->vfmt->Gloss, - info->vfmt->Bloss, info->vfmt->Aloss, info->current_w, info->current_h, + info->vfmt->Ashift, PG_FORMAT_R_LOSS(info->vfmt), + PG_FORMAT_G_LOSS(info->vfmt), PG_FORMAT_B_LOSS(info->vfmt), + PG_FORMAT_A_LOSS(info->vfmt), info->current_w, info->current_h, pixel_format_name); } @@ -415,7 +418,7 @@ static pg_VideoInfo * pg_GetVideoInfo(pg_VideoInfo *info) { SDL_DisplayMode mode; - SDL_PixelFormat *tempformat; + PG_PixelFormat *tempformat; Uint32 formatenum; pgSurfaceObject *winsurfobj; SDL_Surface *winsurf; @@ -431,7 +434,12 @@ pg_GetVideoInfo(pg_VideoInfo *info) winsurf = pgSurface_AsSurface(winsurfobj); info->current_w = winsurf->w; info->current_h = winsurf->h; - info->vfmt_data = *(winsurf->format); + PG_PixelFormat *fmt = PG_GetSurfaceFormat(winsurf); + if (!fmt) { + PyErr_SetString(pgExc_SDLError, SDL_GetError()); + return (pg_VideoInfo *)NULL; + } + info->vfmt_data = *fmt; info->vfmt = &info->vfmt_data; } else { @@ -449,7 +457,9 @@ pg_GetVideoInfo(pg_VideoInfo *info) if ((tempformat = SDL_AllocFormat(formatenum))) { info->vfmt_data = *tempformat; info->vfmt = &info->vfmt_data; +#if !SDL_VERSION_ATLEAST(3, 0, 0) SDL_FreeFormat(tempformat); +#endif } else { PyErr_SetString(pgExc_SDLError, SDL_GetError()); @@ -1423,7 +1433,11 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) Py_DECREF(surface); /* ensure window is always black after a set_mode call */ +#if SDL_VERSION_ATLEAST(3, 0, 0) + SDL_FillRect(surf, NULL, SDL_MapSurfaceRGB(surf, 0, 0, 0)); +#else SDL_FillRect(surf, NULL, SDL_MapRGB(surf->format, 0, 0, 0)); +#endif } /*set the window icon*/ @@ -1968,7 +1982,7 @@ pg_set_palette(PyObject *self, PyObject *args) Py_INCREF(surface); surf = pgSurface_AsSurface(surface); - pal = surf->format->palette; + pal = PG_GetSurfacePalette(surf); if (PG_SURF_BytesPerPixel(surf) != 1 || !pal) { Py_DECREF(surface); return RAISE(pgExc_SDLError, "Display mode is not colormapped"); diff --git a/src_c/include/_pygame.h b/src_c/include/_pygame.h index c3bcc5ec55..03f4e8b772 100644 --- a/src_c/include/_pygame.h +++ b/src_c/include/_pygame.h @@ -284,8 +284,14 @@ typedef struct { Uint32 blit_sw_A : 1; Uint32 blit_fill : 1; Uint32 video_mem; +#if PG_SDL3 + /* We cannot use PG_PixelFormat here because it aliases to const */ + SDL_PixelFormatDetails *vfmt; + SDL_PixelFormatDetails vfmt_data; +#else SDL_PixelFormat *vfmt; SDL_PixelFormat vfmt_data; +#endif int current_w; int current_h; } pg_VideoInfo; From 3954e79fec317ead42a01bbfc19d550215427e74 Mon Sep 17 00:00:00 2001 From: Ankith Date: Sun, 18 May 2025 20:17:31 +0530 Subject: [PATCH 06/11] sdl3(display): handle display mode/id changes --- src_c/display.c | 203 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 168 insertions(+), 35 deletions(-) diff --git a/src_c/display.c b/src_c/display.c index 3a918b7fdf..0fc2e52538 100644 --- a/src_c/display.c +++ b/src_c/display.c @@ -417,7 +417,11 @@ pgVidInfo_New(const pg_VideoInfo *i) static pg_VideoInfo * pg_GetVideoInfo(pg_VideoInfo *info) { +#if SDL_VERSION_ATLEAST(3, 0, 0) + const SDL_DisplayMode *mode_ptr; +#else SDL_DisplayMode mode; +#endif PG_PixelFormat *tempformat; Uint32 formatenum; pgSurfaceObject *winsurfobj; @@ -443,11 +447,19 @@ pg_GetVideoInfo(pg_VideoInfo *info) info->vfmt = &info->vfmt_data; } else { +#if SDL_VERSION_ATLEAST(3, 0, 0) + if ((mode_ptr = SDL_GetCurrentDisplayMode(0))) { + info->current_w = mode_ptr->w; + info->current_h = mode_ptr->h; + formatenum = mode_ptr->format; + } +#else if (SDL_GetCurrentDisplayMode(0, &mode) == 0) { info->current_w = mode.w; info->current_h = mode.h; formatenum = mode.format; } +#endif else { info->current_w = -1; info->current_h = -1; @@ -864,6 +876,24 @@ _get_display(SDL_Window *win) int num_displays, i; SDL_Rect display_bounds; SDL_Point mouse_position; +#if SDL_VERSION_ATLEAST(3, 0, 0) + float x, y; + SDL_GetGlobalMouseState(&x, &y); + mouse_position.x = (int)x; + mouse_position.y = (int)y; + SDL_DisplayID *displays = SDL_GetDisplays(&num_displays); + if (displays) { + for (i = 0; i < num_displays; i++) { + if (SDL_GetDisplayBounds(displays[i], &display_bounds) == 0) { + if (SDL_PointInRect(&mouse_position, &display_bounds)) { + display = displays[i]; + break; + } + } + } + SDL_free(displays); + } +#else SDL_GetGlobalMouseState(&mouse_position.x, &mouse_position.y); num_displays = SDL_GetNumVideoDisplays(); @@ -875,6 +905,7 @@ _get_display(SDL_Window *win) } } } +#endif } return display; } @@ -996,19 +1027,28 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) { Uint32 sdl_flags = 0; - SDL_DisplayMode display_mode; - if (SDL_GetDesktopDisplayMode(display, &display_mode) != 0) { +#if SDL_VERSION_ATLEAST(3, 0, 0) + const SDL_DisplayMode *display_mode; + if (!(display_mode = SDL_GetDesktopDisplayMode(display))) { + return RAISE(pgExc_SDLError, SDL_GetError()); + } +#else + SDL_DisplayMode display_mode_local; + SDL_DisplayMode *display_mode = &display_mode_local; + + if (SDL_GetDesktopDisplayMode(display, display_mode) != 0) { return RAISE(pgExc_SDLError, SDL_GetError()); } +#endif if (w == 0 && h == 0 && !(flags & PGS_SCALED)) { /* We are free to choose a resolution in this case, so we can avoid changing the physical resolution. This used to default to the max supported by the monitor, but we can use current desktop resolution without breaking compatibility. */ - w = display_mode.w; - h = display_mode.h; + w = display_mode->w; + h = display_mode->h; zero_size = 1; } @@ -1016,7 +1056,7 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) if (flags & PGS_SCALED) { sdl_flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; } - else if (w == display_mode.w && h == display_mode.h) { + else if (w == display_mode->w && h == display_mode->h) { /* No need to change physical resolution. Borderless fullscreen is preferred when possible */ sdl_flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; @@ -1603,7 +1643,11 @@ pg_mode_ok(PyObject *self, PyObject *args, PyObject *kwds) { SDL_DisplayMode desired, closest; int bpp = 0; +#if SDL_VERSION_ATLEAST(3, 0, 0) + int flags = 0; +#else int flags = SDL_SWSURFACE; +#endif int display_index = 0; char *keywords[] = {"size", "flags", "depth", "display", NULL}; @@ -1615,14 +1659,17 @@ pg_mode_ok(PyObject *self, PyObject *args, PyObject *kwds) &display_index)) { return NULL; } +#if !SDL_VERSION_ATLEAST(3, 0, 0) + /* Display ID is not bounded by number of displays in SDL3 */ if (display_index < 0 || display_index >= SDL_GetNumVideoDisplays()) { return RAISE(PyExc_ValueError, "The display index must be between 0" " and the number of displays."); } + desired.driverdata = 0; +#endif #pragma PG_WARN(Ignoring most flags) - desired.driverdata = 0; desired.refresh_rate = 0; if (bpp == 0) { @@ -1637,7 +1684,14 @@ pg_mode_ok(PyObject *self, PyObject *args, PyObject *kwds) desired.format = SDL_MasksToPixelFormatEnum(bpp, Rmask, Gmask, Bmask, 0); } + +#if SDL_VERSION_ATLEAST(3, 0, 0) + if (!SDL_GetClosestFullscreenDisplayMode(display_index, desired.w, + desired.h, desired.refresh_rate, + 1, &closest)) { +#else if (!SDL_GetClosestDisplayMode(display_index, &desired, &closest)) { +#endif if (flags & PGS_FULLSCREEN) { return PyLong_FromLong((long)0); } @@ -1671,13 +1725,32 @@ pg_list_modes(PyObject *self, PyObject *args, PyObject *kwds) return NULL; } +#if !SDL_VERSION_ATLEAST(3, 0, 0) + /* Display ID is not bounded by number of displays in SDL3 */ if (display_index < 0 || display_index >= SDL_GetNumVideoDisplays()) { return RAISE(PyExc_ValueError, "The display index must be between 0" " and the number of displays."); } +#endif + #pragma PG_WARN(Ignoring flags) +#if SDL_VERSION_ATLEAST(3, 0, 0) + if (bpp == 0) { + const SDL_DisplayMode *curmode; + if (!(curmode = SDL_GetCurrentDisplayMode(display_index))) { + return RAISE(pgExc_SDLError, SDL_GetError()); + } + bpp = SDL_BITSPERPIXEL(curmode->format); + } + + SDL_DisplayMode **modes = + SDL_GetFullscreenDisplayModes(display_index, &nummodes); + if (nummodes < 0) { + return RAISE(pgExc_SDLError, SDL_GetError()); + } +#else if (bpp == 0) { SDL_DisplayMode curmode; if (SDL_GetCurrentDisplayMode(display_index, &curmode)) { @@ -1690,16 +1763,21 @@ pg_list_modes(PyObject *self, PyObject *args, PyObject *kwds) if (nummodes < 0) { return RAISE(pgExc_SDLError, SDL_GetError()); } +#endif if (!(list = PyList_New(0))) { return NULL; } for (i = 0; i < nummodes; i++) { +#if SDL_VERSION_ATLEAST(3, 0, 0) + mode = *modes[i]; +#else if (SDL_GetDisplayMode(display_index, i, &mode) < 0) { Py_DECREF(list); return RAISE(pgExc_SDLError, SDL_GetError()); } +#endif /* use reasonable defaults (cf. SDL_video.c) */ if (!mode.format) { mode.format = SDL_PIXELFORMAT_XRGB8888; @@ -1730,6 +1808,9 @@ pg_list_modes(PyObject *self, PyObject *args, PyObject *kwds) } Py_DECREF(size); } +#if SDL_VERSION_ATLEAST(3, 0, 0) + SDL_free(modes); +#endif return list; } @@ -1800,7 +1881,12 @@ pg_flip(PyObject *self, PyObject *_null) static PyObject * pg_num_displays(PyObject *self, PyObject *_null) { +#if SDL_VERSION_ATLEAST(3, 0, 0) + int ret = -1; + SDL_free(SDL_GetDisplays(&ret)); +#else int ret = SDL_GetNumVideoDisplays(); +#endif if (ret < 0) { return RAISE(pgExc_SDLError, SDL_GetError()); } @@ -2345,15 +2431,21 @@ static PyObject * pg_get_desktop_screen_sizes(PyObject *self, PyObject *_null) { int display_count, i; - SDL_DisplayMode dm; PyObject *result, *size_tuple; VIDEO_INIT_CHECK(); +#if SDL_VERSION_ATLEAST(3, 0, 0) + SDL_DisplayID *displays = SDL_GetDisplays(&display_count); + if (!displays) { + return RAISE(pgExc_SDLError, SDL_GetError()); + } +#else display_count = SDL_GetNumVideoDisplays(); if (display_count < 0) { return RAISE(pgExc_SDLError, SDL_GetError()); } +#endif result = PyList_New(display_count); if (!result) { @@ -2361,12 +2453,21 @@ pg_get_desktop_screen_sizes(PyObject *self, PyObject *_null) } for (i = 0; i < display_count; i++) { - if (SDL_GetDesktopDisplayMode(i, &dm)) { +#if SDL_VERSION_ATLEAST(3, 0, 0) + const SDL_DisplayMode *dm = SDL_GetDesktopDisplayMode(displays[i]); + if (!dm) { Py_DECREF(result); return RAISE(pgExc_SDLError, SDL_GetError()); } - - size_tuple = pg_tuple_couple_from_values_int(dm.w, dm.h); +#else + SDL_DisplayMode dm_local; + SDL_DisplayMode *dm = &dm_local; + if (SDL_GetDesktopDisplayMode(i, dm)) { + Py_DECREF(result); + return RAISE(pgExc_SDLError, SDL_GetError()); + } +#endif + size_tuple = pg_tuple_couple_from_values_int(dm->w, dm->h); if (!size_tuple) { Py_DECREF(result); return NULL; @@ -2374,6 +2475,9 @@ pg_get_desktop_screen_sizes(PyObject *self, PyObject *_null) PyList_SET_ITEM(result, i, size_tuple); } +#if SDL_VERSION_ATLEAST(3, 0, 0) + SDL_free(displays); +#endif return result; } @@ -2467,7 +2571,6 @@ static PyObject * pg_current_refresh_rate(PyObject *self, PyObject *_null) { SDL_Window *win = pg_GetDefaultWindow(); - SDL_DisplayMode mode; int display_index; VIDEO_INIT_CHECK(); @@ -2480,26 +2583,42 @@ pg_current_refresh_rate(PyObject *self, PyObject *_null) return RAISE(pgExc_SDLError, SDL_GetError()); } +#if SDL_VERSION_ATLEAST(3, 0, 0) + const SDL_DisplayMode *mode = SDL_GetCurrentDisplayMode(display_index); + if (!mode) { + return RAISE(pgExc_SDLError, SDL_GetError()); + } + /* TODO: Consider returning a float here in an API breaking release */ + return PyLong_FromLong((long)mode->refresh_rate); +#else + SDL_DisplayMode mode; if (SDL_GetCurrentDisplayMode(display_index, &mode) != 0) { return RAISE(pgExc_SDLError, SDL_GetError()); } return PyLong_FromLong(mode.refresh_rate); +#endif } static PyObject * pg_desktop_refresh_rates(PyObject *self, PyObject *_null) { int display_count, i; - SDL_DisplayMode dm; PyObject *result, *refresh_rate; VIDEO_INIT_CHECK(); +#if SDL_VERSION_ATLEAST(3, 0, 0) + SDL_DisplayID *displays = SDL_GetDisplays(&display_count); + if (!displays) { + return RAISE(pgExc_SDLError, SDL_GetError()); + } +#else display_count = SDL_GetNumVideoDisplays(); if (display_count < 0) { return RAISE(pgExc_SDLError, SDL_GetError()); } +#endif result = PyList_New(display_count); if (!result) { @@ -2507,12 +2626,23 @@ pg_desktop_refresh_rates(PyObject *self, PyObject *_null) } for (i = 0; i < display_count; i++) { - if (SDL_GetDesktopDisplayMode(i, &dm)) { +#if SDL_VERSION_ATLEAST(3, 0, 0) + const SDL_DisplayMode *dm = SDL_GetDesktopDisplayMode(displays[i]); + if (!dm) { Py_DECREF(result); return RAISE(pgExc_SDLError, SDL_GetError()); } +#else + SDL_DisplayMode dm_local; + SDL_DisplayMode *dm = &dm_local; + if (SDL_GetDesktopDisplayMode(i, dm)) { + Py_DECREF(result); + return RAISE(pgExc_SDLError, SDL_GetError()); + } +#endif - refresh_rate = PyLong_FromLong(dm.refresh_rate); + /* TODO: Consider returning a float here in an API breaking release */ + refresh_rate = PyLong_FromLong((long)dm->refresh_rate); if (!refresh_rate) { Py_DECREF(result); return NULL; @@ -2520,6 +2650,9 @@ pg_desktop_refresh_rates(PyObject *self, PyObject *_null) PyList_SET_ITEM(result, i, refresh_rate); } +#if SDL_VERSION_ATLEAST(3, 0, 0) + SDL_free(displays); +#endif return result; } @@ -2529,7 +2662,6 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) SDL_Window *win = pg_GetDefaultWindow(); int result, flags; int window_w, window_h, w, h, window_display, x, y; - SDL_DisplayMode display_mode; pgSurfaceObject *display_surface; _DisplayState *state = DISPLAY_MOD_STATE(self); GL_glViewport_Func p_glViewport = NULL; @@ -2615,10 +2747,19 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) SDL_GetWindowSize(win, &window_w, &window_h); SDL_GetWindowPosition(win, &x, &y); window_display = SDL_GetWindowDisplayIndex(win); - if (SDL_GetDesktopDisplayMode(window_display, &display_mode) != 0) { +#if SDL_VERSION_ATLEAST(3, 0, 0) + const SDL_DisplayMode *display_mode = + SDL_GetDesktopDisplayMode(window_display); + if (!display_mode) { return RAISE(pgExc_SDLError, SDL_GetError()); } - +#else + SDL_DisplayMode dm_local; + SDL_DisplayMode *display_mode = &dm_local; + if (SDL_GetDesktopDisplayMode(window_display, display_mode)) { + return RAISE(pgExc_SDLError, SDL_GetError()); + } +#endif /* if (pg_renderer != NULL) { SDL_RenderGetLogicalSize(pg_renderer, &w, &h); @@ -2695,7 +2836,7 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) ((float)state->toggle_windowed_w) / (float)state->toggle_windowed_h; float window_aspect_ratio = - ((float)display_mode.w) / (float)display_mode.h; + ((float)display_mode->w) / (float)display_mode->h; if (window_aspect_ratio > saved_aspect_ratio) { int width = (int)(state->toggle_windowed_h * @@ -2829,23 +2970,23 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) float saved_aspect_ratio = ((float)state->scaled_gl_w) / (float)state->scaled_gl_h; float window_aspect_ratio = - ((float)display_mode.w) / (float)display_mode.h; + ((float)display_mode->w) / (float)display_mode->h; if (window_aspect_ratio > saved_aspect_ratio) { - int width = (int)(display_mode.h * saved_aspect_ratio); - p_glViewport((display_mode.w - width) / 2, 0, width, - display_mode.h); + int width = (int)(display_mode->h * saved_aspect_ratio); + p_glViewport((display_mode->w - width) / 2, 0, width, + display_mode->h); } else { - p_glViewport(0, 0, display_mode.w, - (int)(display_mode.w / saved_aspect_ratio)); + p_glViewport(0, 0, display_mode->w, + (int)(display_mode->w / saved_aspect_ratio)); } } else { - p_glViewport(0, 0, display_mode.w, display_mode.h); + p_glViewport(0, 0, display_mode->w, display_mode->h); } } - else if (w == display_mode.w && h == display_mode.h) { + else if (w == display_mode->w && h == display_mode->h) { result = SDL_SetWindowFullscreen(win, SDL_WINDOW_FULLSCREEN_DESKTOP); if (result != 0) { @@ -2908,8 +3049,7 @@ pg_display_resize_event(PyObject *self, PyObject *event) int hnew = PyLong_AsLong(PyObject_GetAttrString(event, "h")); SDL_Window *win = pg_GetDefaultWindow(); int flags; - int window_w, window_h, w, h, window_display, result; - SDL_DisplayMode display_mode; + int w, h, result; _DisplayState *state = DISPLAY_MOD_STATE(self); GL_glViewport_Func p_glViewport = NULL; @@ -2925,13 +3065,6 @@ pg_display_resize_event(PyObject *self, PyObject *event) return PyLong_FromLong(-1); } - // could also take the size of the old display surface - SDL_GetWindowSize(win, &window_w, &window_h); - window_display = SDL_GetWindowDisplayIndex(win); - if (SDL_GetDesktopDisplayMode(window_display, &display_mode) != 0) { - return RAISE(pgExc_SDLError, SDL_GetError()); - } - if (state->using_gl) { p_glViewport = (GL_glViewport_Func)SDL_GL_GetProcAddress("glViewport"); SDL_SetWindowSize(win, wnew, hnew); From d1f0e9d9d8c810b7ddddd481cc75eda9dae2f001 Mon Sep 17 00:00:00 2001 From: Ankith Date: Sun, 18 May 2025 20:27:09 +0530 Subject: [PATCH 07/11] sdl3(display): handle event/env api changes --- src_c/display.c | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/src_c/display.c b/src_c/display.c index 0fc2e52538..f2fb28b1fa 100644 --- a/src_c/display.c +++ b/src_c/display.c @@ -239,7 +239,11 @@ pg_display_init(PyObject *self, PyObject *_null) drivername = SDL_getenv("SDL_VIDEODRIVER"); if (drivername && !SDL_strncasecmp("windib", drivername, SDL_strlen(drivername))) { +#if SDL_VERSION_ATLEAST(3, 0, 0) + SDL_setenv_unsafe("SDL_VIDEODRIVER", "windows", 1); +#else SDL_setenv("SDL_VIDEODRIVER", "windows", 1); +#endif } if (!SDL_WasInit(SDL_INIT_VIDEO)) { if (!_pg_mac_display_init()) { @@ -733,7 +737,11 @@ _get_video_window_pos(int *x, int *y, int *center_window) return 0; } +#if SDL_VERSION_ATLEAST(3, 0, 0) +static bool +#else static int SDLCALL +#endif pg_ResizeEventWatch(void *userdata, SDL_Event *event) { SDL_Window *pygame_window; @@ -759,7 +767,11 @@ pg_ResizeEventWatch(void *userdata, SDL_Event *event) } if (state->unscaled_render && pg_renderer != NULL) { +#if SDL_VERSION_ATLEAST(3, 0, 0) + if (event->type == SDL_WINDOWEVENT_SIZE_CHANGED) { +#else if (event->window.event == SDL_WINDOWEVENT_SIZE_CHANGED) { +#endif int w = event->window.data1; int h = event->window.data2; pgSurfaceObject *display_surface = pg_GetDefaultWindowSurface(); @@ -779,10 +791,18 @@ pg_ResizeEventWatch(void *userdata, SDL_Event *event) } if (pg_renderer != NULL) { +#if SDL_VERSION_ATLEAST(3, 0, 0) + if (event->type == SDL_WINDOWEVENT_MAXIMIZED) { +#else if (event->window.event == SDL_WINDOWEVENT_MAXIMIZED) { +#endif SDL_RenderSetIntegerScale(pg_renderer, SDL_FALSE); } +#if SDL_VERSION_ATLEAST(3, 0, 0) + if (event->type == SDL_WINDOWEVENT_RESTORED) { +#else if (event->window.event == SDL_WINDOWEVENT_RESTORED) { +#endif SDL_RenderSetIntegerScale( pg_renderer, !(SDL_GetHintBoolean( "SDL_HINT_RENDER_SCALE_QUALITY", SDL_FALSE))); @@ -791,7 +811,11 @@ pg_ResizeEventWatch(void *userdata, SDL_Event *event) } if (state->using_gl) { +#if SDL_VERSION_ATLEAST(3, 0, 0) + if (event->type == SDL_WINDOWEVENT_SIZE_CHANGED) { +#else if (event->window.event == SDL_WINDOWEVENT_SIZE_CHANGED) { +#endif GL_glViewport_Func p_glViewport = (GL_glViewport_Func)SDL_GL_GetProcAddress("glViewport"); int wnew = event->window.data1; @@ -817,7 +841,11 @@ pg_ResizeEventWatch(void *userdata, SDL_Event *event) return 0; } +#if SDL_VERSION_ATLEAST(3, 0, 0) + if (event->type == SDL_WINDOWEVENT_SIZE_CHANGED) { +#else if (event->window.event == SDL_WINDOWEVENT_SIZE_CHANGED) { +#endif SDL_Surface *sdl_surface = SDL_GetWindowSurface(window); pgSurfaceObject *old_surface = pg_GetDefaultWindowSurface(); if (sdl_surface != old_surface->surf) { @@ -853,7 +881,7 @@ pg_display_set_autoresize(PyObject *self, PyObject *arg) int _get_display(SDL_Window *win) { - char *display_env = SDL_getenv("PYGAME_DISPLAY"); + const char *display_env = SDL_getenv("PYGAME_DISPLAY"); int display = 0; /* default display 0 */ if (win != NULL) { @@ -932,7 +960,7 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) screen as the old one */ int display = _get_display(win); char *title = state->title; - char *scale_env, *winid_env; + const char *scale_env, *winid_env; SDL_SysWMinfo wm_info; SDL_VERSION(&wm_info.version); From a95dd7149073e7adc3e44eb80495313173daef83 Mon Sep 17 00:00:00 2001 From: Ankith Date: Sun, 18 May 2025 20:31:32 +0530 Subject: [PATCH 08/11] sdl3(display): handle renderer API changes --- src_c/display.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 78 insertions(+), 2 deletions(-) diff --git a/src_c/display.c b/src_c/display.c index f2fb28b1fa..ee9137929d 100644 --- a/src_c/display.c +++ b/src_c/display.c @@ -737,6 +737,25 @@ _get_video_window_pos(int *x, int *y, int *center_window) return 0; } +static inline int +PG_RenderSetIntegerScale(SDL_Renderer *renderer, int enable) +{ +#if SDL_VERSION_ATLEAST(3, 0, 0) + int w = 0, h = 0; + if (!SDL_GetRenderLogicalPresentation(renderer, &w, &h, NULL)) { + return -1; + } + return SDL_SetRenderLogicalPresentation( + renderer, w, h, + enable ? SDL_LOGICAL_PRESENTATION_INTEGER_SCALE + : SDL_LOGICAL_PRESENTATION_LETTERBOX) + ? 0 + : -1; +#else + return SDL_RenderSetIntegerScale(renderer, enable); +#endif +} + #if SDL_VERSION_ATLEAST(3, 0, 0) static bool #else @@ -796,14 +815,14 @@ pg_ResizeEventWatch(void *userdata, SDL_Event *event) #else if (event->window.event == SDL_WINDOWEVENT_MAXIMIZED) { #endif - SDL_RenderSetIntegerScale(pg_renderer, SDL_FALSE); + PG_RenderSetIntegerScale(pg_renderer, SDL_FALSE); } #if SDL_VERSION_ATLEAST(3, 0, 0) if (event->type == SDL_WINDOWEVENT_RESTORED) { #else if (event->window.event == SDL_WINDOWEVENT_RESTORED) { #endif - SDL_RenderSetIntegerScale( + PG_RenderSetIntegerScale( pg_renderer, !(SDL_GetHintBoolean( "SDL_HINT_RENDER_SCALE_QUALITY", SDL_FALSE))); } @@ -981,10 +1000,13 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) if (scale_env != NULL) { flags |= PGS_SCALED; + /* TODO: figure out SDL3 equivalent */ +#if !SDL_VERSION_ATLEAST(3, 0, 0) if (strcmp(scale_env, "photo") == 0) { SDL_SetHintWithPriority(SDL_HINT_RENDER_SCALE_QUALITY, "best", SDL_HINT_NORMAL); } +#endif } if (size != NULL) { @@ -1363,8 +1385,12 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) if (flags & PGS_SCALED || state->unscaled_render) { if (pg_renderer == NULL) { +#if !SDL_VERSION_ATLEAST(3, 0, 0) + /* TODO: check if this behaviour is still to be retained + * in SDL3 */ SDL_SetHintWithPriority(SDL_HINT_RENDER_SCALE_QUALITY, "nearest", SDL_HINT_DEFAULT); +#endif #if SDL_VERSION_ATLEAST(2, 28, 0) /* If the window has a surface associated with it already, @@ -1375,6 +1401,12 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) } #endif +#if SDL_VERSION_ATLEAST(3, 0, 0) + pg_renderer = SDL_CreateRenderer(win, NULL); + if (vsync && pg_renderer) { + SDL_SetRenderVSync(pg_renderer, 1); + } +#else if (vsync) { pg_renderer = SDL_CreateRenderer( win, -1, SDL_RENDERER_PRESENTVSYNC); @@ -1382,6 +1414,7 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) else { pg_renderer = SDL_CreateRenderer(win, -1, 0); } +#endif if (pg_renderer == NULL) { return RAISE(pgExc_SDLError, SDL_GetError()); @@ -1391,12 +1424,24 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) /* use whole screen with uneven pixels on fullscreen, exact scale otherwise. we chose the window size for this to work */ +#if SDL_VERSION_ATLEAST(3, 0, 0) + int enable_intscale = + !(flags & PGS_FULLSCREEN || + SDL_GetHintBoolean( + "SDL_HINT_RENDER_SCALE_QUALITY", SDL_FALSE)); + SDL_SetRenderLogicalPresentation( + pg_renderer, w, h, + enable_intscale + ? SDL_LOGICAL_PRESENTATION_INTEGER_SCALE + : SDL_LOGICAL_PRESENTATION_LETTERBOX); +#else SDL_RenderSetIntegerScale( pg_renderer, !(flags & PGS_FULLSCREEN || SDL_GetHintBoolean( "SDL_HINT_RENDER_SCALE_QUALITY", SDL_FALSE))); SDL_RenderSetLogicalSize(pg_renderer, w, h); +#endif /* this must be called after creating the renderer!*/ SDL_SetWindowMinimumSize(win, w, h); } @@ -2835,18 +2880,31 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) /* display surface lost? */ SDL_DestroyTexture(pg_texture); SDL_DestroyRenderer(pg_renderer); +#if SDL_VERSION_ATLEAST(3, 0, 0) + pg_renderer = SDL_CreateRenderer(win, SDL_SOFTWARE_RENDERER); +#else pg_renderer = SDL_CreateRenderer(win, -1, SDL_RENDERER_SOFTWARE); +#endif pg_texture = SDL_CreateTexture(pg_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, w, h); } +#if SDL_VERSION_ATLEAST(3, 0, 0) + int enable_intscale = !SDL_GetHintBoolean( + "SDL_HINT_RENDER_SCALE_QUALITY", SDL_FALSE); + SDL_SetRenderLogicalPresentation( + pg_renderer, w, h, + enable_intscale ? SDL_LOGICAL_PRESENTATION_INTEGER_SCALE + : SDL_LOGICAL_PRESENTATION_LETTERBOX); +#else SDL_RenderSetLogicalSize(pg_renderer, w, h); /* use exact integer scale in windowed mode */ SDL_RenderSetIntegerScale( pg_renderer, !SDL_GetHintBoolean( "SDL_HINT_RENDER_SCALE_QUALITY", SDL_FALSE)); +#endif SDL_SetWindowMinimumSize(win, w, h); } else if (state->using_gl) { @@ -2977,15 +3035,24 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) /* display surface lost? only on x11? */ SDL_DestroyTexture(pg_texture); SDL_DestroyRenderer(pg_renderer); +#if SDL_VERSION_ATLEAST(3, 0, 0) + pg_renderer = SDL_CreateRenderer(win, SDL_SOFTWARE_RENDERER); +#else pg_renderer = SDL_CreateRenderer(win, -1, SDL_RENDERER_SOFTWARE); +#endif pg_texture = SDL_CreateTexture(pg_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, w, h); } +#if SDL_VERSION_ATLEAST(3, 0, 0) + SDL_SetRenderLogicalPresentation( + pg_renderer, w, h, SDL_LOGICAL_PRESENTATION_LETTERBOX); +#else SDL_RenderSetLogicalSize(pg_renderer, w, h); SDL_RenderSetIntegerScale(pg_renderer, SDL_FALSE); +#endif } else if (state->using_gl) { result = @@ -3115,9 +3182,18 @@ pg_display_resize_event(PyObject *self, PyObject *event) } } else if (pg_renderer != NULL) { + /* TODO: verify why this block exists and whether SDL3 port is + * equivalent */ +#if SDL_VERSION_ATLEAST(3, 0, 0) + SDL_RendererLogicalPresentation mode; + SDL_GetRenderLogicalPresentation(pg_renderer, &w, &h, &mode); + SDL_SetWindowSize(win, (w > wnew) ? w : wnew, (h > hnew) ? h : hnew); + result = SDL_SetRenderLogicalPresentation(pg_renderer, w, h, mode); +#else SDL_RenderGetLogicalSize(pg_renderer, &w, &h); SDL_SetWindowSize(win, (w > wnew) ? w : wnew, (h > hnew) ? h : hnew); result = SDL_RenderSetLogicalSize(pg_renderer, w, h); +#endif if (result != 0) { return RAISE(pgExc_SDLError, SDL_GetError()); } From 68d1ae79858c8a0044020300847576d8e6d259e2 Mon Sep 17 00:00:00 2001 From: Ankith Date: Sun, 18 May 2025 21:27:18 +0530 Subject: [PATCH 09/11] sdl3(display): syswm porting --- src_c/display.c | 204 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 192 insertions(+), 12 deletions(-) diff --git a/src_c/display.c b/src_c/display.c index ee9137929d..fdc7baec9e 100644 --- a/src_c/display.c +++ b/src_c/display.c @@ -31,7 +31,9 @@ #include "doc/display_doc.h" +#ifndef PG_SDL3 #include +#endif static PyTypeObject pgVidInfo_Type; @@ -499,12 +501,14 @@ pg_get_wm_info(PyObject *self, PyObject *_null) { PyObject *dict; PyObject *tmp; - SDL_SysWMinfo info; SDL_Window *win; VIDEO_INIT_CHECK(); +#if !SDL_VERSION_ATLEAST(3, 0, 0) + SDL_SysWMinfo info; SDL_VERSION(&(info.version)) +#endif dict = PyDict_New(); if (!dict) { return NULL; @@ -514,12 +518,32 @@ pg_get_wm_info(PyObject *self, PyObject *_null) if (!win) { return dict; } +#if !SDL_VERSION_ATLEAST(3, 0, 0) if (!SDL_GetWindowWMInfo(win, &info)) { return dict; } +#endif (void)tmp; #if defined(SDL_VIDEO_DRIVER_WINDOWS) +#if SDL_VERSION_ATLEAST(3, 0, 0) + tmp = PyLong_FromLongLong((long long)SDL_GetPointerProperty( + SDL_GetWindowProperties(win), SDL_PROP_WINDOW_WIN32_HWND_POINTER, + NULL)); + PyDict_SetItemString(dict, "window", tmp); + Py_DECREF(tmp); + + tmp = PyLong_FromLongLong((long long)SDL_GetPointerProperty( + SDL_GetWindowProperties(win), SDL_PROP_WINDOW_WIN32_HDC_POINTER, + NULL)); + PyDict_SetItemString(dict, "hdc", tmp); + Py_DECREF(tmp); + tmp = PyLong_FromLongLong((long long)SDL_GetPointerProperty( + SDL_GetWindowProperties(win), SDL_PROP_WINDOW_WIN32_INSTANCE_POINTER, + NULL)); + PyDict_SetItemString(dict, "hinstance", tmp); + Py_DECREF(tmp); +#else tmp = PyLong_FromLongLong((long long)info.info.win.window); PyDict_SetItemString(dict, "window", tmp); Py_DECREF(tmp); @@ -531,12 +555,26 @@ pg_get_wm_info(PyObject *self, PyObject *_null) PyDict_SetItemString(dict, "hinstance", tmp); Py_DECREF(tmp); #endif -#if defined(SDL_VIDEO_DRIVER_WINRT) +#endif +#if defined(SDL_VIDEO_DRIVER_WINRT) && !SDL_VERSION_ATLEAST(3, 0, 0) tmp = PyCapsule_New(info.info.winrt.window, "window", NULL); PyDict_SetItemString(dict, "window", tmp); Py_DECREF(tmp); #endif #if defined(SDL_VIDEO_DRIVER_X11) +#if SDL_VERSION_ATLEAST(3, 0, 0) + tmp = PyLong_FromLong(SDL_GetNumberProperty( + SDL_GetWindowProperties(win), SDL_PROP_WINDOW_X11_WINDOW_NUMBER, 0)); + PyDict_SetItemString(dict, "window", tmp); + Py_DECREF(tmp); + + tmp = PyCapsule_New( + SDL_GetPointerProperty(SDL_GetWindowProperties(win), + SDL_PROP_WINDOW_X11_DISPLAY_POINTER, NULL), + "display", NULL); + PyDict_SetItemString(dict, "display", tmp); + Py_DECREF(tmp); +#else tmp = PyLong_FromLong(info.info.x11.window); PyDict_SetItemString(dict, "window", tmp); Py_DECREF(tmp); @@ -545,7 +583,8 @@ pg_get_wm_info(PyObject *self, PyObject *_null) PyDict_SetItemString(dict, "display", tmp); Py_DECREF(tmp); #endif -#if defined(SDL_VIDEO_DRIVER_DIRECTFB) +#endif +#if defined(SDL_VIDEO_DRIVER_DIRECTFB) && !SDL_VERSION_ATLEAST(3, 0, 0) tmp = PyCapsule_New(info.info.dfb.dfb, "dfb", NULL); PyDict_SetItemString(dict, "dfb", tmp); Py_DECREF(tmp); @@ -559,11 +598,46 @@ pg_get_wm_info(PyObject *self, PyObject *_null) Py_DECREF(tmp); #endif #if defined(SDL_VIDEO_DRIVER_COCOA) +#if SDL_VERSION_ATLEAST(3, 0, 0) + tmp = PyCapsule_New( + SDL_GetPointerProperty(SDL_GetWindowProperties(win), + SDL_PROP_WINDOW_COCOA_WINDOW_POINTER, NULL), + "window", NULL); + PyDict_SetItemString(dict, "window", tmp); + Py_DECREF(tmp); +#else tmp = PyCapsule_New(info.info.cocoa.window, "window", NULL); PyDict_SetItemString(dict, "window", tmp); Py_DECREF(tmp); #endif +#endif #if defined(SDL_VIDEO_DRIVER_UIKIT) +#if SDL_VERSION_ATLEAST(3, 0, 0) + tmp = PyCapsule_New( + SDL_GetPointerProperty(SDL_GetWindowProperties(win), + SDL_PROP_WINDOW_UIKIT_WINDOW_POINTER, NULL), + "window", NULL); + PyDict_SetItemString(dict, "window", tmp); + Py_DECREF(tmp); + + tmp = PyLong_FromLong(SDL_GetPointerNumber( + SDL_GetWindowProperties(win), + SDL_PROP_WINDOW_UIKIT_OPENGL_FRAMEBUFFER_NUMBER, 0)); + PyDict_SetItemString(dict, "framebuffer", tmp); + Py_DECREF(tmp); + + tmp = PyLong_FromLong(SDL_GetPointerNumber( + SDL_GetWindowProperties(win), + SDL_PROP_WINDOW_UIKIT_OPENGL_RENDERBUFFER_NUMBER, 0)); + PyDict_SetItemString(dict, "colorbuffer", tmp); + Py_DECREF(tmp); + + tmp = PyLong_FromLong(SDL_GetPointerNumber( + SDL_GetWindowProperties(win), + SDL_PROP_WINDOW_UIKIT_OPENGL_RESOLVE_FRAMEBUFFER_NUMBER, 0)); + PyDict_SetItemString(dict, "resolveFramebuffer", tmp); + Py_DECREF(tmp); +#else tmp = PyCapsule_New(info.info.uikit.window, "window", NULL); PyDict_SetItemString(dict, "window", tmp); Py_DECREF(tmp); @@ -580,7 +654,23 @@ pg_get_wm_info(PyObject *self, PyObject *_null) PyDict_SetItemString(dict, "resolveFramebuffer", tmp); Py_DECREF(tmp); #endif +#endif #if defined(SDL_VIDEO_DRIVER_WAYLAND) +#if SDL_VERSION_ATLEAST(3, 0, 0) + tmp = PyCapsule_New( + SDL_GetPointerProperty(SDL_GetWindowProperties(win), + SDL_PROP_WINDOW_WAYLAND_DISPLAY_POINTER, NULL), + "display", NULL); + PyDict_SetItemString(dict, "display", tmp); + Py_DECREF(tmp); + + tmp = PyCapsule_New( + SDL_GetPointerProperty(SDL_GetWindowProperties(win), + SDL_PROP_WINDOW_WAYLAND_SURFACE_POINTER, NULL), + "surface", NULL); + PyDict_SetItemString(dict, "surface", tmp); + Py_DECREF(tmp); +#else tmp = PyCapsule_New(info.info.wl.display, "display", NULL); PyDict_SetItemString(dict, "display", tmp); Py_DECREF(tmp); @@ -593,7 +683,22 @@ pg_get_wm_info(PyObject *self, PyObject *_null) PyDict_SetItemString(dict, "shell_surface", tmp); Py_DECREF(tmp); #endif +#endif #if defined(SDL_VIDEO_DRIVER_ANDROID) +#if SDL_VERSION_ATLEAST(3, 0, 0) + tmp = PyCapsule_New( + SDL_GetPointerProperty(SDL_GetWindowProperties(win), + SDL_PROP_WINDOW_ANDROID_WINDOW_POINTER, NULL), + "window", NULL); + PyDict_SetItemString(dict, "window", tmp); + Py_DECREF(tmp); + + tmp = PyLong_FromLong((long)SDL_GetPointerProperty( + SDL_GetWindowProperties(win), SDL_PROP_WINDOW_ANDROID_SURFACE_POINTER, + NULL)); + PyDict_SetItemString(dict, "surface", tmp); + Py_DECREF(tmp); +#else tmp = PyCapsule_New(info.info.android.window, "window", NULL); PyDict_SetItemString(dict, "window", tmp); Py_DECREF(tmp); @@ -602,7 +707,21 @@ pg_get_wm_info(PyObject *self, PyObject *_null) PyDict_SetItemString(dict, "surface", tmp); Py_DECREF(tmp); #endif +#endif #if defined(SDL_VIDEO_DRIVER_VIVANTE) +#if SDL_VERSION_ATLEAST(3, 0, 0) + tmp = PyLong_FromLong((long)SDL_GetPointerProperty( + SDL_GetWindowProperties(win), SDL_PROP_WINDOW_VIVANTE_DISPLAY_POINTER, + NULL)); + PyDict_SetItemString(dict, "display", tmp); + Py_DECREF(tmp); + + tmp = PyLong_FromLong((long)SDL_GetPointerProperty( + SDL_GetWindowProperties(win), SDL_PROP_WINDOW_VIVANTE_WINDOW_POINTER, + NULL)); + PyDict_SetItemString(dict, "window", tmp); + Py_DECREF(tmp); +#else tmp = PyLong_FromLong((long)info.info.vivante.display); PyDict_SetItemString(dict, "display", tmp); Py_DECREF(tmp); @@ -610,6 +729,7 @@ pg_get_wm_info(PyObject *self, PyObject *_null) tmp = PyLong_FromLong((long)info.info.vivante.window); PyDict_SetItemString(dict, "window", tmp); Py_DECREF(tmp); +#endif #endif return dict; @@ -980,9 +1100,6 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) int display = _get_display(win); char *title = state->title; const char *scale_env, *winid_env; - SDL_SysWMinfo wm_info; - - SDL_VERSION(&wm_info.version); char *keywords[] = {"size", "flags", "depth", "display", "vsync", NULL}; @@ -2729,6 +2846,63 @@ pg_desktop_refresh_rates(PyObject *self, PyObject *_null) return result; } +#if SDL_VERSION_ATLEAST(3, 0, 0) +typedef enum { + SDL_SYSWM_UNKNOWN, + SDL_SYSWM_WINDOWS, + SDL_SYSWM_X11, + SDL_SYSWM_DIRECTFB, + SDL_SYSWM_COCOA, + SDL_SYSWM_UIKIT, + SDL_SYSWM_WAYLAND, + SDL_SYSWM_MIR, /* no longer available, left for API/ABI compatibility. */ + SDL_SYSWM_WINRT, + SDL_SYSWM_ANDROID, + SDL_SYSWM_VIVANTE, + SDL_SYSWM_OS2, + SDL_SYSWM_HAIKU, + SDL_SYSWM_KMSDRM, + SDL_SYSWM_RISCOS +} SDL_SYSWM_TYPE; + +static SDL_SYSWM_TYPE +get_syswm_type() +{ + const char *driver = SDL_GetCurrentVideoDriver(); + if (!driver) { + return SDL_SYSWM_UNKNOWN; + } + + if (strcmp(driver, "android") == 0) { + return SDL_SYSWM_ANDROID; + } + else if (strcmp(driver, "cocoa") == 0) { + return SDL_SYSWM_COCOA; + } + else if (strcmp(driver, "kmsdrm") == 0) { + return SDL_SYSWM_KMSDRM; + } + else if (strcmp(driver, "uikit") == 0) { + return SDL_SYSWM_UIKIT; + } + else if (strcmp(driver, "vivante") == 0) { + return SDL_SYSWM_VIVANTE; + } + else if (strcmp(driver, "wayland") == 0) { + return SDL_SYSWM_WAYLAND; + } + else if (strcmp(driver, "windows") == 0) { + return SDL_SYSWM_WINDOWS; + } + else if (strcmp(driver, "x11") == 0) { + return SDL_SYSWM_X11; + } + else { + return SDL_SYSWM_UNKNOWN; + } +} +#endif + static PyObject * pg_toggle_fullscreen(PyObject *self, PyObject *_null) { @@ -2738,7 +2912,7 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) pgSurfaceObject *display_surface; _DisplayState *state = DISPLAY_MOD_STATE(self); GL_glViewport_Func p_glViewport = NULL; - SDL_SysWMinfo wm_info; + SDL_SYSWM_TYPE subsystem; int is_renderer_software = 0; VIDEO_INIT_CHECK(); @@ -2748,10 +2922,16 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) flags = SDL_GetWindowFlags(win); +#if SDL_VERSION_ATLEAST(3, 0, 0) + subsystem = get_syswm_type(); +#else + SDL_SysWMinfo wm_info; SDL_VERSION(&wm_info.version); if (!SDL_GetWindowWMInfo(win, &wm_info)) { return RAISE(pgExc_SDLError, SDL_GetError()); } + subsystem = wm_info.subsystem; +#endif if (state->using_gl && pg_renderer != NULL) { return RAISE(pgExc_SDLError, @@ -2774,7 +2954,7 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) #endif } - switch (wm_info.subsystem) { + switch (subsystem) { // if we get this to work correctly with more systems, move them here case SDL_SYSWM_WINDOWS: case SDL_SYSWM_X11: @@ -2876,7 +3056,7 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) } SDL_SetWindowSize(win, w * scale, h * scale); - if (is_renderer_software && wm_info.subsystem == SDL_SYSWM_X11) { + if (is_renderer_software && subsystem == SDL_SYSWM_X11) { /* display surface lost? */ SDL_DestroyTexture(pg_texture); SDL_DestroyRenderer(pg_renderer); @@ -2950,7 +3130,7 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) } display_surface->surf = SDL_GetWindowSurface(win); } - else if (wm_info.subsystem == SDL_SYSWM_X11) { + else if (subsystem == SDL_SYSWM_X11) { /* This is a HACK, specifically to work around faulty behaviour of * SDL_SetWindowFullscreen on X11 when switching out of fullscreen * would change the physical resolution of the display back to the @@ -3025,7 +3205,7 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) if (result != 0) { return RAISE(pgExc_SDLError, SDL_GetError()); } - if (is_renderer_software && wm_info.subsystem == SDL_SYSWM_X11) { + if (is_renderer_software && subsystem == SDL_SYSWM_X11) { if (PyErr_WarnEx( PyExc_Warning, "recreating software renderer in toggle_fullscreen", @@ -3089,7 +3269,7 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) } display_surface->surf = SDL_GetWindowSurface(win); } - else if (wm_info.subsystem == SDL_SYSWM_WAYLAND) { + else if (subsystem == SDL_SYSWM_WAYLAND) { /* This only happens AFTER other options have been exhausted. * with GL, Renderer, or the correct window size, toggling works. * Only entering a hard fullscreen state is unsupported. */ From 71dbbe68d315be96e5e1e4c7e8584f360a2493f1 Mon Sep 17 00:00:00 2001 From: Ankith Date: Sun, 18 May 2025 22:50:28 +0530 Subject: [PATCH 10/11] sdl3(display): handle window API changes --- src_c/display.c | 171 ++++++++++++++++++++++++++++++++++++++++++++++-- src_c/window.c | 4 ++ 2 files changed, 168 insertions(+), 7 deletions(-) diff --git a/src_c/display.c b/src_c/display.c index fdc7baec9e..4d50eb1c8b 100644 --- a/src_c/display.c +++ b/src_c/display.c @@ -279,9 +279,15 @@ pg_get_init(PyObject *self, PyObject *_null) static PyObject * pg_get_active(PyObject *self, PyObject *_null) { - Uint32 flags = SDL_GetWindowFlags(pg_GetDefaultWindow()); + SDL_WindowFlags flags = SDL_GetWindowFlags(pg_GetDefaultWindow()); + +#if SDL_VERSION_ATLEAST(3, 0, 0) + return PyBool_FromLong(!(flags & SDL_WINDOW_HIDDEN) && + !(flags & SDL_WINDOW_MINIMIZED)); +#else return PyBool_FromLong((flags & SDL_WINDOW_SHOWN) && !(flags & SDL_WINDOW_MINIMIZED)); +#endif } /* vidinfo object */ @@ -1077,6 +1083,82 @@ _get_display(SDL_Window *win) return display; } +/* Based on code from sdl2-compat */ +static SDL_Window * +PG_CreateWindowCompat(const char *title, int x, int y, int w, int h, + SDL_WindowFlags flags) +{ +#if SDL_VERSION_ATLEAST(3, 0, 0) + SDL_Window *window = NULL; + + SDL_PropertiesID props = SDL_CreateProperties(); + if (!props) { + return NULL; + } + + if (title && *title) { + SDL_SetStringProperty(props, SDL_PROP_WINDOW_CREATE_TITLE_STRING, + title); + } + SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_X_NUMBER, x); + SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_Y_NUMBER, y); + SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER, w); + SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, h); + SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_FLAGS_NUMBER, flags); + SDL_SetBooleanProperty( + props, SDL_PROP_WINDOW_CREATE_EXTERNAL_GRAPHICS_CONTEXT_BOOLEAN, + SDL_GetHintBoolean("SDL_VIDEO_EXTERNAL_CONTEXT", false)); + + window = SDL_CreateWindowWithProperties(props); + SDL_DestroyProperties(props); + return window; +#else + return SDL_CreateWindow(title, x, y, w, h, flags); +#endif +} + +#if SDL_VERSION_ATLEAST(3, 0, 0) +/* Returns 0 on success, negative on failure. */ +static int +PG_SetWindowFullscreen(SDL_Window *window, bool fullscreen, + bool non_desktop_fullscreen) +{ + int ret = -1; + SDL_DisplayMode **modes = NULL; + SDL_DisplayMode *chosen_mode = NULL; + if (!SDL_SetWindowFullscreen(window, fullscreen)) { + goto end; + } + if (fullscreen) { + if (non_desktop_fullscreen) { + /* if not desktop fullscreen, get the first display mode available + */ + SDL_DisplayID disp = SDL_GetDisplayForWindow(window); + if (!disp) { + goto end; + } + modes = SDL_GetFullscreenDisplayModes(disp, NULL); + if (!modes) { + goto end; + } + chosen_mode = modes[0]; + if (!chosen_mode) { + SDL_SetError("Could not get fullscreen display mode"); + goto end; + } + } + if (!SDL_SetWindowFullscreenMode(window, chosen_mode)) { + goto end; + } + } + + ret = 0; +end: + SDL_free(modes); + return ret; +} +#endif + static PyObject * pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) { @@ -1100,6 +1182,9 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) int display = _get_display(win); char *title = state->title; const char *scale_env, *winid_env; +#if SDL_VERSION_ATLEAST(3, 0, 0) + int non_desktop_fullscreen = 0; +#endif char *keywords[] = {"size", "flags", "depth", "display", "vsync", NULL}; @@ -1221,12 +1306,22 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) if (flags & PGS_FULLSCREEN) { if (flags & PGS_SCALED) { +#if SDL_VERSION_ATLEAST(3, 0, 0) + sdl_flags |= SDL_WINDOW_FULLSCREEN; + non_desktop_fullscreen = 1; +#else sdl_flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; +#endif } else if (w == display_mode->w && h == display_mode->h) { /* No need to change physical resolution. Borderless fullscreen is preferred when possible */ +#if SDL_VERSION_ATLEAST(3, 0, 0) + sdl_flags |= SDL_WINDOW_FULLSCREEN; + non_desktop_fullscreen = 1; +#else sdl_flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; +#endif } else { sdl_flags |= SDL_WINDOW_FULLSCREEN; @@ -1252,15 +1347,19 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) SDL_AddEventWatch(pg_ResizeEventWatch, self); } } +#if !SDL_VERSION_ATLEAST(3, 0, 0) if (flags & PGS_SHOWN) { sdl_flags |= SDL_WINDOW_SHOWN; } +#endif if (flags & PGS_HIDDEN) { sdl_flags |= SDL_WINDOW_HIDDEN; } +#if !SDL_VERSION_ATLEAST(3, 0, 0) if (!(sdl_flags & SDL_WINDOW_HIDDEN)) { sdl_flags |= SDL_WINDOW_SHOWN; } +#endif if (flags & PGS_OPENGL) { /* Must be called before creating context */ if (flags & PGS_DOUBLEBUF) { @@ -1289,9 +1388,14 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) if (win) { if (SDL_GetWindowDisplayIndex(win) == display) { // fullscreen windows don't hold window x and y as needed + +#if SDL_VERSION_ATLEAST(3, 0, 0) + if (SDL_GetWindowFlags(win) & SDL_WINDOW_FULLSCREEN) { +#else if (SDL_GetWindowFlags(win) & (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_FULLSCREEN_DESKTOP)) { +#endif x = state->fullscreen_backup_x; y = state->fullscreen_backup_y; @@ -1380,8 +1484,12 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) // SDL doesn't preserve window position in fullscreen mode // However, windows coming out of fullscreen need these to go back // into the correct position +#if SDL_VERSION_ATLEAST(3, 0, 0) + if (sdl_flags & SDL_WINDOW_FULLSCREEN) { +#else if (sdl_flags & (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_FULLSCREEN_DESKTOP)) { +#endif state->fullscreen_backup_x = x; state->fullscreen_backup_y = y; } @@ -1389,10 +1497,14 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) if (!win) { /*open window*/ if (hwnd != 0) { +/* TODO: figure SDL3 equivalent */ +#if !SDL_VERSION_ATLEAST(3, 0, 0) win = SDL_CreateWindowFrom((void *)hwnd); +#endif } else { - win = SDL_CreateWindow(title, x, y, w_1, h_1, sdl_flags); + win = PG_CreateWindowCompat(title, x, y, w_1, h_1, + sdl_flags); w_actual = w_1; h_actual = h_1; } @@ -1417,12 +1529,20 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) * resize/bordered/hidden changes due to SDL ignoring those * 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)) { + return RAISE(pgExc_SDLError, SDL_GetError()); + } +#else if (0 != SDL_SetWindowFullscreen( win, sdl_flags & (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_FULLSCREEN_DESKTOP))) { return RAISE(pgExc_SDLError, SDL_GetError()); } +#endif SDL_SetWindowResizable(win, flags & PGS_RESIZABLE); SDL_SetWindowBordered(win, (flags & PGS_NOFRAME) == 0); @@ -1713,7 +1833,11 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) !vsync && (((flags & PGS_RESIZABLE) == 0) || !zero_size)) { if (((surface->surf->w != w_actual) || (surface->surf->h != h_actual)) && +#if SDL_VERSION_ATLEAST(3, 0, 0) + ((surface->surf->flags & SDL_WINDOW_FULLSCREEN) != 0)) { +#else ((surface->surf->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != 0)) { +#endif char buffer[150]; char *format_string = "Requested window was forcibly resized by the OS.\n\t" @@ -2675,14 +2799,18 @@ static PyObject * pg_is_fullscreen(PyObject *self, PyObject *_null) { SDL_Window *win = pg_GetDefaultWindow(); - int flags; + SDL_WindowFlags flags; VIDEO_INIT_CHECK(); if (!win) { return RAISE(pgExc_SDLError, "No open window"); } +#if SDL_VERSION_ATLEAST(3, 0, 0) + flags = SDL_GetWindowFlags(win); +#else flags = SDL_GetWindowFlags(win) & SDL_WINDOW_FULLSCREEN_DESKTOP; +#endif if (flags & SDL_WINDOW_FULLSCREEN) { Py_RETURN_TRUE; @@ -2907,7 +3035,8 @@ static PyObject * pg_toggle_fullscreen(PyObject *self, PyObject *_null) { SDL_Window *win = pg_GetDefaultWindow(); - int result, flags; + int result; + SDL_WindowFlags flags; int window_w, window_h, w, h, window_display, x, y; pgSurfaceObject *display_surface; _DisplayState *state = DISPLAY_MOD_STATE(self); @@ -3122,8 +3251,12 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) } } } +#if SDL_VERSION_ATLEAST(3, 0, 0) + else if ((flags & SDL_WINDOW_FULLSCREEN) == SDL_WINDOW_FULLSCREEN) { +#else else if ((flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP) { +#endif result = SDL_SetWindowFullscreen(win, 0); if (result != 0) { return RAISE(pgExc_SDLError, SDL_GetError()); @@ -3144,9 +3277,13 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) 1) != 0) { return NULL; } +#if SDL_VERSION_ATLEAST(3, 0, 0) + flags &= ~SDL_WINDOW_FULLSCREEN; +#else flags &= ~SDL_WINDOW_FULLSCREEN_DESKTOP; +#endif /* SDL_WINDOW_FULLSCREEN_DESKTOP includes SDL_WINDOW_FULLSCREEN */ - win = SDL_CreateWindow(state->title, wx, wy, w, h, flags); + win = PG_CreateWindowCompat(state->title, wx, wy, w, h, flags); if (win == NULL) { return RAISE(pgExc_SDLError, SDL_GetError()); } @@ -3193,15 +3330,23 @@ 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) { 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) { return RAISE(pgExc_SDLError, SDL_GetError()); } @@ -3235,8 +3380,12 @@ 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) { return RAISE(pgExc_SDLError, SDL_GetError()); } @@ -3262,8 +3411,12 @@ 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) { return RAISE(pgExc_SDLError, SDL_GetError()); } @@ -3290,7 +3443,7 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) h != display_surface->surf->h) { int wx = SDL_WINDOWPOS_UNDEFINED_DISPLAY(window_display); int wy = SDL_WINDOWPOS_UNDEFINED_DISPLAY(window_display); - win = SDL_CreateWindow(state->title, wx, wy, w, h, flags); + win = PG_CreateWindowCompat(state->title, wx, wy, w, h, flags); if (win == NULL) { return RAISE(pgExc_SDLError, SDL_GetError()); } @@ -3323,7 +3476,7 @@ pg_display_resize_event(PyObject *self, PyObject *event) int wnew = PyLong_AsLong(PyObject_GetAttrString(event, "w")); int hnew = PyLong_AsLong(PyObject_GetAttrString(event, "h")); SDL_Window *win = pg_GetDefaultWindow(); - int flags; + SDL_WindowFlags flags; int w, h, result; _DisplayState *state = DISPLAY_MOD_STATE(self); GL_glViewport_Func p_glViewport = NULL; @@ -3332,10 +3485,14 @@ pg_display_resize_event(PyObject *self, PyObject *event) if (!win) { return RAISE(pgExc_SDLError, "No open window"); } +#if SDL_VERSION_ATLEAST(3, 0, 0) + flags = SDL_GetWindowFlags(win) & SDL_WINDOW_FULLSCREEN; +#else flags = SDL_GetWindowFlags(win) & (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_FULLSCREEN_DESKTOP); +#endif if (flags) { return PyLong_FromLong(-1); } diff --git a/src_c/window.c b/src_c/window.c index 594c0321d2..702c47c375 100644 --- a/src_c/window.c +++ b/src_c/window.c @@ -331,6 +331,10 @@ pg_window_set_fullscreen(SDL_Window *window, int desktop) goto end; } } + + if (!SDL_SetWindowFullscreen(window, 1)) { + goto end; + } if (!SDL_SetWindowFullscreenMode(window, chosen_mode)) { goto end; } From 1ab8b9766fb9bc9e3cedcae1ecdad472e43827c2 Mon Sep 17 00:00:00 2001 From: Ankith Date: Sun, 18 May 2025 23:21:37 +0530 Subject: [PATCH 11/11] sdl3(display): start compiling --- src_c/meson.build | 3 --- 1 file changed, 3 deletions(-) diff --git a/src_c/meson.build b/src_c/meson.build index 0c1479a812..ff66e90f58 100644 --- a/src_c/meson.build +++ b/src_c/meson.build @@ -27,8 +27,6 @@ constants = py.extension_module( subdir: pg, ) -# TODO: support SDL3 -if sdl_api != 3 display = py.extension_module( 'display', 'display.c', @@ -37,7 +35,6 @@ display = py.extension_module( install: true, subdir: pg, ) -endif event = py.extension_module( 'event',