Today I'm documenting my migration from SDL2 to SDL3, starting on Windows and then macOS and Linux.
Installation
Windows
Since I keep the SDL include and lib files local to the msvs project for Windows, I downloaded SDL3-devel-3.2.8-VC.zip file from GitHub.
Since I keep the SDL include and lib files local to the msvs project for Windows, I downloaded SDL3-devel-3.2.8-VC.zip file from GitHub.
I added the files to msvs\lib\sdl\include\SDL3\include and msvs\lib\sdl\lib\x86.
macOS/Linux
On macOS and Linux, just run the following commands in the terminal.
# macOS brew install sdl3 # Linux sudo apt install libsdl3-dev
Don't forget change our include to SDL3/SDL.h.
Logging
Everywhere I am using fprintf I've changed to SDL_Log like so:
SDL_Log("Unable to initialize SDL: %s", SDL_GetError());
Initialize SDL
Currently we are initializing every SDL subsystem with SDL_Init. As part of this upgrade, I'm going to change this to only initialize the video subsystem. This now returns a bool instead of an int, so we no longer have to check against 0.
if (!SDL_InitSubSystem(SDL_INIT_VIDEO)) { SDL_Log("Couldn't initialize SDL: %s", SDL_GetError()); return false; }
Create Window
To create a window with SDL 3 we can use SDL_CreateWindowWithProperties and provide it with the configuration we want. First, we make sure we can successfully create a SDL_PropertiesID, which is a typedef for a Uint32.
SDL_PropertiesID window_properties = SDL_CreateProperties(); if (!window_properties) { SDL_Log("Unable to initialize SDL: %s", SDL_GetError()); return false; }
We set integer properties by using SDL_SetNumberProperty. This is our window properties for a centered position and using our width and height.
SDL_PropertiesID window_properties = SDL_CreateProperties(); if (!window_properties) { SDL_Log("Unable to initialize SDL: %s", SDL_GetError()); return false; } SDL_SetNumberProperty(window_properties, SDL_PROP_WINDOW_CREATE_X_NUMBER, SDL_WINDOWPOS_CENTERED); SDL_SetNumberProperty(window_properties, SDL_PROP_WINDOW_CREATE_Y_NUMBER, SDL_WINDOWPOS_CENTERED); SDL_SetNumberProperty(window_properties, SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER, window_width); SDL_SetNumberProperty(window_properties, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, window_height); window = SDL_CreateWindowWithProperties(window_properties);
Create Renderer
There's a slight change to the API for SDL_CreateRenderer in that we no longer need to provide it with an int for the index of the rendering driver. Before we passed -1 which will initialize the first one found that supports the flags.
Now the method has two parameters, an SDL_Window and a const char* for the name of the rendering driver. We can provide NULL for SDL to choose the best option based on the system.
renderer = SDL_CreateRenderer(window, NULL);
Event Type
There are a few changes to the naming for the events we're using.
switch (event.type) { case SDL_EVENT_QUIT: is_running = false; break; case SDL_EVENT_KEY_DOWN: if (event.key.key == SDLK_ESCAPE) is_running = false; break; }
Quit Subsystem
Finally, I'm calling SDL_QuitSubSystem in destroy_window as part of cleanup.
void destroy_window(void) { SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_QuitSubSystem(SDL_INIT_VIDEO); SDL_Quit(); }
Summary
With that done, we're now running the latest stable version of SDL3. Here's the resulting code after the upgrade.
#include <stdio.h> #include <stdbool.h> #include <SDL3/SDL.h> SDL_Window* window = NULL; SDL_Renderer* renderer = NULL; bool is_running = false; int window_width = 800; int window_height = 600; bool initialize_window(void) { if (!SDL_InitSubSystem(SDL_INIT_VIDEO)) { SDL_Log("Couldn't initialize SDL: %s", SDL_GetError()); return false; } SDL_PropertiesID window_properties = SDL_CreateProperties(); if (!window_properties) { SDL_Log("Unable to initialize SDL: %s", SDL_GetError()); return false; } SDL_SetNumberProperty(window_properties, SDL_PROP_WINDOW_CREATE_X_NUMBER, SDL_WINDOWPOS_CENTERED); SDL_SetNumberProperty(window_properties, SDL_PROP_WINDOW_CREATE_Y_NUMBER, SDL_WINDOWPOS_CENTERED); SDL_SetNumberProperty(window_properties, SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER, window_width); SDL_SetNumberProperty(window_properties, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, window_height); window = SDL_CreateWindowWithProperties(window_properties); if (!window) { SDL_Log("Unable to initialize SDL: %s", SDL_GetError()); return false; } renderer = SDL_CreateRenderer(window, NULL); if (!renderer) { SDL_Log("Unable to initialize SDL: %s", SDL_GetError()); return false; } return true; } void destroy_window(void) { SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_QuitSubSystem(SDL_INIT_VIDEO); SDL_Quit(); } void process_input(void) { SDL_Event event; SDL_PollEvent(&event); switch (event.type) { case SDL_EVENT_QUIT: is_running = false; break; case SDL_EVENT_KEY_DOWN: if (event.key.key == SDLK_ESCAPE) is_running = false; break; } void update(void) { // TODO: Something fun here :) } void render(void) { SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255); SDL_RenderClear(renderer); // TODO: Render some graphics! SDL_RenderPresent(renderer); } int main(void) { is_running = initialize_window(); while (is_running) { process_input(); update(); render(); } destroy_window(); return 0; }
Take care.
Stay awesome.