Double buffering with XDGA 2.0

Hi -

I finally upgraded from an ancient pre-1.0 version of
SDL to the latest version (1.1.5) and have run into a
nasty surprise w.r.t. to how double buffering now works
with the dga driver (dga 2.0; xfree86 4.0.1; matrox/mga).

Under my old copy of SDL, when doublebuf is enabled
then the backbuf starts as a copy of the front buffer,
which my code then modifies as required, then calls for
a page flip. This appears to be true in 1.1.5 when the
SDL_DOUBLEBUF is false. However, if SDL_DOUBLEBUF is true,
then the front and back buffers are completely unrelated
(I assume this is is because the DGA extension is using
different memory banks for each buffer).

This makes sense given that in the first case double
buffering from probably implmented by copying the backbuf
to the screen memory during the vert retrace and in the
second by real page flipping (switching between displaying
two different physical memory blocks for each buffer during
the retrace). Is this correct??

My real problem is that code for one breaks on the
other, is there a correct way to deal with this? One
hack I’ve considered is to stick a wrapper on my
SDL_PageFlip to copy the new frontbuf to the backbuf
after each flip, but this seems a bit ugly.

I guess I was kind of surprised to find that my code
ran differently with SDL_DOUBLEBUF set and unset. I
had been working under the assumption that the flag
would only affect performance and tearing :frowning:

Thanks,
/jamie–
office: 510-643-3573 mail: 3210 Tolman Hall #1650
lab: 510-642-1950 U.C. Berkeley
fax: 510-642-5293 Berkeley, CA 94720-1650
email: @James_Mazer

However, if SDL_DOUBLEBUF is true,
then the front and back buffers are completely unrelated
(I assume this is is because the DGA extension is using
different memory banks for each buffer).

This is how page flipping is supposed to work

This makes sense given that in the first case double
buffering from probably implmented by copying the backbuf
to the screen memory during the vert retrace and in the
second by real page flipping (switching between displaying
two different physical memory blocks for each buffer during
the retrace). Is this correct??

Well, in the absence of page flipping you rarely get a guarantee that
the shadow surface is copied during vertical retrace. Usually it’s done
right away

My real problem is that code for one breaks on the
other, is there a correct way to deal with this? One
hack I’ve considered is to stick a wrapper on my
SDL_PageFlip to copy the new frontbuf to the backbuf
after each flip, but this seems a bit ugly.

SDL_DOUBLEBUF is an unfortunate name since double-buffering does not
necessary imply page-flipping capability. Check for SDL_DOUBLEBUF
and act accordingly. With page-flipping, your game either has to
repaint the entire screen each frame or keep track of the contents
two frames back instead of one

Mattias Engdeg?rd writes:

However, if SDL_DOUBLEBUF is true,
then the front and back buffers are completely unrelated

This is how page flipping is supposed to work

I understand that, unfortunately, I cheated 2 years ago and
recoded all my tools to take advantage of the "simulated"
page flipping in the old version and now I’ve been burned
by upgrading and switching to a faster card/x-server combo :frowning:

SDL_DOUBLEBUF is an unfortunate name since double-buffering does not
necessary imply page-flipping capability. Check for SDL_DOUBLEBUF
and act accordingly. With page-flipping, your game either has to
repaint the entire screen each frame or keep track of the contents
two frames back instead of one

Then perhaps I’m asking the wrong question – what I’m really
most concerned about is that updates to the physical video
ram occur ONLY during the retrace to avoid tearing. I’ve always
assumed that setting SDL_DOUBLEBUF and using PageFlip() would
safely address that concern. Can you have double buffering
without page flipping in SDL? I mean you could have an
on-screen shadow and blit the shadow to the screen during
the retrace with every call to PageFlip, if the blitter’s
fast enough, is this what happens if you don’t set SDL_DOUBLEBUF?
Will it still be properly locked to the retrace?

Part of the problem is that I really need something like
SDL_PageFlip() that can be used to block until the screen
is completely updated. This is for synchronization to
external events that depend upon what’s appearing on the
video screen (it’s not a game, it’s part of a data
realtime lab data collection system).

/jamie–
office: 510-643-3573 mail: 3210 Tolman Hall #1650
lab: 510-642-1950 U.C. Berkeley
fax: 510-642-5293 Berkeley, CA 94720-1650
email: @James_Mazer

I understand that, unfortunately, I cheated 2 years ago and
recoded all my tools to take advantage of the "simulated"
page flipping in the old version and now I’ve been burned
by upgrading and switching to a faster card/x-server combo :frowning:

Heheh.

Then perhaps I’m asking the wrong question – what I’m really
most concerned about is that updates to the physical video
ram occur ONLY during the retrace to avoid tearing. I’ve always
assumed that setting SDL_DOUBLEBUF and using PageFlip() would
safely address that concern.

If the returned video surface indeed has SDL_DOUBLEBUF set in the
flags, then the surface is set up for double-buffered page flipping,
and the flip occurs during the vertical retrace.

if the blitter’s fast enough, is this what happens if you don’t
set SDL_DOUBLEBUF?
Will it still be properly locked to the retrace?

No, most hardware will either support page flipping and vertical retrace,
or no vertical retrace sync at all. At some point (when the drivers have
advanced enough), I will provide a way to sync with vertical retrace, but
if you have to use SDL_UpdateRects(), it’s very likely that the underlying
driver doesn’t support vertical retrace sync.

Part of the problem is that I really need something like
SDL_PageFlip() that can be used to block until the screen
is completely updated.

The semantics of SDL_Flip() guarantee this. The SDL_Flip() and update
rect calls will block until the requested portions of the screen are
updated. When the video surface has double-buffering enabled, the flip
will indeed wait for the vertical retrace before returning.

This is for synchronization to
external events that depend upon what’s appearing on the
video screen (it’s not a game, it’s part of a data
realtime lab data collection system).

Very cool. :slight_smile:

See ya!
-Sam Lantinga, Lead Programmer, Loki Entertainment Software

Then perhaps I’m asking the wrong question – what I’m really
most concerned about is that updates to the physical video
ram occur ONLY during the retrace to avoid tearing. I’ve always
assumed that setting SDL_DOUBLEBUF and using PageFlip() would
safely address that concern.

In the absence of hardware page flipping, SDL_Flip() will do an
UpdateRects(screen, 0, 0, 0, 0). This is documented

Can you have double buffering
without page flipping in SDL? I mean you could have an
on-screen shadow and blit the shadow to the screen during
the retrace with every call to PageFlip, if the blitter’s
fast enough, is this what happens if you don’t set SDL_DOUBLEBUF?

I agree that this could be useful at times, and with accelerated
blitters it would not be much slower than page flipping. I’m not
sure if any drivers support this. Sam suggested a separation of
double-buffering and page-flipping in an earlier message, and I agree.

Will it still be properly locked to the retrace?

Only if hardware allows it (and SDL drivers support it). It would be nice
to have way to find out whether it is supported on a given target.

Part of the problem is that I really need something like
SDL_PageFlip() that can be used to block until the screen
is completely updated. This is for synchronization to
external events that depend upon what’s appearing on the
video screen (it’s not a game, it’s part of a data
realtime lab data collection system).

Everything’s a game :slight_smile: