Skip to main content

Swing Update: No More Gray Rect

Posted by chet on April 20, 2005 at 8:31 AM PDT

Exposee!

News Flash!

Clear Skies Ahead!

Perceived Performance Problem Perforated!

This feature's so huge, so cool, so visible, there's just got
to be a catchy title for it. I spent a few minutes coming up with the
above list, but somehow it just doesn't get the point across, at least
not in a spew-coffee-onto-your-keyboard-laughing kind of way that I
was after.

Dang - I guess I'll have to dispense with the superficial headlines and
actually write some content instead.

The Swing folks, and Scott Violet in particular, have just checked in
a very cool fix to a long-standing problem with Swing; there are no
more "gray rects" in Swing GUIs. Check out Scott's blog about it or download the binaries.

I think most Swing developers and users will know what I'm talking about
here; it's the unfortunate effect you get when you cause an "expose"
event on a Swing window. Maybe you alt-tab over to a Swing application,
which brings it to the foreground. Or maybe you un-minimize the app.
Or maybe you drag another application window across the top of it.

In applications that have complex GUIs, or involved graphics, or for whatever
reason spend a long time actually rendering the window, these operations
typically caused a "gray rect" effect that the user could see; the
Swing application would erase the area affected to a background gray
color, would then do whatever repaint was required for that region, and
would finally copy from the back buffer to the screen and cover the
gray area.

(These regions are rectangular, hence our internal phrase "gray rect").

The root cause of this artifact was in the way that Swing double-buffering
worked. Swing usually has an offscreen image that it uses to buffer-up
all rendering before copying it to the screen. This mechanism is commonly
used in applications that want smooth rendering, and it helps Swing avoid
"flashing" artifacts as it paints the GUI widgets, or other graphics,
into the application window. Instead of one-by-one updates of the
various elements in the window, Swing updates the entire update region
behind the scenes and then Bam! it copies the update region to the
window in one operation.

The use of a back buffer is a Good Thing, and Swing benefits from smooth
window rendering because of it. However, the buffering mechanism was
created in a time when system memory was a constrained resource, so
it was considered important to share this back buffer with all Swing windows.
So instead of a buffer that acts as a backup for the contents on the screen,
as back buffers typically do, the Swing buffer acted more as a scratch
buffer for any pending operations. Whenever there was an update that needed
to occur on the Swing window, Swing would render that region into the upper-left
area of the back buffer and then copy that region into the proper
location in the Window.

The end result was that the contents in the back buffer were not persistent,
nor did they typcially reflect the contents in the Swing window. So, for
example, if another window was dragged across the Swing window and caused
that window to be updated, then Swing would have to repaint that entire
area again, since it didn't know what used to be there.

With this new approach, Swing now has a buffer per Swing window on the
screen, and those buffers' contents are consistent with the graphics in
the actual window. So now, if you drag a window across the Swing
application window, Swing can simply copy from the back buffer back to
the screen and save all the work of erasing and then repainting that
area.

And what's more, Swing does this fast copy operation on the native
event thread, which means that there is immediate response, and thus
immediate responsiveness of your GUI. Previously, Swing would do the
following on an update event:

  • Erase affected region
  • Post paint event to Event Dispatch Thread
  • Receive paint event on Event Dispatch Thread
  • Render contents to back buffer
  • Copy back buffer to screen

Now, here's what happens:

  • Copy back buffer to screen

... and that's it! (Swing still generates a paint event for the region in case the application wants to do anything with that event, but by default this redundant paint event is ignored and Swing does not waste time on it).

For now, this feature is only enabled on Windows (where we get the biggest
bang out of the copy-to-screen operation, due to the graphics acceleration
features on that platform). The Swing team is investigating enabling it
on other platforms by default as well.
Copy back buffer to screen

Now doesn't this feature sound great! Don't you want it? How long do you
think you'll have to wait for it? 3 months? 6 months? When Mustang
ships? Longer?

No! Try now! That's right: if you act now, you can download this
feature immediately and play with it today. So check out Scott's blog
and upcoming article about it. And check out the Mustang site and download
build 32 (or later). Try it out, let us know if you have problems.

Expose yourself. We think you'll like it so much you'll want to do it
as often as possible.


Related Topics >>