UpdateRects sketchy

I just started playing with SDL yesterday, and pretty quickly ran into a
problem with screen updates. Calls to UpdateRect() do not always result
in an image being drawn on the screen. Rather, after a number of calls
to UpdateRect a vaguely rectangular portion of the window/screen may be
updated, but not necessarily the entire portion that ought to have been
updated. I am reasonably confident that my update rectangles are
correct, as some of the time UpdateRect() behaves as I would expect.
Also, in windowed mode, moving my window off the screen and back on will
update regions that went off the screen.

NB: I am using SDL 1.2 Mac OS X.

I have seen a number of questions like these in a cursory search of the
mailing list archives, but I have not yet seen an explanation or
solution. Any suggestions?

Thanks

Paul Hansen

I just started playing with SDL yesterday, and pretty quickly ran into
a problem with screen updates. Calls to UpdateRect() do not always
result in an image being drawn on the screen. Rather, after a number
of calls to UpdateRect a vaguely rectangular portion of the
window/screen may be updated, but not necessarily the entire portion
that ought to have been updated. I am reasonably confident that my
update rectangles are correct, as some of the time UpdateRect()
behaves as I would expect. Also, in windowed mode, moving my window
off the screen and back on will update regions that went off the
screen.

NB: I am using SDL 1.2 Mac OS X.

I have seen a number of questions like these in a cursory search of
the mailing list archives, but I have not yet seen an explanation or
solution. Any suggestions?

You shouldn’t be using SDL_UpdateRect() to do multiple dirty rects per
frame, as the cost of SDL_UpdateRect() is very - dare I say extremely

  • high. The reason is that each time you call UpdateRect() or
    UpdateRects() or Flip(), the window server copies the region you
    specified to the display, in sync with the retrace of the monitor
    (VBL), and possibly involving compositing if the window is occluded.
    Even if there is no compositing required, just the sync with the VBL
    causes a huge hit while the CPU is idle waiting for the CRT beam to go
    by.

Each frame, pass all of your dirty rects together to SDL_UpdateRects()

  • this minimizes the penalty associated with the VBL since all the
    rects are processed at the same time. Also, that should solve the
    problem with some areas not redrawing at the same time.

Note that SDL_UpdateRects() is the low-level function. SDL_UpdateRect()
and SDL_Flip() call SDL_UpdateRects().

For even better performance, in the case you have a lot of rects to
pass per frame or most of the screen area is updated, try tossing out
dirty rects altogether and call SDL_UpdateRect (screen,0,0,0,0).
Updating the whole screen can be faster since the window server has
less work to do.

Benchmarking has shown that the best performance on Mac OS X is using a
software fullscreen surface (SDL_SWSURFACE | SDL_FULLSCREEN) of the bit
depth you desire (lower bit depths are faster).

If you are using 10.2 (Jaguar), I am aware of the flickering issue in
windowed mode (which is actually different from your problem it seems)
and I have a fix which should make it into SDL soon.

Cheers,
DarrellOn Saturday, September 14, 2002, at 12:17 PM, pchans at wm.edu wrote:

You shouldn’t be using SDL_UpdateRect() to do multiple dirty rects per
frame, as the cost of SDL_UpdateRect() is very - dare I say
extremely - high. The reason is that each time you call UpdateRect()
or UpdateRects() or Flip(), the window server copies the region you
specified to the display, in sync with the retrace of the monitor
(VBL), and possibly involving compositing if the window is occluded.
Even if there is no compositing required, just the sync with the VBL
causes a huge hit while the CPU is idle waiting for the CRT beam to go
by.

Yes, I am planning on using UpdateRects down the road, but I am still
perplexed by why UpdateRect does not work. My test program catches
mouse events and blits a sprite at the click position. I’m not
interested in efficiency – I just want the picture to draw, and it
doesn’t do so every time I click.

Is UpdateRect(screen, 0, 0, 0, 0) optimized so it will be faster than
updating a rectangle covering the majority of the screen? That is, will
it buy me any efficiency beyond a good algorithm for joining overlapping
dirty rectangles?

Thanks for the help

pOn Saturday, September 14, 2002, at 03:43 PM, Darrell Walisser wrote:

pchans at wm.edu wrote:

I just started playing with SDL yesterday, and pretty quickly ran into a
problem with screen updates. Calls to UpdateRect() do not always result
in an image being drawn on the screen. Rather, after a number of calls
to UpdateRect a vaguely rectangular portion of the window/screen may be
updated, but not necessarily the entire portion that ought to have been
updated. I am reasonably confident that my update rectangles are
correct, as some of the time UpdateRect() behaves as I would expect.
Also, in windowed mode, moving my window off the screen and back on will
update regions that went off the screen.

NB: I am using SDL 1.2 Mac OS X.

Mac OS X.2, by chance? I’ve observed quite a few (non-SDL related
display glitches in Jaguar, which I speculate are due to the new Quartz
optimizations.

-John

No, it’s version 10.1.

p

Each frame, pass all of your dirty rects together to SDL_UpdateRects()

  • this minimizes the penalty associated with the VBL since all the
    rects are processed at the same time. Also, that should solve the
    problem with some areas not redrawing at the same time.

Is this always the best solution though? I haven’t got round to
experimenting, but say you had a 2D game where there were a number of
moving sprites plus various (occasionally only updated) status info like
score and lives. What I tend to do (e.g. for my ZXLIB C++ game library) -
and, like I said,
I haven’t tested this yet - is use UpdateRects() for the sprites (as they
move each time) but, for the scores, just blit them and update them as
needed as they are only occasionally updated. Otherwise (I’m using the STL
vector container to store my update rects) I’d have to add in the score
update rectangle to the list of update rectangles each time I want to
update it, do the updating with UpdateRects(), then remove the score
update rectangle from the list of “dirty” rects. At a guess, this seems
slower but I may be wrong?

For even better performance, in the case you have a lot of rects to
pass per frame or most of the screen area is updated, try tossing out
dirty rects altogether and call SDL_UpdateRect (screen,0,0,0,0).
Updating the whole screen can be faster since the window server has
less work to do.

This (aka SDL_Flip() I presume) seems to be extraordinarily slow on my
system (X3.3.6, 16bpp display, SDL1.2.1, windowed, software surface) -
don’t know why.

Nick

Nick Whitelegg wrote:

Is this always the best solution though? I haven’t got round to
experimenting, but say you had a 2D game where there were a number of
moving sprites plus various (occasionally only updated) status info
like score and lives. What I tend to do (e.g. for my ZXLIB C++ game
library) - and, like I said,
I haven’t tested this yet - is use UpdateRects() for the sprites (as
they move each time) but, for the scores, just blit them and update
them as needed as they are only occasionally updated. Otherwise (I’m
using the STL vector container to store my update rects) I’d have to
add in the score update rectangle to the list of update rectangles
each time I want to update it, do the updating with UpdateRects(),
then remove the score update rectangle from the list of "dirty"
rects. At a guess, this seems slower but I may be wrong?

I doubt there’s going to be a speed bottleneck in the collecting up of
the rectangles, and I expect most people change the list of dirty rects
each frame anyway. Compared to the actual updating, changing the list
around is trivial. I expect that on some platforms you might incur some
sort of penalty for calling UpdateRects twice per frame rather than
once, although I can’t be sure of this. And if you’re keeping the sprite
rectangles constant (in number, at least) then pushing and popping the
scores on the end of the std::vector on occasion is a very cheap
operation.–
Kylotan
http://pages.eidosnet.co.uk/kylotan

Is this always the best solution though? I haven’t got round to
experimenting, but say you had a 2D game where there were a number of
moving sprites plus various (occasionally only updated) status info like
score and lives. What I tend to do (e.g. for my ZXLIB C++ game library) -
and, like I said,
I haven’t tested this yet - is use UpdateRects() for the sprites (as they
move each time) but, for the scores, just blit them and update them as
needed as they are only occasionally updated. Otherwise (I’m using the STL
vector container to store my update rects) I’d have to add in the score
update rectangle to the list of update rectangles each time I want to
update it, do the updating with UpdateRects(), then remove the score
update rectangle from the list of “dirty” rects. At a guess, this seems
slower but I may be wrong?

Depending on your application and your algorithm, the use of
dirty rectangles can be faster or slower. You mileage will
always vary. Just for you reference, I have a general purpose
dirty rectangle implementation at

http://www.gime.org/twiki/bin/view/Gime/WebDownload

There is always a tradeoff of using dirty rectangles, but the
key is not to update (or even redraw) your whole screen surface
by all means, unless you are using hardware surface. If you
don’t have too much stuff changing on screen EVERY frame, dirty
rectangles definitely helps.

This (aka SDL_Flip() I presume) seems to be extraordinarily slow on my
system (X3.3.6, 16bpp display, SDL1.2.1, windowed, software surface) -
don’t know why.

AFAIK, SDL does not support hardware surface with X11, therefore,
SDL_Flip() is not going to do you any good since the screen surface
you get is only software surface that resides in main memory. In
this case, SDL_Flip() is equal to SDL_UpdateRect(screen, 0, 0, 0, 0)

Regards,
.paul.On Sun, Sep 15, 2002 at 09:39:00AM +0100, Nick Whitelegg wrote:

You shouldn’t be using SDL_UpdateRect() to do multiple dirty rects
per frame, as the cost of SDL_UpdateRect() is very - dare I say
extremely - high. The reason is that each time you call
UpdateRect() or UpdateRects() or Flip(), the window server copies the
region you specified to the display, in sync with the retrace of the
monitor (VBL), and possibly involving compositing if the window is
occluded. Even if there is no compositing required, just the sync
with the VBL causes a huge hit while the CPU is idle waiting for the
CRT beam to go by.

Yes, I am planning on using UpdateRects down the road, but I am still
perplexed by why UpdateRect does not work. My test program catches
mouse events and blits a sprite at the click position. I’m not
interested in efficiency – I just want the picture to draw, and it
doesn’t do so every time I click.

This would appear to be an error in your program. Try using the
QuartzDebug application in /Developer/Applications to see visually what
rectangles you are passing to UpdateRect().

Is UpdateRect(screen, 0, 0, 0, 0) optimized so it will be faster than
updating a rectangle covering the majority of the screen? That is,
will it buy me any efficiency beyond a good algorithm for joining
overlapping dirty rectangles?

Yes. If you are going to update the entire screen (or almost the entire
screen), the advantage of managing dirty rectangles usually becomes
insignificant.On Saturday, September 14, 2002, at 05:07 PM, pchans at wm.edu wrote:

On Saturday, September 14, 2002, at 03:43 PM, Darrell Walisser wrote:

pchans at wm.edu wrote:

Mac OS X.2, by chance? I’ve observed quite a few (non-SDL related
display glitches in Jaguar, which I speculate are due to the new
Quartz optimizations.

There are glitches, which I have a patch for and will be fixed soon.
The optimizations cause UpdateRects() to be asynchronous in 10.2 which
is the cause of the various flickering issues.On Saturday, September 14, 2002, at 07:22 PM, John R. Hall wrote:

Each frame, pass all of your dirty rects together to SDL_UpdateRects()

  • this minimizes the penalty associated with the VBL since all the
    rects are processed at the same time. Also, that should solve the
    problem with some areas not redrawing at the same time.

Is this always the best solution though? I haven’t got round to
experimenting, but say you had a 2D game where there were a number of
moving sprites plus various (occasionally only updated) status info
like
score and lives. What I tend to do (e.g. for my ZXLIB C++ game
library) -
and, like I said,
I haven’t tested this yet - is use UpdateRects() for the sprites (as
they
move each time) but, for the scores, just blit them and update them as
needed as they are only occasionally updated. Otherwise (I’m using the
STL
vector container to store my update rects) I’d have to add in the score
update rectangle to the list of update rectangles each time I want to
update it, do the updating with UpdateRects(), then remove the score
update rectangle from the list of “dirty” rects. At a guess, this seems
slower but I may be wrong?

Your approach will likely be slower than global dirty rects management.
But if it would be significantly slower I can’t say - that would have
to be determined by testing.

I worked on an app where global rects management was noticeably faster

  • but this isn’t necessarily the case for you.On Sunday, September 15, 2002, at 04:39 AM, Nick Whitelegg wrote:

Nick Whitelegg wrote:

I doubt there’s going to be a speed bottleneck in the collecting up of
the rectangles, and I expect most people change the list of dirty rects
each frame anyway. Compared to the actual updating, changing the list
around is trivial.

I agree that compared to blitting and updating video memory, managing
dirty rects takes orders of magnitude less processor time and is worth
the extra effort. You might even get that extra time for free if the
CPU is idle waiting for DMA to VRAM to complete.

I expect that on some platforms you might incur some
sort of penalty for calling UpdateRects twice per frame rather than
once, although I can’t be sure of this.

I can’t speak for other platforms, but on Mac OS X you’ll likely incur
a significant penalty for multiple UpdateRects per frame. On higher-end
machines you might not notice it, but on slower machines it tends to
make a big difference.On Sunday, September 15, 2002, at 08:50 AM, Kylotan wrote:

Well, my problem turned out to be with the rectangles… I am used to
(left, top, right, bottom) rectangles, not (left, right, width, height)
and that seems to have caused the problem. Thank you all for the tips
though.

p