Disabling swing.bufferPerWindow does not fix the problem. Disabling ddraw does.
Note how the black rectangles in ssetbad.png are exactly the size of the window borders on the left (for the vertical rectangle) and on the top (for the horizontal rectangle). Presumably we are double-counting the insets in some situations.
Not clear whether this is a 2D issue or an AWT one, but since it's not reproducible with ddraw disabled, it seems like it's specific to the ddraw/2D code.
This bug is present on all builds of Vista since Beta1 (Beta1, 5219 and 5231)
My testing was done on Vista build 5270 and mustang b65.
The insets problem is only the tip of the iceberg. It's not like the
rendering is offset by twice the insets needed, the application window
doesn't refresh correctly as well - like you'd click on the menu
and it won't appear but the tracing says that we do render it.
Also, it's not necessary to resize the window to get the effect,
sometimes it's enough to just move the application frame around a bit.
There are many other funny issues.
For example, run SwingSet2 and drag one of the internal frames down (or
just scroll down) - the rendering gets messed up. After this menus stop
working, for example. Dragging it up or left-right works fine. I can't
yet reproduce it with smaller test case with just copyAreas.
It appears that all these problems are related to using ddraw for
blitting to the screen.
When DDraw blits to the screen are disabled (offscreen->offscreen blits
remain enabled), all problems disappear.
So, for example, if -Dsun.java2d.ddblits=false flag is used everything
works fine, but we lose the offscreen->offscreen blits as well.
I've modified the code to only allow offscreen blits and the bug went away.
I suspect that this is really a vista bug. I've seen very weird things
happening with the way application frame is updated, which couldn't have been
caused by our stuff.
I've been able to reproduce similar behavior in [an attached] native
Here's what it does:
- creates and initializes an offscreen dd surface
- for paint event it uses GDI to clear the window with
changing colors, so you can see if the window was repainted;
and every third time it also copies the dd surface to the window
This is done to show that painting with GDI only w/o copying
the bb to the screen works fine
- just to make things more visual it can launch a separate thread
that repaints the window every 2 seconds (File/Run Update
Thread). The thread doesn't just request a repaint event but
- you can request the back-buffer to be updated before it's copied
to the screen (see below to why this is interesting) -
- by default it uses DDraw to clear the window on each
rendering/repant event - this is to illustrate that the bug
doesn't manifest if ddraw only is used for rendering to the window.
You can change this in the File/ menu.
The app clears the window with different color on every repaint, and
copies the offscreen surface to the window on every third repaint.
Here's what happens: on Vista when the app is launched you can see
that it it works fine - this is because by default it uses only DDraw for
rendering to the window.
But if you uncheck the "File/Clear using DD" menu, it will use GDI for clearing
the window and you'll see that the repainting stops as soon as the back-buffer
is copied to the window.
Actually what happens is that the app keeps the rendering, but the window doesn't
If you check "Update BackBuffer", then it'll update the offscreen surface
before copying it to the screen (by filling it with some color). In this
case you'll see a funny effect: the area where the bb is copied to is
updated, but the rest of the window still isn't.
I haven't been able to reproduce the problem where the image of the
window is shifted by the insets - I guess the way Java does insets
stuff is a bit different, but I'm sure I can reproduce it as well
given more time. I bet it involves fiddling with the
OffsetViewportOrgEx function, which we use when setting up a display GC
prior to using it (see Win32SurfaceData.cpp : SetupThreadGraphicsInfo() function).
I've also attached an AWT application which does the same thing as the
native one, except w/o all the different menu choices.
The bug was reported to Microsoft and it appears that this is something
we'll have to live with.
Basically, applications are not supposed to render to onscreen surfaces using
DDraw and GDI, at least, to the same area. Unfortunately we do that and there
appears to be no easy way to fix this given our current pipelines.
It does work in previous releases but apparently it was never guaranteed.
So, an application should either use GDI or DDraw exclusively.
Since rendering to offscreen surfaces using DDraw and copying them to the screen
using GDI is extremely slow (basically it's a read from vram to system memory
and then back to vram), we'll have to disable ddraw completely.
This actually yields quite acceptable performance on Vista.
There's still an issue of full screen mode, where we would like to use
DDraw and Direct3D.
A simple fix was put in for now, which disables the use of DDraw on Windows Vista.
To override, use -Dsun.java2d.noddraw=false .