Tue, 05 Aug 2025 20:00:24 +0200
upgrade to SDL 3
--- a/DEPENDENCIES Tue Aug 05 16:53:25 2025 +0200 +++ b/DEPENDENCIES Tue Aug 05 20:00:24 2025 +0200 @@ -1,3 +1,3 @@ -Fedora: dnf install SDL2-devel SDL2_ttf-devel SDL2_image-devel glew-devel -Arch: pacman -Sy sdl2 sdl2_ttf sdl2_image glew pkgconf -FreeBSD: pkg install sdl2 sdl2_ttf sdl2_image glew pkgconf +Fedora: dnf install SDL3-devel SDL3_ttf-devel SDL3_image-devel glew-devel +Arch: pacman -Sy sdl3 sdl3_ttf sdl3_image glew pkgconf +FreeBSD: pkg install sdl3 sdl3_ttf sdl3_image glew pkgconf
--- a/configure Tue Aug 05 16:53:25 2025 +0200 +++ b/configure Tue Aug 05 20:00:24 2025 +0200 @@ -299,30 +299,6 @@ fi } -dependency_error_sdl2_ttf() -{ - print_check_msg "$dep_checked_sdl2_ttf" "checking for sdl2_ttf... " - # dependency sdl2_ttf - while true - do - if [ -z "$PKG_CONFIG" ]; then - break - fi - if test_pkg_config "SDL2_ttf" "" "" "" ; then - TEMP_CFLAGS="$TEMP_CFLAGS `"$PKG_CONFIG" --cflags SDL2_ttf`" - TEMP_LDFLAGS="$TEMP_LDFLAGS `"$PKG_CONFIG" --libs SDL2_ttf`" - else - break - fi - print_check_msg "$dep_checked_sdl2_ttf" "yes\n" - dep_checked_sdl2_ttf=1 - return 1 - done - - print_check_msg "$dep_checked_sdl2_ttf" "no\n" - dep_checked_sdl2_ttf=1 - return 0 -} dependency_error_asan() { print_check_msg "$dep_checked_asan" "checking for asan... " @@ -343,52 +319,28 @@ dep_checked_asan=1 return 0 } -dependency_error_sdl2() +dependency_error_sdl3_ttf() { - print_check_msg "$dep_checked_sdl2" "checking for sdl2... " - # dependency sdl2 + print_check_msg "$dep_checked_sdl3_ttf" "checking for sdl3_ttf... " + # dependency sdl3_ttf while true do if [ -z "$PKG_CONFIG" ]; then break fi - if test_pkg_config "sdl2" "" "" "" ; then - TEMP_CFLAGS="$TEMP_CFLAGS `"$PKG_CONFIG" --cflags sdl2`" - TEMP_LDFLAGS="$TEMP_LDFLAGS `"$PKG_CONFIG" --libs sdl2`" + if test_pkg_config "sdl3-ttf" "" "" "" ; then + TEMP_CFLAGS="$TEMP_CFLAGS `"$PKG_CONFIG" --cflags sdl3-ttf`" + TEMP_LDFLAGS="$TEMP_LDFLAGS `"$PKG_CONFIG" --libs sdl3-ttf`" else break fi - print_check_msg "$dep_checked_sdl2" "yes\n" - dep_checked_sdl2=1 + print_check_msg "$dep_checked_sdl3_ttf" "yes\n" + dep_checked_sdl3_ttf=1 return 1 done - print_check_msg "$dep_checked_sdl2" "no\n" - dep_checked_sdl2=1 - return 0 -} -dependency_error_sdl2_image() -{ - print_check_msg "$dep_checked_sdl2_image" "checking for sdl2_image... " - # dependency sdl2_image - while true - do - if [ -z "$PKG_CONFIG" ]; then - break - fi - if test_pkg_config "SDL2_image" "" "" "" ; then - TEMP_CFLAGS="$TEMP_CFLAGS `"$PKG_CONFIG" --cflags SDL2_image`" - TEMP_LDFLAGS="$TEMP_LDFLAGS `"$PKG_CONFIG" --libs SDL2_image`" - else - break - fi - print_check_msg "$dep_checked_sdl2_image" "yes\n" - dep_checked_sdl2_image=1 - return 1 - done - - print_check_msg "$dep_checked_sdl2_image" "no\n" - dep_checked_sdl2_image=1 + print_check_msg "$dep_checked_sdl3_ttf" "no\n" + dep_checked_sdl3_ttf=1 return 0 } dependency_error_glew() @@ -415,6 +367,30 @@ dep_checked_glew=1 return 0 } +dependency_error_sdl3_image() +{ + print_check_msg "$dep_checked_sdl3_image" "checking for sdl3_image... " + # dependency sdl3_image + while true + do + if [ -z "$PKG_CONFIG" ]; then + break + fi + if test_pkg_config "sdl3-image" "" "" "" ; then + TEMP_CFLAGS="$TEMP_CFLAGS `"$PKG_CONFIG" --cflags sdl3-image`" + TEMP_LDFLAGS="$TEMP_LDFLAGS `"$PKG_CONFIG" --libs sdl3-image`" + else + break + fi + print_check_msg "$dep_checked_sdl3_image" "yes\n" + dep_checked_sdl3_image=1 + return 1 + done + + print_check_msg "$dep_checked_sdl3_image" "no\n" + dep_checked_sdl3_image=1 + return 0 +} dependency_error_ucx() { print_check_msg "$dep_checked_ucx" "checking for ucx... " @@ -436,6 +412,30 @@ dep_checked_ucx=1 return 0 } +dependency_error_sdl3() +{ + print_check_msg "$dep_checked_sdl3" "checking for sdl3... " + # dependency sdl3 + while true + do + if [ -z "$PKG_CONFIG" ]; then + break + fi + if test_pkg_config "sdl3" "" "" "" ; then + TEMP_CFLAGS="$TEMP_CFLAGS `"$PKG_CONFIG" --cflags sdl3`" + TEMP_LDFLAGS="$TEMP_LDFLAGS `"$PKG_CONFIG" --libs sdl3`" + else + break + fi + print_check_msg "$dep_checked_sdl3" "yes\n" + dep_checked_sdl3=1 + return 1 + done + + print_check_msg "$dep_checked_sdl3" "no\n" + dep_checked_sdl3=1 + return 0 +} # start collecting dependency information echo > "$TEMP_DIR/flags.mk" @@ -505,16 +505,16 @@ DEPENDENCIES_FAILED="$DEPENDENCIES_FAILED ucx " ERROR=1 fi -if dependency_error_sdl2; then - DEPENDENCIES_FAILED="$DEPENDENCIES_FAILED sdl2 " +if dependency_error_sdl3; then + DEPENDENCIES_FAILED="$DEPENDENCIES_FAILED sdl3 " ERROR=1 fi -if dependency_error_sdl2_ttf; then - DEPENDENCIES_FAILED="$DEPENDENCIES_FAILED sdl2_ttf " +if dependency_error_sdl3_ttf; then + DEPENDENCIES_FAILED="$DEPENDENCIES_FAILED sdl3_ttf " ERROR=1 fi -if dependency_error_sdl2_image; then - DEPENDENCIES_FAILED="$DEPENDENCIES_FAILED sdl2_image " +if dependency_error_sdl3_image; then + DEPENDENCIES_FAILED="$DEPENDENCIES_FAILED sdl3_image " ERROR=1 fi if dependency_error_glew; then
--- a/make/project.xml Tue Aug 05 16:53:25 2025 +0200 +++ b/make/project.xml Tue Aug 05 20:00:24 2025 +0200 @@ -14,16 +14,16 @@ <ldflags>-lucx</ldflags> </dependency> - <dependency name="sdl2"> - <pkgconfig>sdl2</pkgconfig> + <dependency name="sdl3"> + <pkgconfig>sdl3</pkgconfig> </dependency> - <dependency name="sdl2_ttf"> - <pkgconfig>SDL2_ttf</pkgconfig> + <dependency name="sdl3_ttf"> + <pkgconfig>sdl3-ttf</pkgconfig> </dependency> - <dependency name="sdl2_image"> - <pkgconfig>SDL2_image</pkgconfig> + <dependency name="sdl3_image"> + <pkgconfig>sdl3-image</pkgconfig> </dependency> <dependency name="glew"> @@ -40,7 +40,7 @@ <desc>Enable address sanitization.</desc> <dependencies>asan</dependencies> </feature> - <dependencies>ucx,sdl2,sdl2_ttf,sdl2_image,glew</dependencies> + <dependencies>ucx,sdl3,sdl3_ttf,sdl3_image,glew</dependencies> </target> </project>
--- a/src/ascension/context.h Tue Aug 05 16:53:25 2025 +0200 +++ b/src/ascension/context.h Tue Aug 05 20:00:24 2025 +0200 @@ -31,13 +31,10 @@ #include "datatypes.h" #include "window.h" #include "input.h" -#include "font.h" #include <cx/buffer.h> #include <cx/string.h> -#include <stdio.h> - /** The flag for the overall initialized state. */ #define ASC_FLAG_INITIALIZED 0x01u
--- a/src/ascension/datatypes.h Tue Aug 05 16:53:25 2025 +0200 +++ b/src/ascension/datatypes.h Tue Aug 05 20:00:24 2025 +0200 @@ -34,8 +34,10 @@ #include <stdbool.h> #include <stdarg.h> +#include <float.h> +#include <math.h> #include <string.h> -#include <SDL2/SDL_pixels.h> +#include <SDL3/SDL_pixels.h> // -------------------------------------------------------------------------- // Useful Macros
--- a/src/ascension/font.h Tue Aug 05 16:53:25 2025 +0200 +++ b/src/ascension/font.h Tue Aug 05 20:00:24 2025 +0200 @@ -28,7 +28,8 @@ #ifndef ASCENSION_FONT_H #define ASCENSION_FONT_H -#include <SDL2/SDL_ttf.h> +// forward declare TTF_font so that we don't need to include the full SDL header here +typedef struct TTF_Font TTF_Font; enum AscFontStyle { ASC_FONT_REGULAR,
--- a/src/ascension/glcontext.h Tue Aug 05 16:53:25 2025 +0200 +++ b/src/ascension/glcontext.h Tue Aug 05 20:00:24 2025 +0200 @@ -28,7 +28,7 @@ #ifndef ASCENSION_GLCONTEXT_H #define ASCENSION_GLCONTEXT_H -#include <SDL2/SDL.h> +#include <SDL3/SDL.h> #include <cx/list.h>
--- a/src/ascension/input.h Tue Aug 05 16:53:25 2025 +0200 +++ b/src/ascension/input.h Tue Aug 05 20:00:24 2025 +0200 @@ -28,7 +28,7 @@ #ifndef ASCENSION_INPUT_H #define ASCENSION_INPUT_H -#include <SDL2/SDL_scancode.h> +#include <SDL3/SDL_scancode.h> typedef struct asc_input_s { /** @@ -59,7 +59,7 @@ * @see asc_key_down() * @see asc_key_up() */ - unsigned char keys[SDL_NUM_SCANCODES]; + unsigned char keys[SDL_SCANCODE_COUNT]; } AscInput; #define ASC_KEY_DOWN_FLAG 1u
--- a/src/ascension/texture.h Tue Aug 05 16:53:25 2025 +0200 +++ b/src/ascension/texture.h Tue Aug 05 20:00:24 2025 +0200 @@ -30,7 +30,7 @@ #include "datatypes.h" -#include <SDL2/SDL_surface.h> +#include <SDL3/SDL_surface.h> typedef struct asc_texture_s { /**
--- a/src/ascension/window.h Tue Aug 05 16:53:25 2025 +0200 +++ b/src/ascension/window.h Tue Aug 05 20:00:24 2025 +0200 @@ -28,7 +28,7 @@ #ifndef ASCENSION_WINDOW_H #define ASCENSION_WINDOW_H -#include <SDL2/SDL.h> +#include <SDL3/SDL.h> #include "datatypes.h" #include "glcontext.h"
--- a/src/context.c Tue Aug 05 16:53:25 2025 +0200 +++ b/src/context.c Tue Aug 05 20:00:24 2025 +0200 @@ -28,9 +28,8 @@ #include "ascension/context.h" #include "ascension/error.h" -#include <SDL2/SDL.h> -#include <SDL2/SDL_ttf.h> -#include <SDL2/SDL_image.h> +#include <SDL3/SDL.h> +#include <SDL3_ttf/SDL_ttf.h> #include <GL/glew.h> @@ -74,13 +73,10 @@ ); // initialize SDL - const int supported_img_flags = IMG_INIT_PNG | IMG_INIT_JPG; - if (SDL_Init(SDL_INIT_VIDEO) < 0) { + if (!SDL_Init(SDL_INIT_VIDEO)) { asc_error("Failed to initialize SDL: %s", SDL_GetError()); - } else if (TTF_Init() < 0) { - asc_error("Failed to initialize SDL_ttf: %s", TTF_GetError()); - } else if (IMG_Init(supported_img_flags) != supported_img_flags) { - asc_error("Failed to initialize SDL_img: %s", IMG_GetError()); + } else if (!TTF_Init()) { + asc_error("Failed to initialize SDL_ttf: %s", SDL_GetError()); } SDL_ClearError(); asc_context.total_nanos = asc_nanos(); @@ -98,7 +94,6 @@ asc_font_cache_destroy(); // quit SDL - IMG_Quit(); TTF_Quit(); SDL_Quit(); @@ -141,7 +136,7 @@ asc_context.input.mouse_yrel = 0; // reset key flags - for (unsigned int i = 0 ; i < SDL_NUM_SCANCODES ; i++) { + for (unsigned int i = 0 ; i < SDL_SCANCODE_COUNT ; i++) { asc_clear_flag(asc_context.input.keys[i], ASC_KEY_RELEASE_FLAG|ASC_KEY_PRESS_FLAG); } @@ -149,26 +144,28 @@ SDL_Event event; while (SDL_PollEvent(&event)) { switch (event.type) { - case SDL_QUIT: + case SDL_EVENT_QUIT: asc_set_flag(asc_context.flags, ASC_FLAG_QUIT); break; - case SDL_WINDOWEVENT: { - if (event.window.event == SDL_WINDOWEVENT_RESIZED) { - asc_event_window_resized( - event.window.windowID, - event.window.data1, - event.window.data2 - ); - } else if (event.window.event == SDL_WINDOWEVENT_FOCUS_GAINED) { - unsigned int idx = asc_window_index(event.window.windowID); - asc_context.windows[idx].focused = true; - } else if (event.window.event == SDL_WINDOWEVENT_FOCUS_LOST) { - unsigned int idx = asc_window_index(event.window.windowID); - asc_context.windows[idx].focused = false; - } + case SDL_EVENT_WINDOW_RESIZED: { + asc_event_window_resized( + event.window.windowID, + event.window.data1, + event.window.data2 + ); break; } - case SDL_MOUSEMOTION: { + case SDL_EVENT_WINDOW_FOCUS_GAINED: { + unsigned int idx = asc_window_index(event.window.windowID); + asc_context.windows[idx].focused = true; + break; + } + case SDL_EVENT_WINDOW_FOCUS_LOST: { + unsigned int idx = asc_window_index(event.window.windowID); + asc_context.windows[idx].focused = false; + break; + } + case SDL_EVENT_MOUSE_MOTION: { // accumulate relative motion asc_context.input.mouse_xrel += event.motion.xrel; asc_context.input.mouse_yrel += event.motion.yrel; @@ -180,15 +177,15 @@ asc_window_index(event.motion.windowID); break; } - case SDL_KEYDOWN: + case SDL_EVENT_KEY_DOWN: // we only set the down and press flags if the key is not already known to be down - if (asc_key_up(event.key.keysym.scancode)) { - asc_context.input.keys[event.key.keysym.scancode] = ASC_KEY_DOWN_FLAG|ASC_KEY_PRESS_FLAG; + if (asc_key_up(event.key.scancode)) { + asc_context.input.keys[event.key.scancode] = ASC_KEY_DOWN_FLAG|ASC_KEY_PRESS_FLAG; } break; - case SDL_KEYUP: + case SDL_EVENT_KEY_UP: // we can directly set the release flag - it will be cleared next round - asc_context.input.keys[event.key.keysym.scancode] = ASC_KEY_RELEASE_FLAG; + asc_context.input.keys[event.key.scancode] = ASC_KEY_RELEASE_FLAG; break; } }
--- a/src/font.c Tue Aug 05 16:53:25 2025 +0200 +++ b/src/font.c Tue Aug 05 20:00:24 2025 +0200 @@ -34,6 +34,8 @@ #include <math.h> #include <cx/array_list.h> +#include <SDL3_ttf/SDL_ttf.h> + static const char *asc_font_filename(enum AscFontStyle style) { switch (style) { case ASC_FONT_REGULAR: @@ -97,7 +99,7 @@ entry.ttf = TTF_OpenFont(fpath.ptr, font.size); cx_strfree(&fpath); if (entry.ttf == NULL) { - asc_error("Failed to load font %s: %s", font_name, TTF_GetError()); + asc_error("Failed to load font %s: %s", font_name, SDL_GetError()); return NULL; } else { cxListAdd(asc_font_cache, &entry);
--- a/src/glcontext.c Tue Aug 05 16:53:25 2025 +0200 +++ b/src/glcontext.c Tue Aug 05 20:00:24 2025 +0200 @@ -109,7 +109,7 @@ return true; } else { asc_error("glewInit failed: %s", glewGetErrorString(err)); - SDL_GL_DeleteContext(ctx->glctx); + SDL_GL_DestroyContext(ctx->glctx); return false; } } @@ -122,7 +122,7 @@ cxListFree(ctx->cleanup_funcs); // destroy the GL context and the window - SDL_GL_DeleteContext(ctx->glctx); + SDL_GL_DestroyContext(ctx->glctx); ctx->glctx = NULL; }
--- a/src/text.c Tue Aug 05 16:53:25 2025 +0200 +++ b/src/text.c Tue Aug 05 20:00:24 2025 +0200 @@ -34,6 +34,8 @@ #include <assert.h> #include <cx/printf.h> +#include <SDL3_ttf/SDL_ttf.h> + typedef struct asc_text_shader_s { AscShaderProgram program; asc_uniform_loc tex; @@ -64,15 +66,16 @@ asc_set_flag(node->flags, ASC_SCENE_NODE_HIDDEN); return; } - static int alignments[] = { - TTF_WRAPPED_ALIGN_LEFT, - TTF_WRAPPED_ALIGN_CENTER, - TTF_WRAPPED_ALIGN_RIGHT + static TTF_HorizontalAlignment alignments[] = { + TTF_HORIZONTAL_ALIGN_LEFT, + TTF_HORIZONTAL_ALIGN_CENTER, + TTF_HORIZONTAL_ALIGN_RIGHT }; - TTF_SetFontWrappedAlign( + TTF_SetFontWrapAlignment( font, alignments[text->base.flags & ASC_TEXT_ALIGNMENT_MASK]); - SDL_Surface *surface = TTF_RenderUTF8_Blended_Wrapped( - font, text->text.ptr, asc_col_sdl(text->color), text->max_width + // TODO: it looks like TTF_RenderText_Blended_Wrapped is broken in SDL 3 + SDL_Surface *surface = TTF_RenderText_Blended( + font, text->text.ptr, text->text.length, asc_col_sdl(text->color)//, text->max_width ); if (surface == NULL) { asc_error("Rendering TTF surface failed: %s", SDL_GetError()); @@ -97,7 +100,7 @@ } // Free the surface - SDL_FreeSurface(surface); + SDL_DestroySurface(surface); // Schedule for transform update asc_scene_node_update_transform(node);
--- a/src/texture.c Tue Aug 05 16:53:25 2025 +0200 +++ b/src/texture.c Tue Aug 05 20:00:24 2025 +0200 @@ -32,7 +32,7 @@ #include <assert.h> #include <GL/glew.h> -#include <SDL2/SDL_image.h> +#include <SDL3_image/SDL_image.h> void asc_texture_bind(const AscTexture *tex, int uniform_location, int unit) { glActiveTexture(GL_TEXTURE0 + unit); @@ -56,13 +56,13 @@ tex->height = surface->h; glBindTexture(tex->target,tex->tex_id); glPixelStorei(GL_UNPACK_ROW_LENGTH, - surface->pitch / surface->format->BytesPerPixel); + surface->pitch / SDL_BYTESPERPIXEL(surface->format)); if (asc_error_catch_gl("Binding texture object")) return; // Determine the format and internal format based on the SDL surface format GLint internal_format; GLenum format; - switch (surface->format->format) { + switch (surface->format) { case SDL_PIXELFORMAT_RGB24: internal_format = GL_RGB8; format = GL_RGB; @@ -82,7 +82,7 @@ format = GL_BGRA; break; default: - asc_error("Unsupported pixel format: %x", surface->format->format); + asc_error("Unsupported pixel format: %x", surface->format); return; } glTexImage2D(tex->target, 0, internal_format, @@ -102,12 +102,12 @@ SDL_Surface *image = IMG_Load(filepath.ptr); cx_strfree(&filepath); if (image == NULL) { - asc_error("Failed to load texture: %s", IMG_GetError()); + asc_error("Failed to load texture: %s", SDL_GetError()); return; } asc_texture_from_surface(tex, image); asc_dprintf("Free temporary surface %"PRIxPTR, (uintptr_t) image); - SDL_FreeSurface(image); + SDL_DestroySurface(image); } void asc_texture_init(
--- a/src/window.c Tue Aug 05 16:53:25 2025 +0200 +++ b/src/window.c Tue Aug 05 20:00:24 2025 +0200 @@ -29,8 +29,10 @@ #include "ascension/window.h" #include "ascension/context.h" +#include <GL/glew.h> + #include <assert.h> -#include <GL/glew.h> +#include <stdio.h> void asc_window_settings_init_defaults(AscWindowSettings *settings) { settings->dimensions.width = 800u; @@ -54,15 +56,13 @@ return; } - Uint32 flags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN; - flags |= settings->fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : SDL_WINDOW_RESIZABLE; + SDL_WindowFlags flags = SDL_WINDOW_OPENGL; + flags |= settings->fullscreen ? SDL_WINDOW_FULLSCREEN : SDL_WINDOW_RESIZABLE; window->window = SDL_CreateWindow( settings->title, - SDL_WINDOWPOS_CENTERED, - SDL_WINDOWPOS_CENTERED, - settings->dimensions.width, - settings->dimensions.height, + (int) settings->dimensions.width, + (int) settings->dimensions.height, flags ); if (window->window == NULL) { @@ -203,13 +203,13 @@ asc_vec2u asc_window_display_resolution(void) { const AscWindow *window = asc_active_window; - SDL_DisplayMode dm; - const int display = SDL_GetWindowDisplayIndex(window->window); - if (SDL_GetDesktopDisplayMode(display, &dm)) { + SDL_DisplayID display = SDL_GetDisplayForWindow(window->window); + const SDL_DisplayMode *dm = SDL_GetDesktopDisplayMode(display); + if (dm == NULL) { asc_error("Failed to get display mode for window %u on display %d: %s", window->id, display, SDL_GetError()); } - return ASC_VEC2U(dm.w, dm.h); + return ASC_VEC2U(dm->w, dm->h); } float asc_window_ui_scale(unsigned int index) {