Incremental updates and hardware/double buffered surfaces

OK, I’m currently doing incremental updates (AKA dirty rectangles) to achieve good speed when using software surfaces. This works quite well in Linux, where software surfaces are all that’s available.

I’ve been trying to improve Win32 support for the same code, and have realized that using hardware surfaces in that case works much better. So when I choose SDL_HWSURFACE|SDL_DOUBLEBUF in Windows, it works great in windowed mode. It uses the incremental update code, and CPU usage drops by more than 50%.

Problem is, when I switch to fullscreen mode, the screen flickers because the next update is a dirty update. The only way I’ve been able to fix it is basically force a full update each frame, eliminating the incremental/dirty update code. But in this case, now performance drops again. Is there a way of combining incremental updates with hardware/double-buffered surfaces in such as way that I don’t have to redraw the whole frame every frame?

Thanks for any info,
Steve

Problem is, when I switch to fullscreen mode, the screen flickers because the next update is a dirty update. The only way I’ve been able to fix it is basically force a full update each frame, eliminating the incremental/dirty update code. But in this case, now performance drops again. Is there a way of combining incremental updates with hardware/double-buffered surfaces in such as way that I don’t have to redraw the whole frame every frame?

It’s pretty simple, you just have to maintain two dirty lists, one for each
back buffer. There are some pretty good descriptions on the mailing list if
you use the search option at www.libsdl.org

See ya,
-Sam Lantinga, Software Engineer, Blizzard Entertainment

My Pig example/game includes this feature, along with a small "engine"
that combines dirty rectangles for efficiency - though it’s not
exactly a simple, minimal example. :wink:

http://olofson.net/examples.html

//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 Wednesday 24 August 2005 06.30, Sam Lantinga wrote:

Problem is, when I switch to fullscreen mode, the screen flickers
because the next update is a dirty update. The only way I’ve been
able to fix it is basically force a full update each frame,
eliminating the incremental/dirty update code. But in this case,
now performance drops again. Is there a way of combining
incremental updates with hardware/double-buffered surfaces in such
as way that I don’t have to redraw the whole frame every frame?

It’s pretty simple, you just have to maintain two dirty lists, one
for each back buffer. There are some pretty good descriptions on
the mailing list if you use the search option at www.libsdl.org

Correct me if I’m wrong, but if you are running your code in “windowed” mode, you are liekly not actually getting a hardware surface… I think you will only get one in fullscreen mode, and that’s why you only notice the flickering in that mode. When windowed, it gives you a software surface. You might check the flags on your video/screen surface and see if it is really giving you one in windowed mode.

One way that I overcame that difficulty, though I’m positive it’s not as good as David Olofson’s, was to create a second hardware surface the same size as the screen, and do all of my blits to that surface, and when I was done composing a scene, blit that one big surface to the video surface. This gave me very good FPS, kept away the flickering, but it is susceptible to “tearing”/not being synched with the vertical refresh(oh yes, this technique does not use SDL_DOUBLEBUF)… well, it probably wasn’t worth much, but that was something I tried long ago.

Let us know what works best for you when you’ve got it figured out!
-Dave----- Original Message -----
From: Stephen Anthony
To: sdl at libsdl.org
Sent: Tuesday, August 23, 2005 9:33 PM
Subject: [SDL] Incremental updates and hardware/double buffered surfaces

OK, I’m currently doing incremental updates (AKA dirty rectangles) to achieve good speed when using software surfaces. This works quite well in Linux, where software surfaces are all that’s available.

I’ve been trying to improve Win32 support for the same code, and have realized that using hardware surfaces in that case works much better. So when I choose SDL_HWSURFACE|SDL_DOUBLEBUF in Windows, it works great in windowed mode. It uses the incremental update code, and CPU usage drops by more than 50%.

Problem is, when I switch to fullscreen mode, the screen flickers because the next update is a dirty update. The only way I’ve been able to fix it is basically force a full update each frame, eliminating the incremental/dirty update code. But in this case, now performance drops again. Is there a way of combining incremental updates with hardware/double-buffered surfaces in such as way that I don’t have to redraw the whole frame every frame?

Thanks for any info,
Steve



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

Correct me if I’m wrong, but if you are running your code in
"windowed" mode, you are liekly not actually getting a hardware
surface… I think you will only get one in fullscreen mode, and
that’s why you only notice the flickering in that mode. When
windowed, it gives you a software surface. You might check the flags
on your video/screen surface and see if it is really giving you one
in windowed mode.

Maybe so, but switching to hardware surfaces and SDL_Flip() instead of
software surfaces and SDL_UpdateRects() increased performance quite a
bit. So while I may not have gotten a hardware surface in windowed
mode, something must have changed. And the performance difference
wasn’t insignificant either.

Let us know what works best for you when you’ve got it figured out!

I’ll have a look at David’s code sometime soon and let you know. More
than likely it will work fine.

SteveOn August 24, 2005 07:18 pm, David Olsen wrote:

[…]

One way that I overcame that difficulty, though I’m positive it’s
not as good as David Olofson’s, was to create a second hardware
surface the same size as the screen, and do all of my blits to that
surface, and when I was done composing a scene, blit that one big
surface to the video surface. This gave me very good FPS, kept away
the flickering, but it is susceptible to “tearing”/not being synched
with the vertical refresh(oh yes, this technique does not use
SDL_DOUBLEBUF)… well, it probably wasn’t worth much, but that was
something I tried long ago.

I use a very similar approach to deal with the performance issues with
software alpha blending into VRAM. Basically the same thing - a
shadow surface, as I call it - except I make sure it’s a software
surface, so that it’s not in VRAM. This avoids the expensive VRAM
reads that the software alpha blitter has to do, and with some luck
(at least theoretically), the blit from the shadow surface to the
display surface can use DMA. (Or it can be made asynchronous by means
of the SDL_ASYNCBLIT flag, in case there’s an extra CPU hanging
around.)

BTW, this can be combined with SDL_DOUBLEBUF just fine. This is what I
used to call “SemiTriple” buffering in Kobo Deluxe. Again, same
setup, but with a double buffered hardware display surface (for
retrace sync’ed page flipping where available), and an SDL_Flip()
call following each shadow->display blit.

Also, both of these arrangements can be combined with dirty
rectangles! :smiley:

IIRC, I do the “full deal” in Pig; double buffered hardware display
surface to eliminate tearing, software shadow buffer for fast alpha
blending (lots of AA and translucency), and dirty rectangles for
reducing the shadow->display blit bandwidth. Perhaps apart from a
better dirty rectangle manager, I think this is pretty much as
optimal as it gets for applications like this; ie “a bunch of sprites
moving over a mostly still background”.

(The Pig dirty rectangle merging algorithm can be suboptimal if you
throw certain sequences at it, because it only considers the current
full state and the new rectangle when adding a new rectangle. It
would be smarter, but probably also a lot more complex if it did all
the merging in one step, with all rectangles at hand. Microtiles
might be a simpler and better alternative - proven and used in a few
GUI toolkits and game engines.)

BTW, anyone doing full screen scrolling should probably forget about
dirty rectangles. The only situation where they’d make sense with a
full screen scroller is if moving sprites is very expensive compared
to blitting from the shadow surface to the display.

Say, you’re doing real time shadow casting and stuff. Maybe the
"sprites" are actually real time rendered structured graphics? Of
course, you want ultra smooth scrolling - but no one can tell whether
slow moving objects and shadows are animated at the full frame rate!
Then it might make sense to set up something like emulated hardware
scrolling, with a “shadow” buffer that is larger than the display
surface.

Otherwise, just repaint the whole screen every frame, using a software
shadow surface if you need alpha blending and only s/w alpha is
available.

//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 Wednesday 24 August 2005 23.48, David Olsen wrote: