Java Solaris Communities Sun Store Join SDN My Profile Why Join?
 
Bug Database
Bug Detail
Quick Lists
Top 25 Bugs
Top 25 RFE's
Recently Closed Bugs
Printable Page Printable Page


Bug Database
Bug ID: 6630702
Votes 0
Synopsis D3D: Rendering artifacts when scrolling/dragging on Vista with Aero/DWM [multiple boards]
Category java:classes_2d
Reported Against
Release Fixed 6u10(b10)
State 10-Fix Delivered, Verified, bug
Priority: 2-High
Related Bugs
Submit Date 16-NOV-2007
Description
As discussed in this thread:
  http://forums.java.net/jive/forum.jspa?forumID=69&start=0

On Windows Vista (multiple machines, video boards),
only with Aero (DWM) enabled, some swing applications
produce rendering artifacts when scrolling or
dragging internal frames. Doesn't happen if Aero
is disabled (even while the application is running) 
by selecting "Vista Basic" color theme in the 
Appearance dialog.

For example, run this this Substance L&F demo
(note that the look and feel doesn't matter, it's
reproducible with all L&Fs):
  javaws https://substance.dev.java.net/webstart/test.jnlp

Play around with the pane on the left side - 
expand/collapse the "tasks". The click at
"List" tab on the right pane, and scroll
the list. The scrolled area then becomes
black or white (depending on laf).

Similar thing happens in the "Desktop" tab - create
a new Internal frame and drag it around - it
produces similar artifacts.
This indicates that the problem is caused
by the copyArea() call.

Interestingly, if the app loses focus and then gains
it back (alt+tab x2) the repainting problems stop until 
the task is collapsed/expanded at which point
they appear again.
Posted Date : 2007-11-16 01:49:14.0
Work Around
Disable Swing's "true double-buffering": -Dswing.bufferPerWindow=false .
Evaluation
This looks like a problem in Vista's DWM (since it's video board-agnostic), 
but I'm not sure why is it triggered by the JXTaskPane.
Posted Date : 2007-11-16 01:51:03.0

OK, I've investigated this a bit more.

This is an issue with DWM, but it is caused by our code.

Essentially it is caused by doing D3D and GDI rendering to the 
same window which is a bad idea on Vista - it's pretty 
much broken.

Unfortunately in some situations Swing allows rendering directly
to the screen - which is what happens in this case.

The JXCollapsiblePane widget does some animation on collasing/expanding.
As part of that animation it apparently first paints the component to 
an off-screen image. This triggers a special code path in 
BufferStrategyPaintManager:
        at javax.swing.BufferStrategyPaintManager$BufferInfo.setInSync(BufferStrategyPaintManager.java:719)
        at javax.swing.BufferStrategyPaintManager.paint(BufferStrategyPaintManager.java:293)
        at javax.swing.RepaintManager.paint(RepaintManager.java:1172)
        at javax.swing.JComponent.paint(JComponent.java:1014)
        at org.jdesktop.swingx.JXCollapsiblePane$WrapperContainer.makeImage(JXCollapsiblePane.java:826)
        at org.jdesktop.swingx.JXCollapsiblePane$WrapperContainer.showImage(JXCollapsiblePane.java:795)
        at org.jdesktop.swingx.JXCollapsiblePane$AnimationListener.reinit(JXCollapsiblePane.java:770)
        at org.jdesktop.swingx.JXCollapsiblePane.setCollapsed(JXCollapsiblePane.java:475)
        at org.jdesktop.swingx.JXTaskPane.setExpanded(JXTaskPane.java:386)
        at org.jdesktop.swingx.plaf.basic.BasicTaskPaneUI$ToggleListener.mouseReleased(BasicTaskPaneUI.java:367)
        at java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:272)

The setInSync() indicates to the paint manager that the back-buffer is
no longer in sync with what's on the screen. After this all copyAreas
get redirected to the screen instead of the back-buffer (why only copyAreas?).
It's not clear why doing painting to another offscreen surface 
necessarily indicates an out of sync back-buffer though.

Now, the D3D pipeline does special handling for rendering to
the screen - it redirects all rendering to a dedicated back-buffer,
a sort of "fake window", which is presented to the screen when
needed. That way we can still accelerated on-screen rendering using
Direct3D (direct on-screen rendering is not possible with Direct3D 9).

However, this special handling is disabled for windows which have their
own BufferStrategy - which is the case here, since Swing uses BufferStrategy
as a back-buffer when it is in "bufferPerWindow" mode - aka the "gray rect fix",
or "true double-buffering".

Because of that the rendering goes directly to the screen, so the
copy area is performed using GDICopyArea. It works fine XP, but
produces artifacts on Vista with Aero.

Looking at the latest code for JXCollapsiblePane it looks like it
no longer uses this approach for doing their animation, so it could 
be that this particular case will no longer trigger the issue, but the 
underlying problem is still there of course.

Since all circumstances under which Swing may switch from
buffer per window mode to the "regular" one, or allow on-screen 
rendering, are not clear it doesn't seem likely that we could
fix swing's "buffer out of sync" cases.

One solution would be to use the old painting mode - where 
Swing's back-buffer is a VolatileImage which is copied to the
screen - in this case the D3D pipeline's on-screen rendering
support will ensure that one never renders directly to the
screen.

Since Aero is already double-buffered (which in particular 
means that applications don't get 'expose' events when another 
window is moved over their window) the 'true double-buffering'
doesn't really give any advantages.

More investigation is needed.

Note: it is possible that this is the cause of other
issues on Vista like the one described here:
  http://forums.java.net/jive/thread.jspa?threadID=32535&tstart=0
It looks especially plausible since disabling buffer per window
also helped there.
Posted Date : 2007-12-12 21:59:15.0

The solution we're working on is disabling Swing's 
"true double-buffering" mode on Vista with DWM(Aero) enabled.

From the code review:
  With buffer per window disabled Swing will use VolatileImage
  as back-buffer and that will allow the D3D pipeline
  to guarantee that no on-screen rendering will occur since
  our mechanism will be working.

  Another reason is that since Aero already does double-buffering
  there's no point in wasting resources, the application 
  doesn't get expose events anyway.

  This solution is also less risky than
  changing the way Swing paints on all platforms.

  Notes about the implementation: while the state of DWM 
  compositing can change during the lifetime of the 
  application it is an extremely rare event, and is
  in most cases temporary (some app turns it off, then
  re-enables it). So if it was turned on when we started
  we'll detect it and not use buffer per window.
  If they disable it during the runtime - no big deal,
  everything will look sucky (flashing) anyway and we'll 
  be no exception.

  If we find that we do need to handle runtime changes -
  they're easy to handle, just add a listener mechanism
  to Win32GraphicsEnv (espose through some shared interface), 
  and have BufferStrategyPaintManager listen to those 
  events and disable bpw if needed.
Posted Date : 2007-12-14 23:18:58.0
Comments
  
  Include a link with my name & email   


PLEASE NOTE: JDK6 is formerly known as Project Mustang