Screen syncronizing

Hi

I am writing my own GUI using pygame on top of SDL. I use
software surfaces and only update the dirtyrectangles and
nearly everything seems to run realy nicely but…

Does any one know how to synchronize with the screen.
I am currently using the clock.tick(60) to get a reasonable
sync. My tft monitor is runing at 60 Hz so in theory it
should run reasonably smooth, but in reallity im getting
62 fps when I check clock.get_fps().

Is there a hidden event for the screen refresh that can be
activated, or are there any other way to achive the bliss
of smooth movement and animation ?

Has there been any atempts to extract the refresh signal
and if so why hasn’t it been implemented.

Bo)

normally SDL waits for a vsync when flipping frame buffers…
have you tried that?

There is the SDL_GL_SwapBuffers if you’re using openGL stuff,
and there is also the SDL_Flip, which according to the manual:

“On hardware that supports double-buffering, this function
sets up a flip and returns. The hardware will wait for vertical
retrace, and then swap video buffers before the next video
surface blit or lock will return. On hardware that doesn’t support
double-buffering, this is equivalent to calling
SDL_UpdateRect(screen, 0, 0, 0, 0)”

hope that helps,
Kos.> ----- Original Message -----

From: sdl-bounces+kos=climaxgroup.com@libsdl.org
[mailto:sdl-bounces+kos=climaxgroup.com at libsdl.org]On Behalf Of Bo
Jangeborg
Sent: 13 May 2004 14:09
To: sdl at libsdl.org
Subject: [SDL] Screen syncronizing

Hi

I am writing my own GUI using pygame on top of SDL. I use
software surfaces and only update the dirtyrectangles and
nearly everything seems to run realy nicely but…

Does any one know how to synchronize with the screen.
I am currently using the clock.tick(60) to get a reasonable
sync. My tft monitor is runing at 60 Hz so in theory it
should run reasonably smooth, but in reallity im getting
62 fps when I check clock.get_fps().

Is there a hidden event for the screen refresh that can be
activated, or are there any other way to achive the bliss
of smooth movement and animation ?

Has there been any atempts to extract the refresh signal
and if so why hasn’t it been implemented.

Bo)


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

Hi

I am writing my own GUI using pygame on top of SDL. I use
software surfaces and only update the dirtyrectangles and
nearly everything seems to run realy nicely but…

Does any one know how to synchronize with the screen.
I am currently using the clock.tick(60) to get a reasonable
sync. My tft monitor is runing at 60 Hz so in theory it
should run reasonably smooth, but in reallity im getting
62 fps when I check clock.get_fps().

Actually, trying to stay near the refresh rate of the screen like this
is about the worst thing you can do WRT tearing. It does avoid
burning all available CPU time rendering graphics that no one will
see, but provided you have reasonably accurate timers, it also makes
the tearing drift slowly across the screen, or jitter around in a
fixed area of the screen. That tends to be more annoying that random
tearing all over the screen.

However, there isn’t much chance of ever seeing this. Most systems
have a 10 ms granularity for scheduling of timer callbacks and
blocking. You could poll SDL_GetTicks() or something, of course, but
then you might as well just render at full speed for reduced tearing.

Is there a hidden event for the screen refresh that can be
activated, or are there any other way to achive the bliss
of smooth movement and animation ?

Has there been any atempts to extract the refresh signal
and if so why hasn’t it been implemented.

If you use (SDL_DOUBLEBUF | SDL_FULLSCREEN), SDL_Flip() may sync
with the retrace. Depends on the backend, OS and drivers. There is
usually no reliable way of achieving explicit “direct” retrace sync
(as in “SDL_WaitRetrace()”), and you can’t really use it for anything
in a normal OS anyway (need an RTOS), so there isn’t much point in
trying to implement it.

As to combining the “smart update” approach (SDL_UpdateRects()) with a
double buffered display surface, you can have a look at my Pig
example:

http://olofson.net/examples.html

It’s not trivial, but I think it’s about as simple as a useful “smart
updating” solution gets if it has to support both “fake” double
buffering and hardware page flipping.

//David Olofson - Programmer, Composer, Open Source Advocate

.- Audiality -----------------------------------------------.
| Free/Open Source audio engine for games and multimedia. |
| MIDI, modular synthesis, real time effects, scripting,… |
`-----------------------------------> http://audiality.org -’
http://olofson.nethttp://www.reologica.se —On Thursday 13 May 2004 15.08, Bo Jangeborg wrote:

Dubbelbuffering seem to work (except for the mouse cursor) but only in
fullscreen mode I assume ? Not using Open GL yet.

Thanks anyway
Bo)

Kostas Kostiadis wrote:>normally SDL waits for a vsync when flipping frame buffers…

have you tried that?

There is the SDL_GL_SwapBuffers if you’re using openGL stuff,
and there is also the SDL_Flip, which according to the manual:

“On hardware that supports double-buffering, this function
sets up a flip and returns. The hardware will wait for vertical
retrace, and then swap video buffers before the next video
surface blit or lock will return. On hardware that doesn’t support
double-buffering, this is equivalent to calling
SDL_UpdateRect(screen, 0, 0, 0, 0)”

hope that helps,
Kos.

David Olofson wrote:

If you use (SDL_DOUBLEBUF | SDL_FULLSCREEN), SDL_Flip() may sync
with the retrace. Depends on the backend, OS and drivers. There is
usually no reliable way of achieving explicit “direct” retrace sync
(as in “SDL_WaitRetrace()”), and you can’t really use it for anything
in a normal OS anyway (need an RTOS), so there isn’t much point in
trying to implement it.

As to combining the “smart update” approach (SDL_UpdateRects()) with a
double buffered display surface, you can have a look at my Pig
example:

http://olofson.net/examples.html

It’s not trivial, but I think it’s about as simple as a useful “smart
updating” solution gets if it has to support both “fake” double
buffering and hardware page flipping.

How does the “fake” dubble buffering work ? Im not very good at reading
C code
Btw, the Pig game looks very smooth.

Bo)

David Olofson wrote:

If you use (SDL_DOUBLEBUF | SDL_FULLSCREEN), SDL_Flip() may sync
with the retrace. Depends on the backend, OS and drivers. There is
usually no reliable way of achieving explicit “direct” retrace
sync (as in “SDL_WaitRetrace()”), and you can’t really use it for
anything in a normal OS anyway (need an RTOS), so there isn’t
much point in trying to implement it.

As to combining the “smart update” approach (SDL_UpdateRects())
with a double buffered display surface, you can have a look at my
Pig example:

http://olofson.net/examples.html

It’s not trivial, but I think it’s about as simple as a useful
"smart updating" solution gets if it has to support both "fake"
double buffering and hardware page flipping.

How does the “fake” dubble buffering work ? Im not very good at
reading C code

By “fake” double buffering, I mean a setup where making a new frame
visible is done by copying a shadow buffer into the display buffer,
as opposed to just swapping two display buffers.

What Pig does when hardware page flipping is not available is stay
away from SDL_Flip() and use SDL_UpdateRects() instead. That way, it
can get away with copying only the areas that have actually changed,
which is how you get those insane frame rates (hundreds or thousands
of fps) even without h/w accelerated blits.

Note that SDL gives you either double buffering with h/w page
flipping, or a single display buffer + s/w shadow buffer! That is,
if you want a s/w back buffer for fast rendering, you’ll have to
create that yourself, and implement your own alternative to
SDL_UpdateRects(). Pig does that to avoid doing alpha blending (which
there is a lot of) directly into VRAM.

Btw, the Pig game looks very smooth.

Yeah, that’s the idea. :wink:

//David Olofson - Programmer, Composer, Open Source Advocate

.- Audiality -----------------------------------------------.
| Free/Open Source audio engine for games and multimedia. |
| MIDI, modular synthesis, real time effects, scripting,… |
`-----------------------------------> http://audiality.org -’
http://olofson.nethttp://www.reologica.se —On Friday 14 May 2004 01.57, Bo Jangeborg wrote:

David Olofson wrote:

By “fake” double buffering, I mean a setup where making a new frame
visible is done by copying a shadow buffer into the display buffer,
as opposed to just swapping two display buffers.

What Pig does when hardware page flipping is not available is stay
away from SDL_Flip() and use SDL_UpdateRects() instead. That way, it
can get away with copying only the areas that have actually changed,
which is how you get those insane frame rates (hundreds or thousands
of fps) even without h/w accelerated blits.

Note that SDL gives you either double buffering with h/w page
flipping, or a single display buffer + s/w shadow buffer! That is,
if you want a s/w back buffer for fast rendering, you’ll have to
create that yourself, and implement your own alternative to
SDL_UpdateRects(). Pig does that to avoid doing alpha blending (which
there is a lot of) directly into VRAM.

I got a quite advanced dirty rect routine that splits overlapping rects
in to the minimum number
of new rects that would cover the same area, this is implemented on a
tree of widgets, some of
who have their own surfaces and some that are drawn directly to the
screen. All with relative positioning
to make life more interesting.
So I think I have that part covered.

In pygame I have three options for updating the screen. Do I understand
you correctly if I say that none
of these represent your s/w back buffer?

  1.                pygame.display.update(s.dirtyrects)
    
  2.                pygame.display.update()
    
  3.                pygame.display.flip()
    

By s/w back buffer you mean a s/w surface that then get blited to the
screen?

Am I correct in assuming that you can’t use double buffering in a window ?

The real trick then is figuring out when to move the sprites. How do you
figure out how much time has passed
so that you know when to update the sprite the next time?

It could be that this is hard to implement in python.

While Im at it, do you think your sound module could be integrated with
pygame ?

Bo)

[…]

In pygame I have three options for updating the screen. Do I
understand you correctly if I say that none
of these represent your s/w back buffer?

  1.                pygame.display.update(s.dirtyrects)
    
  2.                pygame.display.update()
    
  3.                pygame.display.flip()
    

Well, I can only guess, as I’ve never used pygame… Assuming that the
first two wrap the SDL_UpdateRect*() calls, and the last one wraps
SDL_Flip(), then yes, that’s correct.

The “semitriple” buffering setup that Pig uses when supported (two h/w
pages + one s/w shadow), is not directly supported by SDL. You have
to implement the shadow surface yourself, on top of an SDL double
buffered h/w display surface.

Now, do keep in mind that this setup is utterly pointless if the blits
you are using are accelerated! Only use this if you do significant
amounts of alpha blending to the screen, and aren’t on a backend that
accelerate alpha. (Only glSDL and DirectFB do that, AFAIK, so don’t
rely on it. Most users won’t have accelerated alpha.)

By s/w back buffer you mean a s/w surface that then get blited to
the screen?

Yes. SDL gives you one of those if you ask for a single buffered s/w
surface display.

Am I correct in assuming that you can’t use double buffering in a
window ?

In theory, no, double buffering in a window is possible. However,
without special (high end) hardware, it’s very tricky to implement,
so very few (if any) widely availably windowing systems support it.

Either way, I strongly recommend that you disregard the
windowed/fullscreen property in this regard. There is no guarantee
that a window cannot use page flipping, nor is there a guarantee that
a target can use page flipping at all even in fullscreen modes.
(Many can’t - including XFree86 without DGA, meaning some 95% of the
Linux users.)

The real trick then is figuring out when to move the sprites. How
do you figure out how much time has passed
so that you know when to update the sprite the next time?

Well, in Pig, that’s handled by decoupling the logic frame rate from
the rendering frame rate. (That’s the main point with the example,
actually. :slight_smile:

The game either generates exactly one frame per monitor refresh (if
retrace sync is possible), or it just generates frames as fast as
possible. (That minimizes the difference between frames, thus reduces
the tearing when animating without retrace sync.)

Before rendering each frame, the engine checks the current time
(SDL_GetTicks()) to see how many logic frames have passed since the
last rendered frame. (Usually 0, since the logic frame rate in Pig is
very low, just to demonstrate the effect of interpolation.) Logic
time is advanced to the right frame, rounded upwards, and then all
graphics coordinates are interpolated from the logic coordinates from
the last two logic frames.

It could be that this is hard to implement in python.

As long as you have a plain SDL API binding, and not some kind of
"smart" engine, it should be easier to do in just about any other
language than C. It’s the logic that is tricky to grasp.

While Im at it, do you think your sound module could be integrated
with pygame ?

Sure, it’s just another sound engine. However, be warned that there
will be changes in the API (cleanups) and file formats (new scripting
engine) in the next few releases. I wouldn’t hack any external code
that relies heavily on the current “object model” of Audiality.

//David Olofson - Programmer, Composer, Open Source Advocate

.- Audiality -----------------------------------------------.
| Free/Open Source audio engine for games and multimedia. |
| MIDI, modular synthesis, real time effects, scripting,… |
`-----------------------------------> http://audiality.org -’
http://olofson.nethttp://www.reologica.se —On Friday 14 May 2004 14.43, Bo Jangeborg wrote:

I’ve compiled your “pig” example for ARM and qtopia 1.5. I’m getting “Failed to open screen!”…> ----- Original Message -----

From: sdl-bounces+cedric.bompart=morse.com@libsdl.org [mailto:sdl-bounces+cedric.bompart=morse.com at libsdl.org] On Behalf Of David Olofson
Sent: 14 May 2004 12:24
To: A list for developers using the SDL library. (includes SDL-announce)
Subject: Re: [SDL] Screen syncronizing

On Friday 14 May 2004 01.57, Bo Jangeborg wrote:

David Olofson wrote:

If you use (SDL_DOUBLEBUF | SDL_FULLSCREEN), SDL_Flip() may sync
with the retrace. Depends on the backend, OS and drivers. There is
usually no reliable way of achieving explicit “direct” retrace sync
(as in “SDL_WaitRetrace()”), and you can’t really use it for
anything in a normal OS anyway (need an RTOS), so there isn’t much
point in trying to implement it.

As to combining the “smart update” approach (SDL_UpdateRects()) with
a double buffered display surface, you can have a look at my Pig
example:

http://olofson.net/examples.html

It’s not trivial, but I think it’s about as simple as a useful
"smart updating" solution gets if it has to support both "fake"
double buffering and hardware page flipping.

How does the “fake” dubble buffering work ? Im not very good at
reading C code

By “fake” double buffering, I mean a setup where making a new frame visible is done by copying a shadow buffer into the display buffer, as opposed to just swapping two display buffers.

What Pig does when hardware page flipping is not available is stay away from SDL_Flip() and use SDL_UpdateRects() instead. That way, it can get away with copying only the areas that have actually changed, which is how you get those insane frame rates (hundreds or thousands of fps) even without h/w
accelerated blits.

Note that SDL gives you either double buffering with h/w page flipping, or a single display buffer + s/w shadow buffer! That is, if you want a s/w back buffer for fast rendering, you’ll have to create that yourself, and implement your own alternative to SDL_UpdateRects(). Pig does that to avoid
doing alpha blending (which there is a lot of) directly into VRAM.

Btw, the Pig game looks very smooth.

Yeah, that’s the idea. :wink:

//David Olofson - Programmer, Composer, Open Source Advocate

.- Audiality -----------------------------------------------.
| Free/Open Source audio engine for games and multimedia. | MIDI,
| modular synthesis, real time effects, scripting,… |
`-----------------------------------> http://audiality.org -’
http://olofson.nethttp://www.reologica.se


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

Yep, it requires an 800x600 video mode.

I figured scaling support and that kind of stuff was way out of
scope for this already too big and complex programming example…

//David Olofson - Programmer, Composer, Open Source Advocate

.- Audiality -----------------------------------------------.
| Free/Open Source audio engine for games and multimedia. |
| MIDI, modular synthesis, real time effects, scripting,… |
`-----------------------------------> http://audiality.org -’
http://olofson.nethttp://www.reologica.se —On Friday 14 May 2004 17.46, Cedric Bompart wrote:

I’ve compiled your “pig” example for ARM and qtopia 1.5. I’m
getting “Failed to open screen!”…

David Olofson wrote:

[…]

In pygame I have three options for updating the screen. Do I
understand you correctly if I say that none
of these represent your s/w back buffer?

  1.                pygame.display.update(s.dirtyrects)
    
  2.                pygame.display.update()
    
  3.                pygame.display.flip()
    

Well, I can only guess, as I’ve never used pygame… Assuming that the
first two wrap the SDL_UpdateRect*() calls, and the last one wraps
SDL_Flip(), then yes, that’s correct.

The “semitriple” buffering setup that Pig uses when supported (two h/w
pages + one s/w shadow), is not directly supported by SDL. You have
to implement the shadow surface yourself, on top of an SDL double
buffered h/w display surface.

Ok lets see if I understand this, you create two h/w surfaces and one
s/w surface. You do all your
work on the s/w surface to since alpha blending is very expensive betwen
a s/w and a h/w surface.
You then blit the finished s/w surface using your own dirty rectangle
routine to the alternating h/w
surfaces and finally blit the current h/w surface to the screen , right ?

In theory, no, double buffering in a window is possible. However,
without special (high end) hardware, it’s very tricky to implement,
so very few (if any) widely availably windowing systems support it.

Either way, I strongly recommend that you disregard the
windowed/fullscreen property in this regard. There is no guarantee
that a window cannot use page flipping, nor is there a guarantee that
a target can use page flipping at all even in fullscreen modes.
(Many can’t - including XFree86 without DGA, meaning some 95% of the
Linux users.)

The flip command should be avoided then, or possibly user selected as an
alternative.

The real trick then is figuring out when to move the sprites. How
do you figure out how much time has passed
so that you know when to update the sprite the next time?

Well, in Pig, that’s handled by decoupling the logic frame rate from
the rendering frame rate. (That’s the main point with the example,
actually. :slight_smile:

The game either generates exactly one frame per monitor refresh (if
retrace sync is possible), or it just generates frames as fast as
possible. (That minimizes the difference between frames, thus reduces
the tearing when animating without retrace sync.)

How do you get a retrace sync (thats when the updating reaches the end
of the screen right ?)

Before rendering each frame, the engine checks the current time
(SDL_GetTicks()) to see how many logic frames have passed since the
last rendered frame. (Usually 0, since the logic frame rate in Pig is
very low, just to demonstrate the effect of interpolation.) Logic
time is advanced to the right frame, rounded upwards, and then all
graphics coordinates are interpolated from the logic coordinates from
the last two logic frames.

Ok, I think I am starting to understand. Will put on my thinking cap now
an try to digest that.

It could be that this is hard to implement in python.

As long as you have a plain SDL API binding, and not some kind of
"smart" engine, it should be easier to do in just about any other
language than C. It’s the logic that is tricky to grasp.

While Im at it, do you think your sound module could be integrated
with pygame ?

Sure, it’s just another sound engine. However, be warned that there
will be changes in the API (cleanups) and file formats (new scripting
engine) in the next few releases. I wouldn’t hack any external code
that relies heavily on the current “object model” of Audiality.

Ok, make an announcement here when you have something :o)

Thanks for the replies, hope this will help some more people.

Bo)

Btw: Im from G?teborg>On Friday 14 May 2004 14.43, Bo Jangeborg wrote:

[…]

The “semitriple” buffering setup that Pig uses when supported (two
h/w pages + one s/w shadow), is not directly supported by SDL.
You have to implement the shadow surface yourself, on top of an
SDL double buffered h/w display surface.

Ok lets see if I understand this, you create two h/w surfaces and
one s/w surface. You do all your
work on the s/w surface to since alpha blending is very expensive
betwen a s/w and a h/w surface.
You then blit the finished s/w surface using your own dirty
rectangle routine to the alternating h/w
surfaces and finally blit the current h/w surface to the screen ,
right ?

Almost. :slight_smile:

I just create one h/w surface: The display surface, using
SDL_SetVideoMode(). That one is double buffered, so technically,
there are two surfaces, but you can’t see that through the SDL API.
There’s just one display surface, though it has two internal buffers,
of which you can see one at a time. SDL_Flip() swaps the internal
buffers, (hopefully) in sync with the retrace.

In theory, no, double buffering in a window is possible.
However, without special (high end) hardware, it’s very tricky to
implement, so very few (if any) widely availably windowing
systems support it.

Either way, I strongly recommend that you disregard the
windowed/fullscreen property in this regard. There is no guarantee
that a window cannot use page flipping, nor is there a guarantee
that a target can use page flipping at all even in fullscreen
modes. (Many can’t - including XFree86 without DGA, meaning some
95% of the Linux users.)

The flip command should be avoided then, or possibly user selected
as an alternative.

Not quite. Use flip with a double buffered h/w surface. Use
SDL_UpdateRects() for anything else. Check what you get from
SDL_SetVideoMode().

(And don’t make it a user option; not even programmers know what to do
with it! :wink:

[…]

How do you get a retrace sync (thats when the updating reaches the
end of the screen right ?)

The driver may sync the actual flip operation with the retrace when
you use SDL_Flip() on a double buffered h/w surface. If that doesn’t
work, there’s nothing you can do, short of flaky and highly platform
dependent hacks.

Unfortunately, there are plenty of drivers and display configurations
that just do not support retrace sync and/or h/w page flipping. Your
best bet is a double buffered h/w display surface in fullscreen mode,
regardless of platform.

[…]

While Im at it, do you think your sound module could be
integrated with pygame ?

Sure, it’s just another sound engine. However, be warned that
there will be changes in the API (cleanups) and file formats (new
scripting engine) in the next few releases. I wouldn’t hack any
external code that relies heavily on the current "object model"
of Audiality.

Ok, make an announcement here when you have something :o)

Will do.

Btw: Im from G?teborg

Not too far away then; I’m from Varberg. :slight_smile:

//David Olofson - Programmer, Composer, Open Source Advocate

.- Audiality -----------------------------------------------.
| Free/Open Source audio engine for games and multimedia. |
| MIDI, modular synthesis, real time effects, scripting,… |
`-----------------------------------> http://audiality.org -’
http://olofson.nethttp://www.reologica.se —On Friday 14 May 2004 19.47, Bo Jangeborg wrote:

Almost. :slight_smile:

I just create one h/w surface: The display surface, using
SDL_SetVideoMode(). That one is double buffered, so technically,
there are two surfaces, but you can’t see that through the SDL API.
There’s just one display surface, though it has two internal buffers,
of which you can see one at a time. SDL_Flip() swaps the internal
buffers, (hopefully) in sync with the retrace.

The windows32 exe file of Pig runs very smooothly in a window. That is
without double buffering
then and just pumping out the maximum number of frames ?

Bo)

Yep.

(Actually, there is double buffering, but no page flipping. The term
"double buffering" applies to any setup where you’re not rendering
directly into the actual VRAM buffer being displayed.)

//David Olofson - Programmer, Composer, Open Source Advocate

.- Audiality -----------------------------------------------.
| Free/Open Source audio engine for games and multimedia. |
| MIDI, modular synthesis, real time effects, scripting,… |
`-----------------------------------> http://audiality.org -’
http://olofson.nethttp://www.reologica.se —On Saturday 15 May 2004 10.08, Bo Jangeborg wrote:

Almost. :slight_smile:

I just create one h/w surface: The display surface, using
SDL_SetVideoMode(). That one is double buffered, so technically,
there are two surfaces, but you can’t see that through the SDL
API. There’s just one display surface, though it has two internal
buffers, of which you can see one at a time. SDL_Flip() swaps the
internal buffers, (hopefully) in sync with the retrace.

The windows32 exe file of Pig runs very smooothly in a window.
That is without double buffering
then and just pumping out the maximum number of frames ?