Solarian Programmer

My programming ramblings

Raspberry Pi - Building SDL 2 on Raspbian

Posted on January 22, 2015 by Sol

This is a short tutorial on how to get started with SDL 2 programming on a Raspberry Pi device that has Raspbian installed. If you want to write C++, or C, games that are easily portable to other platforms SDL 2 is the way to go on Raspbian. Unfortunately, at the time of this writing Raspbian comes with the outdated SDL 1.2 installed.

Let’s start by updating our Raspbian installation, feel free to skip this step if your system was recently updated:

1 sudo apt-get update
2 sudo apt-get upgrade

Next, we will need to install some libraries that will be used when we build SDL 2:

1 sudo apt-get install build-essential libfreeimage-dev libopenal-dev libpango1.0-dev libsndfile-dev libudev-dev libasound2-dev libjpeg8-dev libtiff5-dev libwebp-dev automake

SDL 2 can be downloaded from https://www.libsdl.org/download-2.0.php, be sure to select the source code archive, SDL2-2.0.3.tar.gz, or a newer version if available. You can download and extract the archive directly on your Raspberry Pi:

1 cd ~
2 wget https://www.libsdl.org/release/SDL2-2.0.3.tar.gz
3 tar zxvf SDL2-2.0.3.tar.gz
4 cd SDL2-2.0.3 && mkdir build && cd build

Now, it is time to configure SDL 2:

1 ../configure --disable-pulseaudio --disable-esd --disable-video-mir --disable-video-wayland --disable-video-x11 --disable-video-opengl

or, if you have a Raspberry Pi 2:

1 ../configure --host=armv7l-raspberry-linux-gnueabihf --disable-pulseaudio --disable-esd --disable-video-mir --disable-video-wayland --disable-video-x11 --disable-video-opengl

The above options will make sure, SDL 2 is built with the OpenGL ES backend and that any SDL application will run as a full screen application, the windowed mode under X tends to be more buggy on Raspberry Pi. On the plus side, you will be able to launch your application, or game, directly from the text interface without the overhead of running the X server. If you wish you can start your application from LXDE (the default window manager for Raspbian) and the application will run full screen.

Assuming, you’ve had no error in the configure phase, you can actually build and install the library:

1 make -j 4
2 sudo make install

Now, you should be able to compile any C++ code that uses SDL 2 with something like:

1 g++ -o program_name program_name.cpp `sdl2-config --cflags --libs`

SDL 2 by itself can use only .bmp graphic files and .wav audio files. If you want to be able to load other image formats, like .png, you can use SDL_image 2.0 or something like FreeImage. The advantage of using SDL_image is that this is directly compatible with SDL 2, basically you will load an image file in a format that will just work with SDL 2. Similarly, there are libraries for loading sound files, SDL_mixer 2.0, or font files SDL_ttf 2.0.

Since working with images in various formats is a must for almost any SDL 2 application, I will exemplify, shortly, how to download, build and install SDL_image:

1 cd ~
2 wget http://www.libsdl.org/projects/SDL_image/release/SDL2_image-2.0.0.tar.gz
3 tar zxvf SDL2_image-2.0.0.tar.gz
4 cd SDL2_image-2.0.0 && mkdir build && cd build
5 ../configure
6 make -j 4
7 sudo make install

If your code uses SDL_image you will need to explicitly link the SDL_image library, e.g.:

1 g++ -o program_name program_name.cpp `sdl2-config --cflags --libs` -lSDL2_image

The SDL_ttf library can be built similarly. If you want to build SDL_mixer you will need to build and install first smpeg2, after which you can build and install SDL_mixer like before.

Time to write a short code example that will open an SDL window and show an image for 10 seconds, after which will free the resources and exit. I assume that you’ve successfully installed SDL 2 and SDL_image on your Raspberry Pi.

 1 #include <SDL2/SDL.h>
 2 #include <SDL2/SDL_image.h>
 3 #include <iostream>
 4 
 5 // Manage error messages
 6 void check_error_sdl(bool check, const char* message);
 7 void check_error_sdl_img(bool check, const char* message);
 8 
 9 // Load an image from "fname" and return an SDL_Texture with the content of the image
10 SDL_Texture* load_texture(const char* fname, SDL_Renderer *renderer);
11 
12 
13 int main(int argc, char** argv) {
14     // Initialize SDL
15     check_error_sdl(SDL_Init(SDL_INIT_VIDEO) != 0, "Unable to initialize SDL");
16 
17     // Create and initialize a 800x600 window
18     SDL_Window* window = SDL_CreateWindow("Test SDL 2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
19                                           800, 600, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL);
20     check_error_sdl(window == nullptr, "Unable to create window");
21 
22     // Create and initialize a hardware accelerated renderer that will be refreshed in sync with your monitor (at approx. 60 Hz)
23     SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
24     check_error_sdl(renderer == nullptr, "Unable to create a renderer");
25 
26     // Set the default renderer color to corn blue
27     SDL_SetRenderDrawColor(renderer, 100, 149, 237, 255);
28 
29     // Initialize SDL_img
30     int flags=IMG_INIT_JPG | IMG_INIT_PNG;
31     int initted = IMG_Init(flags);
32     check_error_sdl_img((initted & flags) != flags, "Unable to initialize SDL_image");
33 
34     // Load the image in a texture
35     SDL_Texture *texture = load_texture("img_test.png", renderer);
36 
37     // We need to create a destination rectangle for the image (where we want this to be show) on the renderer area
38     SDL_Rect dest_rect;
39     dest_rect.x = 50; dest_rect.y = 50;
40     dest_rect.w = 337; dest_rect.h = 210;
41 
42     // Clear the window content (using the default renderer color)
43     SDL_RenderClear(renderer);
44 
45     // Copy the texture on the renderer
46     SDL_RenderCopy(renderer, texture, NULL, &dest_rect);
47 
48     // Update the window surface (show the renderer)
49     SDL_RenderPresent(renderer);
50 
51     // Wait for 10 seconds
52     SDL_Delay(10000);
53 
54     // Clear the allocated resources
55     SDL_DestroyTexture(texture);
56     IMG_Quit();
57     SDL_DestroyRenderer(renderer);
58     SDL_DestroyWindow(window);
59     SDL_Quit();
60 
61     return 0;
62 }
63 
64 // In case of error, print the error code and close the application
65 void check_error_sdl(bool check, const char* message) {
66     if (check) {
67         std::cout << message << " " << SDL_GetError() << std::endl;
68         SDL_Quit();
69         std::exit(-1);
70     }
71 }
72 
73 // In case of error, print the error code and close the application
74 void check_error_sdl_img(bool check, const char* message) {
75     if (check) {
76         std::cout << message << " " << IMG_GetError() << std::endl;
77         IMG_Quit();
78         SDL_Quit();
79         std::exit(-1);
80     }
81 }
82 
83 // Load an image from "fname" and return an SDL_Texture with the content of the image
84 SDL_Texture* load_texture(const char* fname, SDL_Renderer *renderer) {
85     SDL_Surface *image = IMG_Load(fname);
86     check_error_sdl_img(image == nullptr, "Unable to load image");
87 
88     SDL_Texture *img_texture = SDL_CreateTextureFromSurface(renderer, image);
89     check_error_sdl_img(img_texture == nullptr, "Unable to create a texture from the image");
90     SDL_FreeSurface(image);
91     return img_texture;
92 }

Assuming that you’ve saved the above code as sdl2_test.cpp and saved this image in the same folder as the C++ source file, you can compile and run the code with:

1 g++ -std=c++0x -Wall -pedantic sdl2_test.cpp -o sdl2_test `sdl2-config --cflags --libs` -lSDL2_image
2 ./sdl2_test

The above instructions will use the default version of GCC, 4.6.x, from Raspbian that has only partial support for C++11. If you want to use a more modern C++ compiler, with full support for C++11 and partial support for C++14, read my previous article. In this case you should use something like:

1 g++-4.9 -std=c++14 -Wall -pedantic sdl2_test.cpp -o sdl2_test `sdl2-config --cflags --libs` -lSDL2_image
2 ./sdl2_test

This is what you should see:

VNC screenshot of the application running in Raspberry Pi

If you want to learn more about SDL I would recommend reading SDL Game Development by Shaun Mitchel.

or The Black Art of Multiplatform Game Programming by Jazon Yamamoto.


Show Comments