Hello, the following code make appear a pull-down menu when the user
move the mouse in the upper part of the screen (screen size = 1024x768).
My pull-down menu is an image (1024x161) and it appear in the upper part
of the screen in the following way:
draw last row
draw last two rows
draw last three rows
…
draw all image
The problem is that using “SDL_Flip” (line #2#) the process is slow and
not very smooth.
Instead, if I use “SDL_UpdateRect” (line #1#), each time updating only
the screen from Y=0 to Y=160, the pull-down animation is very fast and
smooth.
Why SDL_Flip is so slow? I know that it update all the screen, but it’s
an hardware process, or not? Am I doing something wrong?
SDL_UpdateRect doesn’t wait vertical sync, it isn’t?
I also read that the sprite size should be “power of two”, is it true?
How much speed I gain doing so and why?
SDL_Flip will only use hardware assisted double buffering if you
actually get a hardware surface. This is not always the case,
typically, one can only get a hardware surface when running in
fullscreen mode. I believe it is not possible to get a hardware
surface on X without being root or something, not a good idea.
If your display surface is a software surface, SDL_Flip is basically
SDL_UpdateRect called on the entire screen. As such it will be as slow
as the time it takes to copy all those pixels.
To test if you are getting a hardware surface, check if the value of (
SDL_GetVideoSurface()->flags & SDL_HWSURFACE ), it will be zero if you
did not get a hardware surface.
If you don’t have a hardware surface, I don’t think drawing will wait
for vsync. I could be wrong though.
Sprite size will not need to be a power of two, SDL is (primarily) a
software blitter so it blits rectangles of any size at pretty much the
same speed.
There may be other techniques to speed up blitting, using RLE on
certain surfaces may help. Using SDL_DisplayFormat() on images may
help. Don’t do alpha blending on hardware surfaces, or any per-pixel
manipulation at all.
As always though, you will need to test the speed differences yourself
to be sure. Test them on multiple machines, what may be super quick on
one machine may not act the same under a different set of hardware.On 12/06/07, voidstar wrote:
Why SDL_Flip is so slow? I know that it update all the screen, but it’s
an hardware process, or not? Am I doing something wrong?
SDL_UpdateRect doesn’t wait vertical sync, it isn’t?
I also read that the sprite size should be “power of two”, is it true?
How much speed I gain doing so and why?
Why SDL_Flip is so slow? I know that it update all the screen, but it’s
an hardware process, or not?
You answer your own question - it updates the whole screen which is always going to
be slower than just updating a part of it. Are you using hardware surfaces? It still has to
copy all the data to video memory…
Am I doing something wrong?
SDL_UpdateRect doesn’t wait vertical sync, it isn’t?
Nope. I don’t see why you need to update the whole screen anyway…
I also read that the sprite size should be “power of two”, is it true?
How much speed I gain doing so and why?
Doesn’t need to be but not a bad idea to have power-of-two IMHO.
You will gain speed because calculations are quicker to perform on these surfaces.
Ed___________________________________________________________
Yahoo! Answers - Got a question? Someone out there knows the answer. Try it
now.
You answer your own question - it updates the whole screen which is always
going to be slower than just updating a part of it. Are you using hardware
surfaces? It still has to copy all the data to video memory…
Yes, it has to copy all data, but my question is: ok it’s a bit slower, but
why the animation is not smooth? I see some little flickering. I read that
SDL_Flip does a vertycal sync before writing to video memory and this
should avoid flickering/tearing. But, again, the animation is not smooth.
Nope. I don’t see why you need to update the whole screen anyway…
No, I don’t want to update whole screen, but I was using SDL_Flip() because
it does a vertical sync (and I want it to avoid flickering/ecc).
Is there a function to wait for vertical sync? Maybe a Win32 function?
So I could call this function, and after that I call SDL_UpdateRect.
For example, when I was using SVGAlib under Linux, there was a function
called “vga_waitretrace()”.
To test if you are getting a hardware surface, check if the value of (
SDL_GetVideoSurface()->flags & SDL_HWSURFACE ), it will be zero if you
did not get a hardware surface.
If you don’t have a hardware surface, I don’t think drawing will wait
for vsync. I could be wrong though.
Oops! You’re right, I did not get a hardware surface!
I do this for the screen surface and for the pull-down image surface:
Is it ok? Why I can’t get a hardware surface?! Do i forgot something?
There may be other techniques to speed up blitting, using RLE on
certain surfaces may help. Using SDL_DisplayFormat() on images may
help. Don’t do alpha blending on hardware surfaces, or any per-pixel
manipulation at all.
I used “SDL_ConvertSurface”. However, I also tried to use SDL_DisplayFormat:
It may not be easy/possible to get a hardware surface on your platform
at all. Linux tends to be very picky about who can write directly to
hardware.
I recommned you give these a read: O'Reilly Media - Technology and Business Training
Ok thanks I’ll read it, but I’m not under Linux, I’m using Windows XP!
Looks to me that SDL_HWSURFACE is 0x00000001, so anything & 0x000001
will either be 1 (have hardware) or 0 (don’t). I cannot understand how
you are getting different values in these 2 tests.
It may be a operator precedence issue. checks yup, it seems to be.
== is higher priority than bitwise &, so your code looks like this:
( screen->flags & SDL_HWSURFACE == SDL_HWSURFACE )
which is
( screen->flags & (!0) )
whereas
( SDL_GetVideoSurface()->flags & SDL_HWSURFACE == 0 )
is
(( SDL_GetVideoSurface()->flags & 0 )
It may not be easy/possible to get a hardware surface on your platform
at all. Linux tends to be very picky about who can write directly to
hardware.
I recommned you give these a read: O'Reilly Media - Technology and Business Training
Ok thanks I’ll read it, but I’m not under Linux, I’m using Windows XP!
You need to use the DirectX driver, not the (default) windib one:
SDL_putenv(“SDL_VIDEODRIVER=directx”);
Of course, that could cause other problems, since I don’t think the
directx driver is really supported any more
I tried. The pull-down animation is still slow but it’s very smooth!
The problem is that all the screen is “crashed”: mixed pictures merged,
the cursor does not erase when I move the mouse, blinking screen, etc
You mean there’s no way to get hardware surface?!
And, at least, what about a function to wait for vertical sync?
You need to use the DirectX driver, not the (default) windib one:
SDL_putenv(“SDL_VIDEODRIVER=directx”);
Of course, that could cause other problems, since I don’t think
the directx driver is really supported any more
I tried. The pull-down animation is still slow but it’s very smooth!
The problem is that all the screen is “crashed”: mixed pictures
merged, the cursor does not erase when I move the mouse, blinking
screen, etc
You mean there’s no way to get hardware surface?!
Well, it looks like you did get one here… The blinking screen is
very typical for double buffering (hardware page flipping) with
incorrect partial updating.
For every change, you need to update both buffers! (Not an issue
when doing full screen redraws every frame, obviously.)
And, at least, what about a function to wait for vertical sync?
Few platforms provide this, and part of the reason is that it doesn’t
really work without hardware page flipping anyway. (*) You get
tearing concentrated to a narrow band on the screen instead of
randomly distributed. Usually looks worse than not using vsync at
all…
(*) Actually, it does work, if you use some sort of timers
“locked” to the retrace to “sync” multiple times per frame;
that is,
1. Sync in the middle of the screen.
2. Repaint the upper half of the screen.
3. Sync on the retrace (and adjust the timer as needed)
4. Repaint the lower half of the screen.
5. Goto 1. (Next frame.)
I’ve tried this on Linux by hacking an OpenGL driver, and
it works rather well - but I can’t think of any portable
way of doing it on the application level.
//David Olofson - Programmer, Composer, Open Source Advocate