oreilly.comSafari Books Online.Conferences.


Animation in SDL: Hardware Surfaces

by Bob Pendleton

The Simple DirectMedia Layer (SDL) provides three kinds of surfaces for rendering graphics: software, hardware, and OpenGL. Software surfaces are stored in the computers main memory. Hardware surfaces are stored in memory on your video card. OpenGL surfaces are handled in whatever way OpenGL does things on your system. My previous SDL article provides basic information about using SDL and details of software surfaces. This article explores the promise and problems of using hardware surfaces.

People assume that because hardware buffers are based on hardware that programs that use them will be faster than programs that use software buffers. That assumption is often not true. In fact, some applications will run slower with hardware than with software buffers. The decision to use a hardware buffer must be based on testing and not on assumptions. People also seem to forget that the hardware is a limited resource. Just because you can get enough memory to make the program fly on your development machine does not mean it will perform as well on another computer. When they work for you hardware surfaces are fast, easy to use, and give you smooth animation without tearing and other unpleasant visual artifacts. When they don't, they can lead to a set of bewildering problems.

Working With Hardware Surfaces

A cross platform development tool like SDL is designed to let you write programs that work without change on many different kinds of hardware and operating systems. Hardware-dependent programming is the opposite of cross platform development. The conflict between the realities of hardware dependent development and the goals of SDL are at the root of many of the problems you may encounter when using hardware surfaces. SDL hardware surfaces are both cross-platform and hardware dependent.

While writing about SDL hardware surfaces, I have used more weasel words than a pork-barrel politician the week before election day. I do that because most features have a few special cases where they don't quite work the way you expect them to. The special cases come from the many factors that affect how hardware surfaces really work:

Related Reading

Even Grues Get Full
The Fourth User Friendly Collection
By J.D. "Illiad" Frazer

  • The actual hardware installed in your computer. There are many ways to build a video card. Your video card may have hundreds of megabytes of dedicated super fast DDR RAM. Then again, it may not have any dedicated memory, instead sharing the computer's main memory. Your hardware may have a blindingly fast graphics accelerator or it may let the CPU do all the work. Using hardware surfaces doesn't tell you much about how they will perform on any given system. In fact, they may perform poorly on a system with a high end graphics accelerator while performing remarkably well on a system with a weak graphics system.

  • How your computer talks to your video card. Most computers talk to the video card over a data bus, like the AGP bus, that is designed to send data from the CPU to the video card, not the other way around. It is almost always the case that the CPU can write to the video card much faster that it can read from the video card. It is usually the case that the CPU can read and write its main memory faster than it can read or write video memory. That all means that using the CPU to copy images (or anything) around in graphics memory is going to be slow.

  • The version of the device drivers you are using. Your hardware may be capable of providing hardware surfaces and hardware acceleration, but the drivers you are using may not make those abilities available to user programs. You can write a program that works great on your computer but that will fail on a similar computer with the same OS and the same graphics card just because it has a different version of the device driver.

  • The way the operating system controls access to hardware. Operating systems control access to the physical hardware and try to keep programs from messing with the hardware in ways that can crash the computer. Because of differences in their design, Windows allows normal programs to get hardware surfaces while on Linux and other Unix-like operating systems, a program must have root privileges to access the hardware.

Having listed so many problems with SDL hardware surfaces, you might think they are not worth using. However, if you are writing a two-dimensional game on a platform with good support for SDL hardware surfaces, they may be the correct choice. You just have to know enough to know when they are a bad choice.

Using Hardware Surfaces

The easiest way to show the differences between hardware and software surfaces is to convert the softlines.cpp program, which I wrote for my last article, from using software to hardware surfaces. The new program is called hardlines.cpp. Converting the code did not require me to change many lines of code. Of course, what seemed like tiny details kept the code form working as expected. The closer you get to the hardware, the pickier the work gets.

hardlines.cpp has the same sections with the same functions as softlines.cpp. Working from the top of the program down, I didn't have to make any changes in the program until I reached the main() function.

Selecting The Driver

The first change I had to make was to add some Linux specific code just before the call to SDL_Init():

#ifdef __linux__

SDL checks the value of the SDL_VIDEODRIVER environment variable to decide which driver to use. To get hardware surfaces while running on Linux under X, you have to specify which driver to use. I've chosen the DGA driver because the default X11 driver does not support hardware surfaces. The SDL FAQ has more information about selecting drivers on Linux and Windows. There is also a detailed list of SDL environment variables and their use. The number of different drivers that you have to choose from is staggering and shows the range of applications for which SDL could be used.

Setting The Video Mode

Then next change is in the call to SDL_SetVideoMode():

screen = SDL_SetVideoMode(screenWidth, 
                          SDL_ANYFORMAT |
                          SDL_FULLSCREEN |
                          SDL_HWSURFACE |

The changes are small, but the reasons for the changes aren't. The options tell SDL that I want a full screen (SDL_FULLSCREEN), double buffered (SDL_DOUBLEBUF), hardware surface (SDL_HWSURFACE). The part that isn't obvious is that on my desktop system if I want a hardware surface, it has to be full screen. I can't get a hardware surface for a window. This is one of those things that is operating system and device driver specific. Some systems let you have a hardware surface for a window. Even if you can get a hardware surface for a window, you may not be able to get a double buffered hardware surface for a window.

There are good reasons to refuse a hardware surface for a window. SDL_SetVideoMode() returns a pointer to an SDL_Surface. Inside that structure is a pointer to the pixel data for the surface. Without that pointer you can't draw anything. The demo program uses that pointer to draw lines. Having a pointer to a window on the screen means there is a good chance that you can write to any pixel on the screen, not just the ones in your window. You can probably read from any pixel on the screen, which creates a nasty security hole. A bug in your program can scramble the whole desktop, not just your window.

Because you have a pointer to the data in the window, you also have to worry about what happens when the window is moved, resized, or obscured. When the window moves, the address of the image data for that window also moves. If it changes and you use an old copy of the pointer, your program winds up drawing in the wrong place. If another window partially covers your window, who is responsible for keeping you from writing to the covered parts of your window? How does an SDL application even find out what those are? Double buffering introduces another set of problems. You may be able to get a hardware surface in a window, and not be able to get a double buffered surface for that window, because the entire desktop is not double buffered.

All of these problems can and in fact have been solved many different ways. By far the easiest solution is just to require that applications that directly access the screen run as full screen applications. If you want to use SDL hardware surfaces, assume that your application will have to run in full screen mode.

To make sure that the program actually got a hardware surface I added code that tests the surface type right after I set the video mode:

if (0 == screen->flags & SDL_HWSURFACE)
  printf("Can't get hardware surface\n");

If SDL can't give you what you ask for it will give you what it can. If it can't give you a hardware surface, SDL will give you a software surface. We have to check to see if we really got a hardware surface.

Pages: 1, 2

Next Pagearrow

Linux Online Certification

Linux/Unix System Administration Certificate Series
Linux/Unix System Administration Certificate Series — This course series targets both beginning and intermediate Linux/Unix users who want to acquire advanced system administration skills, and to back those skills up with a Certificate from the University of Illinois Office of Continuing Education.

Enroll today!

Linux Resources
  • Linux Online
  • The Linux FAQ
  • Linux Kernel Archives
  • Kernel Traffic

  • Sponsored by: