A Crash Course in SDL
Before we can begin blitting surfaces to the screen, we need to initialize the SDL library and switch the display into an appropriate mode. Take a look at Listing 1, the equivalent of “Hello, world!” in SDL.
This program includes the SDL.h header file, which is the master header for SDL. Every SDL application should include this file. The program also includes two standard headers, for the printf and atexit functions.
We begin by calling SDL_Init to initialize SDL. This function takes an ORed list of arguments to indicate which subsystems should be initialized; we are only interested in the video subsystem, so we pass SDL_INIT_VIDEO (if we wanted audio, for instance, we would call this function with SDL_INIT_VIDEO | SDL_INIT_AUDIO). Unless a fatal error occurs, this function should return zero. We also use C's atexit facility to request that SDL_Quit be called before the program exits. This function makes sure that SDL has a chance to shut down properly (which becomes especially important if a fullscreen application crashes).
Next, we use the SDL_SetVideoMode function to inform the display of our desired resolution (in this case 640 pixels across by 480 pixels down) and color depth (16-bit packed pixel). There is a catch here: SDL will try to set up the display as requested, but it might fail. If this happens, SDL won't tell us, but it will instead emulate the requested mode internally. This is usually acceptable, since the emulation code is relatively fast, and we would usually rather not deal with multiple modes internally. SDL_SetVideoMode returns a pointer to the surface that represents the display. If something goes wrong, this function returns NULL.
Finally, we report success and exit. The C library calls SDL_Quit automatically (since we registered it with atexit), and SDL returns the video display to its original mode. (We could also call SDL_Quit explicitly if we wanted to shut the system down before exiting our application; there's no harm in calling it more than once.)
Now that we've created an SDL application, we need to compile it. SDL applications are easy to build; assuming a proper installation of SDL, they just require a few flags and libraries. The standard SDL distribution includes a program called sdl-config (similar to the gtk-config and glib-config programs that ship with the GTK+ toolkit) for supplying the appropriate commandline arguments to gcc. The command sdl-config --cflags produces a list of the options that should be passed to the compiler, and sdl-config --libs produces a list of libraries that should be linked in. We can use backtick substitution to drop this into the gcc command line. If SDL is installed on your system, you can compile this example with the following command:
$ gcc sdltest.c -o sdltest `sdl-config --cflags --libs`
Putting data into an SDL surface is simple. Each SDL_Surface structure contains a pixels member. This is a void pointer to the raw graphic image, and we can write to it directly if we know which type of pixel the surface is set up for. We must call the SDL_LockSurface function before we access this data (because some surfaces reside in special memory areas and require special handling). When we are finished with the surface, we must call SDL_UnlockSurface to release it. The width and the height of the image are given by the w and h members of the structure, and the pixel format is specified by the format member (which is of type SDL_PixelFormat). SDL often emulates nonstandard screen resolutions with higher resolutions, and the pitch member of the pixel format structure indicates the actual width of the frame buffer. You should always use pitch instead of w for calculating offsets into the pixels buffer, or else your application might not work on some display devices.
The example shown in Listing 2 will use the SDL pixel format information to draw individual pixels on the screen. We have chosen to use a 16-bit (hicolor) mode for demonstration purposes, but other modes are equally simple to program.
The code's comments give the play-by-play, but a few things might not be obvious. This program employs a very general routine for constructing hicolor pixel values; this routine will work with any hicolor (16-bit) pixel format that SDL recognizes. Although we could write a separate (faster) routine for each possible hicolor data layout, this would require a lot of work and would only marginally improve performance. The hicolor 565 (5 red bits, 6 green bits, and 5 blue bits) pixel format is perhaps the most widely used and could be reasonably optimized, but 556 and 555 are not uncommon. In addition, there is no guarantee that the bit fields will be in the red-green-blue order. Our CreateHicolorPixel routine solves this problem by referring to the data in the SDL_PixelFormat structure. For instance, the routine uses the Rloss member of the structure to determine how many bits to drop from the 8-bit red component, and it then uses the Rshift member to determine where the red bits should be located within the 16-bit pixel value.
Another important issue involves the SDL_UpdateRect function. As we mentioned earlier, SDL sometimes emulates video modes if the video card is unable to provide a certain mode itself. If the video card does not support a requested 24-bit mode, for instance, SDL might select a 16-bit mode instead and return a fake frame buffer setup for 24-bit pixels. This would allow your program to continue normally, and SDL would handle the conversion from 24-bits to 16-bits on the fly (with a slight performance loss). The SDL_UpdateRect function informs SDL that a portion of the screen has been updated and that it should perform the appropriate conversions to display that area. If a program does not use this function, there is a chance that it will still work. It is better to be on the safe side and call this function whenever the frame buffer surface has been changed.
Finally, if you run the program you might notice that it runs in a window instead of taking over the entire screen. To change this, replace the zero in the SDL_SetVideoMode call with the constant SDL_FULLSCREEN. Be careful, though; fullscreen applications are harder to debug, and they tend to mess things up badly when they crash.
|Designing Electronics with Linux||May 22, 2013|
|Dynamic DNS—an Object Lesson in Problem Solving||May 21, 2013|
|Using Salt Stack and Vagrant for Drupal Development||May 20, 2013|
|Making Linux and Android Get Along (It's Not as Hard as It Sounds)||May 16, 2013|
|Drupal Is a Framework: Why Everyone Needs to Understand This||May 15, 2013|
|Home, My Backup Data Center||May 13, 2013|
- Designing Electronics with Linux
- New Products
- Making Linux and Android Get Along (It's Not as Hard as It Sounds)
- Dynamic DNS—an Object Lesson in Problem Solving
- Using Salt Stack and Vagrant for Drupal Development
- Validate an E-Mail Address with PHP, the Right Way
- Tech Tip: Really Simple HTTP Server with Python
- Why Python?
- Build a Skype Server for Your Home Phone System
- Drupal Is a Framework: Why Everyone Needs to Understand This
- Reply to comment | Linux Journal
34 min 19 sec ago
- Reply to comment | Linux Journal
1 hour 24 min ago
- Not free anymore
5 hours 26 min ago
9 hours 13 min ago
- Reply to comment | Linux Journal
9 hours 21 min ago
- Understanding the Linux Kernel
11 hours 36 min ago
14 hours 6 min ago
- Kernel Problem
1 day 8 min ago
- BASH script to log IPs on public web server
1 day 4 hours ago
1 day 8 hours ago
Enter to Win an Adafruit Pi Cobbler Breakout Kit for Raspberry Pi
It's Raspberry Pi month at Linux Journal. Each week in May, Adafruit will be giving away a Pi-related prize to a lucky, randomly drawn LJ reader. Winners will be announced weekly.
Fill out the fields below to enter to win this week's prize-- a Pi Cobbler Breakout Kit for Raspberry Pi.
Congratulations to our winners so far:
- 5-8-13, Pi Starter Pack: Jack Davis
- 5-15-13, Pi Model B 512MB RAM: Patrick Dunn
- 5-21-13, Prototyping Pi Plate Kit: Philip Kirby
- Next winner announced on 5-27-13!
Free Webinar: Hadoop
How to Build an Optimal Hadoop Cluster to Store and Maintain Unlimited Amounts of Data Using Microservers
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Some of key questions to be discussed are:
- What is the “typical” Hadoop cluster and what should be installed on the different machine types?
- Why should you consider the typical workload patterns when making your hardware decisions?
- Are all microservers created equal for Hadoop deployments?
- How do I plan for expansion if I require more compute, memory, storage or networking?