SDL_Flip() and SDL_DOUBLEBUF questions

Hi all,

My questions are:

  1. SDL_Flip():
    For performance reasons I draw on the screen only the new
    changes. However after SDL_Flip() the new buffer will/may
    not be up-to-date with the latest changes.
    This is not an issue with SDL_SWSURFACE.
    So I suppose I must have a flag to indicate whether the last
    changes need to be drawn again for the current surface.
    This is not very convenient.

  2. SDL_DOUBLEBUF:
    I noticed that SDL_DOUBLEBUF makes the screen flicker
    when the game is started in the console framebuffer (fbcon).

    I read somewhere here to switch to SDL_SWSURFACE.

    However I want to use SDL_DOUBLEBUF to squeeze all I can
    from the hardware (arm cpu: xscale PXA250 with built in
    LCD controller)
    I made some changes in the framebuffer driver (pxafb.c)
    that allocates more memory to fit in the two pages,
    but I notice that the drawing always happens in the
    page that is currently being displayd.

The question is:
Who is responsible for this?

  • The SDL library which does not initialize properly the
    screen->pixels to point to the other page
  • or the fb driver which when started begins to display the image
    at offset 0x0 of the allocated memory.

Hi all,

My questions are:

  1. SDL_Flip():
    For performance reasons I draw on the screen only the new
    changes. However after SDL_Flip() the new buffer will/may
    not be up-to-date with the latest changes.
    This is not an issue with SDL_SWSURFACE.
    So I suppose I must have a flag to indicate whether the last
    changes need to be drawn again for the current surface.
    This is not very convenient.

The easiest way to explain this might be with a simple scenario. Using
double buffering, if I were to draw a square to the back buffer, then
continually flip the screen, I’d see the square blinking.

What is most likely happening to you is that HALF of your drawing is
the most being displayed at any one time. That seems rather unlikely
since I’d guess you would be able to tell if that was happening.
However, I don’t know the intricacies of your code, perhaps it’s not as
obvious as I imagine. Try blitting the contents of the front buffer
back to the back buffer after each page flip, that way you’re always
drawing on the latest frame’s contents.

  1. SDL_DOUBLEBUF:
    I noticed that SDL_DOUBLEBUF makes the screen flicker
    when the game is started in the console framebuffer (fbcon).

Flickering you say? That certainly seems to corroborate my theory about
what’s going on :wink:

I read somewhere here to switch to SDL_SWSURFACE.

However I want to use SDL_DOUBLEBUF to squeeze all I can
from the hardware (arm cpu: xscale PXA250 with built in
LCD controller)

I’m curious why using double buffering is “squeezing all you can from
the hardware controller.” Perhaps you could elaborate on this?

I made some changes in the framebuffer driver (pxafb.c)
that allocates more memory to fit in the two pages,
but I notice that the drawing always happens in the
page that is currently being displayd.

I’ve never modified the SDL source code, so I can’t help you much here.
But here’s a shot in the dark: is it possible that your custom SDL
library is never actually giving your application a pointer to the back
buffer? Perhaps your application is only ever drawing to the front
buffer because the library fails to swap the pointer to which the
application draws to during the SDL_Flip function. It’s just a guess
though.

The question is:
Who is responsible for this?

  • The SDL library which does not initialize properly the
    screen->pixels to point to the other page

Yeah that sounds like what I was saying might be possible. Related to
your changes perhaps? Perhaps not, you don’t sound like you’re using
very common hardware.

  • or the fb driver which when started begins to display the image
    at offset 0x0 of the allocated memory.

I wish I could help you here but I honestly have no idea. I hope
someone else can field this question for you.

Good luck, hope I was useful.On Sep 8, 2004, at 9:27 AM, Velyo Chanin wrote:

Thanks for the answers.
I’ll try to be more specific:============
1.

This is the scenario:
Start game: I have 2 hardware buffers (1 and 2) initialized to black.

1st cycle (buffer 1): I draw two objects (A and B).
call SDL_Flip()

2nd cycle (buffer 2): Only object B has changed.
I draw object B only.
call SDL_Flip()

3rd cycle (buffer 1): Here object B is not up-to-date

I am drawing only the changes (object B) for performance reasons.
So blitting between the two buffers after each page flip doesn’t
help to increase the performance.
What first comes to my mind is not to unset the “object_changed” flag
for two consecutive frames.

============
2.

I’m curious why using double buffering is “squeezing all you can from
the hardware controller.” Perhaps you could elaborate on this?

Here is what I can say about this:

With SDL_SWSURFACE a call to SDL_Flip() takes approximately 20~30 ms.
I have approximately 10 frames per second.

With SDL_HWSURFACE SDL_Flip() takes 0 ms (zero).
without SDL_DOUBLEBUF all the drawing takes place
on the screen directly,
and I want the new frame to be displayed only when ready.
That’s why I use SDL_DOUBLEBUF.

============
3.

So about the framebuffer driver:
I made a change to support double buffering
(implemented FBIOPAN_DISPLAY ioctl call)
I did not touch the SDL source code.
And I noticed that the drawing happens on the front buffer
(not the hidden back buffer).
So I guess that somewhere in the SDL source code
there is a bug when initialized with the flag SDL_DOUBLEBUF.
I suppose that screen->pixels is not initialized with the
backbuffer, but with the front buffer.
This is just a speculation though.
I’ll look at the SDL source code when I have time.

Any way, this was just a clarification.

Thanks for your answers
Velyo

This is the scenario:
Start game: I have 2 hardware buffers (1 and 2) initialized to black.

1st cycle (buffer 1): I draw two objects (A and B).
call SDL_Flip()

2nd cycle (buffer 2): Only object B has changed.
I draw object B only.
call SDL_Flip()

At this point, object A is not shown, because you didn’t draw it on
buffer 2. When you actually have 2 hardware buffers and are flipping
between them, you need to update for changes on each buffer separately.

See ya,
-Sam Lantinga, Software Engineer, Blizzard Entertainment

Hi,

It sounds like you are using something like dirty rectangles. Now, maybe
I’m mistaken, but using dirty rectangles in a double-buffered set up
will mean having to keep track of changes not since last frame, but from
the frame before that, which may be considered too much bookkeeping.
(To enlighten me, is there anybody out there actually using this approach?)
If your application is a 2D game or something (with mostly static
backgrounds) or the like, you may be better off having a single buffer
only (aka the screen) and have your sprites (if applicable) in video
memory and just blit them to the screen when needed (video memory to
video memory copies may not be as fast as page flips, but they are quite
fast.)

The whole lot above may no be applicable or downright wrong, so let’s
have the more-experienced people’s ideas on this too.

-yzt

Velyo Chanin wrote:> Thanks for the answers.

I’ll try to be more specific:

============
1.

This is the scenario:
Start game: I have 2 hardware buffers (1 and 2) initialized to black.

1st cycle (buffer 1): I draw two objects (A and B).
call SDL_Flip()

2nd cycle (buffer 2): Only object B has changed.
I draw object B only.
call SDL_Flip()

3rd cycle (buffer 1): Here object B is not up-to-date

I am drawing only the changes (object B) for performance reasons.
So blitting between the two buffers after each page flip doesn’t
help to increase the performance.
What first comes to my mind is not to unset the “object_changed” flag
for two consecutive frames.

============
2.

I’m curious why using double buffering is “squeezing all you can from
the hardware controller.” Perhaps you could elaborate on this?

Here is what I can say about this:

With SDL_SWSURFACE a call to SDL_Flip() takes approximately 20~30 ms.
I have approximately 10 frames per second.

With SDL_HWSURFACE SDL_Flip() takes 0 ms (zero).
without SDL_DOUBLEBUF all the drawing takes place
on the screen directly,
and I want the new frame to be displayed only when ready.
That’s why I use SDL_DOUBLEBUF.

============
3.

So about the framebuffer driver:
I made a change to support double buffering
(implemented FBIOPAN_DISPLAY ioctl call)
I did not touch the SDL source code.
And I noticed that the drawing happens on the front buffer
(not the hidden back buffer).
So I guess that somewhere in the SDL source code
there is a bug when initialized with the flag SDL_DOUBLEBUF.
I suppose that screen->pixels is not initialized with the
backbuffer, but with the front buffer.
This is just a speculation though.
I’ll look at the SDL source code when I have time.

Any way, this was just a clarification.

Thanks for your answers
Velyo


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

Sam Lantinga wrote:

This is the scenario:
Start game: I have 2 hardware buffers (1 and 2) initialized to black.

1st cycle (buffer 1): I draw two objects (A and B).
call SDL_Flip()

2nd cycle (buffer 2): Only object B has changed.
I draw object B only.
call SDL_Flip()

At this point, object A is not shown, because you didn’t draw it on
buffer 2. When you actually have 2 hardware buffers and are flipping
between them, you need to update for changes on each buffer separately.

See ya,
-Sam Lantinga, Software Engineer, Blizzard Entertainment
Sorry if this is a stupid Question, but how can i write to each buffer?
I mean, i thought i only must write to the surface i flip?

Quoth Benjamin Sonnemann <B.Sonnemann at t-online.de>, on 2004-09-17 01:12:28 +0200:

Sorry if this is a stupid Question, but how can i write to each buffer?
I mean, i thought i only must write to the surface i flip?

But when you’re double-buffering you have two buffers that correspond
to the same “surface”. You’re generally always drawing to the back
buffer, whereas the front buffer is what’s being displayed; then the
flip operation causes the back buffer to become the new front buffer
et vice versa. Example (someone correct this if I’ve made glaring
mistakes, please):

          Back buffer               Front buffer
          -----------               ------------

Start (empty) (empty)

Draw square square (empty)

Flip! (empty) square

Draw circle circle square

Flip! square circle

                                No square in front buffer!

If you wanted the square to appear in the front buffer in this case,
you would also have to draw it on the second buffer:

          Back buffer               Front buffer
          -----------               ------------

Start (empty) (empty)

Draw square square (empty)

Flip! (empty) square

Draw square square square

Draw circle circle square
square

Flip! square circle
square

Incremental drawing on double-buffered video surfaces tends to be a
pain, for this reason; my impression is that mostly when drawing to
double-buffered surfaces, people simply clear the buffer at each
frame, then redraw everything, since it’s significantly easier…

—> Drake Wilson

-------------- next part --------------
A non-text attachment was scrubbed…
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20040916/4de2c1a9/attachment.pgp

One thing I’ve been telling people for quite some time is to blit the
contents of the front buffer onto the back buffer immediately after
flipping (or vice versa, immediately before flipping.) However, this
seems to suggest you can’t do this in SDL:

  • SDL_Flip(). This is usually slower than the normal single-buffering
  • scheme, but prevents “tearing” artifacts caused by modifying video
  • memory while the monitor is refreshing. It should only be used by
  • applications that redraw the entire screen on every update.

I think I used to do this using DirectX, or possibly some other
graphics API, and somehow got it into my head that you could do it in
SDL as well.

The solution then would be to either recreate the screen from scratch
each frame, or, sync the contents of both buffers. Keeping then
synchronized may be less costly depending on your particular
application, but here are a few simple steps that can get you
synchronizing in no time.

First, if you haven’t already done so, disassociate all drawing
routines from “progress” routines. This means that code that affects
the game’s state should be separated from the code that affects the
screen’s state.

Second, alter your main game routine so that it progress your game
state first, and performs actual drawing second.

Third, after performing the flip, simply reinvoke the same code you
used to draw the last frame, only this time, you will be operating on
what will become your future drawing surface.

I hope I wasn’t too ambiguous with step three. No matter, I think it’s
not too hard to understand even if I neglected to actually spell out
step three anyhow.

Hope this helps.On Sep 16, 2004, at 11:24 PM, Drake Wilson wrote:

Quoth Benjamin Sonnemann <B.Sonnemann at t-online.de>, on 2004-09-17
01:12:28 +0200:

Sorry if this is a stupid Question, but how can i write to each
buffer?
I mean, i thought i only must write to the surface i flip?

But when you’re double-buffering you have two buffers that correspond
to the same “surface”. You’re generally always drawing to the back
buffer, whereas the front buffer is what’s being displayed; then the
flip operation causes the back buffer to become the new front buffer
et vice versa. Example (someone correct this if I’ve made glaring
mistakes, please):

          Back buffer               Front buffer
          -----------               ------------

Start (empty) (empty)

Draw square square (empty)

Flip! (empty) square

Draw circle circle square

Flip! square circle

                                No square in front buffer!

If you wanted the square to appear in the front buffer in this case,
you would also have to draw it on the second buffer:

          Back buffer               Front buffer
          -----------               ------------

Start (empty) (empty)

Draw square square (empty)

Flip! (empty) square

Draw square square square

Draw circle circle square
square

Flip! square circle
square

Incremental drawing on double-buffered video surfaces tends to be a
pain, for this reason; my impression is that mostly when drawing to
double-buffered surfaces, people simply clear the buffer at each
frame, then redraw everything, since it’s significantly easier…

—> Drake Wilson


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