Skip to content

Support SDL3 backend alongside SDL2#19

Merged
jserv merged 1 commit into
mainfrom
sdl3
Jun 22, 2026
Merged

Support SDL3 backend alongside SDL2#19
jserv merged 1 commit into
mainfrom
sdl3

Conversation

@jserv

@jserv jserv commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

This builds the compat stack against either SDL major version from one source tree, selected by the SDL_BACKEND make variable. When unset, the build auto-detects: it prefers SDL3 when both sdl3 and sdl3-ttf are visible to pkg-config, and falls back to SDL2; an explicit SDL_BACKEND= sdl2|sdl3 always wins. SDL2 remains the wrapper-shim path (dlopen the host SDL2); SDL3 links libSDL3 / libSDL3_ttf directly.

Translation lives in two new chokepoint headers, src/sdl-compat.h and src/sdl-ttf-compat.h, that every source includes instead of <SDL2/SDL.h>. The SDL2 branch is a pass-through; the SDL3 branch enables SDL_ENABLE_OLD_NAMES (so SDL3's old-names layer carries the pure renames) and wraps only the symbols whose signature or semantics changed: the render float migration, surface mask->enum creation, the MapRGB/GetRGB palette argument, SDL_RenderReadPixels returning a surface, SDL_CreateWindow losing x/y, SDL_SetTextInputArea, mouse-coordinate floats, ns->ms event timestamps, the SDL_ttf 3.x renames, and the SDL2 int (0/-1) return convention the call sites test. Wrappers are defined before the #define that renames the call sites so their bodies bind the real SDL3 symbol.

mk/sdl.mk gains the SDL_BACKEND switch + auto-detect and a content-hashed SDL_BACKEND_STAMP that every object depends on, so switching backends forces a rebuild without manual object deletion. The SDL2 dlopen wrapper is gated off under SDL3 (mk/sdl-wrapper.mk), and the two wrappers' shared dlopen/dlsym/atomic-cache machinery is consolidated into src/wrapper/dlwrap.h.

Per-site SDL3 fixes: font.c pins the glyph texture to nearest scaling (SDL3 defaults to linear, which smeared opaque strokes); pixmap.c populates the render-target pixmap via a staging-texture render (SDL_UpdateTexture into a target did not survive readback on SDL3's software renderer); events.c restructures the flattened window events, key fields, and timestamps, and reconciles the per-display event-queue accounting at the client SDL_FlushEvent/PeepEvents/WaitEvent boundary.


Summary by cubic

Add optional SDL3 backend alongside SDL2, selectable via SDL_BACKEND, with auto-detect that prefers sdl3 when available. Compat headers keep source changes small; CI adds an sdl3 job to exercise the new path.

  • New Features

    • Build against SDL2 or SDL3 via SDL_BACKEND=sdl2|sdl3; auto-detect prefers sdl3/sdl3-ttf, unknown values fail fast.
    • Compat headers: src/sdl-compat.h and src/sdl-ttf-compat.h unify APIs (SDL_ENABLE_OLD_NAMES + small wrappers for changed calls/returns); all sources and examples include them.
    • Build: SDL_BACKEND_STAMP forces rebuilds on backend switch; sdl2 uses dlopen shims, sdl3 links libSDL3/libSDL3_ttf; shared dlopen/dlsym logic moved to src/wrapper/dlwrap.h.
    • CI: new sdl3 job builds and tests the SDL3 path from source, caches the prefix, and runs headless; other jobs stay on sdl2.
    • SDL3 fixes: nearest scaling for glyph textures; pixmap targets populated via a staging texture; updated event fields and ms timestamps.
    • Security: replaced banned strcpy in the text-event shim with bounded snprintf.
  • Migration

    • To use SDL3: install sdl3 and sdl3-ttf, then build with SDL_BACKEND=sdl3.
    • To force SDL2: build with SDL_BACKEND=sdl2; auto-detect picks sdl3 when both sdl3 and sdl3-ttf are available.
    • Runtime: sdl2 uses wrapper shims; sdl3 links libSDL3/libSDL3_ttf directly.

Written for commit 9046ba1. Summary will update on new commits.

Review in cubic

cubic-dev-ai[bot]

This comment was marked as resolved.

This builds the compat stack against either SDL major version from one
source tree, selected by the SDL_BACKEND make variable. When unset, the
build auto-detects: it prefers SDL3 when both sdl3 and sdl3-ttf are
visible to pkg-config, and falls back to SDL2; an explicit SDL_BACKEND=
sdl2|sdl3 always wins. SDL2 remains the wrapper-shim path (dlopen the
host SDL2); SDL3 links libSDL3 / libSDL3_ttf directly.

Translation lives in two new chokepoint headers, src/sdl-compat.h and
src/sdl-ttf-compat.h, that every source includes instead of <SDL2/SDL.h>.
The SDL2 branch is a pass-through; the SDL3 branch enables
SDL_ENABLE_OLD_NAMES (so SDL3's old-names layer carries the pure renames)
and wraps only the symbols whose signature or semantics changed: the
render float migration, surface mask->enum creation, the MapRGB/GetRGB
palette argument, SDL_RenderReadPixels returning a surface, SDL_CreateWindow
losing x/y, SDL_SetTextInputArea, mouse-coordinate floats, ns->ms event
timestamps, the SDL_ttf 3.x renames, and the SDL2 int (0/-1) return
convention the call sites test. Wrappers are defined before the #define
that renames the call sites so their bodies bind the real SDL3 symbol.

mk/sdl.mk gains the SDL_BACKEND switch + auto-detect and a content-hashed
SDL_BACKEND_STAMP that every object depends on, so switching backends
forces a rebuild without manual object deletion. The SDL2 dlopen wrapper
is gated off under SDL3 (mk/sdl-wrapper.mk), and the two wrappers' shared
dlopen/dlsym/atomic-cache machinery is consolidated into
src/wrapper/dlwrap.h.

Per-site SDL3 fixes: font.c pins the glyph texture to nearest scaling
(SDL3 defaults to linear, which smeared opaque strokes); pixmap.c
populates the render-target pixmap via a staging-texture render
(SDL_UpdateTexture into a target did not survive readback on SDL3's
software renderer); events.c restructures the flattened window events,
key fields, and timestamps, and reconciles the per-display event-queue
accounting at the client SDL_FlushEvent/PeepEvents/WaitEvent boundary.
@jserv jserv merged commit fe03aac into main Jun 22, 2026
15 checks passed
@jserv jserv deleted the sdl3 branch June 22, 2026 16:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant