Hey,
I’ve been having bad problems with tearing and so I am attempting
to synch my animation to the vertical retrace of the monitor. I
understand that in SDL the only way to do this is to use double
buffered hardware surfaces and SDL_Flip(). However, as my game uses
a significant amount of alpha-bending, I can’t use HW surfaces
because of the speed hit.
The speed hit is when you blend into VRAM - but that doesn’t mean you
can’t use h/w surfaces at all.
I have tried using glSDL for accelerated
alpha blends, but that was a huge speed shock in itself, maybe
because of all the still unoptimized code.
Well, I don’t know what you’re doing, or how, but do note that glSDL
can only accelerate blits to the screen…
In any event, I thought the easiest way to go about synching to the
vertical retrace might be a platform specific solution. I am
working primarily on Win32, and have found a simple way to wait for
the start of a vertical retrace. I am doing this directly before I
am calling SDL_UpdateRect for each area of the screen that has
changed since the last animation frame, so according to my theory
the screen should be updated completely during the retrace and
everything should be peachy. However, the tearing persists. Is this
not a sound theory? I am sure that the mechanism to wait for the
vertical retrace is working correctly.
Problem with this kind of solution is that it requires a hard real
time OS to work properly. Even if the actual sync works properly,
there’s no way Windows or (standard) Linux can get the blitting done
at the right moment. It might work most of the time, at best. More
likely is the commonly seen (with OpenGL on Linux) “stationary
tearing” near the top of the screen, which can actually be worse than
normal “no sync” tearing in some cases.
Does SDL_UpdateRect update the screen immediately? That is, does it
actually do the writing to video memory? Or does it just flag a
rect to be updated later? The documentation says that in "ensures"
that the given rect will be updated. I’m not sure exactly what that
means.
That may differ between backends, I think, but your biggest problem
here is that it doesn’t really matter; you can’t ensure that the
blits are done at the right moment anyway.
Anyway, there’s no way a general purpose OS will allow you to schedule
blits to start a fraction of a ms after the retrace sync. What you
need is slack. Hardware pageflipping gives you N-1 full frame
durations of slack, where N is the number of buffers. Use that
whenever possible.
It does mean you have to render into an off-screen s/w buffer and then
blit from that to VRAM - but that blit can be accelerated on some
machines, including your average Windows/DirectX + PCI or AGP video
card setup.
Keep in mind that you don’t have to copy the whole screen every
frame just because you’re rendering into a shadow buffer. Just do
what SDL_UpdateRects() does internally; blit only the requested areas
from the shadow surface to the screen. Then SDL_Flip() to make the
updated page visible, hopefully after the next retrace.
//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.net — http://www.reologica.se —On Friday 17 October 2003 21.39, Dave wrote: