Code that produces low framerates

Hello again,
so here is the init routine:

if ( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_AUDIO )
< 0 )
{
return;
}

back_buff = SDL_SetVideoMode( 800, 600, 16, SDL_HWSURFACE | SDL_DOUBLEBUF | SDL_HWACCEL );
if ( back_buff )  {
  set_rectangle( screen_rect, 0, 0, 800, 600 );
  SDL_ShowCursor( SDL_DISABLE );
  return;

}

The bitmap surfaces are loaded via LoadBitmap and converted to screen format using SDL_DisplayFormat.

My blit looks like this:
SDL_BlitSurface( background, NULL, back_buff, NULL );
SDL_BlitSurface( fruits[ball->type()], NULL, back_buff, &ball->r );
SDL_BlitSurface( paddels[0], NULL, back_buff, &player1->r );
SDL_BlitSurface( paddels[0], NULL, back_buff, &player2->r );

I could improve the framerate by using SDL_DisplayFormat, but 60 fps aren’t too much for a simple game like pong. My vertical refresh rate is 85 Hz, so it should produce at least 25 frames more.

Thank you,
Marc

Hello!

SDL_BlitSurface( background, NULL, back_buff, NULL );

You really shouldn’t redraw the whole background every frame.
Overdraw the old ball’s position, draw the new ball, same for
the paddels, flip(), and you’re off with much less MBytes
moved over the busses.

Ciao,
Eike

Hello!

SDL_BlitSurface( background, NULL, back_buff, NULL );

You really shouldn’t redraw the whole background every frame.
Overdraw the old ball’s position, draw the new ball, same for
the paddels, flip(), and you’re off with much less MBytes
moved over the busses.

OK, that’s probably right for this specific case, but for the sake of
the argument, it should be possible to do this on the specific hw,
shouldn’t it (with DGA or FB)? Imagine the background is animated, then
he cannot just resort to dirty rects, right?

latimeriusOn Mon, Nov 25, 2002 at 12:33:36PM +0100, Eike Sauer wrote:

Marc Essinger wrote:

Hello again,so here is the init routine: if ( SDL_Init(
SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_AUDIO )
< 0 )
{
return;
}

back_buff = SDL_SetVideoMode( 800, 600, 16, SDL_HWSURFACE |

SDL_DOUBLEBUF | SDL_HWACCEL );
if ( back_buff ) {
set_rectangle( screen_rect, 0, 0, 800, 600 );
SDL_ShowCursor( SDL_DISABLE );
return;
}

This looks OK.

SDL_BlitSurface( background, NULL, back_buff, NULL );

There’s your problem. As I mentioned before, you are blitting the
ENTIRE background, all 960K of it, every single frame. The only parts
you need to update are the spots where the ships are and the spots where
the ships have been.

This would be something along the lines of:

/Begin code block/

//Update the background where the players are and where they used to be
SDL_BlitSurface( background, &player1->r, back_buff, &player1->r );
SDL_BlitSurface( background, &player1->prev_r, back_buff,
&player1->prev_r );
SDL_BlitSurface( background, &player2->r, back_buff, &player2->r );
SDL_BlitSurface( background, &player2->prev_r, back_buff,
&player2->prev_r );

//Update where the ball is and where it used to be
SDL_BlitSurface( background, &ball->r , back_buff, &ball->r );
SDL_BlitSurface( background, &ball->prev_r , back_buff, &ball->prev_r );

//Draw the players and ball
SDL_BlitSurface( paddels[0], NULL, back_buff, &player1->r );
SDL_BlitSurface( paddels[0], NULL, back_buff, &player2->r );
SDL_BlitSurface( fruits[ball->type()], NULL, back_buff, &ball->r );

/End code block/

The prev_r member I’m using represents the rectangle the sprite occupied
in the last frame. If your sprites don’t have anything like that, then
put it in 'cause you’ll need it.

Let me ask the most basic question first, you are using SDL_flip and not
SDL_UpdateRect after you’ve updated back_buf? You aren’t using a frame
limiter of any sort are you like WaitFrame? What video card are you
currently using? I ask these questions only because I can’t see
anything obviously wrong with the code you’ve listed.

gotta sleep,
RobertOn Mon, 2002-11-25 at 05:01, Marc Essinger wrote:

Hello again,
so here is the init routine:

if ( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_AUDIO )
< 0 )
{
return;
}

back_buff = SDL_SetVideoMode( 800, 600, 16, SDL_HWSURFACE | SDL_DOUBLEBUF | SDL_HWACCEL );
if ( back_buff )  {
  set_rectangle( screen_rect, 0, 0, 800, 600 );
  SDL_ShowCursor( SDL_DISABLE );
  return;

}

The bitmap surfaces are loaded via LoadBitmap and converted to screen format using SDL_DisplayFormat.

My blit looks like this:
SDL_BlitSurface( background, NULL, back_buff, NULL );
SDL_BlitSurface( fruits[ball->type()], NULL, back_buff, &ball->r );
SDL_BlitSurface( paddels[0], NULL, back_buff, &player1->r );
SDL_BlitSurface( paddels[0], NULL, back_buff, &player2->r );

I could improve the framerate by using SDL_DisplayFormat, but 60 fps aren’t too much for a simple game like pong. My vertical refresh rate is 85 Hz, so it should produce at least 25 frames more.

Thank you,
Marc

back_buff = SDL_SetVideoMode( 800, 600, 16,
SDL_HWSURFACE | SDL_DOUBLEBUF | SDL_HWACCEL );

SDL_HWACCEL is not a valid flag for SDL_SetVideoMode. Since you did
not specify SDL_FULLSCREEN, you probably did not get a hwsurface,
but a swsurface, which is slower for your purposes (blitting). If
your desktop is not 16-bit mode, you did not get a 16-bit surface,
either, but SDL will emulate it. To prevent this emulation from
happening, you should pass the SDL_ANYFORMAT flag.–
Matthijs Hollemans
www.allyoursoftware.com

Let me put my two cents on the table, or actually probably four after
the last comments. It is really rather processor/video card dependent
if you can or cannot accomplish this 800x600 full screen animation
thing. However, I would expect that you shouldn’t have that much of a
problem getting at least a somewhat reasonable frame rate. The
fullscreen animations I am currently running at 800x600x32 have to be
frame limited to 50fps, because they are running so fast. Now, this is
not so surprising, since I am running an Nforce1 Athelon 1400+.
However, this system is very serious overkill and I cannot imagine that
you couldn’t get the refresh rate you wanted with half to a quarter of
this systems resources.

RobertOn Mon, 2002-11-25 at 05:42, Corona688 wrote:

Marc Essinger wrote:

Hello again,so here is the init routine: if ( SDL_Init(
SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_AUDIO )
< 0 )
{
return;
}

back_buff = SDL_SetVideoMode( 800, 600, 16, SDL_HWSURFACE |

SDL_DOUBLEBUF | SDL_HWACCEL );
if ( back_buff ) {
set_rectangle( screen_rect, 0, 0, 800, 600 );
SDL_ShowCursor( SDL_DISABLE );
return;
}

This looks OK.

SDL_BlitSurface( background, NULL, back_buff, NULL );

There’s your problem. As I mentioned before, you are blitting the
ENTIRE background, all 960K of it, every single frame. The only parts
you need to update are the spots where the ships are and the spots where
the ships have been.

This would be something along the lines of:

/Begin code block/

//Update the background where the players are and where they used to be
SDL_BlitSurface( background, &player1->r, back_buff, &player1->r );
SDL_BlitSurface( background, &player1->prev_r, back_buff,
&player1->prev_r );
SDL_BlitSurface( background, &player2->r, back_buff, &player2->r );
SDL_BlitSurface( background, &player2->prev_r, back_buff,
&player2->prev_r );

//Update where the ball is and where it used to be
SDL_BlitSurface( background, &ball->r , back_buff, &ball->r );
SDL_BlitSurface( background, &ball->prev_r , back_buff, &ball->prev_r );

//Draw the players and ball
SDL_BlitSurface( paddels[0], NULL, back_buff, &player1->r );
SDL_BlitSurface( paddels[0], NULL, back_buff, &player2->r );
SDL_BlitSurface( fruits[ball->type()], NULL, back_buff, &ball->r );

/End code block/

The prev_r member I’m using represents the rectangle the sprite occupied
in the last frame. If your sprites don’t have anything like that, then
put it in 'cause you’ll need it.


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

Imagine the background is animated, then
he cannot just resort to dirty rects, right?

You’re right, for a Nemesis/Gradius type of game
(scrolling all the time), we wouldn’t get away with that.
And I feel this should be possible on our hardware,
even if it isn’t anymore accelerated for that type
of graphics.

Ciao,
Eike