Blitting Speed/Surface formats

My game was going really slowly - around 28fps most of the time. I was
doing very little:

- clear the screen (blit a black rectangle onto the screen)
- render 100 60x40 animated tiles on an 800x600 screen surface
- render a few animated sprites
- repeat

I guessed that it might have something to do with my loading functions
(I wasn’t really bothering to think about pixel formats/bitdepth). This
is what I was doing to load spritemaps:

- loadBMP the whole animation strip	
- create a frame template/buffer surface of the size of one frame (no 

proper formatting at all)

repeat for all frames {
- convert the template to the format of the original strip, and put 

this new empty surface where I want my final loaded surface frame to be
- blit a frame from the complete strip into where I want it to go
}

So I saw this was wrong. I changed it to this:

- loadBMP the whole animation strip
- create a frame buffer with the format of the strip

repeat for all frames {
	- blit a frame from the strip onto the buffer
	- convert buffer to format of screen as I put it where I want it
}

That algorithm seems to make a lot more sense - but it doesn’t work.
SDL only seems to draw some of the frames, but not others! It
definitely seems to be faster though. How should I be doing this?

Thanks,
–Joe

Hello,

You should do something like this :

  • load your animation with loadBMP
  • convert it to the screen format (SDL_DisplayFormat)

-loop {
blit directly from the converted surface to the screen. You needn’t a
temporary surface for that.
}

If your game redraws the whole screen each frame, you needn’t to render the
black rectangle, call SDL_Flip().

Also, if you setup your screen to 800x600x32 with a SW surface, remember
that it represents a lot of data to transfer from the system memory to the
video memory. It’s around 1.8Mo per frame, so if you want 50 frames per
second … There is not this problem HW surfaces are available.

Hope that helps

Julien> ----- Original Message -----

From: joseph@mansefield.net (Joseph Humfrey)
To: “SDL Mailing List”
Sent: Monday, April 07, 2003 12:59 AM
Subject: [SDL] Blitting Speed/Surface formats

My game was going really slowly - around 28fps most of the time. I was
doing very little:

  • clear the screen (blit a black rectangle onto the screen)
  • render 100 60x40 animated tiles on an 800x600 screen surface
  • render a few animated sprites
  • repeat

I guessed that it might have something to do with my loading functions
(I wasn’t really bothering to think about pixel formats/bitdepth). This
is what I was doing to load spritemaps:

  • loadBMP the whole animation strip
  • create a frame template/buffer surface of the size of one frame (no
    proper formatting at all)

repeat for all frames {

  • convert the template to the format of the original strip, and put
    this new empty surface where I want my final loaded surface frame to be
  • blit a frame from the complete strip into where I want it to go
    }

So I saw this was wrong. I changed it to this:

  • loadBMP the whole animation strip
  • create a frame buffer with the format of the strip

repeat for all frames {

  • blit a frame from the strip onto the buffer
  • convert buffer to format of screen as I put it where I want it
    }

That algorithm seems to make a lot more sense - but it doesn’t work.
SDL only seems to draw some of the frames, but not others! It
definitely seems to be faster though. How should I be doing this?

Thanks,
–Joe


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

You should do something like this :

  • load your animation with loadBMP
  • convert it to the screen format (SDL_DisplayFormat)

-loop {
blit directly from the converted surface to the screen. You
needn’t a
temporary surface for that.
}

Okay great, thanks - yeah that’s much better way of doing things - I’ve
changed it now and the code is a lot nicer and shorter :slight_smile:

But the speed problems are still there! Still fluctuating between 20
and 30 fps, even though I’m now using a hardware surface now, limiting
to 16bpp, and only making the screen 640x480! I’m using an iMac with a
800Mhz G4/GeForce4mx - there is NO way that it shouldn’t be able to
cope.

When I was doing other stuff on my Duron 850 (not using SDL - I was
actually using a game coding language - blitzbasic - should be slow,
right?), I could render a background picture (800x600) every frame to
the background as well as doing loads of stuff on top, and get
consistent 60fps (my refresh rate). I know the Ge4mx cards aren’t great
(what I have in this imac), but they’re at least comparable with a GeF2
(not mx) aren’t they?

But that shouldn’t even be an issue - so far I’m doing so little
blitting (just blitting a screen full of tiles). They’ve been doing
that for years (admittedly at 8bit and lower, but surely today’s
computers should cope?)

If your game redraws the whole screen each frame, you needn’t to
render the
black rectangle, call SDL_Flip().

Well, you see sometimes you get to the edge of the map, and I need a
black background or I get the blurring effects. What was strange though
was that when I did turn off the black rect, it speeded up by around
10fps! I was getting between 30 and 40fps instead of 20-30. To blit a
640x480 black rectangle?! What’s going on there?!

Hmm, something’s going wrong here!

–Joe

When I was doing other stuff on my Duron 850 (not using SDL - I was
actually using a game coding language - blitzbasic - should be slow,
right?), I could render a background picture (800x600) every frame to
the background as well as doing loads of stuff on top, and get
consistent 60fps (my refresh rate).

I think BlitzBasic uses directly Directx, and uses it well. So even if it’s
interpretted, it gives good graphical performances. You can make good games
will Python as well.

If your game redraws the whole screen each frame, you needn’t to
render the
black rectangle, call SDL_Flip().

Well, you see sometimes you get to the edge of the map, and I need a
black background or I get the blurring effects.

I think you should modify your code so that you always have an entire map
displayed. For example, for horizontal moves, when you have displayed the
last column ot the map it should stop scrolling horizontally. I think that
the result would be better, IMHO. It would give a result like in zelda on
SuperNES. If you want to keep your actual method, you could blit just the
smallest possible rectangle and not a whole screen rectangle.

Now, back to SDL problem.

If you don’t see any performance changes, maybe there is no support for
hardware surface for the mac. I don’t know what is supported by the mac
version of SDL, but there is a method to know this. Request a video mode
with the HW surface flag, I think you must also add the fullscreen flag.
Next you have to look in the flags of the returned surface to see if it’s
video memory or in system memory. Do something like this :
if(surface->flags & SDL_HWSURFACE) print(“surface in vid. mem”);
else print(“surface in system mem”);

If you are sure you can use HW surfaces then you can add the flags
SDL_DOUBLEBUF|SDL_FULLSCREEN and redo the the above test to see if you can
have double buffering. If it’s ok you can call the SDL_Flip function after
the frame drawing. This way you have two buffers : one is displayed and you
draw in the other. SDL_Flip just exchange the pointers, so it’s really fast
since it doesn’t imply data copying, but it’s only available in fulscreen
with HW surfaces.

The problem may be in another part of your game. The video init is
important, but there may be a bottleneck in an other part of your game. You
could extract the video part and send it, to see if the problem is
elsewhere. If it’s too big send to me directly (with the data).

If you can have HW surfaces with double buffering you should be able to have
60 fps (at least in 640x480x16)

Julien

I think BlitzBasic uses directly Directx, and uses it well. So even if
it’s
interpretted, it gives good graphical performances.

Yep it uses directx, and it’s compiled, not interpreted. But why
shouldn’t SDL be as fast as directx?

I think you should modify your code so that you always have an entire
map
displayed.

Yeah, I tried that, but I found the algorithm surprisingly difficult
because of knowing when to scroll and when not to scroll… I won’t go
into those problems here though - that’s another story :slight_smile:

If you want to keep your actual method, you could blit just the
smallest possible rectangle and not a whole screen rectangle.

Yeah, I might do that.

Now, back to SDL problem.

[…] Do something like this :
if(surface->flags & SDL_HWSURFACE) print(“surface in vid. mem”);
else print(“surface in system mem”);

Okay, I did this, and you’re right, for it to use hardware it must be
fullscreen. And that worked - apparently it can use hardware. BUT, not
only was it still really slow, but it had nasty tearing effects due to
the frame buffer being displayed in mid-draw.

If you are sure you can use HW surfaces then you can add the flags
SDL_DOUBLEBUF|SDL_FULLSCREEN and redo the the above test to see if you
can
have double buffering. If it’s ok […]

It’s not okay! :frowning: I have no idea why, but for some reason, the double
buffering flag wouldn’t work - I tried testing to see if it had worked
using the method you described above ( if(surface->flags &
SDL_DOUBLEBUF) ).

you can call the SDL_Flip function after
the frame drawing.

I used this before anyway… but it seems that the problem is with
getting double buffering to work.

Perhaps this was why I found BlitzBasic to be so fast - I never used
anything but double buffering, but now I don’t have it :-/
Frustrating… I wish I could find out what is stopping double
buffering from working. Should I maybe send another message the list
since someone who knows the answer might not have bothered reading the
rest?

Thanks,
–Joe

Yep it uses directx, and it’s compiled, not interpreted. But why
shouldn’t SDL be as fast as directx?

SDL is as fast as directx but under windows.

[…] Do something like this :
if(surface->flags & SDL_HWSURFACE) print(“surface in vid. mem”);
else print(“surface in system mem”);
Okay, I did this, and you’re right, for it to use hardware it must be
fullscreen. And that worked - apparently it can use hardware. BUT, not
only was it still really slow, but it had nasty tearing effects due to
the frame buffer being displayed in mid-draw.

I think I can help you a bit more if you send me your program.

Should I maybe send another message the list
since someone who knows the answer might not have bothered reading the
rest?

Yes, I don’t know anything about the Mac version, but there are people on
this list that have Mac (there is often question about mac problems) that
may know what is possible with a Mac and what is not. So maybe you should
repost your problem with “Mac” in the subject.

Julien