I don't think this is a plug-in bug. We need java2d team to take a look at this.
Mantis b19 plugin works fine on my Dell laptop. Probably a specific issue
with Trident video cards.
Definitely looks video-card specifc and seems to be tied to d3d functionality
introduced in the changes that went into 1.4.1_02 and 1.4.2 b7; previous
builds of both releases (and 1.4.0) work fine. Also, using the d3d=false
flag makes everything work (better workaround than noddraw).
The effects are weird, though; they do not appear to have anything to do with
the 3d functionality we are using (just drawing d3d lines). Instead, it seems
like simply enabling d3d for some drawing surfaces causes strange interaction
between ddraw and gdi. For example, scrolling on the crayons panel in
SwingSet2 does nothing until you alt-tab to a different app, at which time
the SwingSet2 window updates with several scroll/paint events. It is as
if the window events are locked out on that window which the app is
in the foreground, but released when the app is backgrounded. This artifact
could explain why some graphics are being drawn in the wrong place while the
window is being moved around; we are perhaps not getting the drawing event
at the right time and then we are updating the screen some later time when
the window has moved, thus the drawing is in the wrong place relative to
the current location of the window.
If this is a driver bug, there is no more recent version of the driver on
the Toshiba site.
I was able to reproduce the bug in a simple native app. I forwarded the app
to Trident tech support, who can hopefully shed more light on the subject.
From what I've seen so far, it seems like the driver is enabling some sort
of caching mechanism where they buffer up all calls into DirectX until one of a couple of events happen: locking/Unlocking the screen (which generally causes
the DirectX pipeline to flush) or rendering a d3d primitive. In our Java2D code, we do not necessarily perform either of these operations with any regularity. DirectX operations are generally either rectangular fills (using ddraw), blts (using ddraw), locks (but not the screen on win2k due to a cursor flicker fix), or lines (using d3d). Locking an offscreen buffer may also force a flush; I have not investigated that. On this graphics driver, lines are disabled due to quality issues so we do not even issue the d3d calls.
One other item that seems to flush the cache is forcing the window to the
background; perhaps they want to make sure that an app is done rendering when other apps come to the foreground.
in any case, there is nothing wrong that we are doing that is causing this
situation; we appear to be causing it simply by creating the d3d device for the screen. This puts the Trident driver in this strange mode.
The only alternatives that I can think of so far for "fixing" this problem in Java2D include:
- enabling d3d for the screen only if the application is fullscreen/
double-buffered. This is the only situation in which we actually need
d3d capability on the primary surface (since we generally do not perform
direct3D operations directly to the screen; we use ddraw for
Blts and GDI for direct rendering operations).
A major problem with this (at least as far as risk-free fixes go)
is that our single shared d3d context is created from the primary.
So if we disable d3d for the primary surface, we need another
mechanism for creating and sharing the d3d context. This is not
unsolvable, but it does involve risks and testing to make sure that
we handle all situations robustly (such as losing the offscreen surface
for which we have created that d3d context).
- detecting the Trident video card and disabling d3d capabilities
in native code automatically (similar to what we do for NT4, since
there is no hw d3d support on that OS). This is an ugly hack because
I would rather avoid driver/card-specific fixes in our code and
(more importantly) we do not actually know all of the devices which
are affected by this odd bug. if this driver is used by all
Trident cards, then we should detect any trident video card and
disable d3d. On the other hand, if the bug is specific to
a particular trident chip (and the driver for that chip), then
disabling d3d for all trident cards is a bit extreme.
My preference is the first fix above: find a way to share the d3d context
without enabling d3d for the primary surface. But given the time in the Mantis
release and the testing required for this fix, I doubt this is a candidate for
Note: I am assuming that the problem is coming from enabling d3d on the
primary surface. But I actually have not yet tested whether enabling
it only for offscreen surfaces also triggers this problem. if it does,
then we are hosed for Trident overall, barring any clever fixes suggested
by the folks at Trident. I should nail this down to see whether this
is even a fixable problem.
I've attached a DevStudio project TridentD3DCrash.zip that has both the
source code and executable for reproducing the problem. Run the app.
Then hit the F5 key to execute a series of ddraw blts to the screen (which
won't appear on the problem platform). then hit F6 to force a lock/unlock
event, which should cause all of the pent-up ddraw commands to spew forth.
hit F5 again (still not output). now quit the app; after the window closes
down, all of the ddraw commands spew forth onto the open desktop.
I've implemented a fix like the second one outlined above; we detect that
we are running on a "Trident Video Accelerator CyberBlade XP Ai1" graphics
card and automatically disable Direct3D support in Java2D (unless the
user has specifically forced d3d support on via the command-line flag
-Dsun.java2d.d3d=true or the environment variable J2D_D3D=true). This
appears to work on the problem platform, so we should integrate this fix
possibly for 1.4.2 and definitely for 1.5 (until we have a better solution
Note about the fix: we currently simply detect that there is one of these
cards on the system and disable d3d support globally. This should work for
this particular configuration, since the problem platform is a laptop that
would never have multiple graphics devices on it. But if we take this
workaround approach for other problem cards/drivers, we should modify the
fix to be multimon-friendly and simply disable d3d on the suspect devices and
not the entire platform globally.
Disable Java2D's use of Direct3D at runtime by using the command-line flag -Dsun.java2d.d3d=false, for example:
java -Dsun.java2d.d3d=false <class>
You can use this same flag inside of plugin, in the "Advanced" tab inside the "Java Runtime Parameters" text field, enter the same flag info:
Since the plugin control panel can be rather messed-up and unusable due to
this bug, you may also want to use the equivalent environment variable, J2D_D3D.
To do this, pull up the System control panel, go to the Advanced tab and
bring up the "Environment Variables" dialog box and enter a new variable named
J2D_D3D with the value false. Or you can do this same thing on a temporary basis by simply setting the variable on a command tool:
Setting this environment variable for the system will also allow the control
panel to work (since every Java execution will use the value of that variable
to turn off d3d support and thus workaround this bug).
A straightforward workaround (at least in Win2K) is:
Settings -> Control Panel -> Display -> Settings -> Advanced -> Troubleshooting.
Set "Hardware Acceleration" to "Disable all DirectDraw accelerations ..."
This workaround has a messaging advantage for customers: "The Trident video
adapter has a problem and needs to be adjusted" (which is true) vs. "Java
requires strange command-line flags to work right." The disadvantage is that it will affect performance of more than just Java.