The problem is caused by the D3DScreenUpdateManager.
In particular, if the onscreen surface is in the lost state when
createGraphics() is called we call validate() which may
restore the surface and return a graphics object with this
However it doesn't issue a repaint after restoring
the surface (like we do in run() method), so the application
assumes that its appearance is fine while in fact it may
Note that initially screen update manager is not
used because Swing uses buffer per window painting
mode (which uses BufferStrategy). However, if while in fs
mode the application attempts to repaint and fail
(meaning that the back-buffer will be lost) and attempts
to restore the back-buffer fail as well then
BufferStrategyPaintManager falls back
to the old repainting mechanism: a VI backbuffer copied
to the screen.
At this point D3DScreenUpdateManager will be able to
create a redirected screen surface because Swing disposes its
buffer strategy when switching to old painting mode.
The fix is simple: do the full repaint in the
validate() method so that we always repaint after
successful surface restoration.
Interesting fact: one would think that with Vista's DWM
video memory management there will be fewer situations
when surface loss event occurs than in XP (where it really
only happens when display mode changed, or some app goes
fs), but it is not so. In Vista with Aero every time user is
prompted to elevate process privileges (or start any admin
program) - which is unfortunately way too often -
a surface loss event occurs. Bummer.
This means that times when the on-screen surface may be lost
may be relatively often.
We have a mechanism for preventing copies of accelerated surface
directly to the screen - special blit (scale, transform) loops
(d3d->gdi) which disable the acceleration in the source surface
manager and mark the surface lost. So the first time an accelerated
surface is attempted to be copied to the screen the
corresponding surface manager forever loses acceleration.
This is done to prevent costly vram->sysmem->vram data
transfers. However this mechanism proved to be too
cautious - because of it we'd lose hw acceleration pretty
much every time Vista asks for permission elevation.
So instead of disabling hw acceleration in this case
we could mark the surface lost. The SunVolatileImage.validate()
will use the backup software surface, which can be copied to
the screen. Next time during validate it will attempt to restore
the surface. If it fails, we'll continue to use the backup
surface. If it succeeds, we'll get to the d3d->gdi blit loop
again and the surface will be marked lost again - and so on
until the condition preventing from creating the on-screen
accelerated surface goes away.
This assumes that the condition which caused the loss of the on-screen
surface is temporary, which will be the case in most situations.
In the worst case we'll continue restoring/losing the surface.
I don't see how to prevent that without introducing some complicated
heuristics for when to continue restoring the surface.
Note that the second part from the description:
> 2. Push the command prompt to FS mode and restore it. After that, move the SwingSet2 from > one screen to the other. The entire UI becomes garbled.
is not reproducible, possibly after the fix for 6593621.
The first issue appears to be caused by copies from VI to
It looks like at some point we get a software
back-buffer, but some of the Swing's volatile images
(like those used for rendering gradients) are still
accelerated. May be they don't get restored properly
or something similar, and produce garbage when
copied to the sw backbuffer.
All issues disappear after a resize (when a new accelerated
back-buffer is created).
More investigation is needed.