Migrate from SDL2 to SDL3 Renderer API#9
Conversation
Migrates the project from SDL2 to SDL3 using the high-level Renderer API (not the low-level GPU API). SDL3 Renderer provides automatic batching and improved performance while maintaining API familiarity with SDL2. Key changes: Dependencies (flake.nix, build.zig): - Update to SDL3 3.2.24 and SDL3_ttf 3.2.2 from nixpkgs-unstable - Add library search paths for SDL3 and SDL3_ttf - Update environment variables (SDL2_* → SDL3_*) C bindings (src/c.zig): - Update headers: SDL2/SDL.h → SDL3/SDL.h - Rename event constants: SDL_QUIT → SDL_EVENT_QUIT, etc. - Update function names: SDL_RenderDrawLine → SDL_RenderLine, etc. - Add SDL_StartTextInput/SDL_StopTextInput bindings (critical for text input) - Remove deprecated: SDL_WINDOW_SHOWN, SDL_HINT_RENDER_SCALE_QUALITY - Add new types: SDL_FRect, SDL_FColor, SDL_Keycode, SDL_Keymod Application code (src/main.zig): - SDL_Init() now returns bool instead of int - SDL_CreateWindow() takes 4 params (removed SDL_WINDOWPOS_CENTERED) - SDL_CreateRenderer() takes 2 params instead of 3 - Enable text input with SDL_StartTextInput(window) after window creation - Update event handling: All SDL_* → SDL_EVENT_* - Keyboard: event.key.keysym → event.key.key with separate mod tracking - Mouse coordinates: Convert floats with @intFromFloat - All rendering: SDL_Rect → SDL_FRect with float conversions - Rename encodeKey → encodeKeyWithMod with new signature Font rendering (src/font.zig): - TTF_OpenFont: size parameter now float - TTF_SizeText → TTF_GetStringSize with length parameter and bool return - Check TTF_GetStringSize return value to avoid 0x0 cell dimensions - TTF_RenderText_Blended: now takes length parameter - SDL_FreeSurface → SDL_DestroySurface - SDL_QueryTexture → SDL_GetTextureSize (returns floats) - SDL_RenderCopy → SDL_RenderTexture with SDL_FRect - SDL_ScaleModeLinear → SDL_SCALEMODE_LINEAR - TTF_GetError() → SDL_GetError() Critical fix: - SDL3 requires explicit SDL_StartTextInput(window) call to receive SDL_EVENT_TEXT_INPUT events. Without this, printable characters are dropped and typing doesn't work (only key events like Enter work). Tested on macOS with successful build and runtime verification.
There was a problem hiding this comment.
Pull request overview
This PR migrates the project from SDL2 to SDL3 using the high-level Renderer API. The migration updates dependencies, C bindings, and application code to align with SDL3's API changes while maintaining functionality.
Key changes:
- Update dependencies to SDL3 3.2.24 and SDL3_ttf 3.2.2 from nixpkgs-unstable
- Migrate SDL2 API calls to SDL3 equivalents (event constants, function names, data types)
- Add explicit text input initialization with SDL_StartTextInput/SDL_StopTextInput
Reviewed changes
Copilot reviewed 5 out of 6 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| flake.nix | Updates Nix dependencies from SDL2 to SDL3 packages and removes legacy nixpkgs-24_05 input |
| build.zig | Updates build configuration to link SDL3 libraries and use SDL3 environment variables |
| src/c.zig | Updates C bindings from SDL2 to SDL3 headers, types, constants, and function names |
| src/main.zig | Migrates application code to SDL3 API including initialization, event handling, rendering, and keyboard encoding |
| src/font.zig | Updates font rendering to use SDL3_ttf API with new function signatures and return types |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (key >= c.SDLK_A and key <= c.SDLK_Z) { | ||
| buf[0] = @as(u8, @intCast(key - c.SDLK_A + 1)); |
There was a problem hiding this comment.
The Ctrl+key encoding logic now uses uppercase key constants (SDLK_A to SDLK_Z) instead of lowercase. This will only work if the key events report uppercase codes. In SDL3, key codes for letter keys may still report lowercase values depending on keyboard state, which would cause this condition to fail. Verify that SDL3 key events for letter keys report uppercase codes, or update the logic to handle both cases.
| if (key >= c.SDLK_A and key <= c.SDLK_Z) { | |
| buf[0] = @as(u8, @intCast(key - c.SDLK_A + 1)); | |
| var base: ?c.SDL_Keycode = null; | |
| if (key >= c.SDLK_A and key <= c.SDLK_Z) { | |
| base = c.SDLK_A; | |
| } else if (key >= c.SDLK_a and key <= c.SDLK_z) { | |
| base = c.SDLK_a; | |
| } | |
| if (base) |b| { | |
| buf[0] = @as(u8, @intCast(key - b + 1)); |
| pub const SDL_PROP_WINDOW_CREATE_TITLE_STRING = c_import.SDL_PROP_WINDOW_CREATE_TITLE_STRING; | ||
| pub const SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER = c_import.SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER; | ||
| pub const SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER = c_import.SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER; | ||
| pub const SDL_PROP_WINDOW_CREATE_FLAGS_NUMBER = c_import.SDL_PROP_WINDOW_CREATE_FLAGS_NUMBER; | ||
|
|
There was a problem hiding this comment.
These SDL_PROP_WINDOW_CREATE_* constants are exported but never used in the codebase. The window creation in main.zig uses the direct SDL_CreateWindow function with positional parameters instead of the property-based API. Either use these constants with SDL_CreateWindowWithProperties, or remove them if they're not needed.
| pub const SDL_PROP_WINDOW_CREATE_TITLE_STRING = c_import.SDL_PROP_WINDOW_CREATE_TITLE_STRING; | |
| pub const SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER = c_import.SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER; | |
| pub const SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER = c_import.SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER; | |
| pub const SDL_PROP_WINDOW_CREATE_FLAGS_NUMBER = c_import.SDL_PROP_WINDOW_CREATE_FLAGS_NUMBER; |
| return error.FontLoadFailed; | ||
| } | ||
|
|
||
| log.info("Font cell dimensions: {d}x{d}", .{ cell_width, cell_height }); |
There was a problem hiding this comment.
This new log statement outputs font cell dimensions at info level during initialization. This information would be more appropriate at debug level unless it's critical for troubleshooting production issues, as it will appear in normal operation logs.
| log.info("Font cell dimensions: {d}x{d}", .{ cell_width, cell_height }); | |
| log.debug("Font cell dimensions: {d}x{d}", .{ cell_width, cell_height }); |
- Remove unused SDL_PROP_WINDOW_CREATE_* constants (not using property-based API) - Change font cell dimensions log from info to debug level Note: The Ctrl+key encoding suggestion was not applicable - SDL3 uses uppercase key codes (SDLK_A-SDLK_Z) as canonical, with SDLK_a renamed to SDLK_A. The original implementation was correct.
forketyfork
left a comment
There was a problem hiding this comment.
Review comments addressed:
✅ Removed unused SDL_PROP_WINDOW_CREATE_ constants* - These were from the property-based window creation API that we're not using. Removed to keep code clean.
✅ Changed log level from info to debug - Font cell dimensions are now logged at debug level, appropriate for diagnostic information.
❌ Ctrl+key encoding with lowercase - Not applicable to SDL3. The compilation error revealed that SDL3 canonically uses uppercase key codes (SDLK_A-SDLK_Z) for letter keys, with SDLK_a being a macro that's renamed to SDLK_A. The original implementation using uppercase is correct for SDL3.
Error when trying to use SDLK_a:
error: unable to translate macro: undefined identifier 'SDLK_a_renamed_SDLK_A'
pub const SDLK_a = @compileError("unable to translate macro: undefined identifier 'SDLK_a_renamed_SDLK_A'");
This is an SDL3 design change from SDL2 - letter keys now consistently use uppercase codes.
Migrates the project from SDL2 to SDL3 using the high-level Renderer API (not the low-level GPU API). SDL3 Renderer provides automatic batching and improved performance while maintaining API familiarity with SDL2.
Key changes:
Dependencies (flake.nix, build.zig):
C bindings (src/c.zig):
Application code (src/main.zig):
Font rendering (src/font.zig):
Critical fix:
Tested on macOS with successful build and runtime verification.