Open a window
This program opens a window and fills it with one color. It is the smallest SDL program that shows something on the screen.
The blue rectangle is the program below, running in your browser. To run it on your computer, follow Set up your computer.
The full program
/* Open a window and fill it with one color. */
#define SDL_MAIN_USE_CALLBACKS
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
/* SDL calls this once, when the program starts. */
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_Log("SDL_Init failed: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("Hello, window", 640, 480, 0,
&window, &renderer)) {
SDL_Log("SDL_CreateWindowAndRenderer failed: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_SetRenderVSync(renderer, 1);
return SDL_APP_CONTINUE;
}
/* SDL calls this for each event, such as a click on the close button. */
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{
if (event->type == SDL_EVENT_QUIT) {
return SDL_APP_SUCCESS;
}
return SDL_APP_CONTINUE;
}
/* SDL calls this again and again, once for each frame. */
SDL_AppResult SDL_AppIterate(void *appstate)
{
SDL_SetRenderDrawColor(renderer, 32, 96, 160, SDL_ALPHA_OPAQUE);
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
return SDL_APP_CONTINUE;
}
/* SDL calls this once, when the program ends. */
void SDL_AppQuit(void *appstate, SDL_AppResult result)
{
/* SDL destroys the window and the renderer for you. */
}/* Open a window and fill it with one color. */
#include <SDL.h>
#include <stdbool.h>
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#endif
static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
static bool running = true;
/* The loop calls this again and again, once for each frame. */
static void frame(void)
{
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
running = false;
}
}
SDL_SetRenderDrawColor(renderer, 32, 96, 160, SDL_ALPHA_OPAQUE);
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
}
int main(int argc, char *argv[])
{
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
SDL_Log("SDL_Init failed: %s", SDL_GetError());
return 1;
}
if (SDL_CreateWindowAndRenderer(640, 480, 0, &window, &renderer) != 0) {
SDL_Log("SDL_CreateWindowAndRenderer failed: %s", SDL_GetError());
SDL_Quit();
return 1;
}
SDL_SetWindowTitle(window, "Hello, window");
SDL_RenderSetVSync(renderer, 1);
#ifdef __EMSCRIPTEN__
/* A browser does not let a program stay in its own loop. */
emscripten_set_main_loop(frame, 0, 1);
#else
while (running) {
frame();
}
#endif
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}How the program runs
Most programs that you write first do their work and end. A graphics program stays open until you close it. It draws a picture, shows the picture, and starts again.
One picture is a frame. Many frames each second give you movement. This program draws the same blue frame each time, and later lessons change the frame.
You do not write main in this program. You write four functions, and SDL calls them for you:
SDL_AppInitruns one time, at the start.SDL_AppEventruns for each event, such as a click on the close button.SDL_AppIterateruns one time for each frame.SDL_AppQuitruns one time, at the end.
These four functions are the main callbacks. A callback is a function that you write and another program calls. The first lines of the file tell SDL to use them:
#define SDL_MAIN_USE_CALLBACKS
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>The SDL_main.h header supplies the real main, so the define must come before it.
You write the loop yourself in SDL2:
while (running) {
frame();
}A browser does not let a program stay in its own loop. The #ifdef __EMSCRIPTEN__ block gives the browser the frame function, and the browser calls it for each frame. On your computer, this block does nothing.
Create the window
if (!SDL_CreateWindowAndRenderer("Hello, window", 640, 480, 0,
&window, &renderer)) {SDL_Init starts SDL, and SDL_INIT_VIDEO tells it to start the part that makes windows.
SDL_CreateWindowAndRenderer makes two objects. The window is the rectangle on the screen, and the renderer is the object that draws in it. The window is 640 pixels wide and 480 pixels high, and the 0 means no special flags.
if (SDL_CreateWindowAndRenderer(640, 480, 0, &window, &renderer) != 0) {SDL_Init starts SDL, and SDL_INIT_VIDEO tells it to start the part that makes windows.
SDL_CreateWindowAndRenderer makes two objects. The window is the rectangle on the screen, and the renderer is the object that draws in it. The window is 640 pixels wide and 480 pixels high, and the 0 means no special flags.
The function must give you two pointers, but C returns one value. For this reason, you give it &window and &renderer, the addresses of your two pointer variables. The function writes the new pointers there.
SDL functions can fail, for example on a computer with no display. If a function fails, SDL_GetError tells you the reason. The program prints the reason and stops.
Draw a frame
SDL_SetRenderDrawColor(renderer, 32, 96, 160, SDL_ALPHA_OPAQUE);
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer); SDL_SetRenderDrawColor(renderer, 32, 96, 160, SDL_ALPHA_OPAQUE);
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);The renderer does not draw directly on the screen. It draws in a hidden picture, the back buffer. This stops you from seeing a frame that is not complete.
SDL_SetRenderDrawColorchooses the color. The numbers are red, green, and blue, from 0 to 255. The last number is the opacity.SDL_RenderClearfills the hidden picture with that color.SDL_RenderPresentshows the hidden picture on the screen.
The program also turns on vsync (wait for the screen to refresh before the next frame). Without vsync, the program draws as fast as it can and uses almost a full CPU core.
End the program
if (event->type == SDL_EVENT_QUIT) {
return SDL_APP_SUCCESS;
}When you click the close button, SDL sends the event SDL_EVENT_QUIT. The function returns SDL_APP_SUCCESS, and this tells SDL to end the program. SDL then calls SDL_AppQuit, destroys the window and the renderer, and stops.
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
running = false;
}
}SDL keeps events in a queue. SDL_PollEvent takes one event from the queue. When the queue is empty, it returns 0. When you click the close button, SDL adds the event SDL_QUIT, and the loop stops.
The end of main then destroys the renderer and the window, in the opposite order to the order that made them.
Try this
- Change the three color numbers to make the window red.
- Change
640and480to make a wide, short window. - Remove the
SDL_RenderPresentline, then build and run. The blue color does not appear, because the hidden picture never gets to the screen.
What you learned
- A graphics program draws frames until you close it.
- A window is the rectangle on the screen, and a renderer draws in it.
- The renderer draws in a hidden picture, and
SDL_RenderPresentshows it.