Copy and restore

I’m sure this is written in big glowing letters in some FAQ, but after
reading through various documentation, I’m stuck:

If I want to move something across the screen (imagine I’m moving an
alien spaceship across the screen), I’m supposed to:

  1. Make a backup of the screen where the ship is about to go so it
    can be restored later
  2. Put the spaceship on the screen at the require co-ordinates
  3. Put the previously made backup over the spaceship to remove it
  4. repeat, altering the co-ords.

How do I do steps 1 and 3? Am I supposed to define a temporary
SDL_Surface, and an SDL_Rect that defines the area to copy, then use
SDL_BlitSurface() to copy the screen to the temp surface? Or is there a
prewritten function?

I’m sure this is written in big glowing letters in some FAQ, but after
reading through various documentation, I’m stuck:

If I want to move something across the screen (imagine I’m moving an
alien spaceship across the screen), I’m supposed to:

  1. Make a backup of the screen where the ship is about to go so it
    can be restored later
  2. Put the spaceship on the screen at the require co-ordinates
  3. Put the previously made backup over the spaceship to remove it
  4. repeat, altering the co-ords.

How do I do steps 1 and 3? Am I supposed to define a temporary
SDL_Surface, and an SDL_Rect that defines the area to copy, then use
SDL_BlitSurface() to copy the screen to the temp surface? Or is there a
prewritten function?

Making a backup of the screen will be very slow if you are using
SDL_HWSURFACE. Your best bet is to redraw the background where the ship
was, then draw the ship. In other words, instead of making a backup of
the screen, have a backup in place already, at all times.

If redrawing the background is a pain, consider using a double-buffered
approach, where the back buffer only contains the background pixels. For
this, you wouldn’t use SDL_DOUBLEBUF, but rather create the two buffers
yourself. At each frame, you can draw the background (if needed), copy
the necessary parts to the front buffer, and draw foreground objects
into the front buffer. The back buffer could be SDL_SWSURFACE or
SDL_HWSURFACE, but if the latter, the front should be SDL_HWSURFACE as
well, to avoid copying pixels from video RAM to system RAM.

Hope this didn’t confuse you more,
DarrellOn Monday, October 8, 2001, at 10:56 AM, James wrote:

Look, ALL you have to do is declare the suface to be SDL_DOUBLEBUF in the
init display mode function. Then when you’re drawing everything just do:

SDL_FIllRect(Surface, NULL, 0);

draw everything to screen

SDL_Flip(Surface);

That’s it. It works fine for me.> ----- Original Message -----

From: dwaliss1@purdue.edu (Darrell Walisser)
To:
Sent: Monday, October 08, 2001 9:17 AM
Subject: Re: [SDL] Copy and restore

On Monday, October 8, 2001, at 10:56 AM, James wrote:

I’m sure this is written in big glowing letters in some FAQ, but after
reading through various documentation, I’m stuck:

If I want to move something across the screen (imagine I’m moving an
alien spaceship across the screen), I’m supposed to:

  1. Make a backup of the screen where the ship is about to go so it
    can be restored later
  2. Put the spaceship on the screen at the require co-ordinates
  3. Put the previously made backup over the spaceship to remove it
  4. repeat, altering the co-ords.

How do I do steps 1 and 3? Am I supposed to define a temporary
SDL_Surface, and an SDL_Rect that defines the area to copy, then use
SDL_BlitSurface() to copy the screen to the temp surface? Or is there a
prewritten function?

Making a backup of the screen will be very slow if you are using
SDL_HWSURFACE. Your best bet is to redraw the background where the ship
was, then draw the ship. In other words, instead of making a backup of
the screen, have a backup in place already, at all times.

If redrawing the background is a pain, consider using a double-buffered
approach, where the back buffer only contains the background pixels. For
this, you wouldn’t use SDL_DOUBLEBUF, but rather create the two buffers
yourself. At each frame, you can draw the background (if needed), copy
the necessary parts to the front buffer, and draw foreground objects
into the front buffer. The back buffer could be SDL_SWSURFACE or
SDL_HWSURFACE, but if the latter, the front should be SDL_HWSURFACE as
well, to avoid copying pixels from video RAM to system RAM.

Hope this didn’t confuse you more,
Darrell


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

Or you can follow these steps

  1. store the full background on a separate surface S
  2. blit the SDL_Rect R of step 4 from S to the video surface V
  3. blit the space-ship on SDL_Rect N on V
  4. R=N;
  5. SDL_Flip(V);
  6. Go to step 2.

You’ll draw only the modified portions…maybe your game will not be slow
for old computers…

Meetul> Look, ALL you have to do is declare the suface to be SDL_DOUBLEBUF in the

init display mode function. Then when you’re drawing everything just do:

SDL_FIllRect(Surface, NULL, 0);

draw everything to screen

SDL_Flip(Surface);

That’s it. It works fine for me.
http://www.libsdl.org/mailman/listinfo/sdl

If redrawing the background is a pain, consider using a
double-buffered approach, where the back buffer only contains the
background pixels. For this, you wouldn’t use SDL_DOUBLEBUF, but
rather create the two buffers yourself. At each frame, you can draw
the background (if needed), copy the necessary parts to the front
buffer, and draw foreground objects into the front buffer. The back
buffer could be SDL_SWSURFACE or SDL_HWSURFACE, but if the latter,
the front should be SDL_HWSURFACE as well, to avoid copying pixels
from video RAM to system RAM.

What are the reasons for drawing the background in a separate surface
and the front elements directly in the front buffer? Would it not be
simpler to draw everything in a backbuffer and then just do a flip
after the scene is composed? What am I missing?

Thanks in advance,

Ney Andr? de Mello Zunino.

"Take of the fruit,
But guard the seed…"On Tuesday, 09 October, 2001, Darrell Walisser wrote:

If redrawing the background is a pain, consider using a
double-buffered approach, where the back buffer only contains the
background pixels. For this, you wouldn’t use SDL_DOUBLEBUF, but
rather create the two buffers yourself. At each frame, you can draw
the background (if needed), copy the necessary parts to the front
buffer, and draw foreground objects into the front buffer. The back
buffer could be SDL_SWSURFACE or SDL_HWSURFACE, but if the latter,
the front should be SDL_HWSURFACE as well, to avoid copying pixels
from video RAM to system RAM.

What are the reasons for drawing the background in a separate surface
and the front elements directly in the front buffer? Would it not be
simpler to draw everything in a backbuffer and then just do a flip
after the scene is composed? What am I missing?

Well, keep in mind that you’ll need a dedicated buffer for the background.
This way, you’ll always be able to redraw the parts of the background that
were covered in the previous frame. Whether your background is made of
separate tiles or one surface, you can devise a method to only draw a
certain part of it to erase the sprite.

If you use a double-buffered surface, flipping will not solve the problem.
Because a flip logically switches the front buffer with the back buffer,
the backbuffer’s pixels after a flip will contain the previous frame’s
pixels.

Page-flipping is only truely advantageous for elminating tearing artifacts
to get super-smooth animation, since on some hardware it can sync to the
monitor’s refresh. On the other hardware, it will be much slower, as the
buffers must be copied from system RAM to video RAM each time you do a
flip. Worse yet, the window manager/server on the OS might already
double-buffer windows, which will then require an additional copy. Don’t
forget that before any of this happens, you are drawing stuff into the
back buffer!

Assuming a static background, the choices are as follows:

Slow on most hardware method (using SDL_DOUBLEBUF):

  1. Draw entire background to backbuffer
  2. Draw sprite in new location in backbuffer
  3. Flip

Lets look the best/worst case for this method:

best - all hardware surfaces (like perhaps DirectX)
worst - all software surfaces (like on Mac OS X, where windows are double
buffered and you can only draw into system RAM)

In the best case, this is very fast, since all copies are VRAM->VRAM.
But in the worst case…

  1. (RAM->RAM speed) * width * height
  2. (RAM->RAM speed) * sprite width * sprite height
  3. (RAM->RAM speed) * width * height + (RAM->VRAM speed) * width * height

Since RAM->RAM and RAM->VRAM speeds are many orders of magnitude slower
than a hardware flip, I think you can see how this could be slow.

Now the previously mentioned method which is fast on most hardware.

  1. Draw background(if changed) in dedicated buffer
  2. Draw parts of background to screen (to erase sprite)
  3. Draw Sprite at new location.
  4. UpdateRects

Lets look at the worst-case performance here:

  1. 0 ( assuming background is static and previously drawn)
  2. (RAM->RAM speed) * sprite width * sprite height
  3. (RAM->RAM speed) * sprite width * sprite height
  4. (RAM->VRAM speed) * sprite width * sprite height

This has been mentioned many times before on this list; if you want good
performance on a variety of systems, use UpdateRects and only redraw those
parts of the screen that change from frame to frame.

If the background is not static, the performance of this method drops off
to nearly the same as the first approach as you change more pixels in the
background from frame to frame. In this case, it will be dog slow without
hardware support on anything greater than 8bit color 640x480, so you may
as well use SDL_DOUBLEBUF.

This is my understand of drawing in SDL, please correct me if I am wrong.

-DarrellOn Tue, 9 Oct 2001, Ney Andr? de Mello Zunino wrote:

On Tuesday, 09 October, 2001, Darrell Walisser wrote: