SDL (Simple DirectMedia Layer) - Rendering surfaces

In this section, we will modify our code to optimise SDL_Surface blitting using SDL_ConvertSurface and stretch our image to fullscreen using SDL_BlitScaled.

You can download the source code of this section in this GitLab repository. All source code is stored in this group.

Optimising a SDL_Surface for blitting

edit

We can optimise a SDL_Surface for blitting, which in turn improves performance. SDL_ConvertSurface is used to optimize images for faster repeat blitting. This is accomplished by converting the original and storing the result as a new surface.

We'll update our wb_loadImage function by using the following code.

/* Set temporary SDL_Surface */
SDL_Surface *temp = NULL;

/* Load the image from its file path to a SDL_Surface */
temp = IMG_Load(WB_IMAGE_PATH);

if (temp == NULL) {
  fprintf(stderr, "WikiBook failed to load image: %s\n", IMG_GetError());
  return -1;
}

/* Optimise SDL_Surface for blitting */
wb->image = SDL_ConvertSurface(temp, wb->screen->format, 0);

/* Destroy temporary SDL_Surface */
SDL_FreeSurface(temp);

Remember to destroy SDL object pointers using their corresponding functions, in this case SDL_FreeSurface.

Blitting a SDL_Surface to fullscreen

edit

We'll replace SDL_BlitSurface with SDL_BlitScaled. We'll write a static (and therefore private) function that blits a surface to fullscreen.

/* Maximise surface to full screen */
static int setSurfaceFullScreen(SDL_Surface *surface, SDL_Surface *screen) {

  /* Create SDL_Rect to full screen */
  SDL_Rect rt = { 0, 0, WB_WIDTH, WB_HEIGHT };

  /* Blit SDL_Surface to the size of SDL_Rect */
  if (SDL_BlitScaled(surface, NULL, screen, &rt) < 0) {
    fprintf(stderr, "Failed to set surface to full screen: %s\n", SDL_GetError());
    return -1;
  }

  return 0;
}

We'll have to initialise and declare a SDL_Rect with the size of the entire window and blit the surface using dimensions of that SDL_Rect.

We replace the blitting function in our wb_loadImage:

/* Blit SDL_Surface to full screen */
if (setSurfaceFullScreen(wb->image, wb->screen) < 0) {
  return -1;
}

You'll notice that we're not declaring a SDL_Rect pointer, it's a relatively small structure compared to SDL_Surface and the like, so we don't have to dynamically allocate memory for it.