United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-6343853 Rendering issues on Vista caused by use of GDI and DDraw on onscreen surfaces
JDK-6343853 : Rendering issues on Vista caused by use of GDI and DDraw on onscreen surfaces

Submit Date:
Updated Date:
Project Name:
Resolved Date:
Affected Versions:
Fixed Versions:

Related Reports

Sub Tasks

Check out the attached pictures.  One (ssetokay.png) shows how SwingSet should look.  Another (ssetbad.png) shows SwingSet with black rectangles and offset rendering.  The last (ssetcomparison.png) shows the good and bad images side by side.

To get the bad results, run SwingSet2 with no command line options (so it will use the defatul ddraw renderer).  The window will probably look fine when it comes up.  Now resize the window and notice how the window cycles through bad offsets and black rectangles, ending up randomly with either bad offsets or not.



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
      renders directly
    - 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
  get updated.

  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 .

Hardware and Software, Engineered to Work Together