From 33b174749a733ab31d32241838f4912910e78b5c Mon Sep 17 00:00:00 2001 From: Jennifer Godinez Date: Fri, 17 Dec 2010 09:39:54 -0800 Subject: [PATCH] 6635462: D3D: REGRESSION: XOR rendering is extremly slow Reviewed-by: igor, prr --- .../javax/swing/DefaultDesktopManager.java | 26 ++++++++++- .../sun/awt/windows/WComponentPeer.java | 21 +++++++++ .../sun/java2d/d3d/D3DSurfaceData.java | 45 ++++++++++++++++++- 3 files changed, 89 insertions(+), 3 deletions(-) diff --git a/jdk/src/share/classes/javax/swing/DefaultDesktopManager.java b/jdk/src/share/classes/javax/swing/DefaultDesktopManager.java index d531526265c..aae1e51ef0c 100644 --- a/jdk/src/share/classes/javax/swing/DefaultDesktopManager.java +++ b/jdk/src/share/classes/javax/swing/DefaultDesktopManager.java @@ -359,7 +359,22 @@ public class DefaultDesktopManager implements DesktopManager, java.io.Serializab f.getWidth()-1, f.getHeight()-1); } g.drawRect( newX, newY, f.getWidth()-1, f.getHeight()-1); - currentLoc = new Point (newX, newY); + /* Work around for 6635462: XOR mode may cause a SurfaceLost on first use. + * Swing doesn't expect that its XOR drawRect did + * not complete, so believes that on re-entering at + * the next update location, that there is an XOR rect + * to draw out at "currentLoc". But in fact + * its now got a new clean surface without that rect, + * so drawing it "out" in fact draws it on, leaving garbage. + * So only update/set currentLoc if the draw completed. + */ + sun.java2d.SurfaceData sData = + ((sun.java2d.SunGraphics2D)g).getSurfaceData(); + + if (!sData.isSurfaceLost()) { + currentLoc = new Point (newX, newY); + } +; g.dispose(); } } else if (dragMode == FASTER_DRAG_MODE) { @@ -412,7 +427,14 @@ public class DefaultDesktopManager implements DesktopManager, java.io.Serializab g.drawRect( currentBounds.x, currentBounds.y, currentBounds.width-1, currentBounds.height-1); } g.drawRect( newX, newY, newWidth-1, newHeight-1); - currentBounds = new Rectangle (newX, newY, newWidth, newHeight); + + // Work around for 6635462, see comment in dragFrame() + sun.java2d.SurfaceData sData = + ((sun.java2d.SunGraphics2D)g).getSurfaceData(); + if (!sData.isSurfaceLost()) { + currentBounds = new Rectangle (newX, newY, newWidth, newHeight); + } + g.setPaintMode(); g.dispose(); } diff --git a/jdk/src/windows/classes/sun/awt/windows/WComponentPeer.java b/jdk/src/windows/classes/sun/awt/windows/WComponentPeer.java index 5a3cd2ddd87..8dc99ed60f2 100644 --- a/jdk/src/windows/classes/sun/awt/windows/WComponentPeer.java +++ b/jdk/src/windows/classes/sun/awt/windows/WComponentPeer.java @@ -999,6 +999,8 @@ public abstract class WComponentPeer extends WObjectPeer public void setBoundsOperation(int operation) { } + private volatile boolean isAccelCapable = true; + /** * Returns whether this component is capable of being hw accelerated. * More specifically, whether rendering to this component or a @@ -1009,11 +1011,22 @@ public abstract class WComponentPeer extends WObjectPeer * {@link GraphicsDevice.WindowTranslucency#PERPIXEL_TRANSLUCENT * PERPIXEL_TRANSLUCENT}. * + * Another condition is if Xor paint mode was detected when rendering + * to an on-screen accelerated surface associated with this peer. + * in this case both on- and off-screen acceleration for this peer is + * disabled. + * * @return {@code true} if this component is capable of being hw * accelerated, {@code false} otherwise * @see GraphicsDevice.WindowTranslucency#PERPIXEL_TRANSLUCENT */ public boolean isAccelCapable() { + if (!isAccelCapable || + !isContainingTopLevelAccelCapable((Component)target)) + { + return false; + } + boolean isTranslucent = SunToolkit.isContainingTopLevelTranslucent((Component)target); // D3D/OGL and translucent windows interacted poorly in Windows XP; @@ -1021,6 +1034,14 @@ public abstract class WComponentPeer extends WObjectPeer return !isTranslucent || Win32GraphicsEnvironment.isVistaOS(); } + /** + * Disables acceleration for this peer. + */ + public void disableAcceleration() { + isAccelCapable = false; + } + + native void setRectangularShape(int lox, int loy, int hix, int hiy, Region region); diff --git a/jdk/src/windows/classes/sun/java2d/d3d/D3DSurfaceData.java b/jdk/src/windows/classes/sun/java2d/d3d/D3DSurfaceData.java index 553d84156b2..bc7dfd8631a 100644 --- a/jdk/src/windows/classes/sun/java2d/d3d/D3DSurfaceData.java +++ b/jdk/src/windows/classes/sun/java2d/d3d/D3DSurfaceData.java @@ -437,6 +437,10 @@ public class D3DSurfaceData extends SurfaceData implements AccelSurface { protected int getElem(final int x, final int y, final SurfaceData sData) { + if (sData.isSurfaceLost()) { + return 0; + } + int retPixel; D3DRenderQueue rq = D3DRenderQueue.getInstance(); rq.lock(); @@ -456,6 +460,10 @@ public class D3DSurfaceData extends SurfaceData implements AccelSurface { protected void setElem(final int x, final int y, final int pixel, final SurfaceData sData) { + if (sData.isSurfaceLost()) { + return; + } + D3DRenderQueue rq = D3DRenderQueue.getInstance(); rq.lock(); try { @@ -512,15 +520,32 @@ public class D3DSurfaceData extends SurfaceData implements AccelSurface { sg2d.surfaceData.getTransparency() == Transparency.OPAQUE; } + /** + * If acceleration should no longer be used for this surface. + * This implementation flags to the manager that it should no + * longer attempt to re-create a D3DSurface. + */ + void disableAccelerationForSurface() { + if (offscreenImage != null) { + SurfaceManager sm = SurfaceManager.getManager(offscreenImage); + if (sm instanceof D3DVolatileSurfaceManager) { + setSurfaceLost(true); + ((D3DVolatileSurfaceManager)sm).setAccelerationEnabled(false); + } + } + } + public void validatePipe(SunGraphics2D sg2d) { TextPipe textpipe; boolean validated = false; // REMIND: the D3D pipeline doesn't support XOR!, more - // fixes will be needed below + // fixes will be needed below. For now we disable D3D rendering + // for the surface which had any XOR rendering done to. if (sg2d.compositeState >= sg2d.COMP_XOR) { super.validatePipe(sg2d); sg2d.imagepipe = d3dImagePipe; + disableAccelerationForSurface(); return; } @@ -894,8 +919,26 @@ public class D3DSurfaceData extends SurfaceData implements AccelSurface { return peer.getTarget(); } + @Override + void disableAccelerationForSurface() { + // for on-screen surfaces we need to make sure a backup GDI surface is + // is used until a new one is set (which may happen during a resize). We + // don't want the screen update maanger to replace the surface right way + // because it causes repainting issues in Swing, so we invalidate it, + // this will prevent SUM from issuing a replaceSurfaceData call. + setSurfaceLost(true); + invalidate(); + flush(); + peer.disableAcceleration(); + ScreenUpdateManager.getInstance().dropScreenSurface(this); + } + @Override void restoreSurface() { + if (!peer.isAccelCapable()) { + throw new InvalidPipeException("Onscreen acceleration " + + "disabled for this surface"); + } Window fsw = graphicsDevice.getFullScreenWindow(); if (fsw != null && fsw != peer.getTarget()) { throw new InvalidPipeException("Can't restore onscreen surface"+