Video
SDL provides many functions to use video and graphics features. Before jumping into video functions I will explain a common data type we will be using. Most video and graphic functions take a SDL_Surface
structure. You could think of this data type as a drawable surface. The SDL_Surface
structure holds information about our drawable surface like width, height and the actual data of the pixels used by our surface. SDL_Surface structures are used both to give access to the current screen and also provide storage for graphics.
To start using video functions you must first call SDL_SetVideoMode()
. This function will create a window and return a pointer to the video surface. SDL_SetVideoMode()'s argument specify the width, height and bps of our video surface. This function also takes unsigned int flags to specify which type of video surface we want. SDL_SetVideoMode() is defined like this:
SDL_Surface *SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags);
Here are a few flags you can pass to the function, for more you should read the SDL_SetVideoMode
man page by typing man SDL_SetVideoMode
at your shell prompt.
SDL_SWSURFACE
SDL_HWSURFACE
SDL_DOUBLEBUF
SDL_FULLSCREEN
SDL_OPENGL
SDL_SWSURFACE
will create a video surface in system memory while SDL_HWSURFACE
will create one in video memory. SDL_DOUBLEBUF
will create a double buffered window and SDL_FULLSCREEN
will set the specified video resolution instead of creating a window of the same size. SDL_OPENGL
is used when you need OpenGL rendering. Here's an example using the SDL_SetVideoMode()
function.
SDL_Surface *screen;
screen = SDL_SetVideoMode(800, 600, 16, SDL_SWSURFACE | SDL_FULLSCREEN);
if(screen == NULL)
{
fprintf(stderr, "Unable to set video mode: %s\n", SDL_GetError());
return -1;
}
Sometimes when you access the video memory to change pixel values the video surface will need to be locked. SDL provides a macro to check if the video memory needs to be locked, or not. This macro is SDL_MUSTLOCK(SDL_Surface)
. Even if you know the video surface does not need locking, it's a good idea to check anyway by enclosing all the drawing functions between if
statements checking if locking is needed. Here's a small example.
SDL_Surface *screen;
screen = SDL_SetVideoMode(800, 600, 16, SDL_SWSURFACE | SDL_FULLSCREEN);
if(SDL_MUSTLOCK(screen))
SDL_LockSurface(screen);
/*(You can write and access video memory here)*/
if(SDL_MUSTLOCK(screen))
SDL_UnlockSurface(screen);
Like I mentioned previously, graphics are also loaded into SDL_Surface
structures. SDL support BMP graphics files and they can be loaded with the SDL_LoadBMP()
function. SDL_LoadBMP() takes a single argument which is the filename that we would like to load. It then returns a pointer to a SDL_Surface
structure which holds the image data. Once loaded, images can be written on the screen with the SDL_BlitSurface()
function. SDL_BlitSurface is defined like this:
int SDL_BlitSurface(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect);
Here we see another data structure, SDL_Rect
. This structure hold four integer values, x, y, w and h. This data structure is used to tell functions about x,y positions, width and height. SDL_BlitSurface
takes two SDL_Rect
other than the source and destination surfaces and are used to tell which part of the image we want to blit and also where on the screen we would like the image to be positioned. If the SDL_Rect
structures in the SDL_BlitSurface
function are NULL
, the function assumes we want to blit the whole surface at 0,0. Here's an example demonstrating the use the SDL_LoadBMP
and SDL_BlitSurface
.
SDL_Surface *screen;
SDL_Surface *image;
screen = SDL_SetVideoMode(800, 600, 16, SDL_SWSURFACE);
if(screen == NULL)
{
fprintf(stderr, "Unable to set video mode: %s\n", SDL_GetError());
return 0;
}
image = SDL_LoadBMP("graphic.bmp");
if(image == NULL)
{
fprintf(stderr, "Unable to load graphic file: %s\n", SDL_GerError());
return 0;
}
while(1)
{
if(SDL_MUSTLOCK(screen))
SDL_LockSurface(screen);
SDL_BlitSurface(image, NULL, screen, &rect);
if(SDL_MUSTLOCK(screen))
SDL_UnlockSurface(screen);
SDL_UpdateRect(screen, 0,0,0,0);
}
In this example we set up our video mode and load a graphic file. Once loaded the program goes into the never-ending loop and displays our graphic on the screen. The new function SDL_UpdateRect()
is used to update the part of the screen we blitted the image on. I pass all zeros to the function to update the whole screen. If you want to only update part of the screen you can pass x, y, w, h values. If you would have specified SDL_DOUBLEBUF
as a video flag, you would use SDL_Flip(screen)
which would flip the buffers and display the graphics.