Bug in SDL DGA driver

Hi!

Tiny little bug in SDL I’ve found:

In SDL_dgavideo.c:

843: static int DGA_FlipHWSurface(_THIS, SDL_Surface surface)
844: {
845: int yoffset;
846:
847: /
Wait for vertical retrace and then flip display /
848: yoffset = flip_page
surface->h;
849: while ( XDGAGetViewportStatus(DGA_Display, DGA_Screen) )
850: /* Keep waiting for the hardware … */ ;
851: XDGASetViewport(DGA_Display, DGA_Screen, 0, yoffset, XDGAFlipRetrace);
852: flip_page = !flip_page;
853:
854: surface->pixels = flip_address[flip_page];
855: return(0);
856: }

Notice that the code is waiting for all pending XDGASetViewport() requests
on line 849. After that it calls XDGASetViewport(). This of course is
totally wrong since it defeat the whole purpose of doing it in the first
place (which is to wait for the vertical retrace to end before switching the
viewport).

What happens in above case is that it waits for the previous viewport change
to complete and then flips it which causes all kinds of flickering.

If you first change the viewport and then polls till it completes you get
the desired effect, i.e. it should be:

849: XDGASetViewport(DGA_Display, DGA_Screen, 0, yoffset, XDGAFlipRetrace);
850: while ( XDGAGetViewportStatus(DGA_Display, DGA_Screen) )
851: /* Keep waiting for the hardware … */ ;

Try it. Make a huge difference (;

Btw, I’d really like to make a suggestion here (one of the main reasons I’m
not keen on using SDL for my projects):

I’d really appreciate it if you guys could change SDL_Flip() from

int SDL_Flip(SDL_Surface *screen);

to

int SDL_Flip(SDL_Surface *screen,int wait_for_vertical_refresh);

Sometimes, especially when programming, it is desirable to disable waiting
for the vertical refresh so that one can get a clear indication of the
framerate achieved.

Forcing people to wait for the screen refresh isn’t very cool…

In fact, I think waiting for the vertical refresh and flipping the screen
shouldn’t even be in the same function since almost always it’s better to
first wait for the vertical refresh, then draw everything, flip it to the
screen, etc. E.g.

SDL_WaitForRefresh ();
draw_all_my_stuff_on_buffer ();
SDL_Flip ();
clear_all_my_stuff_on_buffer ();-- 

Regards
Abraham


Abraham vd Merwe [ZR1BBQ] - Frogfoot Networks
P.O. Box 3472, Matieland, Stellenbosch, 7602
Cell: +27 82 565 4451 - Tel: +27 21 887 8703
Http: http://www.frogfoot.net
Email: @Abraham_vd_Merwe

-------------- next part --------------
A non-text attachment was scrubbed…
Name: not available
Type: application/pgp-signature
Size: 232 bytes
Desc: not available
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20010109/7f0133d5/attachment.pgp

Abraham vd Merwe wrote:

What happens in above case is that it waits for the previous viewport change
to complete and then flips it which causes all kinds of flickering.

I don’t see how this can cause flickering. This is what’s supposed to happen:

client calls SDL_Flip():
waits for previous flip to complete
XDGASetViewport() to the other buffer (to complete asynchronously)

client draws something on the screen (either by locking the display and
bashing bits directly or by doing a BlitSurface or FillRect):
DGA_WaitHardware() waits for above XDGASetViewport to take effect
(in essence waiting for retrace)
client then updates the not currently displayed buffer

client calls SDL_Flip():
waits for the flip above to complete, which is a no-op (since the client
already did a wait when drawing something to the screen)
XDGASetViewport() to the other buffer (to complete asynchronously)

If you still find flickering that is a bug in your code or possibly in SDL.
Please post a minimal but complete example that exhibits the problem

If you first change the viewport and then polls till it completes you get
the desired effect, i.e. it should be:

849: XDGASetViewport(DGA_Display, DGA_Screen, 0, yoffset, XDGAFlipRetra=
ce);
850: while ( XDGAGetViewportStatus(DGA_Display, DGA_Screen) )
851: /* Keep waiting for the hardware … */ ;

If this makes a difference then you are doing something wrong. Perhaps
you have forgotten to lock the screen before accessing pixels on it?
Your change will only defeat the attempt to avoid blocking for retrace
until absolutely necessary

Sometimes, especially when programming, it is desirable to disable waiting
for the vertical refresh so that one can get a clear indication of the
framerate achieved.

This makes no sense. Measure the time over several frames, divide by the
number of frames, and you get the frame rate

This makes no sense. Measure the time over several frames, divide by the
number of frames, and you get the frame rate

er, the inverted frame rate :slight_smile:

I assume hes talking about performance testing here. In the real world,
drawing more frames than can actually be displayed is of course as futile as
capacitance…uh…resistance. However, if you want to see how well your
code/hardware is performing it is handy to be able to unthrottle it.On Tue, Jan 09, 2001 at 11:15:39AM +0100, Mattias Engdegard wrote:

Sometimes, especially when programming, it is desirable to disable waiting
for the vertical refresh so that one can get a clear indication of the
framerate achieved.

This makes no sense. Measure the time over several frames, divide by the
number of frames, and you get the frame rate

Martin

Bother! said Pooh, as Garak told an obvious lie.

What happens in above case is that it waits for the previous viewport change
to complete and then flips it which causes all kinds of flickering.

As Mattias said, the code tries to perform the flip asynchronously if
possible, only blocking for the flip to complete on the lock or the next
flip. If this causes flickering, then either there is a bug in the
underlying XFree86 DGA driver (possible, depending on the hardware),
or you are not locking the video memory before accessing it.

I’d really appreciate it if you guys could change SDL_Flip() from

int SDL_Flip(SDL_Surface *screen);

to

int SDL_Flip(SDL_Surface *screen,int wait_for_vertical_refresh);

This kind of API change may be included for SDL 1.3 (or a completely
new API for handling refresh rates and VBL synchronization).

Forcing people to wait for the screen refresh isn’t very cool…

You are always welcome to disable the refresh wait code in the SDL
driver if you are doing specific benchmarking. The reason the refresh
code isn’t generally exposed, is that it’s not supported on any windowed
driver, and is supported on only a couple of fullscreen drivers. In order
for an SDL API to be exposed, the functionality should be available on
at least most of the common platforms and drivers.

In fact, I think waiting for the vertical refresh and flipping the screen
shouldn’t even be in the same function since almost always it’s better to
first wait for the vertical refresh, then draw everything, flip it to the
screen, etc. E.g.

SDL_WaitForRefresh ();

draw_all_my_stuff_on_buffer ();
SDL_Flip ();
clear_all_my_stuff_on_buffer ();

In the double buffered case, this isn’t necessary. You can draw on the
back buffer at any time, and then flip during the vertical refresh, which
is what the SDL_DOUBLEBUF code is designed to do. More than that isn’t
currently supported in SDL (though may be in SDL 1.3)

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

It indeeds makes a lot of sense, since if your application is limited at
60fps due to the vertical blank, you cannot have any idea about how fast it
could get without it. This is at least true under Win32.

Moreover, looking at the DX5 video implementation, I can see that
DDFLIP_WAIT flag is always specified. In this way, the flipping call is
syncronous, at it waits till the real flip happens (instead of just
scheduling the flip, as the SDL documentation says). This is very bad in
case of triple buffering, but it seems that SDL does not support triple
buffering. Do you think it is feasable for the future? It would be just
great.—
Giovanni Bajo
Lead Programmer

Protonic Interactive
www.protonic.net

  • Black holes are generated when God divides by zero -

-----Messaggio originale-----
Da: owner-sdl at lokigames.com [mailto:owner-sdl at lokigames.com]Per conto di
Mattias Engdeg?rd
Inviato: marted? 9 gennaio 2001 11.52
A: sdl at lokigames.com
Cc: abz at frogfoot.net
Oggetto: Re: [SDL] bug in SDL DGA driver

This makes no sense. Measure the time over several frames, divide by the
number of frames, and you get the frame rate

er, the inverted frame rate :slight_smile:

It indeeds makes a lot of sense, since if your application is limited at
60fps due to the vertical blank, you cannot have any idea about how fast it
could get without it. This is at least true under Win32.

If you just want to profile your code, then don’t flip at all

Moreover, looking at the DX5 video implementation, I can see that
DDFLIP_WAIT flag is always specified. In this way, the flipping call is
syncronous, at it waits till the real flip happens (instead of just
scheduling the flip, as the SDL documentation says).

That sounds wrong — someone who knows DirectX should look at that

This is very bad in
case of triple buffering, but it seems that SDL does not support triple
buffering. Do you think it is feasable for the future? It would be just
great.

I personally think the usefulness of triple buffering is limited, but
it might be worth supporting anyway. It probably requires an api
revision though

-----Messaggio originale-----
Mattias Engdeg?rd
Inviato: marted? 9 gennaio 2001 15.35

It indeeds makes a lot of sense, since if your application is limited at
60fps due to the vertical blank, you cannot have any idea about
how fast it
could get without it. This is at least true under Win32.

If you just want to profile your code, then don’t flip at all

I want to profile my code including the flip operation. However, I think
this only means introducing a new flag. Since I’m very new at SDL, I don’t
know if this kind of process (i.e. adding a new flag) is common or it is
discouraged by API mantainers.

Moreover, looking at the DX5 video implementation, I can see that
DDFLIP_WAIT flag is always specified. In this way, the flipping call is
syncronous, at it waits till the real flip happens (instead of just
scheduling the flip, as the SDL documentation says).

That sounds wrong — someone who knows DirectX should look at that

I’m really sorry about this, but you are right, I was just wrong. The
meaning of the flag is different, and it does exactly what it is supposed to
do.

This is very bad in
case of triple buffering, but it seems that SDL does not support triple
buffering. Do you think it is feasable for the future? It would be just
great.

I personally think the usefulness of triple buffering is limited, but
it might be worth supporting anyway. It probably requires an api
revision though

I use it rarely, but I understand that some kind of applications can take
performance gains from that.> Da: owner-sdl at lokigames.com [mailto:owner-sdl at lokigames.com]Per conto di

A: sdl at lokigames.com
Oggetto: Re: R: [SDL] bug in SDL DGA driver


Giovanni Bajo
Lead Programmer

Protonic Interactive
www.protonic.net

  • Black holes are generated when God divides by zero -

“Giovanni Bajo” wrote

Moreover, looking at the DX5 video implementation, I can see that
DDFLIP_WAIT flag is always specified. In this way, the flipping call is
syncronous, at it waits till the real flip happens (instead of just
scheduling the flip, as the SDL documentation says

i don’t think this is quite right, here’s a snip from the directx docs…

DDFLIP_WAIT
Typically, if the flip cannot be set up because the state of the
display hardware is not appropriate, the DDERR_WASSTILLDRAWING error
returns immediately, and no flip occurs. Setting this flag causes the
method to continue trying to flip if it receives the DDERR_WASSTILLDRAWING
error from the hardware abstraction layer (HAL). The method does not
return until the flipping operation has been successfully set up, or
another error, such as DDERR_SURFACEBUSY, is returned.

in otherwords, DDFLIP_WAIT does wait until the flip can be scheduled,
but does not wait for it to complete. this would include situations
like if the previous flip event han’t occured yet.

I personally think the usefulness of triple buffering is limited, but
it might be worth supporting anyway. It probably requires an api
revision though

Having grown up in the Apple][+ world where double buffering
was the rule (and we were glad we even had that), I admit
I had very similar sentiments about tripple buffering,
before it was explained to me better:

Tripple buffering is to increase the frame-rate when your
draw-time is slightly longer than, but close to the
vertical scan time:

* In double buffering:
	+ You draw the frame starting (because we
		became unblocked on the page-flip)
		when the front buffer (assuming
		we're drawing to the back-buffer)
		gets scanned onto the screen.
	+ Because our draw-time is longer than the
		scan time, by the time we finish
		writing the frame, the vid-card
		has already begun scanning the
		front buffer to the screen a SECOND
		TIME.
	+ So when we page-flip, we block the whole
		rest of the frame, and get a frame-
		rate somewhere CLOSE TO HALF of
		what it could be...

* In tripple buffering:
	+ You start out as in tripple-buffering,
		but instead of blocking on a page-
		flip, you switch back-buffers.
	+ You draw the next frame starting after
		switching back-buffers (because
		that's when we were finished with
		the previous frame).
	+ This second frame still take longer than
		the scan time to draw, but since we
		didn't block waiting for the rescan,
		we've finished the second frame, and
		started the third by the time the
		second frame has been scanned to the
		CRT...
	+ So what we end up with is a pattern like
		1-1-2-3-4-4-5-6-7-7-8-9-etc. instead
		of blocking every rescan, and
		getting half the maximum frame
		rate, you'ld get (in this case)
		three frames per four scans...
		(A vast improvement!)

I really don’t think tripple buffering needs an API change
(unless you want to expose not-blocking on rescan, which
I agree with Sam isn’t such a great idea)… All you need
to do is change back-buffers on SDL_Flip() and only block
if BOTH back-buffers are dirty… (and, of course, schedule
the front-buffer to flip on the next rescan…)

I hope this helps… If not feel free to tell me to close my
trap… :wink:

Best Regards,

-Loren


Great news! Get free KNXmail here!
http://www.knx1070.com

Having grown up in the Apple][+ world where double buffering
was the rule (and we were glad we even had that), I admit
I had very similar sentiments about tripple buffering,
before it was explained to me better:

I know very well how triple buffering works; I just don’t like wasting
valuable video memory. I agree that it can be useful in some cases

I really don’t think tripple buffering needs an API change

there’s more to this than triple buffering; there is more than one way to
do it, and other changes that I’d like to have integrated smoothly

Tue, 09 Jan 2001 Mattias Engdeg?rd wrote:
[…]

I personally think the usefulness of triple buffering is limited, but
it might be worth supporting anyway. It probably requires an api
revision though

Tripple buffering is a performance hack that can improve performance a great
deal in at least two cases:

1. Software rasterizing + flipping involving hardware blitting.
   The CPU can get started with the next frame while the flip is
   in progress; double buffering would force the operations to
   be serialized.

2. Software or hardware rasterizing at less than full frame rate.
   The engine can keep working most of the time, rather than
   wasting time waiting for the *next* frame it it's a bit late.

   For example, if it takes 110% of a frame period to render one
   frame, double buffering would run at half frame rate, while
   triple buffering would drop approximatey one frame in ten; ie
   run at almost full frame rate.

Right, it’s said that game engines are not all about speed. But if that’s
true, how come almost every serious action gamer and engine coder is obsessed
with it…? :wink:

//David

…- M A I A -------------------------------------------------.
| Multimedia Application Integration Architecture |
| A Free/Open Source Plugin API for Professional Multimedia |
----------------------> http://www.linuxaudiodev.com/maia -' ..- David Olofson -------------------------------------------. | Audio Hacker - Open Source Advocate - Singer - Songwriter |--------------------------------------> david at linuxdj.com -’

Hi Sam!

int SDL_Flip(SDL_Surface *screen,int wait_for_vertical_refresh);

This kind of API change may be included for SDL 1.3 (or a completely
new API for handling refresh rates and VBL synchronization).

Cool. Anybody drafting the new API yet?

You are always welcome to disable the refresh wait code in the SDL
driver if you are doing specific benchmarking. The reason the refresh
code isn’t generally exposed, is that it’s not supported on any windowed
driver, and is supported on only a couple of fullscreen drivers. In order
for an SDL API to be exposed, the functionality should be available on
at least most of the common platforms and drivers.

Maybe have a flag in SDL_Init() then e.g. SDL_WAITREFRESH wich enables it if
available (or vice versa - SDL_NOWAITREFRESH)

In the double buffered case, this isn’t necessary. You can draw on the
back buffer at any time, and then flip during the vertical refresh, which
is what the SDL_DOUBLEBUF code is designed to do. More than that isn’t
currently supported in SDL (though may be in SDL 1.3)

Hmm, the double buffering doesn’t seem to work very well (or maybe I’m doing
it completely wrong). I’ll post a message now with an example of my thinking.

What I’m basically doing (my understanding of double buffering) is I’m
drawing everything on the non-visible part of the video card’s memory and
then doing an SDL_Flip() to get it to the visible part.–

Regards
Abraham


Abraham vd Merwe [ZR1BBQ] - Frogfoot Networks
P.O. Box 3472, Matieland, Stellenbosch, 7602
Cell: +27 82 565 4451 - Tel: +27 21 887 8703
Http: http://www.frogfoot.net
Email: @Abraham_vd_Merwe

-------------- next part --------------
A non-text attachment was scrubbed…
Name: not available
Type: application/pgp-signature
Size: 232 bytes
Desc: not available
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20010110/fbe40029/attachment.pgp

Hi Sam!

int SDL_Flip(SDL_Surface *screen,int wait_for_vertical_refresh);

This kind of API change may be included for SDL 1.3 (or a completely
new API for handling refresh rates and VBL synchronization).

Cool. Anybody drafting the new API yet?

Not yet. SDL 1.2 will be released and then there will be some months
of thinking, tinkering, and development list discussion, before the new
API is actually drafted. If all goes well, it will be the precursor
to SDL 2.0, but we’ll see how things go. :slight_smile:

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