diff options
author | tdv <none@none> | 2008-07-18 10:48:44 -0700 |
---|---|---|
committer | tdv <none@none> | 2008-07-18 10:48:44 -0700 |
commit | ece64035a19f19d319b74da7f27b2fe7c2edbe8c (patch) | |
tree | 920ff3f87f4af71cf604006d8d76144f17d649fd /src/share | |
parent | 85fa01e3802900948bea08a012a908ae85e1d1a1 (diff) |
6725214: D3D: forward-port the new pipeline from 6u10
Summary: Forward port of the new Direct3D 9 rendering pipeline from 6u10. Also includes fixes for 6690659 6689025 6658398 6596234.
Reviewed-by: campbell, prr
--HG--
rename : src/windows/classes/sun/java2d/windows/Win32SurfaceData.java => src/windows/classes/sun/java2d/windows/GDIWindowSurfaceData.java
rename : src/windows/native/sun/java2d/windows/Win32SurfaceData.cpp => src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.cpp
rename : src/windows/native/sun/java2d/windows/Win32SurfaceData.h => src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h
Diffstat (limited to 'src/share')
60 files changed, 3715 insertions, 334 deletions
diff --git a/src/share/classes/java/awt/Component.java b/src/share/classes/java/awt/Component.java index 9c54250df..03749b4ca 100644 --- a/src/share/classes/java/awt/Component.java +++ b/src/share/classes/java/awt/Component.java @@ -74,7 +74,11 @@ import sun.awt.dnd.SunDropTargetEvent; import sun.awt.im.CompositionArea; import sun.java2d.SunGraphics2D; import sun.java2d.pipe.Region; +import sun.awt.image.VSyncedBSManager; +import sun.java2d.pipe.hw.ExtendedBufferCapabilities; +import static sun.java2d.pipe.hw.ExtendedBufferCapabilities.VSyncType.*; import sun.awt.RequestFocusController; +import sun.java2d.SunGraphicsEnvironment; /** * A <em>component</em> is an object having a graphical representation @@ -3508,6 +3512,11 @@ public abstract class Component implements ImageObserver, MenuContainer, if (numBuffers == 1) { bufferStrategy = new SingleBufferStrategy(caps); } else { + SunGraphicsEnvironment sge = (SunGraphicsEnvironment) + GraphicsEnvironment.getLocalGraphicsEnvironment(); + if (!caps.isPageFlipping() && sge.isFlipStrategyPreferred(peer)) { + caps = new ProxyCapabilities(caps); + } // assert numBuffers > 1; if (caps.isPageFlipping()) { bufferStrategy = new FlipSubRegionBufferStrategy(numBuffers, caps); @@ -3518,6 +3527,25 @@ public abstract class Component implements ImageObserver, MenuContainer, } /** + * This is a proxy capabilities class used when a FlipBufferStrategy + * is created instead of the requested Blit strategy. + * + * @see sun.awt.SunGraphicsEnvironment#isFlipStrategyPreferred(ComponentPeer) + */ + private class ProxyCapabilities extends ExtendedBufferCapabilities { + private BufferCapabilities orig; + private ProxyCapabilities(BufferCapabilities orig) { + super(orig.getFrontBufferCapabilities(), + orig.getBackBufferCapabilities(), + orig.getFlipContents() == + BufferCapabilities.FlipContents.BACKGROUND ? + BufferCapabilities.FlipContents.BACKGROUND : + BufferCapabilities.FlipContents.COPIED); + this.orig = orig; + } + } + + /** * @return the buffer strategy used by this component * @see Window#createBufferStrategy * @see Canvas#createBufferStrategy @@ -3646,16 +3674,30 @@ public abstract class Component implements ImageObserver, MenuContainer, width = getWidth(); height = getHeight(); - if (drawBuffer == null) { - peer.createBuffers(numBuffers, caps); - } else { + if (drawBuffer != null) { // dispose the existing backbuffers drawBuffer = null; drawVBuffer = null; destroyBuffers(); // ... then recreate the backbuffers - peer.createBuffers(numBuffers, caps); } + + if (caps instanceof ExtendedBufferCapabilities) { + ExtendedBufferCapabilities ebc = + (ExtendedBufferCapabilities)caps; + if (ebc.getVSync() == VSYNC_ON) { + // if this buffer strategy is not allowed to be v-synced, + // change the caps that we pass to the peer but keep on + // trying to create v-synced buffers; + // do not throw IAE here in case it is disallowed, see + // ExtendedBufferCapabilities for more info + if (!VSyncedBSManager.vsyncAllowed(this)) { + caps = ebc.derive(VSYNC_DEFAULT); + } + } + } + + peer.createBuffers(numBuffers, caps); updateInternalBuffers(); } @@ -3700,7 +3742,23 @@ public abstract class Component implements ImageObserver, MenuContainer, */ protected void flip(BufferCapabilities.FlipContents flipAction) { if (peer != null) { - peer.flip(flipAction); + Image backBuffer = getBackBuffer(); + if (backBuffer != null) { + peer.flip(0, 0, + backBuffer.getWidth(null), + backBuffer.getHeight(null), flipAction); + } + } else { + throw new IllegalStateException( + "Component must have a valid peer"); + } + } + + void flipSubRegion(int x1, int y1, int x2, int y2, + BufferCapabilities.FlipContents flipAction) + { + if (peer != null) { + peer.flip(x1, y1, x2, y2, flipAction); } else { throw new IllegalStateException( "Component must have a valid peer"); @@ -3711,6 +3769,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * Destroys the buffers created through this object */ protected void destroyBuffers() { + VSyncedBSManager.releaseVsync(this); if (peer != null) { peer.destroyBuffers(); } else { @@ -3723,7 +3782,11 @@ public abstract class Component implements ImageObserver, MenuContainer, * @return the buffering capabilities of this strategy */ public BufferCapabilities getCapabilities() { - return caps; + if (caps instanceof ProxyCapabilities) { + return ((ProxyCapabilities)caps).orig; + } else { + return caps; + } } /** @@ -3811,6 +3874,14 @@ public abstract class Component implements ImageObserver, MenuContainer, } /** + * Makes specified region of the the next available buffer visible + * by either blitting or flipping. + */ + void showSubRegion(int x1, int y1, int x2, int y2) { + flipSubRegion(x1, y1, x2, y2, caps.getFlipContents()); + } + + /** * {@inheritDoc} * @since 1.6 */ @@ -4080,8 +4151,6 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Private class to perform sub-region flipping. - * REMIND: this subclass currently punts on subregions and - * flips the entire buffer. */ private class FlipSubRegionBufferStrategy extends FlipBufferStrategy implements SubRegionShowable @@ -4095,14 +4164,13 @@ public abstract class Component implements ImageObserver, MenuContainer, } public void show(int x1, int y1, int x2, int y2) { - show(); + showSubRegion(x1, y1, x2, y2); } // This is invoked by Swing on the toolkit thread. - public boolean validateAndShow(int x1, int y1, int x2, int y2) { - revalidate(false); - if (!contentsRestored() && !contentsLost()) { - show(); + public boolean showIfNotLost(int x1, int y1, int x2, int y2) { + if (!contentsLost()) { + showSubRegion(x1, y1, x2, y2); return !contentsLost(); } return false; @@ -4130,9 +4198,8 @@ public abstract class Component implements ImageObserver, MenuContainer, } // This method is called by Swing on the toolkit thread. - public boolean validateAndShow(int x1, int y1, int x2, int y2) { - revalidate(false); - if (!contentsRestored() && !contentsLost()) { + public boolean showIfNotLost(int x1, int y1, int x2, int y2) { + if (!contentsLost()) { showSubRegion(x1, y1, x2, y2); return !contentsLost(); } diff --git a/src/share/classes/java/awt/GraphicsDevice.java b/src/share/classes/java/awt/GraphicsDevice.java index ee7b14624..e9dfd5a1d 100644 --- a/src/share/classes/java/awt/GraphicsDevice.java +++ b/src/share/classes/java/awt/GraphicsDevice.java @@ -1,5 +1,5 @@ /* - * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2008 Sun Microsystems Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -236,6 +236,10 @@ public abstract class GraphicsDevice { */ public void setFullScreenWindow(Window w) { if (fullScreenWindow != null && windowedModeBounds != null) { + // if the window went into fs mode before it was realized it may + // have (0,0) dimensions + if (windowedModeBounds.width == 0) windowedModeBounds.width = 1; + if (windowedModeBounds.height == 0) windowedModeBounds.height = 1; fullScreenWindow.setBounds(windowedModeBounds); } // Set the full screen window diff --git a/src/share/classes/java/awt/Robot.java b/src/share/classes/java/awt/Robot.java index 636961101..95d383e5b 100644 --- a/src/share/classes/java/awt/Robot.java +++ b/src/share/classes/java/awt/Robot.java @@ -1,5 +1,5 @@ /* - * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2008 Sun Microsystems Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,12 +25,18 @@ package java.awt; -import java.awt.peer.*; -import java.awt.image.*; -import java.awt.event.*; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.image.BufferedImage; +import java.awt.image.DataBufferInt; +import java.awt.image.DirectColorModel; +import java.awt.image.Raster; +import java.awt.image.WritableRaster; +import java.awt.peer.RobotPeer; import java.lang.reflect.InvocationTargetException; import sun.awt.ComponentFactory; import sun.awt.SunToolkit; +import sun.awt.image.SunWritableRaster; import sun.security.util.SecurityConstants; /** @@ -335,6 +341,10 @@ public class Robot { /* blue mask */ 0x000000FF); } + // need to sync the toolkit prior to grabbing the pixels since in some + // cases rendering to the screen may be delayed + Toolkit.getDefaultToolkit().sync(); + int pixels[]; int[] bandmasks = new int[3]; @@ -346,6 +356,7 @@ public class Robot { bandmasks[2] = screenCapCM.getBlueMask(); raster = Raster.createPackedRaster(buffer, translatedRect.width, translatedRect.height, translatedRect.width, bandmasks, null); + SunWritableRaster.makeTrackable(buffer); image = new BufferedImage(screenCapCM, raster, false, null); diff --git a/src/share/classes/java/awt/image/DataBuffer.java b/src/share/classes/java/awt/image/DataBuffer.java index a2cbfbc19..c53707fab 100644 --- a/src/share/classes/java/awt/image/DataBuffer.java +++ b/src/share/classes/java/awt/image/DataBuffer.java @@ -1,5 +1,5 @@ /* - * Portions Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. + * Portions Copyright 1997-2008 Sun Microsystems Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -530,6 +530,12 @@ public abstract class DataBuffer { public StateTrackableDelegate getTrackable(DataBuffer db) { return db.theTrackable; } + + public void setTrackable(DataBuffer db, + StateTrackableDelegate trackable) + { + db.theTrackable = trackable; + } }); } } diff --git a/src/share/classes/java/awt/peer/ComponentPeer.java b/src/share/classes/java/awt/peer/ComponentPeer.java index 603a83a3e..5abe647c9 100644 --- a/src/share/classes/java/awt/peer/ComponentPeer.java +++ b/src/share/classes/java/awt/peer/ComponentPeer.java @@ -1,5 +1,5 @@ /* - * Copyright 1995-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1995-2008 Sun Microsystems Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -88,7 +88,7 @@ public interface ComponentPeer { boolean handlesWheelScrolling(); void createBuffers(int numBuffers, BufferCapabilities caps) throws AWTException; Image getBackBuffer(); - void flip(BufferCapabilities.FlipContents flipAction); + void flip(int x1, int y1, int x2, int y2, BufferCapabilities.FlipContents flipAction); void destroyBuffers(); /** diff --git a/src/share/classes/javax/swing/BufferStrategyPaintManager.java b/src/share/classes/javax/swing/BufferStrategyPaintManager.java index d28113b91..241ff3f4e 100644 --- a/src/share/classes/javax/swing/BufferStrategyPaintManager.java +++ b/src/share/classes/javax/swing/BufferStrategyPaintManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-2008 Sun Microsystems Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -263,7 +263,7 @@ class BufferStrategyPaintManager extends RepaintManager.PaintManager { (SubRegionShowable)bufferStrategy; boolean paintAllOnExpose = info.getPaintAllOnExpose(); info.setPaintAllOnExpose(false); - if (bsSubRegion.validateAndShow(x, y, (x + w), (y + h))) { + if (bsSubRegion.showIfNotLost(x, y, (x + w), (y + h))) { return !paintAllOnExpose; } // Mark the buffer as needing to be repainted. We don't diff --git a/src/share/classes/sun/awt/NullComponentPeer.java b/src/share/classes/sun/awt/NullComponentPeer.java index e5939e4e2..f18699e95 100644 --- a/src/share/classes/sun/awt/NullComponentPeer.java +++ b/src/share/classes/sun/awt/NullComponentPeer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2008 Sun Microsystems Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -255,7 +255,9 @@ public class NullComponentPeer implements LightweightPeer, throw new IllegalStateException( "Page-flipping is not allowed on a lightweight component"); } - public void flip(BufferCapabilities.FlipContents flipAction) { + public void flip(int x1, int y1, int x2, int y2, + BufferCapabilities.FlipContents flipAction) + { throw new IllegalStateException( "Page-flipping is not allowed on a lightweight component"); } diff --git a/src/share/classes/sun/awt/SubRegionShowable.java b/src/share/classes/sun/awt/SubRegionShowable.java index 5b779a7ed..c279e7096 100644 --- a/src/share/classes/sun/awt/SubRegionShowable.java +++ b/src/share/classes/sun/awt/SubRegionShowable.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,10 +39,11 @@ public interface SubRegionShowable { public void show(int x1, int y1, int x2, int y2); /** - * Validates the buffer and if successful shows the specified region. + * Shows the specified region if the buffer is not lost and the dimensions + * of the back-buffer match those of the component. * * @return true if successful */ // NOTE: this is invoked by swing on the toolkit thread! - public boolean validateAndShow(int x1, int y1, int x2, int y2); + public boolean showIfNotLost(int x1, int y1, int x2, int y2); } diff --git a/src/share/classes/sun/awt/image/SunVolatileImage.java b/src/share/classes/sun/awt/image/SunVolatileImage.java index d0c18f386..4f430af60 100644 --- a/src/share/classes/sun/awt/image/SunVolatileImage.java +++ b/src/share/classes/sun/awt/image/SunVolatileImage.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2008 Sun Microsystems Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,19 +29,18 @@ import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Component; import java.awt.Font; -import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GraphicsConfiguration; import java.awt.ImageCapabilities; import java.awt.Transparency; import java.awt.image.BufferedImage; -import java.awt.image.ColorModel; import java.awt.image.ImageObserver; import java.awt.image.VolatileImage; -import java.awt.image.WritableRaster; import sun.java2d.SunGraphics2D; -import sun.java2d.SurfaceData; import sun.java2d.SurfaceManagerFactory; +import sun.java2d.DestSurfaceProvider; +import sun.java2d.Surface; +import static sun.java2d.pipe.hw.AccelSurface.*; /** * This class is the base implementation of the VolatileImage @@ -52,23 +51,28 @@ import sun.java2d.SurfaceManagerFactory; * appropriate VolatileSurfaceManager for the GraphicsConfiguration * under which this SunVolatileImage was created. */ -public class SunVolatileImage extends VolatileImage { +public class SunVolatileImage extends VolatileImage + implements DestSurfaceProvider +{ protected VolatileSurfaceManager volSurfaceManager; protected Component comp; private GraphicsConfiguration graphicsConfig; private Font defaultFont; private int width, height; + private int forcedAccelSurfaceType; - private SunVolatileImage(Component comp, - GraphicsConfiguration graphicsConfig, - int width, int height, Object context, - int transparency, ImageCapabilities caps) + protected SunVolatileImage(Component comp, + GraphicsConfiguration graphicsConfig, + int width, int height, Object context, + int transparency, ImageCapabilities caps, + int accType) { this.comp = comp; this.graphicsConfig = graphicsConfig; this.width = width; this.height = height; + this.forcedAccelSurfaceType = accType; if (!(transparency == Transparency.OPAQUE || transparency == Transparency.BITMASK || transparency == Transparency.TRANSLUCENT)) @@ -92,7 +96,7 @@ public class SunVolatileImage extends VolatileImage { ImageCapabilities caps) { this(comp, graphicsConfig, - width, height, context, Transparency.OPAQUE, caps); + width, height, context, Transparency.OPAQUE, caps, UNDEFINED); } public SunVolatileImage(Component comp, int width, int height) { @@ -110,7 +114,8 @@ public class SunVolatileImage extends VolatileImage { int width, int height, int transparency, ImageCapabilities caps) { - this(null, graphicsConfig, width, height, null, transparency, caps); + this(null, graphicsConfig, width, height, null, transparency, + caps, UNDEFINED); } public int getWidth() { @@ -144,6 +149,10 @@ public class SunVolatileImage extends VolatileImage { return comp; } + public int getForcedAccelSurfaceType() { + return forcedAccelSurfaceType; + } + protected VolatileSurfaceManager createSurfaceManager(Object context, ImageCapabilities caps) { @@ -248,4 +257,14 @@ public class SunVolatileImage extends VolatileImage { public ImageCapabilities getCapabilities() { return volSurfaceManager.getCapabilities(graphicsConfig); } + + /** + * {@inheritDoc} + * + * @see sun.java2d.DestSurfaceProvider#getDestSurface + */ + @Override + public Surface getDestSurface() { + return volSurfaceManager.getPrimarySurfaceData(); + } } diff --git a/src/share/classes/sun/awt/image/SunWritableRaster.java b/src/share/classes/sun/awt/image/SunWritableRaster.java index 1c8df2710..b312add69 100644 --- a/src/share/classes/sun/awt/image/SunWritableRaster.java +++ b/src/share/classes/sun/awt/image/SunWritableRaster.java @@ -1,5 +1,5 @@ /* - * Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2001-2008 Sun Microsystems Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,6 +35,7 @@ import java.awt.image.DataBufferInt; import java.awt.image.SampleModel; import java.awt.image.WritableRaster; +import sun.java2d.StateTrackable.State; import sun.java2d.SurfaceData; import sun.java2d.StateTrackableDelegate; @@ -54,6 +55,7 @@ public class SunWritableRaster extends WritableRaster { public short[] getData(DataBufferUShort dbus, int bank); public int[] getData(DataBufferInt dbi, int bank); public StateTrackableDelegate getTrackable(DataBuffer db); + public void setTrackable(DataBuffer db, StateTrackableDelegate trackable); } public static void setDataStealer(DataStealer ds) { @@ -79,6 +81,14 @@ public class SunWritableRaster extends WritableRaster { return stealer.getTrackable(db); } + public static void setTrackable(DataBuffer db, StateTrackableDelegate trackable) { + stealer.setTrackable(db, trackable); + } + + public static void makeTrackable(DataBuffer db) { + stealer.setTrackable(db, StateTrackableDelegate.createInstance(State.STABLE)); + } + public static void markDirty(DataBuffer db) { stealer.getTrackable(db).markDirty(); } diff --git a/src/share/classes/sun/awt/image/VSyncedBSManager.java b/src/share/classes/sun/awt/image/VSyncedBSManager.java new file mode 100644 index 000000000..2a072e3ed --- /dev/null +++ b/src/share/classes/sun/awt/image/VSyncedBSManager.java @@ -0,0 +1,121 @@ +/* + * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.awt.image; + +import java.awt.image.BufferStrategy; +import java.lang.ref.WeakReference; + +/** + * Manages v-synced buffer strategies. + */ +public abstract class VSyncedBSManager { + + private static VSyncedBSManager theInstance; + + private static final boolean vSyncLimit = + Boolean.valueOf((String)java.security.AccessController.doPrivileged( + new sun.security.action.GetPropertyAction( + "sun.java2d.vsynclimit", "true"))); + + private static VSyncedBSManager getInstance(boolean create) { + if (theInstance == null && create) { + theInstance = + vSyncLimit ? new SingleVSyncedBSMgr() : new NoLimitVSyncBSMgr(); + } + return theInstance; + } + + abstract boolean checkAllowed(BufferStrategy bs); + abstract void relinquishVsync(BufferStrategy bs); + + /** + * Returns true if the buffer strategy is allowed to be created + * v-synced. + * + * @return true if the bs is allowed to be v-synced, false otherwise + */ + public static boolean vsyncAllowed(BufferStrategy bs) { + VSyncedBSManager bsm = getInstance(true); + return bsm.checkAllowed(bs); + } + + /** + * Lets the manager know that this buffer strategy is no longer interested + * in being v-synced. + */ + public static synchronized void releaseVsync(BufferStrategy bs) { + VSyncedBSManager bsm = getInstance(false); + if (bsm != null) { + bsm.relinquishVsync(bs); + } + } + + /** + * An instance of the manager which allows any buffer strategy to be + * v-synced. + */ + private static final class NoLimitVSyncBSMgr extends VSyncedBSManager { + @Override + boolean checkAllowed(BufferStrategy bs) { + return true; + } + + @Override + void relinquishVsync(BufferStrategy bs) { + } + } + + /** + * An instance of the manager which allows only one buffer strategy to + * be v-synced at any give moment in the vm. + */ + private static final class SingleVSyncedBSMgr extends VSyncedBSManager { + private WeakReference<BufferStrategy> strategy; + + @Override + public synchronized boolean checkAllowed(BufferStrategy bs) { + if (strategy != null) { + BufferStrategy current = strategy.get(); + if (current != null) { + return (current == bs); + } + } + strategy = new WeakReference<BufferStrategy>(bs); + return true; + } + + @Override + public synchronized void relinquishVsync(BufferStrategy bs) { + if (strategy != null) { + BufferStrategy b = strategy.get(); + if (b == bs) { + strategy.clear(); + strategy = null; + } + } + } + } +} diff --git a/src/share/classes/sun/awt/image/VolatileSurfaceManager.java b/src/share/classes/sun/awt/image/VolatileSurfaceManager.java index 9be25ee64..2b9cd73b0 100644 --- a/src/share/classes/sun/awt/image/VolatileSurfaceManager.java +++ b/src/share/classes/sun/awt/image/VolatileSurfaceManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2008 Sun Microsystems Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,7 @@ import sun.awt.image.SunVolatileImage; import sun.java2d.SunGraphicsEnvironment; import sun.java2d.SurfaceData; import sun.java2d.loops.CompositeType; +import static sun.java2d.pipe.hw.AccelSurface.*; /** * This SurfaceManager variant manages an accelerated volatile surface, if it @@ -117,7 +118,11 @@ public abstract class VolatileSurfaceManager sdCurrent = sdAccel; } } - if (sdCurrent == null) { + // only initialize the backup surface for images with unforced + // acceleration type + if (sdCurrent == null && + vImg.getForcedAccelSurfaceType() == UNDEFINED) + { sdCurrent = getBackupSurface(); } } @@ -270,9 +275,13 @@ public abstract class VolatileSurfaceManager * the background). */ public void initContents() { - Graphics g = vImg.createGraphics(); - g.clearRect(0, 0, vImg.getWidth(), vImg.getHeight()); - g.dispose(); + // images with forced acceleration type may have a null sdCurrent + // because we do not create a backup surface for them + if (sdCurrent != null) { + Graphics g = vImg.createGraphics(); + g.clearRect(0, 0, vImg.getWidth(), vImg.getHeight()); + g.dispose(); + } } /** diff --git a/src/share/classes/sun/font/StrikeCache.java b/src/share/classes/sun/font/StrikeCache.java index bfcf032db..041c4ca59 100644 --- a/src/share/classes/sun/font/StrikeCache.java +++ b/src/share/classes/sun/font/StrikeCache.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2008 Sun Microsystems Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,16 +25,17 @@ package sun.font; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsEnvironment; import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; import java.lang.ref.WeakReference; -import java.awt.Font; -import java.awt.FontFormatException; -import java.util.logging.Level; -import java.util.logging.Logger; import sun.java2d.Disposer; +import sun.java2d.pipe.BufferedContext; +import sun.java2d.pipe.RenderQueue; +import sun.java2d.pipe.hw.AccelGraphicsConfig; import sun.misc.Unsafe; /** @@ -192,13 +193,13 @@ public final class StrikeCache { recentStrikeIndex = index; } - static void disposeStrike(FontStrikeDisposer disposer) { + private static final void doDispose(FontStrikeDisposer disposer) { if (disposer.intGlyphImages != null) { freeIntMemory(disposer.intGlyphImages, - disposer.pScalerContext); + disposer.pScalerContext); } else if (disposer.longGlyphImages != null) { freeLongMemory(disposer.longGlyphImages, - disposer.pScalerContext); + disposer.pScalerContext); } else if (disposer.segIntGlyphImages != null) { /* NB Now making multiple JNI calls in this case. * But assuming that there's a reasonable amount of locality @@ -207,7 +208,7 @@ public final class StrikeCache { for (int i=0; i<disposer.segIntGlyphImages.length; i++) { if (disposer.segIntGlyphImages[i] != null) { freeIntMemory(disposer.segIntGlyphImages[i], - disposer.pScalerContext); + disposer.pScalerContext); /* native will only free the scaler context once */ disposer.pScalerContext = 0L; disposer.segIntGlyphImages[i] = null; @@ -223,7 +224,7 @@ public final class StrikeCache { for (int i=0; i<disposer.segLongGlyphImages.length; i++) { if (disposer.segLongGlyphImages[i] != null) { freeLongMemory(disposer.segLongGlyphImages[i], - disposer.pScalerContext); + disposer.pScalerContext); disposer.pScalerContext = 0L; disposer.segLongGlyphImages[i] = null; } @@ -234,6 +235,44 @@ public final class StrikeCache { } } + static void disposeStrike(final FontStrikeDisposer disposer) { + // we need to execute the strike disposal on the rendering thread + // because they may be accessed on that thread at the time of the + // disposal (for example, when the accel. cache is invalidated) + + // REMIND: this look a bit heavyweight, but should be ok + // because strike disposal is a relatively infrequent operation, + // more worrisome is the necessity of getting a GC here. + RenderQueue rq = null; + GraphicsEnvironment ge = + GraphicsEnvironment.getLocalGraphicsEnvironment(); + if (!ge.isHeadless()) { + GraphicsConfiguration gc = + ge.getDefaultScreenDevice().getDefaultConfiguration(); + if (gc instanceof AccelGraphicsConfig) { + AccelGraphicsConfig agc = (AccelGraphicsConfig)gc; + BufferedContext bc = agc.getContext(); + if (bc != null) { + rq = bc.getRenderQueue(); + } + } + } + if (rq != null) { + rq.lock(); + try { + rq.flushAndInvokeNow(new Runnable() { + public void run() { + doDispose(disposer); + } + }); + } finally { + rq.unlock(); + } + } else { + doDispose(disposer); + } + } + static native void freeIntPointer(int ptr); static native void freeLongPointer(long ptr); private static native void freeIntMemory(int[] glyphPtrs, long pContext); diff --git a/src/share/classes/sun/java2d/DestSurfaceProvider.java b/src/share/classes/sun/java2d/DestSurfaceProvider.java new file mode 100644 index 000000000..d06e05ef8 --- /dev/null +++ b/src/share/classes/sun/java2d/DestSurfaceProvider.java @@ -0,0 +1,41 @@ +/* + * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.java2d; + +import sun.java2d.pipe.hw.*; + +/** + * Classes implementing this interface provide access to their + * destination surfaces. + */ +public interface DestSurfaceProvider { + /** + * Returns a surface currently used as a destination surface for rendering. + * + * @return destination surface + */ + public Surface getDestSurface(); +} diff --git a/src/share/classes/sun/java2d/SunGraphics2D.java b/src/share/classes/sun/java2d/SunGraphics2D.java index 46896e311..b95d53a3b 100644 --- a/src/share/classes/sun/java2d/SunGraphics2D.java +++ b/src/share/classes/sun/java2d/SunGraphics2D.java @@ -1,5 +1,5 @@ /* - * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2008 Sun Microsystems Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,24 +41,17 @@ import java.awt.image.renderable.RenderableImage; import java.awt.image.renderable.RenderContext; import java.awt.image.AffineTransformOp; import java.awt.image.Raster; -import java.awt.image.SampleModel; -import java.awt.image.VolatileImage; import java.awt.image.WritableRaster; import java.awt.Image; import java.awt.Composite; import java.awt.Color; -import java.awt.color.ColorSpace; -import java.awt.image.DataBuffer; import java.awt.image.ColorModel; -import java.awt.image.IndexColorModel; -import java.awt.image.DirectColorModel; import java.awt.GraphicsConfiguration; import java.awt.Paint; import java.awt.GradientPaint; import java.awt.LinearGradientPaint; import java.awt.RadialGradientPaint; import java.awt.TexturePaint; -import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.awt.geom.PathIterator; import java.awt.geom.GeneralPath; @@ -69,19 +62,16 @@ import java.awt.Rectangle; import java.text.AttributedCharacterIterator; import java.awt.Font; import java.awt.image.ImageObserver; -import java.awt.image.ColorConvertOp; import java.awt.Transparency; import java.awt.font.GlyphVector; import java.awt.font.TextLayout; import sun.font.FontDesignMetrics; -import sun.font.StandardGlyphVector; import sun.java2d.pipe.PixelDrawPipe; import sun.java2d.pipe.PixelFillPipe; import sun.java2d.pipe.ShapeDrawPipe; import sun.java2d.pipe.ValidatePipe; import sun.java2d.pipe.ShapeSpanIterator; import sun.java2d.pipe.Region; -import sun.java2d.pipe.RegionIterator; import sun.java2d.pipe.TextPipe; import sun.java2d.pipe.DrawImagePipe; import sun.java2d.pipe.LoopPipe; @@ -90,7 +80,6 @@ import sun.java2d.loops.RenderLoops; import sun.java2d.loops.CompositeType; import sun.java2d.loops.SurfaceType; import sun.java2d.loops.Blit; -import sun.java2d.loops.BlitBg; import sun.java2d.loops.MaskFill; import sun.font.FontManager; import java.awt.font.FontRenderContext; @@ -99,7 +88,7 @@ import sun.awt.ConstrainableGraphics; import sun.awt.SunHints; import java.util.Map; import java.util.Iterator; -import sun.awt.image.OffScreenImage; +import sun.java2d.DestSurfaceProvider; import sun.misc.PerformanceLogger; /** @@ -113,7 +102,7 @@ import sun.misc.PerformanceLogger; */ public final class SunGraphics2D extends Graphics2D - implements ConstrainableGraphics, Cloneable + implements ConstrainableGraphics, Cloneable, DestSurfaceProvider { /* * Attribute States @@ -3306,4 +3295,14 @@ public final class SunGraphics2D public Object getDestination() { return surfaceData.getDestination(); } + + /** + * {@inheritDoc} + * + * @see sun.java2d.DestSurfaceProvider#getDestSurface + */ + @Override + public Surface getDestSurface() { + return surfaceData; + } } diff --git a/src/share/classes/sun/java2d/SunGraphicsEnvironment.java b/src/share/classes/sun/java2d/SunGraphicsEnvironment.java index d4f9424ef..89f9e103c 100644 --- a/src/share/classes/sun/java2d/SunGraphicsEnvironment.java +++ b/src/share/classes/sun/java2d/SunGraphicsEnvironment.java @@ -1,5 +1,5 @@ /* - * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2008 Sun Microsystems Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,6 +36,7 @@ import java.awt.Rectangle; import java.awt.Toolkit; import java.awt.font.TextAttribute; import java.awt.image.BufferedImage; +import java.awt.peer.ComponentPeer; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; @@ -1313,4 +1314,18 @@ public abstract class SunGraphicsEnvironment extends GraphicsEnvironment /* * ----END DISPLAY CHANGE SUPPORT---- */ + + /** + * Returns true if FlipBufferStrategy with COPIED buffer contents + * is preferred for this peer's GraphicsConfiguration over + * BlitBufferStrategy, false otherwise. + * + * The reason FlipBS could be preferred is that in some configurations + * an accelerated copy to the screen is supported (like Direct3D 9) + * + * @return true if flip strategy should be used, false otherwise + */ + public boolean isFlipStrategyPreferred(ComponentPeer peer) { + return false; + } } diff --git a/src/share/classes/sun/java2d/Surface.java b/src/share/classes/sun/java2d/Surface.java new file mode 100644 index 000000000..7a0fa44c6 --- /dev/null +++ b/src/share/classes/sun/java2d/Surface.java @@ -0,0 +1,34 @@ +/* + * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.java2d; + +/** + * This is a tag interface for a surface. + * @see sun.java2d.SurfaceData + * @see sun.java2d.pipe.hw.AccelSurface + */ +public interface Surface { +} diff --git a/src/share/classes/sun/java2d/SurfaceData.java b/src/share/classes/sun/java2d/SurfaceData.java index fa4429dd2..e5431679b 100644 --- a/src/share/classes/sun/java2d/SurfaceData.java +++ b/src/share/classes/sun/java2d/SurfaceData.java @@ -1,5 +1,5 @@ /* - * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2008 Sun Microsystems Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -93,7 +93,7 @@ import sun.awt.image.SurfaceManager; * retrieved the tracker. */ public abstract class SurfaceData - implements Transparency, DisposerTarget, StateTrackable + implements Transparency, DisposerTarget, StateTrackable, Surface { private long pData; private boolean valid; diff --git a/src/share/classes/sun/java2d/SurfaceDataProxy.java b/src/share/classes/sun/java2d/SurfaceDataProxy.java index 66ee63444..f94419ca4 100644 --- a/src/share/classes/sun/java2d/SurfaceDataProxy.java +++ b/src/share/classes/sun/java2d/SurfaceDataProxy.java @@ -1,5 +1,5 @@ /* - * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -521,7 +521,7 @@ public abstract class SurfaceDataProxy CompositeType.SrcNoEa, dstType); blitbg.BlitBg(srcData, dstData, - AlphaComposite.Src, null, bgColor, + AlphaComposite.Src, null, bgColor.getRGB(), 0, 0, 0, 0, w, h); dstData.markDirty(); } diff --git a/src/share/classes/sun/java2d/loops/BlitBg.java b/src/share/classes/sun/java2d/loops/BlitBg.java index a64e8e81f..7385bbd0f 100644 --- a/src/share/classes/sun/java2d/loops/BlitBg.java +++ b/src/share/classes/sun/java2d/loops/BlitBg.java @@ -1,5 +1,5 @@ /* - * Copyright 1999-2004 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2008 Sun Microsystems Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -109,7 +109,7 @@ public class BlitBg extends GraphicsPrimitive */ public native void BlitBg(SurfaceData src, SurfaceData dst, Composite comp, Region clip, - Color bgColor, + int bgColor, int srcx, int srcy, int dstx, int dsty, int width, int height); @@ -142,19 +142,19 @@ public class BlitBg extends GraphicsPrimitive compositeType = comptype; } + @Override public void BlitBg(SurfaceData srcData, SurfaceData dstData, Composite comp, Region clip, - Color bgColor, + int bgArgb, int srcx, int srcy, int dstx, int dsty, int width, int height) { ColorModel dstModel = dstData.getColorModel(); - if (!dstModel.hasAlpha() && - bgColor.getTransparency() != Transparency.OPAQUE) - { + boolean bgHasAlpha = (bgArgb >>> 24) != 0xff; + if (!dstModel.hasAlpha() && bgHasAlpha) { dstModel = ColorModel.getRGBdefault(); } WritableRaster wr = @@ -163,6 +163,7 @@ public class BlitBg extends GraphicsPrimitive BufferedImage bimg = new BufferedImage(dstModel, wr, isPremult, null); SurfaceData tmpData = BufImgSurfaceData.createData(bimg); + Color bgColor = new Color(bgArgb, bgHasAlpha); SunGraphics2D sg2d = new SunGraphics2D(tmpData, bgColor, bgColor, defaultFont); FillRect fillop = FillRect.locate(SurfaceType.AnyColor, @@ -201,9 +202,10 @@ public class BlitBg extends GraphicsPrimitive return this; } + @Override public void BlitBg(SurfaceData src, SurfaceData dst, Composite comp, Region clip, - Color bgColor, + int bgColor, int srcx, int srcy, int dstx, int dsty, int width, int height) { diff --git a/src/share/classes/sun/java2d/loops/GeneralRenderer.java b/src/share/classes/sun/java2d/loops/GeneralRenderer.java index 8c7a4862a..57d1e373b 100644 --- a/src/share/classes/sun/java2d/loops/GeneralRenderer.java +++ b/src/share/classes/sun/java2d/loops/GeneralRenderer.java @@ -1,5 +1,5 @@ /* - * Copyright 1998-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1998-2008 Sun Microsystems Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -159,6 +159,10 @@ public final class GeneralRenderer { { int mx, my, x1, y1; int[] tmp = null; + + if (nPoints <= 0) { + return; + } mx = x1 = xPoints[off] + transx; my = y1 = yPoints[off] + transy; while (--nPoints > 0) { diff --git a/src/share/classes/sun/java2d/opengl/OGLBufImgOps.java b/src/share/classes/sun/java2d/opengl/OGLBufImgOps.java index 2b62bd473..1becb763c 100644 --- a/src/share/classes/sun/java2d/opengl/OGLBufImgOps.java +++ b/src/share/classes/sun/java2d/opengl/OGLBufImgOps.java @@ -1,5 +1,5 @@ /* - * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,6 +35,7 @@ import sun.java2d.SunGraphics2D; import sun.java2d.SurfaceData; import sun.java2d.loops.CompositeType; import sun.java2d.pipe.BufferedBufImgOps; +import static sun.java2d.opengl.OGLContext.OGLContextCaps.*; class OGLBufImgOps extends BufferedBufImgOps { @@ -94,7 +95,7 @@ class OGLBufImgOps extends BufferedBufImgOps { OGLSurfaceData oglSrc = (OGLSurfaceData)srcData; OGLGraphicsConfig gc = oglSrc.getOGLGraphicsConfig(); if (oglSrc.getType() != OGLSurfaceData.TEXTURE || - !gc.isCapPresent(OGLContext.CAPS_EXT_BIOP_SHADER)) + !gc.isCapPresent(CAPS_EXT_BIOP_SHADER)) { return false; } diff --git a/src/share/classes/sun/java2d/opengl/OGLContext.java b/src/share/classes/sun/java2d/opengl/OGLContext.java index 99bff126f..9b0bc46db 100644 --- a/src/share/classes/sun/java2d/opengl/OGLContext.java +++ b/src/share/classes/sun/java2d/opengl/OGLContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2004-2008 Sun Microsystems Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,91 +25,24 @@ package sun.java2d.opengl; -import java.awt.AlphaComposite; -import java.awt.Composite; -import java.awt.Paint; -import java.awt.geom.AffineTransform; -import sun.java2d.SunGraphics2D; import sun.java2d.pipe.BufferedContext; -import sun.java2d.pipe.Region; import sun.java2d.pipe.RenderBuffer; import sun.java2d.pipe.RenderQueue; +import sun.java2d.pipe.hw.ContextCapabilities; import static sun.java2d.pipe.BufferedOpCodes.*; +import static sun.java2d.pipe.hw.ContextCapabilities.*; /** * Note that the RenderQueue lock must be acquired before calling any of * the methods in this class. */ -class OGLContext extends BufferedContext { - - /** Indicates that the context has no capabilities. */ - static final int CAPS_EMPTY = (0 << 0); - /** Indicates that the context is doublebuffered. */ - static final int CAPS_DOUBLEBUFFERED = (1 << 0); - /** Indicates that the context supports a stored alpha channel. */ - static final int CAPS_STORED_ALPHA = (1 << 1); - /** Indicates the presence of the GL_ARB_multitexture extension. */ - static final int CAPS_EXT_MULTITEXTURE = (1 << 2); - /** Indicates the presence of the GL_ARB_texture_non_power_of_two ext. */ - static final int CAPS_EXT_TEXNONPOW2 = (1 << 3); - /** - * Indicates the presence of the GL_EXT_framebuffer_object extension. - * This cap will only be set if the fbobject system property has been - * enabled and we are able to create an FBO with depth buffer. - */ - static final int CAPS_EXT_FBOBJECT = (1 << 4); - /** - * Indicates the presence of the GL_ARB_fragment_shader extension. - * This cap will only be set if the lcdshader system property has been - * enabled and the hardware supports the minimum number of texture units. - */ - static final int CAPS_EXT_LCD_SHADER = (1 << 5); - /** Indicates the presence of the GL_ARB_texture_rectangle extension. */ - static final int CAPS_EXT_TEXRECT = (1 << 6); - /** - * Indicates the presence of the GL_ARB_fragment_shader extension. - * This cap will only be set if the biopshader system property has been - * enabled and the hardware meets our minimum requirements. - */ - static final int CAPS_EXT_BIOP_SHADER = (1 << 7); - /** - * Indicates the presence of the GL_ARB_fragment_shader extension. - * This cap will only be set if the gradshader system property has been - * enabled and the hardware meets our minimum requirements. - */ - static final int CAPS_EXT_GRAD_SHADER = (1 << 8); +public class OGLContext extends BufferedContext { - OGLContext(RenderQueue rq) { - super(rq); - } + private final OGLGraphicsConfig config; - /** - * Fetches the OGLContext associated with the current GraphicsConfig - * and validates the context using the given parameters. Most rendering - * operations will call this method first in order to set the necessary - * state before issuing rendering commands. - */ - static void validateContext(OGLSurfaceData srcData, - OGLSurfaceData dstData, - Region clip, Composite comp, - AffineTransform xform, - Paint paint, SunGraphics2D sg2d, - int flags) - { - // assert rq.lock.isHeldByCurrentThread(); - OGLContext oglc = dstData.getContext(); - oglc.validate(srcData, dstData, - clip, comp, xform, paint, sg2d, flags); - } - - /** - * Simplified version of validateContext() that disables all context - * state settings. - */ - static void validateContext(OGLSurfaceData dstData) { - // assert rq.lock.isHeldByCurrentThread(); - validateContext(dstData, dstData, - null, null, null, null, null, NO_CONTEXT_FLAGS); + OGLContext(RenderQueue rq, OGLGraphicsConfig config) { + super(rq); + this.config = config; } /** @@ -160,19 +93,128 @@ class OGLContext extends BufferedContext { static void invalidateCurrentContext() { // assert OGLRenderQueue.getInstance().lock.isHeldByCurrentThread(); - // first invalidate the context reference at the native level, and + // invalidate the current Java-level context so that we + // revalidate everything the next time around + if (currentContext != null) { + currentContext.invalidateContext(); + currentContext = null; + } + + // invalidate the context reference at the native level, and // then flush the queue so that we have no pending operations // dependent on the current context OGLRenderQueue rq = OGLRenderQueue.getInstance(); rq.ensureCapacity(4); rq.getBuffer().putInt(INVALIDATE_CONTEXT); rq.flushNow(); + } - // then invalidate the current Java-level context so that we - // revalidate everything the next time around - if (currentContext != null) { - currentContext.invalidateSurfaces(); - currentContext = null; + public RenderQueue getRenderQueue() { + return OGLRenderQueue.getInstance(); + } + + /** + * Returns a string representing adapter id (vendor, renderer, version). + * Must be called on the rendering thread. + * + * @return an id string for the adapter + */ + static final native String getOGLIdString(); + + @Override + public void saveState() { + // assert rq.lock.isHeldByCurrentThread(); + + // reset all attributes of this and current contexts + invalidateContext(); + invalidateCurrentContext(); + + setScratchSurface(config); + + // save the state on the native level + rq.ensureCapacity(4); + buf.putInt(SAVE_STATE); + rq.flushNow(); + } + + @Override + public void restoreState() { + // assert rq.lock.isHeldByCurrentThread(); + + // reset all attributes of this and current contexts + invalidateContext(); + invalidateCurrentContext(); + + setScratchSurface(config); + + // restore the state on the native level + rq.ensureCapacity(4); + buf.putInt(RESTORE_STATE); + rq.flushNow(); + } + + static class OGLContextCaps extends ContextCapabilities { + /** + * Indicates the presence of the GL_EXT_framebuffer_object extension. + * This cap will only be set if the fbobject system property has been + * enabled and we are able to create an FBO with depth buffer. + */ + static final int CAPS_EXT_FBOBJECT = + (CAPS_RT_TEXTURE_ALPHA | CAPS_RT_TEXTURE_OPAQUE); + /** Indicates that the context supports a stored alpha channel. */ + static final int CAPS_STORED_ALPHA = CAPS_RT_PLAIN_ALPHA; + /** Indicates that the context is doublebuffered. */ + static final int CAPS_DOUBLEBUFFERED = (FIRST_PRIVATE_CAP << 0); + /** + * Indicates the presence of the GL_ARB_fragment_shader extension. + * This cap will only be set if the lcdshader system property has been + * enabled and the hardware supports the minimum number of texture units + */ + static final int CAPS_EXT_LCD_SHADER = (FIRST_PRIVATE_CAP << 1); + /** + * Indicates the presence of the GL_ARB_fragment_shader extension. + * This cap will only be set if the biopshader system property has been + * enabled and the hardware meets our minimum requirements. + */ + static final int CAPS_EXT_BIOP_SHADER = (FIRST_PRIVATE_CAP << 2); + /** + * Indicates the presence of the GL_ARB_fragment_shader extension. + * This cap will only be set if the gradshader system property has been + * enabled and the hardware meets our minimum requirements. + */ + static final int CAPS_EXT_GRAD_SHADER = (FIRST_PRIVATE_CAP << 3); + /** Indicates the presence of the GL_ARB_texture_rectangle extension. */ + static final int CAPS_EXT_TEXRECT = (FIRST_PRIVATE_CAP << 4); + + OGLContextCaps(int caps, String adapterId) { + super(caps, adapterId); + } + + @Override + public String toString() { + StringBuffer buf = new StringBuffer(super.toString()); + if ((caps & CAPS_EXT_FBOBJECT) != 0) { + buf.append("CAPS_EXT_FBOBJECT|"); + } + if ((caps & CAPS_STORED_ALPHA) != 0) { + buf.append("CAPS_STORED_ALPHA|"); + } + if ((caps & CAPS_DOUBLEBUFFERED) != 0) { + buf.append("CAPS_DOUBLEBUFFERED|"); + } + if ((caps & CAPS_EXT_LCD_SHADER) != 0) { + buf.append("CAPS_EXT_LCD_SHADER|"); + } + if ((caps & CAPS_EXT_BIOP_SHADER) != 0) { + buf.append("CAPS_BIOP_SHADER|"); + } + if ((caps & CAPS_EXT_GRAD_SHADER) != 0) { + buf.append("CAPS_EXT_GRAD_SHADER|"); + } + if ((caps & CAPS_EXT_TEXRECT) != 0) { + buf.append("CAPS_EXT_TEXRECT|"); + } + return buf.toString(); } } } diff --git a/src/share/classes/sun/java2d/opengl/OGLGraphicsConfig.java b/src/share/classes/sun/java2d/opengl/OGLGraphicsConfig.java index 32de60627..b8b8cf46c 100644 --- a/src/share/classes/sun/java2d/opengl/OGLGraphicsConfig.java +++ b/src/share/classes/sun/java2d/opengl/OGLGraphicsConfig.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-2008 Sun Microsystems Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,13 +27,16 @@ package sun.java2d.opengl; import sun.java2d.SurfaceData; import sun.awt.image.SurfaceManager; +import sun.java2d.pipe.hw.AccelGraphicsConfig; /** * This interface collects the methods that are provided by both * GLXGraphicsConfig and WGLGraphicsConfig, making it easier to invoke these * methods directly from OGLSurfaceData. */ -interface OGLGraphicsConfig extends SurfaceManager.ProxiedGraphicsConfig { +interface OGLGraphicsConfig extends + AccelGraphicsConfig, SurfaceManager.ProxiedGraphicsConfig +{ OGLContext getContext(); long getNativeConfigInfo(); boolean isCapPresent(int cap); diff --git a/src/share/classes/sun/java2d/opengl/OGLPaints.java b/src/share/classes/sun/java2d/opengl/OGLPaints.java index 4dc828e99..472063482 100644 --- a/src/share/classes/sun/java2d/opengl/OGLPaints.java +++ b/src/share/classes/sun/java2d/opengl/OGLPaints.java @@ -1,5 +1,5 @@ /* - * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,6 +39,7 @@ import sun.java2d.SunGraphics2D; import sun.java2d.SurfaceData; import sun.java2d.loops.CompositeType; import static sun.java2d.pipe.BufferedPaints.*; +import static sun.java2d.opengl.OGLContext.OGLContextCaps.*; abstract class OGLPaints { @@ -170,7 +171,7 @@ abstract class OGLPaints { OGLSurfaceData dstData = (OGLSurfaceData)sg2d.surfaceData; OGLGraphicsConfig gc = dstData.getOGLGraphicsConfig(); - if (!gc.isCapPresent(OGLContext.CAPS_EXT_GRAD_SHADER)) { + if (!gc.isCapPresent(CAPS_EXT_GRAD_SHADER)) { return false; } diff --git a/src/share/classes/sun/java2d/opengl/OGLRenderer.java b/src/share/classes/sun/java2d/opengl/OGLRenderer.java index a3afd13e3..9df727327 100644 --- a/src/share/classes/sun/java2d/opengl/OGLRenderer.java +++ b/src/share/classes/sun/java2d/opengl/OGLRenderer.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2008 Sun Microsystems Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ import java.awt.geom.Path2D; import sun.java2d.SunGraphics2D; import sun.java2d.loops.GraphicsPrimitive; import sun.java2d.pipe.BufferedRenderPipe; +import sun.java2d.pipe.ParallelogramPipe; import sun.java2d.pipe.RenderQueue; import sun.java2d.pipe.SpanIterator; import static sun.java2d.pipe.BufferedOpCodes.*; @@ -51,6 +52,15 @@ class OGLRenderer extends BufferedRenderPipe { null, sg2d.paint, sg2d, ctxflags); } + @Override + protected void validateContextAA(SunGraphics2D sg2d) { + int ctxflags = OGLContext.NO_CONTEXT_FLAGS; + OGLSurfaceData dstData = (OGLSurfaceData)sg2d.surfaceData; + OGLContext.validateContext(dstData, dstData, + sg2d.getCompClip(), sg2d.composite, + null, sg2d.paint, sg2d, ctxflags); + } + void copyArea(SunGraphics2D sg2d, int x, int y, int w, int h, int dx, int dy) { @@ -88,6 +98,31 @@ class OGLRenderer extends BufferedRenderPipe { super(oglr.rq); this.oglr = oglr; } + public ParallelogramPipe getAAParallelogramPipe() { + final ParallelogramPipe realpipe = oglr.getAAParallelogramPipe(); + return new ParallelogramPipe() { + public void fillParallelogram(SunGraphics2D sg2d, + double x, double y, + double dx1, double dy1, + double dx2, double dy2) + { + GraphicsPrimitive.tracePrimitive("OGLFillAAParallelogram"); + realpipe.fillParallelogram(sg2d, + x, y, dx1, dy1, dx2, dy2); + } + public void drawParallelogram(SunGraphics2D sg2d, + double x, double y, + double dx1, double dy1, + double dx2, double dy2, + double lw1, double lw2) + { + GraphicsPrimitive.tracePrimitive("OGLDrawAAParallelogram"); + realpipe.drawParallelogram(sg2d, + x, y, dx1, dy1, dx2, dy2, + lw1, lw2); + } + }; + } protected void validateContext(SunGraphics2D sg2d) { oglr.validateContext(sg2d); } @@ -130,6 +165,23 @@ class OGLRenderer extends BufferedRenderPipe { GraphicsPrimitive.tracePrimitive("OGLFillSpans"); oglr.fillSpans(sg2d, si, transx, transy); } + public void fillParallelogram(SunGraphics2D sg2d, + double x, double y, + double dx1, double dy1, + double dx2, double dy2) + { + GraphicsPrimitive.tracePrimitive("OGLFillParallelogram"); + oglr.fillParallelogram(sg2d, x, y, dx1, dy1, dx2, dy2); + } + public void drawParallelogram(SunGraphics2D sg2d, + double x, double y, + double dx1, double dy1, + double dx2, double dy2, + double lw1, double lw2) + { + GraphicsPrimitive.tracePrimitive("OGLDrawParallelogram"); + oglr.drawParallelogram(sg2d, x, y, dx1, dy1, dx2, dy2, lw1, lw2); + } public void copyArea(SunGraphics2D sg2d, int x, int y, int w, int h, int dx, int dy) { diff --git a/src/share/classes/sun/java2d/opengl/OGLSurfaceData.java b/src/share/classes/sun/java2d/opengl/OGLSurfaceData.java index a47918700..3b721082a 100644 --- a/src/share/classes/sun/java2d/opengl/OGLSurfaceData.java +++ b/src/share/classes/sun/java2d/opengl/OGLSurfaceData.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2008 Sun Microsystems Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,23 +27,26 @@ package sun.java2d.opengl; import java.awt.AlphaComposite; import java.awt.GraphicsEnvironment; +import java.awt.Rectangle; import java.awt.Transparency; import java.awt.image.ColorModel; import java.awt.image.Raster; import sun.awt.SunHints; import sun.awt.image.PixelConverter; +import sun.java2d.pipe.hw.AccelSurface; import sun.java2d.SunGraphics2D; import sun.java2d.SurfaceData; import sun.java2d.SurfaceDataProxy; +import sun.java2d.loops.CompositeType; import sun.java2d.loops.GraphicsPrimitive; import sun.java2d.loops.MaskFill; import sun.java2d.loops.SurfaceType; -import sun.java2d.pipe.PixelToShapeConverter; +import sun.java2d.pipe.ParallelogramPipe; +import sun.java2d.pipe.PixelToParallelogramConverter; import sun.java2d.pipe.RenderBuffer; -import sun.java2d.pipe.RenderQueue; import sun.java2d.pipe.TextPipe; import static sun.java2d.pipe.BufferedOpCodes.*; -import static sun.java2d.opengl.OGLContext.*; +import static sun.java2d.opengl.OGLContext.OGLContextCaps.*; /** * This class describes an OpenGL "surface", that is, a region of pixels @@ -92,17 +95,16 @@ import static sun.java2d.opengl.OGLContext.*; * FLIP_BACKBUFFER OpenGLSurface * FBOBJECT OpenGLSurfaceRTT */ -public abstract class OGLSurfaceData extends SurfaceData { +public abstract class OGLSurfaceData extends SurfaceData + implements AccelSurface { /** * OGL-specific surface types + * + * @see sun.java2d.pipe.hw.AccelSurface */ - public static final int UNDEFINED = 0; - public static final int WINDOW = 1; - public static final int PBUFFER = 2; - public static final int TEXTURE = 3; - public static final int FLIP_BACKBUFFER = 4; - public static final int FBOBJECT = 5; + public static final int PBUFFER = RT_PLAIN; + public static final int FBOBJECT = RT_TEXTURE; /** * Pixel formats @@ -148,11 +150,14 @@ public abstract class OGLSurfaceData extends SurfaceData { private static boolean isGradShaderEnabled; private OGLGraphicsConfig graphicsConfig; - private int textureTarget; protected int type; + // these fields are set from the native code when the surface is + // initialized + private int nativeWidth, nativeHeight; protected static OGLRenderer oglRenderPipe; - protected static PixelToShapeConverter oglTxRenderPipe; + protected static PixelToParallelogramConverter oglTxRenderPipe; + protected static ParallelogramPipe oglAAPgramPipe; protected static OGLTextRenderer oglTextPipe; protected static OGLDrawImage oglImagePipe; @@ -170,6 +175,7 @@ public abstract class OGLSurfaceData extends SurfaceData { int width, int height); private native int getTextureTarget(long pData); + private native int getTextureID(long pData); static { if (!GraphicsEnvironment.isHeadless()) { @@ -203,9 +209,14 @@ public abstract class OGLSurfaceData extends SurfaceData { oglRenderPipe = new OGLRenderer(rq); if (GraphicsPrimitive.tracingEnabled()) { oglTextPipe = oglTextPipe.traceWrap(); - oglRenderPipe = oglRenderPipe.traceWrap(); + //The wrapped oglRenderPipe will wrap the AA pipe as well... + //oglAAPgramPipe = oglRenderPipe.traceWrap(); } - oglTxRenderPipe = new PixelToShapeConverter(oglRenderPipe); + oglAAPgramPipe = oglRenderPipe.getAAParallelogramPipe(); + oglTxRenderPipe = + new PixelToParallelogramConverter(oglRenderPipe, + oglRenderPipe, + 1.0, 0.25, true); OGLBlitLoops.register(); OGLMaskFill.register(); @@ -282,9 +293,7 @@ public abstract class OGLSurfaceData extends SurfaceData { break; } - if (success) { - textureTarget = getTextureTarget(getNativeOps()); - } else { + if (!success) { throw new OutOfMemoryError("can't create offscreen surface"); } } @@ -323,7 +332,7 @@ public abstract class OGLSurfaceData extends SurfaceData { * Returns the OGLContext for the GraphicsConfig associated with this * surface. */ - final OGLContext getContext() { + public final OGLContext getContext() { return graphicsConfig.getContext(); } @@ -337,7 +346,7 @@ public abstract class OGLSurfaceData extends SurfaceData { /** * Returns one of the surface type constants defined above. */ - final int getType() { + public final int getType() { return type; } @@ -346,8 +355,41 @@ public abstract class OGLSurfaceData extends SurfaceData { * for that texture (either GL_TEXTURE_2D or GL_TEXTURE_RECTANGLE_ARB). * Otherwise, this method will return zero. */ - final int getTextureTarget() { - return textureTarget; + public final int getTextureTarget() { + return getTextureTarget(getNativeOps()); + } + + /** + * If this surface is backed by a texture object, returns the texture ID + * for that texture. + * Otherwise, this method will return zero. + */ + public final int getTextureID() { + return getTextureID(getNativeOps()); + } + + /** + * Returns native resource of specified {@code resType} associated with + * this surface. + * + * Specifically, for {@code OGLSurfaceData} this method returns the + * the following: + * <pre> + * TEXTURE - texture id + * </pre> + * + * Note: the resource returned by this method is only valid on the rendering + * thread. + * + * @return native resource of specified type or 0L if + * such resource doesn't exist or can not be retrieved. + * @see sun.java2d.pipe.hw.AccelSurface#getNativeResource + */ + public long getNativeResource(int resType) { + if (resType == TEXTURE) { + return getTextureID(); + } + return 0L; } public Raster getRaster(int x, int y, int w, int h) { @@ -366,7 +408,7 @@ public abstract class OGLSurfaceData extends SurfaceData { */ public boolean canRenderLCDText(SunGraphics2D sg2d) { return - graphicsConfig.isCapPresent(OGLContext.CAPS_EXT_LCD_SHADER) && + graphicsConfig.isCapPresent(CAPS_EXT_LCD_SHADER) && sg2d.compositeState <= SunGraphics2D.COMP_ISCOPY && sg2d.paintState <= SunGraphics2D.PAINT_OPAQUECOLOR; } @@ -405,7 +447,7 @@ public abstract class OGLSurfaceData extends SurfaceData { validated = true; } - PixelToShapeConverter txPipe = null; + PixelToParallelogramConverter txPipe = null; OGLRenderer nonTxPipe = null; if (sg2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON) { @@ -422,12 +464,28 @@ public abstract class OGLSurfaceData extends SurfaceData { // custom paints handled by super.validatePipe() below } } else { - if (sg2d.paintState <= sg2d.PAINT_ALPHACOLOR && - sg2d.compositeState == sg2d.COMP_XOR) - { - // install the solid pipes when AA and XOR are both enabled - txPipe = oglTxRenderPipe; - nonTxPipe = oglRenderPipe; + if (sg2d.paintState <= sg2d.PAINT_ALPHACOLOR) { + if (graphicsConfig.isCapPresent(CAPS_PS30) && + (sg2d.imageComp == CompositeType.SrcOverNoEa || + sg2d.imageComp == CompositeType.SrcOver)) + { + if (!validated) { + super.validatePipe(sg2d); + validated = true; + } + PixelToParallelogramConverter aaConverter = + new PixelToParallelogramConverter(sg2d.shapepipe, + oglAAPgramPipe, + 1.0/8.0, 0.499, + false); + sg2d.drawpipe = aaConverter; + sg2d.fillpipe = aaConverter; + sg2d.shapepipe = aaConverter; + } else if (sg2d.compositeState == sg2d.COMP_XOR) { + // install the solid pipes when AA and XOR are both enabled + txPipe = oglTxRenderPipe; + nonTxPipe = oglRenderPipe; + } } // other cases handled by super.validatePipe() below } @@ -443,7 +501,11 @@ public abstract class OGLSurfaceData extends SurfaceData { sg2d.drawpipe = nonTxPipe; sg2d.fillpipe = nonTxPipe; } - sg2d.shapepipe = nonTxPipe; + // Note that we use the transforming pipe here because it + // will examine the shape and possibly perform an optimized + // operation if it can be simplified. The simplifications + // will be valid for all STROKE and TRANSFORM types. + sg2d.shapepipe = txPipe; } else { if (!validated) { super.validatePipe(sg2d); @@ -472,7 +534,7 @@ public abstract class OGLSurfaceData extends SurfaceData { * validation code will choose a more general software-based loop. */ if (!OGLPaints.isValid(sg2d) || - !graphicsConfig.isCapPresent(CAPS_EXT_MULTITEXTURE)) + !graphicsConfig.isCapPresent(CAPS_MULTITEXTURE)) { return null; } @@ -564,7 +626,7 @@ public abstract class OGLSurfaceData extends SurfaceData { * when using the basic GL_TEXTURE_2D target. */ boolean isTexNonPow2Available() { - return graphicsConfig.isCapPresent(OGLContext.CAPS_EXT_TEXNONPOW2); + return graphicsConfig.isCapPresent(CAPS_TEXNONPOW2); } /** @@ -573,6 +635,16 @@ public abstract class OGLSurfaceData extends SurfaceData { * GL_ARB_texture_rectangle extension is present). */ boolean isTexRectAvailable() { - return graphicsConfig.isCapPresent(OGLContext.CAPS_EXT_TEXRECT); + return graphicsConfig.isCapPresent(CAPS_EXT_TEXRECT); + } + + public Rectangle getNativeBounds() { + OGLRenderQueue rq = OGLRenderQueue.getInstance(); + rq.lock(); + try { + return new Rectangle(nativeWidth, nativeHeight); + } finally { + rq.unlock(); + } } } diff --git a/src/share/classes/sun/java2d/pipe/BufferedContext.java b/src/share/classes/sun/java2d/pipe/BufferedContext.java index d14b4277d..059895230 100644 --- a/src/share/classes/sun/java2d/pipe/BufferedContext.java +++ b/src/share/classes/sun/java2d/pipe/BufferedContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,12 +26,13 @@ package sun.java2d.pipe; import java.awt.AlphaComposite; +import java.awt.Color; import java.awt.Composite; import java.awt.Paint; import java.awt.geom.AffineTransform; +import sun.java2d.pipe.hw.AccelSurface; import sun.java2d.InvalidPipeException; import sun.java2d.SunGraphics2D; -import sun.java2d.SurfaceData; import sun.java2d.loops.XORComposite; import static sun.java2d.pipe.BufferedOpCodes.*; import static sun.java2d.pipe.BufferedRenderPipe.BYTES_PER_SPAN; @@ -43,8 +44,10 @@ import static sun.java2d.pipe.BufferedRenderPipe.BYTES_PER_SPAN; * single thread. Note that the RenderQueue lock must be acquired before * calling the validate() method (or any other method in this class). See * the RenderQueue class comments for a sample usage scenario. + * + * @see RenderQueue */ -public class BufferedContext { +public abstract class BufferedContext { /* * The following flags help the internals of validate() determine @@ -82,13 +85,17 @@ public class BufferedContext { */ protected static BufferedContext currentContext; - private SurfaceData validatedSrcData; - private SurfaceData validatedDstData; + private AccelSurface validatedSrcData; + private AccelSurface validatedDstData; private Region validatedClip; private Composite validatedComp; private Paint validatedPaint; + private boolean isValidatedPaintAColor; + private int validatedRGB; private int validatedFlags; private boolean xformInUse; + private int transX; + private int transY; protected BufferedContext(RenderQueue rq) { this.rq = rq; @@ -96,6 +103,49 @@ public class BufferedContext { } /** + * Fetches the BufferedContextContext associated with the dst. surface + * and validates the context using the given parameters. Most rendering + * operations will call this method first in order to set the necessary + * state before issuing rendering commands. + * + * Note: must be called while the RenderQueue lock is held. + * + * @throws InvalidPipeException if either src or dest surface is not valid + * or lost + * @see RenderQueue#lock + * @see RenderQueue#unlock + */ + public static void validateContext(AccelSurface srcData, + AccelSurface dstData, + Region clip, Composite comp, + AffineTransform xform, + Paint paint, SunGraphics2D sg2d, + int flags) + { + // assert rq.lock.isHeldByCurrentThread(); + BufferedContext d3dc = dstData.getContext(); + d3dc.validate(srcData, dstData, + clip, comp, xform, paint, sg2d, flags); + } + + /** + * Fetches the BufferedContextassociated with the surface + * and disables all context state settings. + * + * Note: must be called while the RenderQueue lock is held. + * + * @throws InvalidPipeException if the surface is not valid + * or lost + * @see RenderQueue#lock + * @see RenderQueue#unlock + */ + public static void validateContext(AccelSurface surface) { + // assert rt.lock.isHeldByCurrentThread(); + validateContext(surface, surface, + null, null, null, null, null, NO_CONTEXT_FLAGS); + } + + /** * Validates the given parameters against the current state for this * context. If this context is not current, it will be made current * for the given source and destination surfaces, and the viewport will @@ -106,19 +156,47 @@ public class BufferedContext { * Note that the SunGraphics2D parameter is only used for the purposes * of validating a (non-null) Paint parameter. In all other cases it * is safe to pass a null SunGraphics2D and it will be ignored. + * + * Note: must be called while the RenderQueue lock is held. + * + * @throws InvalidPipeException if either src or dest surface is not valid + * or lost */ - public void validate(SurfaceData srcData, SurfaceData dstData, + public void validate(AccelSurface srcData, AccelSurface dstData, Region clip, Composite comp, AffineTransform xform, Paint paint, SunGraphics2D sg2d, int flags) { // assert rq.lock.isHeldByCurrentThread(); - boolean updateClip = (clip != validatedClip); - boolean updatePaint = (paint != validatedPaint); + boolean updateClip = false; + boolean updatePaint = false; - if (!dstData.isValid()) { - throw new InvalidPipeException("bounds changed"); + if (!dstData.isValid() || + dstData.isSurfaceLost() || srcData.isSurfaceLost()) + { + invalidateContext(); + throw new InvalidPipeException("bounds changed or surface lost"); + } + + if (paint instanceof Color) { + // REMIND: not 30-bit friendly + int newRGB = ((Color)paint).getRGB(); + if (isValidatedPaintAColor) { + if (newRGB != validatedRGB) { + validatedRGB = newRGB; + updatePaint = true; + } + } else { + validatedRGB = newRGB; + updatePaint = true; + isValidatedPaintAColor = true; + } + } else if (validatedPaint != paint) { + updatePaint = true; + // this should be set when we are switching from paint to color + // in which case this condition will be true + isValidatedPaintAColor = false; } if ((currentContext != this) || @@ -147,9 +225,18 @@ public class BufferedContext { } // validate clip - if (updateClip) { + if ((clip != validatedClip) || updateClip) { if (clip != null) { - setClip(clip); + if (updateClip || + validatedClip == null || + !(validatedClip.isRectangular() && clip.isRectangular()) || + ((clip.getLoX() != validatedClip.getLoX() || + clip.getLoY() != validatedClip.getLoY() || + clip.getHiX() != validatedClip.getHiX() || + clip.getHiY() != validatedClip.getHiY()))) + { + setClip(clip); + } } else { resetClip(); } @@ -173,14 +260,29 @@ public class BufferedContext { } // validate transform + boolean txChanged = false; if (xform == null) { if (xformInUse) { resetTransform(); xformInUse = false; + txChanged = true; + } else if (sg2d != null) { + if (transX != sg2d.transX || transY != sg2d.transY) { + txChanged = true; + } + } + if (sg2d != null) { + transX = sg2d.transX; + transY = sg2d.transY; } } else { setTransform(xform); xformInUse = true; + txChanged = true; + } + // non-Color paints may require paint revalidation + if (!isValidatedPaintAColor && txChanged) { + updatePaint = true; } // validate paint @@ -194,6 +296,7 @@ public class BufferedContext { } // mark dstData dirty + // REMIND: is this really needed now? we do it in SunGraphics2D.. dstData.markDirty(); } @@ -201,13 +304,20 @@ public class BufferedContext { * Invalidates the surfaces associated with this context. This is * useful when the context is no longer needed, and we want to break * the chain caused by these surface references. + * + * Note: must be called while the RenderQueue lock is held. + * + * @see RenderQueue#lock + * @see RenderQueue#unlock */ public void invalidateSurfaces() { validatedSrcData = null; validatedDstData = null; } - private void setSurfaces(SurfaceData srcData, SurfaceData dstData) { + private void setSurfaces(AccelSurface srcData, + AccelSurface dstData) + { // assert rq.lock.isHeldByCurrentThread(); rq.ensureCapacityAndAlignment(20, 4); buf.putInt(SET_SURFACES); @@ -304,4 +414,54 @@ public class BufferedContext { buf.putDouble(xform.getTranslateX()); buf.putDouble(xform.getTranslateY()); } + + /** + * Resets this context's surfaces and all attributes. + * + * Note: must be called while the RenderQueue lock is held. + * + * @see RenderQueue#lock + * @see RenderQueue#unlock + */ + public void invalidateContext() { + resetTransform(); + resetComposite(); + resetClip(); + invalidateSurfaces(); + validatedComp = null; + validatedClip = null; + validatedPaint = null; + xformInUse = false; + } + + /** + * Returns a singleton {@code RenderQueue} object used by the rendering + * pipeline. + * + * @return a render queue + * @see RenderQueue + */ + public abstract RenderQueue getRenderQueue(); + + /** + * Saves the the state of this context. + * It may reset the current context. + * + * Note: must be called while the RenderQueue lock is held. + * + * @see RenderQueue#lock + * @see RenderQueue#unlock + */ + public abstract void saveState(); + + /** + * Restores the native state of this context. + * It may reset the current context. + * + * Note: must be called while the RenderQueue lock is held. + * + * @see RenderQueue#lock + * @see RenderQueue#unlock + */ + public abstract void restoreState(); } diff --git a/src/share/classes/sun/java2d/pipe/BufferedOpCodes.java b/src/share/classes/sun/java2d/pipe/BufferedOpCodes.java index 0523d27bd..450ea4a27 100644 --- a/src/share/classes/sun/java2d/pipe/BufferedOpCodes.java +++ b/src/share/classes/sun/java2d/pipe/BufferedOpCodes.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-2008 Sun Microsystems Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,10 +32,14 @@ public class BufferedOpCodes { public static final int DRAW_POLY = 12; public static final int DRAW_PIXEL = 13; public static final int DRAW_SCANLINES = 14; + public static final int DRAW_PARALLELOGRAM = 15; + public static final int DRAW_AAPARALLELOGRAM = 16; // fill ops public static final int FILL_RECT = 20; public static final int FILL_SPANS = 21; + public static final int FILL_PARALLELOGRAM = 22; + public static final int FILL_AAPARALLELOGRAM = 23; // copy-related ops public static final int COPY_AREA = 30; @@ -67,6 +71,9 @@ public class BufferedOpCodes { public static final int DISPOSE_CONFIG = 74; public static final int INVALIDATE_CONTEXT = 75; public static final int SYNC = 76; + public static final int RESTORE_DEVICES = 77; + public static final int SAVE_STATE = 78; + public static final int RESTORE_STATE = 79; // multibuffering ops public static final int SWAP_BUFFERS = 80; diff --git a/src/share/classes/sun/java2d/pipe/BufferedRenderPipe.java b/src/share/classes/sun/java2d/pipe/BufferedRenderPipe.java index 71feb4b9b..e9f418a96 100644 --- a/src/share/classes/sun/java2d/pipe/BufferedRenderPipe.java +++ b/src/share/classes/sun/java2d/pipe/BufferedRenderPipe.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-2008 Sun Microsystems Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ package sun.java2d.pipe; +import java.awt.BasicStroke; import java.awt.Polygon; import java.awt.Shape; import java.awt.geom.AffineTransform; @@ -33,6 +34,7 @@ import java.awt.geom.Ellipse2D; import java.awt.geom.Path2D; import java.awt.geom.IllegalPathStateException; import java.awt.geom.PathIterator; +import java.awt.geom.Rectangle2D; import java.awt.geom.RoundRectangle2D; import sun.java2d.SunGraphics2D; import sun.java2d.loops.ProcessPath; @@ -51,8 +53,10 @@ import static sun.java2d.pipe.BufferedOpCodes.*; * simply delegate to draw(Shape) and fill(Shape), respectively. */ public abstract class BufferedRenderPipe - implements PixelDrawPipe, PixelFillPipe, ShapeDrawPipe + implements PixelDrawPipe, PixelFillPipe, ShapeDrawPipe, ParallelogramPipe { + ParallelogramPipe aapgrampipe = new AAParallelogramPipe(); + static final int BYTES_PER_POLY_POINT = 8; static final int BYTES_PER_SCANLINE = 12; static final int BYTES_PER_SPAN = 16; @@ -67,12 +71,17 @@ public abstract class BufferedRenderPipe this.drawHandler = new BufferedDrawHandler(); } + public ParallelogramPipe getAAParallelogramPipe() { + return aapgrampipe; + } + /** * Validates the state in the provided SunGraphics2D object and sets up * any special resources for this operation (e.g. enabling gradient * shading). */ protected abstract void validateContext(SunGraphics2D sg2d); + protected abstract void validateContextAA(SunGraphics2D sg2d); public void drawLine(SunGraphics2D sg2d, int x1, int y1, int x2, int y2) @@ -398,6 +407,98 @@ public abstract class BufferedRenderPipe } } + public void fillParallelogram(SunGraphics2D sg2d, + double x, double y, + double dx1, double dy1, + double dx2, double dy2) + { + rq.lock(); + try { + validateContext(sg2d); + rq.ensureCapacity(28); + buf.putInt(FILL_PARALLELOGRAM); + buf.putFloat((float) x); + buf.putFloat((float) y); + buf.putFloat((float) dx1); + buf.putFloat((float) dy1); + buf.putFloat((float) dx2); + buf.putFloat((float) dy2); + } finally { + rq.unlock(); + } + } + + public void drawParallelogram(SunGraphics2D sg2d, + double x, double y, + double dx1, double dy1, + double dx2, double dy2, + double lw1, double lw2) + { + rq.lock(); + try { + validateContext(sg2d); + rq.ensureCapacity(36); + buf.putInt(DRAW_PARALLELOGRAM); + buf.putFloat((float) x); + buf.putFloat((float) y); + buf.putFloat((float) dx1); + buf.putFloat((float) dy1); + buf.putFloat((float) dx2); + buf.putFloat((float) dy2); + buf.putFloat((float) lw1); + buf.putFloat((float) lw2); + } finally { + rq.unlock(); + } + } + + private class AAParallelogramPipe implements ParallelogramPipe { + public void fillParallelogram(SunGraphics2D sg2d, + double x, double y, + double dx1, double dy1, + double dx2, double dy2) + { + rq.lock(); + try { + validateContextAA(sg2d); + rq.ensureCapacity(28); + buf.putInt(FILL_AAPARALLELOGRAM); + buf.putFloat((float) x); + buf.putFloat((float) y); + buf.putFloat((float) dx1); + buf.putFloat((float) dy1); + buf.putFloat((float) dx2); + buf.putFloat((float) dy2); + } finally { + rq.unlock(); + } + } + + public void drawParallelogram(SunGraphics2D sg2d, + double x, double y, + double dx1, double dy1, + double dx2, double dy2, + double lw1, double lw2) + { + rq.lock(); + try { + validateContextAA(sg2d); + rq.ensureCapacity(36); + buf.putInt(DRAW_AAPARALLELOGRAM); + buf.putFloat((float) x); + buf.putFloat((float) y); + buf.putFloat((float) dx1); + buf.putFloat((float) dy1); + buf.putFloat((float) dx2); + buf.putFloat((float) dy2); + buf.putFloat((float) lw1); + buf.putFloat((float) lw2); + } finally { + rq.unlock(); + } + } + } + public void draw(SunGraphics2D sg2d, Shape s) { if (sg2d.strokeState == sg2d.STROKE_THIN) { if (s instanceof Polygon) { diff --git a/src/share/classes/sun/java2d/pipe/DrawImage.java b/src/share/classes/sun/java2d/pipe/DrawImage.java index 21397906d..15ade8dd3 100644 --- a/src/share/classes/sun/java2d/pipe/DrawImage.java +++ b/src/share/classes/sun/java2d/pipe/DrawImage.java @@ -1,5 +1,5 @@ /* - * Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2001-2008 Sun Microsystems Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -955,7 +955,7 @@ public class DrawImage implements DrawImagePipe } else { BlitBg blit = BlitBg.getFromCache(srcType, comp, dstType); blit.BlitBg(srcData, dstData, sg.composite, clipRegion, - bgColor, sx, sy, dx, dy, w, h); + bgColor.getRGB(), sx, sy, dx, dy, w, h); } } diff --git a/src/share/classes/sun/java2d/pipe/ParallelogramPipe.java b/src/share/classes/sun/java2d/pipe/ParallelogramPipe.java new file mode 100644 index 000000000..33278dd90 --- /dev/null +++ b/src/share/classes/sun/java2d/pipe/ParallelogramPipe.java @@ -0,0 +1,66 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.java2d.pipe; + +import sun.java2d.SunGraphics2D; + +/** + * This interface defines the set of calls that pipeline objects + * can use to pass on responsibility for drawing arbitrary + * parallelogram shapes. + * Six floating point numbers are provided and the parallelogram + * is defined as the quadrilateral with the following vertices: + * <pre> + * origin: (x, y) + * => (x+dx1, y+dy1) + * => (x+dx1+dx2, y+dy1+dy2) + * => (x+dx2, y+dy2) + * => origin + * </pre> + */ +public interface ParallelogramPipe { + public void fillParallelogram(SunGraphics2D sg, + double x, double y, + double dx1, double dy1, + double dx2, double dy2); + + /** + * Draw a Parallelogram with the indicated line widths + * assuming a standard BasicStroke with MITER joins. + * lw1 specifies the width of the stroke along the dx1,dy1 + * vector and lw2 specifies the width of the stroke along + * the dx2,dy2 vector. + * This is equivalent to outsetting the indicated + * parallelogram by lw/2 pixels, then insetting the + * same parallelogram by lw/2 pixels and filling the + * difference between the outer and inner parallelograms. + */ + public void drawParallelogram(SunGraphics2D sg, + double x, double y, + double dx1, double dy1, + double dx2, double dy2, + double lw1, double lw2); +} diff --git a/src/share/classes/sun/java2d/pipe/PixelToParallelogramConverter.java b/src/share/classes/sun/java2d/pipe/PixelToParallelogramConverter.java new file mode 100644 index 000000000..dcbebb2fb --- /dev/null +++ b/src/share/classes/sun/java2d/pipe/PixelToParallelogramConverter.java @@ -0,0 +1,417 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.java2d.pipe; + +import java.awt.Shape; +import java.awt.BasicStroke; +import java.awt.geom.Line2D; +import java.awt.geom.Rectangle2D; +import java.awt.geom.AffineTransform; +import sun.java2d.SunGraphics2D; +import sun.awt.SunHints; + +/** + * This class converts calls to the basic pixel rendering methods + * into calls to the methods on a ParallelogramPipe. + * Most calls are transformed into calls to the fill(Shape) method + * by the parent PixelToShapeConverter class, but some calls are + * transformed into calls to fill/drawParallelogram(). + */ +public class PixelToParallelogramConverter extends PixelToShapeConverter + implements ShapeDrawPipe +{ + ParallelogramPipe outrenderer; + double minPenSize; + double normPosition; + double normRoundingBias; + boolean adjustfill; + + /** + * @param shapepipe pipeline to forward shape calls to + * @param pgrampipe pipeline to forward parallelogram calls to + * (and drawLine calls if possible) + * @param minPenSize minimum pen size for dropout control + * @param normPosition sub-pixel location to normalize endpoints + * for STROKE_NORMALIZE cases + * @param adjustFill boolean to control whethere normalization + * constants are also applied to fill operations + * (normally true for non-AA, false for AA) + */ + public PixelToParallelogramConverter(ShapeDrawPipe shapepipe, + ParallelogramPipe pgrampipe, + double minPenSize, + double normPosition, + boolean adjustfill) + { + super(shapepipe); + outrenderer = pgrampipe; + this.minPenSize = minPenSize; + this.normPosition = normPosition; + this.normRoundingBias = 0.5 - normPosition; + this.adjustfill = adjustfill; + } + + public void drawLine(SunGraphics2D sg2d, + int x1, int y1, int x2, int y2) + { + if (!drawGeneralLine(sg2d, x1, y1, x2, y2)) { + super.drawLine(sg2d, x1, y1, x2, y2); + } + } + + public void drawRect(SunGraphics2D sg2d, + int x, int y, int w, int h) + { + if (w >= 0 && h >= 0) { + if (sg2d.strokeState < SunGraphics2D.STROKE_CUSTOM) { + BasicStroke bs = ((BasicStroke) sg2d.stroke); + if (w > 0 && h > 0) { + if (bs.getLineJoin() == BasicStroke.JOIN_MITER && + bs.getDashArray() == null) + { + double lw = bs.getLineWidth(); + drawRectangle(sg2d, x, y, w, h, lw); + return; + } + } else { + // Note: This calls the integer version which + // will verify that the local drawLine optimizations + // work and call super.drawLine(), if not. + drawLine(sg2d, x, y, x+w, y+h); + return; + } + } + super.drawRect(sg2d, x, y, w, h); + } + } + + public void fillRect(SunGraphics2D sg2d, + int x, int y, int w, int h) + { + if (w > 0 && h > 0) { + fillRectangle(sg2d, x, y, w, h); + } + } + + public void draw(SunGraphics2D sg2d, Shape s) { + if (sg2d.strokeState < SunGraphics2D.STROKE_CUSTOM) { + BasicStroke bs = ((BasicStroke) sg2d.stroke); + if (s instanceof Rectangle2D) { + if (bs.getLineJoin() == BasicStroke.JOIN_MITER && + bs.getDashArray() == null) + { + Rectangle2D r2d = (Rectangle2D) s; + double w = r2d.getWidth(); + double h = r2d.getHeight(); + double x = r2d.getX(); + double y = r2d.getY(); + if (w >= 0 && h >= 0) { + double lw = bs.getLineWidth(); + drawRectangle(sg2d, x, y, w, h, lw); + } + return; + } + } else if (s instanceof Line2D) { + Line2D l2d = (Line2D) s; + if (drawGeneralLine(sg2d, + l2d.getX1(), l2d.getY1(), + l2d.getX2(), l2d.getY2())) + { + return; + } + } + } + + outpipe.draw(sg2d, s); + } + + public void fill(SunGraphics2D sg2d, Shape s) { + if (s instanceof Rectangle2D) { + Rectangle2D r2d = (Rectangle2D) s; + double w = r2d.getWidth(); + double h = r2d.getHeight(); + if (w > 0 && h > 0) { + double x = r2d.getX(); + double y = r2d.getY(); + fillRectangle(sg2d, x, y, w, h); + } + return; + } + + outpipe.fill(sg2d, s); + } + + static double len(double x, double y) { + return ((x == 0) ? Math.abs(y) + : ((y == 0) ? Math.abs(x) + : Math.sqrt(x * x + y * y))); + } + + double normalize(double v) { + return Math.floor(v + normRoundingBias) + normPosition; + } + + public boolean drawGeneralLine(SunGraphics2D sg2d, + double x1, double y1, + double x2, double y2) + { + if (sg2d.strokeState == SunGraphics2D.STROKE_CUSTOM || + sg2d.strokeState == SunGraphics2D.STROKE_THINDASHED) + { + return false; + } + BasicStroke bs = (BasicStroke) sg2d.stroke; + int cap = bs.getEndCap(); + if (cap == BasicStroke.CAP_ROUND || bs.getDashArray() != null) { + // TODO: we could construct the GeneralPath directly + // for CAP_ROUND and save a lot of processing in that case... + // And again, we would need to deal with dropout control... + return false; + } + double lw = bs.getLineWidth(); + // Save the original dx, dy in case we need it to transform + // the linewidth as a perpendicular vector below + double dx = x2 - x1; + double dy = y2 - y1; + switch (sg2d.transformState) { + case SunGraphics2D.TRANSFORM_GENERIC: + case SunGraphics2D.TRANSFORM_TRANSLATESCALE: + { + double coords[] = {x1, y1, x2, y2}; + sg2d.transform.transform(coords, 0, coords, 0, 2); + x1 = coords[0]; + y1 = coords[1]; + x2 = coords[2]; + y2 = coords[3]; + } + break; + case SunGraphics2D.TRANSFORM_ANY_TRANSLATE: + case SunGraphics2D.TRANSFORM_INT_TRANSLATE: + { + double tx = sg2d.transform.getTranslateX(); + double ty = sg2d.transform.getTranslateY(); + x1 += tx; + y1 += ty; + x2 += tx; + y2 += ty; + } + break; + case SunGraphics2D.TRANSFORM_ISIDENT: + break; + default: + throw new InternalError("unknown TRANSFORM state..."); + } + if (sg2d.strokeHint != SunHints.INTVAL_STROKE_PURE) { + if (sg2d.strokeState == SunGraphics2D.STROKE_THIN && + outrenderer instanceof PixelDrawPipe) + { + // PixelDrawPipes will add sg2d.transXY so we need to factor + // that out... + int ix1 = (int) Math.floor(x1 - sg2d.transX); + int iy1 = (int) Math.floor(y1 - sg2d.transY); + int ix2 = (int) Math.floor(x2 - sg2d.transX); + int iy2 = (int) Math.floor(y2 - sg2d.transY); + ((PixelDrawPipe)outrenderer).drawLine(sg2d, ix1, iy1, ix2, iy2); + return true; + } + x1 = normalize(x1); + y1 = normalize(y1); + x2 = normalize(x2); + y2 = normalize(y2); + } + if (sg2d.transformState >= SunGraphics2D.TRANSFORM_TRANSLATESCALE) { + // Transform the linewidth... + // calculate the scaling factor for a unit vector + // perpendicular to the original user space line. + double len = len(dx, dy); + if (len == 0) { + dx = len = 1; + // dy = 0; already + } + // delta transform the transposed (90 degree rotated) unit vector + double unitvector[] = {dy/len, -dx/len}; + sg2d.transform.deltaTransform(unitvector, 0, unitvector, 0, 1); + lw *= len(unitvector[0], unitvector[1]); + } + lw = Math.max(lw, minPenSize); + dx = x2 - x1; + dy = y2 - y1; + double len = len(dx, dy); + double udx, udy; + if (len == 0) { + if (cap == BasicStroke.CAP_BUTT) { + return true; + } + udx = lw; + udy = 0; + } else { + udx = lw * dx / len; + udy = lw * dy / len; + } + double px = x1 + udy / 2.0; + double py = y1 - udx / 2.0; + if (cap == BasicStroke.CAP_SQUARE) { + px -= udx / 2.0; + py -= udy / 2.0; + dx += udx; + dy += udy; + } + outrenderer.fillParallelogram(sg2d, px, py, -udy, udx, dx, dy); + return true; + } + + public void fillRectangle(SunGraphics2D sg2d, + double rx, double ry, + double rw, double rh) + { + double px, py; + double dx1, dy1, dx2, dy2; + AffineTransform txform = sg2d.transform; + dx1 = txform.getScaleX(); + dy1 = txform.getShearY(); + dx2 = txform.getShearX(); + dy2 = txform.getScaleY(); + px = rx * dx1 + ry * dx2 + txform.getTranslateX(); + py = rx * dy1 + ry * dy2 + txform.getTranslateY(); + dx1 *= rw; + dy1 *= rw; + dx2 *= rh; + dy2 *= rh; + if (adjustfill && + sg2d.strokeState < SunGraphics2D.STROKE_CUSTOM && + sg2d.strokeHint != SunHints.INTVAL_STROKE_PURE) + { + double newx = normalize(px); + double newy = normalize(py); + dx1 = normalize(px + dx1) - newx; + dy1 = normalize(py + dy1) - newy; + dx2 = normalize(px + dx2) - newx; + dy2 = normalize(py + dy2) - newy; + px = newx; + py = newy; + } + outrenderer.fillParallelogram(sg2d, px, py, dx1, dy1, dx2, dy2); + } + + public void drawRectangle(SunGraphics2D sg2d, + double rx, double ry, + double rw, double rh, + double lw) + { + double px, py; + double dx1, dy1, dx2, dy2; + double lw1, lw2; + AffineTransform txform = sg2d.transform; + dx1 = txform.getScaleX(); + dy1 = txform.getShearY(); + dx2 = txform.getShearX(); + dy2 = txform.getScaleY(); + px = rx * dx1 + ry * dx2 + txform.getTranslateX(); + py = rx * dy1 + ry * dy2 + txform.getTranslateY(); + // lw along dx1,dy1 scale by transformed length of dx2,dy2 vectors + // and vice versa + lw1 = len(dx1, dy1) * lw; + lw2 = len(dx2, dy2) * lw; + dx1 *= rw; + dy1 *= rw; + dx2 *= rh; + dy2 *= rh; + if (sg2d.strokeState < SunGraphics2D.STROKE_CUSTOM && + sg2d.strokeHint != SunHints.INTVAL_STROKE_PURE) + { + double newx = normalize(px); + double newy = normalize(py); + dx1 = normalize(px + dx1) - newx; + dy1 = normalize(py + dy1) - newy; + dx2 = normalize(px + dx2) - newx; + dy2 = normalize(py + dy2) - newy; + px = newx; + py = newy; + } + lw1 = Math.max(lw1, minPenSize); + lw2 = Math.max(lw2, minPenSize); + double len1 = len(dx1, dy1); + double len2 = len(dx2, dy2); + if (lw1 >= len1 || lw2 >= len2) { + // The line widths are large enough to consume the + // entire hole in the middle of the parallelogram + // so we can just fill the outer parallelogram. + fillOuterParallelogram(sg2d, + px, py, dx1, dy1, dx2, dy2, + len1, len2, lw1, lw2); + } else { + outrenderer.drawParallelogram(sg2d, + px, py, dx1, dy1, dx2, dy2, + lw1 / len1, lw2 / len2); + } + } + + /** + * This utility function handles the case where a drawRectangle + * operation discovered that the interior hole in the rectangle + * or parallelogram has been completely filled in by the stroke + * width. It calculates the outer parallelogram of the stroke + * and issues a single fillParallelogram request to fill it. + */ + public void fillOuterParallelogram(SunGraphics2D sg2d, + double px, double py, + double dx1, double dy1, + double dx2, double dy2, + double len1, double len2, + double lw1, double lw2) + { + double udx1 = dx1 / len1; + double udy1 = dy1 / len1; + double udx2 = dx2 / len2; + double udy2 = dy2 / len2; + if (len1 == 0) { + // len1 is 0, replace udxy1 with perpendicular of udxy2 + if (len2 == 0) { + // both are 0, use a unit Y vector for udxy2 + udx2 = 0; + udy2 = 1; + } + udx1 = udy2; + udy1 = -udx2; + } else if (len2 == 0) { + // len2 is 0, replace udxy2 with perpendicular of udxy1 + udx2 = udy1; + udy2 = -udx1; + } + udx1 *= lw1; + udy1 *= lw1; + udx2 *= lw2; + udy2 *= lw2; + px -= (udx1 + udx2) / 2; + py -= (udy1 + udy2) / 2; + dx1 += udx1; + dy1 += udy1; + dx2 += udx2; + dy2 += udy2; + + outrenderer.fillParallelogram(sg2d, px, py, dx1, dy1, dx2, dy2); + } +} diff --git a/src/share/classes/sun/java2d/pipe/hw/AccelDeviceEventListener.java b/src/share/classes/sun/java2d/pipe/hw/AccelDeviceEventListener.java new file mode 100644 index 000000000..a6cacbdee --- /dev/null +++ b/src/share/classes/sun/java2d/pipe/hw/AccelDeviceEventListener.java @@ -0,0 +1,59 @@ +/* + * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.java2d.pipe.hw; + +/** + * An interface for receiving notifications about imminent accelerated device's + * events. Upon receiving such event appropriate actions can be taken (for + * example, resources associated with the device can be freed). + */ +public interface AccelDeviceEventListener { + /** + * Called when the device is about to be reset. + * + * One must release all native resources associated with the device which + * prevent the device from being reset (such as Default Pool resources for + * the D3D pipeline). + * + * It is safe to remove the listener while in the call back. + * + * Note: this method is called on the rendering thread, + * do not call into user code, do not take RQ lock! + */ + public void onDeviceReset(); + + /** + * Called when the device is about to be disposed of. + * + * One must release all native resources associated with the device. + * + * It is safe to remove the listener while in the call back. + * + * Note: this method is called on the rendering thread, + * do not call into user code, do not take RQ lock! + */ + public void onDeviceDispose(); +} diff --git a/src/share/classes/sun/java2d/pipe/hw/AccelDeviceEventNotifier.java b/src/share/classes/sun/java2d/pipe/hw/AccelDeviceEventNotifier.java new file mode 100644 index 000000000..73a387a6c --- /dev/null +++ b/src/share/classes/sun/java2d/pipe/hw/AccelDeviceEventNotifier.java @@ -0,0 +1,167 @@ +/* + * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.java2d.pipe.hw; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +/** + * This class is used to notify listeners about accelerated device's + * events such as device reset or dispose that are about to occur. + */ +public class AccelDeviceEventNotifier { + + private static AccelDeviceEventNotifier theInstance; + + /** + * A device is about to be reset. The listeners have to release all + * resources associated with the device which are required for the device + * to be reset. + */ + public static final int DEVICE_RESET = 0; + + /** + * A device is about to be disposed. The listeners have to release all + * resources associated with the device. + */ + public static final int DEVICE_DISPOSED = 1; + + private final Map<AccelDeviceEventListener, Integer> listeners; + + private AccelDeviceEventNotifier() { + listeners = Collections.synchronizedMap( + new HashMap<AccelDeviceEventListener, Integer>(1)); + } + + /** + * Returns a singleton of AccelDeviceEventNotifier if it exists. If the + * passed boolean is false and singleton doesn't exist yet, null is + * returned. If the passed boolean is {@code true} and singleton doesn't + * exist it will be created and returned. + * + * @param create whether to create a singleton instance if doesn't yet + * exist + * @return a singleton instance or null + */ + private static synchronized + AccelDeviceEventNotifier getInstance(boolean create) + { + if (theInstance == null && create) { + theInstance = new AccelDeviceEventNotifier(); + } + return theInstance; + } + + /** + * Called to indicate that a device event had occured. + * If a singleton exists, the listeners (those associated with + * the device) will be notified. + * + * @param screen a screen number of the device which is a source of + * the event + * @param eventType a type of the event + * @see #DEVICE_DISPOSED + * @see #DEVICE_RESET + */ + public static final void eventOccured(int screen, int eventType) { + AccelDeviceEventNotifier notifier = getInstance(false); + if (notifier != null) { + notifier.notifyListeners(eventType, screen); + } + } + + /** + * Adds the listener associated with a device on particular screen. + * + * Note: the listener must be removed as otherwise it will forever + * be referenced by the notifier. + * + * @param l the listener + * @param screen the screen number indicating which device the listener is + * interested in. + */ + public static final void addListener(AccelDeviceEventListener l,int screen){ + getInstance(true).add(l, screen); + } + + /** + * Removes the listener. + * + * @param l the listener + */ + public static final void removeListener(AccelDeviceEventListener l) { + getInstance(true).remove(l); + } + + private final void add(AccelDeviceEventListener theListener, int screen) { + listeners.put(theListener, screen); + } + private final void remove(AccelDeviceEventListener theListener) { + listeners.remove(theListener); + } + + /** + * Notifies the listeners associated with the screen's device about the + * event. + * + * Implementation note: the current list of listeners is first duplicated + * which allows the listeners to remove themselves during the iteration. + * + * @param screen a screen number with which the device which is a source of + * the event is associated with + * @param eventType a type of the event + * @see #DEVICE_DISPOSED + * @see #DEVICE_RESET + */ + private final void notifyListeners(int deviceEventType, int screen) { + HashMap<AccelDeviceEventListener, Integer> listClone; + Set<AccelDeviceEventListener> cloneSet; + + synchronized(listeners) { + listClone = + new HashMap<AccelDeviceEventListener, Integer>(listeners); + } + + cloneSet = listClone.keySet(); + Iterator<AccelDeviceEventListener> itr = cloneSet.iterator(); + while (itr.hasNext()) { + AccelDeviceEventListener current = itr.next(); + Integer i = listClone.get(current); + // only notify listeners which are interested in this device + if (i != null && i.intValue() != screen) { + continue; + } + if (deviceEventType == DEVICE_RESET) { + current.onDeviceReset(); + } else if (deviceEventType == DEVICE_DISPOSED) { + current.onDeviceDispose(); + } + } + } +} diff --git a/src/share/classes/sun/java2d/pipe/hw/AccelGraphicsConfig.java b/src/share/classes/sun/java2d/pipe/hw/AccelGraphicsConfig.java new file mode 100644 index 000000000..ab799d947 --- /dev/null +++ b/src/share/classes/sun/java2d/pipe/hw/AccelGraphicsConfig.java @@ -0,0 +1,95 @@ +/* + * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.java2d.pipe.hw; + +import java.awt.image.VolatileImage; + +/** + * Implementors of this interface provida a way to create a + * {@code VolatileImage} whose destination surface is an + * {@link AccelSurface} of specified type. + * + * @see AccelSurface + */ +public interface AccelGraphicsConfig extends BufferedContextProvider { + /** + * Returns a VolatileImage with specified width, height, transparency + * and guaranteed accelerated surface type. If such image can not be created + * (out of vram error, specific surface type is not supported) null + * is returned. + * + * Note: if {@link AccelSurface#TEXTURE} type is requested, rendering + * to the image will be denied by throwing + * {@code UnsupportedOperationException } + * from {@link java.awt.image.VolatileImage#getGraphics} and + * {@link java.awt.image.VolatileImage#createGraphics} + * + * @param width the width of the returned {@code VolatileImage} + * @param height the height of the returned {@code VolatileImage} + * @param transparency the specified transparency mode + * @param type requested accelerated surface type as specified by constants + * in AccelSurface interface + * @return a {@code VolatileImage} backed up by requested accelerated + * surface type or null + * @throws IllegalArgumentException if the transparency is not a valid value + * @see AccelSurface#TEXTURE + * @see AccelSurface#RT_PLAIN + * @see AccelSurface#RT_TEXTURE + */ + public VolatileImage createCompatibleVolatileImage(int width, int height, + int transparency, + int type); + /** + * Returns object representing capabilities of the context associated + * with this {@code AccelGraphicsConfig}. + * + * @return ContextCapabilities object representing caps + * @see ContextCapabilities + */ + public ContextCapabilities getContextCapabilities(); + + /** + * Adds an {@code AccelDeviceEventListener} to listen to accelerated + * device's (which is associated with this {@code AccelGraphicsConfig}) + * events. + * + * Note: a hard link to the listener may be kept so it must be explicitly + * removed via {@link #removeDeviceEventListener()}. + * + * @param l the listener + * @see AccelDeviceEventListener + */ + public void addDeviceEventListener(AccelDeviceEventListener l); + + /** + * Removes an {@code AccelDeviceEventListener} from the list of listeners + * for this device's events. + * + * @param l the listener + * @see AccelDeviceEventListener + */ + public void removeDeviceEventListener(AccelDeviceEventListener l); +} diff --git a/src/share/classes/sun/java2d/pipe/hw/AccelSurface.java b/src/share/classes/sun/java2d/pipe/hw/AccelSurface.java new file mode 100644 index 000000000..c8692cb5e --- /dev/null +++ b/src/share/classes/sun/java2d/pipe/hw/AccelSurface.java @@ -0,0 +1,136 @@ +/* + * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.java2d.pipe.hw; + +import java.awt.Rectangle; +import sun.java2d.Surface; + +/** + * Abstraction for a hardware accelerated surface. + */ +public interface AccelSurface extends BufferedContextProvider, Surface { + /** + * Undefined + */ + public static final int UNDEFINED = 0; + /** + * Window (or window substitute) surface + */ + public static final int WINDOW = 1; + /** + * Render-To Plain surface (pbuffer for OpenGL, Render Target surface + * for Direct3D) + */ + public static final int RT_PLAIN = 2; + /** + * Texture surface + */ + public static final int TEXTURE = 3; + /** + * A back-buffer surface (SwapChain surface for Direct3D, backbuffer for + * OpenGL) + */ + public static final int FLIP_BACKBUFFER = 4; + /** + * Render-To Texture surface (fbobject for OpenGL, texture with render-to + * attribute for Direct3D) + */ + public static final int RT_TEXTURE = 5; + + /** + * Returns {@code int} representing surface's type as defined by constants + * in this interface. + * + * @return an integer representing this surface's type + * @see AccelSurface#UNDEFINED + * @see AccelSurface#WINDOW + * @see AccelSurface#RT_PLAIN + * @see AccelSurface#TEXTURE + * @see AccelSurface#FLIP_BACKBUFFER + * @see AccelSurface#RT_TEXTURE + */ + public int getType(); + + /** + * Returns a pointer to the native surface data associated with this + * surface. + * Note: this pointer is only valid on the rendering thread. + * + * @return pointer to the native surface's data + */ + public long getNativeOps(); + + /** + * Returns a pointer to the real native resource + * of the specified type associated with this AccelSurface. + * Note: this pointer is only valid on the rendering thread. + * + * @param resType the type of the requested resource + * @return a long containing a pointer to the native resource of the + * specified type or 0L if such resource doesn't exist for this surface + */ + public long getNativeResource(int resType); + + /** + * Marks this surface dirty. + */ + public void markDirty(); + + /** + * Returns whether the pipeline considers this surface valid. A surface + * may become invalid if it is disposed of, or resized. + * + * @return true if valid, false otherwise + */ + public boolean isValid(); + + /** + * Returns whether this surface is lost. The return value is only valid + * on the render thread, meaning that even if this method returns + * {@code true} it could be lost in the next moment unless it is called + * on the rendering thread. + * + * @return true if the surface is known to be lost, false otherwise + */ + public boolean isSurfaceLost(); + + /** + * Returns the requested bounds of the destination surface. The real bounds + * of the native accelerated surface may differ. Use + * {@link #getNativeBounds} to get the bounds of the native surface. + * + * @return Rectangle representing java surface's bounds + */ + public Rectangle getBounds(); + + /** + * Returns real bounds of the native surface, which may differ from those + * returned by {@link #getBounds}. + * + * @return Rectangle representing native surface's bounds + */ + public Rectangle getNativeBounds(); +} diff --git a/src/share/classes/sun/java2d/pipe/hw/AccelTypedVolatileImage.java b/src/share/classes/sun/java2d/pipe/hw/AccelTypedVolatileImage.java new file mode 100644 index 000000000..e855201d7 --- /dev/null +++ b/src/share/classes/sun/java2d/pipe/hw/AccelTypedVolatileImage.java @@ -0,0 +1,74 @@ +/* + * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.java2d.pipe.hw; + +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import sun.awt.image.SunVolatileImage; +import static sun.java2d.pipe.hw.AccelSurface.*; + +/** + * This is an image with forced type of the accelerated surface. + */ +public class AccelTypedVolatileImage extends SunVolatileImage { + + /** + * Creates a volatile image with specified type of accelerated surface. + * + * @param graphicsConfig a GraphicsConfiguration for which this image should + * be created. + * @param width width + * @param height width + * @param transparency type of {@link java.awt.Transparency transparency} + * requested for the image + * @param accType type of the desired accelerated surface as defined in + * AccelSurface interface + * @see sun.java2d.pipe.hw.AccelSurface + */ + public AccelTypedVolatileImage(GraphicsConfiguration graphicsConfig, + int width, int height, int transparency, + int accType) + { + super(null, graphicsConfig, width, height, null, transparency, + null, accType); + } + + /** + * {@inheritDoc} + * + * This method will throw {@code UnsupportedOperationException} if it this + * image's destination surface can not be rendered to. + */ + @Override + public Graphics2D createGraphics() { + if (getForcedAccelSurfaceType() == TEXTURE) { + throw new UnsupportedOperationException("Can't render " + + "to a non-RT Texture"); + } + return super.createGraphics(); + } +} diff --git a/src/share/classes/sun/java2d/pipe/hw/BufferedContextProvider.java b/src/share/classes/sun/java2d/pipe/hw/BufferedContextProvider.java new file mode 100644 index 000000000..86df94442 --- /dev/null +++ b/src/share/classes/sun/java2d/pipe/hw/BufferedContextProvider.java @@ -0,0 +1,45 @@ +/* + * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.java2d.pipe.hw; + +import sun.java2d.pipe.BufferedContext; + +/** + * Classes implementing this interface can provide the {@code BufferedContext} + * associated with or used by them. + * + * @see sun.java2d.pipe.BufferedContext + */ +public interface BufferedContextProvider { + /** + * Retrieves a context associated with object implementing this + * interface. + * + * @return associated context + * @see sun.java2d.pipe.BufferedContext + */ + public BufferedContext getContext(); +} diff --git a/src/share/classes/sun/java2d/pipe/hw/ContextCapabilities.java b/src/share/classes/sun/java2d/pipe/hw/ContextCapabilities.java new file mode 100644 index 000000000..5f17028b0 --- /dev/null +++ b/src/share/classes/sun/java2d/pipe/hw/ContextCapabilities.java @@ -0,0 +1,128 @@ +/* + * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.java2d.pipe.hw; + +/** + * Represents a set of capabilities of a BufferedContext and associated + * AccelGraphicsConfig. + * + * @see AccelGraphicsConfig + */ +public class ContextCapabilities { + /** Indicates that the context has no capabilities. */ + public static final int CAPS_EMPTY = (0 << 0); + /** Indicates that the context supports RT surfaces with alpha channel. */ + public static final int CAPS_RT_PLAIN_ALPHA = (1 << 1); + /** Indicates that the context supports RT textures with alpha channel. */ + public static final int CAPS_RT_TEXTURE_ALPHA = (1 << 2); + /** Indicates that the context supports opaque RT textures. */ + public static final int CAPS_RT_TEXTURE_OPAQUE = (1 << 3); + /** Indicates that the context supports multitexturing. */ + public static final int CAPS_MULTITEXTURE = (1 << 4); + /** Indicates that the context supports non-pow2 texture dimensions. */ + public static final int CAPS_TEXNONPOW2 = (1 << 5); + /** Indicates that the context supports non-square textures. */ + public static final int CAPS_TEXNONSQUARE = (1 << 6); + /** Indicates that the context supports pixel shader 2.0 or better. */ + public static final int CAPS_PS20 = (1 << 7); + /** Indicates that the context supports pixel shader 3.0 or better. */ + public static final int CAPS_PS30 = (1 << 8); + /* + * Pipeline contexts should use this for defining pipeline-specific + * capabilities, for example: + * int CAPS_D3D_1 = (FIRST_PRIVATE_CAP << 0); + * int CAPS_D3D_2 = (FIRST_PRIVATE_CAP << 1); + */ + protected static final int FIRST_PRIVATE_CAP = (1 << 16); + + protected final int caps; + protected final String adapterId; + + /** + * Constructs a {@code ContextCapabilities} object. + * @param caps an {@code int} representing the capabilities + * @param a {@code String} representing the name of the adapter, or null, + * in which case the adapterId will be set to "unknown adapter". + */ + protected ContextCapabilities(int caps, String adapterId) { + this.caps = caps; + this.adapterId = adapterId != null ? adapterId : "unknown adapter"; + } + + /** + * Returns a string representing the name of the graphics adapter if such + * could be determined. It is guaranteed to never return {@code null}. + * @return string representing adapter id + */ + public String getAdapterId() { + return adapterId; + } + + /** + * Returns an {@code int} with capabilities (OR-ed constants defined in + * this class and its pipeline-specific subclasses). + * @return capabilities as {@code int} + */ + public int getCaps() { + return caps; + } + + @Override + public String toString() { + StringBuffer buf = + new StringBuffer("ContextCapabilities: adapter=" + + adapterId+", caps="); + if (caps == CAPS_EMPTY) { + buf.append("CAPS_EMPTY"); + } else { + if ((caps & CAPS_RT_PLAIN_ALPHA) != 0) { + buf.append("CAPS_RT_PLAIN_ALPHA|"); + } + if ((caps & CAPS_RT_TEXTURE_ALPHA) != 0) { + buf.append("CAPS_RT_TEXTURE_ALPHA|"); + } + if ((caps & CAPS_RT_TEXTURE_OPAQUE) != 0) { + buf.append("CAPS_RT_TEXTURE_OPAQUE|"); + } + if ((caps & CAPS_MULTITEXTURE) != 0) { + buf.append("CAPS_MULTITEXTURE|"); + } + if ((caps & CAPS_TEXNONPOW2) != 0) { + buf.append("CAPS_TEXNONPOW2|"); + } + if ((caps & CAPS_TEXNONSQUARE) != 0) { + buf.append("CAPS_TEXNONSQUARE|"); + } + if ((caps & CAPS_PS20) != 0) { + buf.append("CAPS_PS20|"); + } + if ((caps & CAPS_PS30) != 0) { + buf.append("CAPS_PS30|"); + } + } + return buf.toString(); + } +} diff --git a/src/share/classes/sun/java2d/pipe/hw/ExtendedBufferCapabilities.java b/src/share/classes/sun/java2d/pipe/hw/ExtendedBufferCapabilities.java new file mode 100644 index 000000000..65eb305ab --- /dev/null +++ b/src/share/classes/sun/java2d/pipe/hw/ExtendedBufferCapabilities.java @@ -0,0 +1,154 @@ +/* + * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.java2d.pipe.hw; + +import java.awt.BufferCapabilities; +import java.awt.ImageCapabilities; + +/** + * Provides extended BufferStrategy capabilities, allowing to specify + * the type of vertical refresh synchronization for a buffer strategy. + * + * This BS capability is always page flipping because v-sync is only relevant + * to flipping buffer strategies. + * + * Note that asking for a v-synced BS doesn't necessarily guarantee that it will + * be v-synced since the vsync capability may be disabled in the driver, or + * there may be other restriction (like a number of v-synced buffer strategies + * allowed per vm). Because of this {@code createBufferStrategy} doesn't + * throw {@code AWTException} when a v-synced BS could not be created when + * requested. + * + * @see java.awt.Canvas#createBufferStrategy(int, BufferCapabilities) + * @see java.awt.Window#createBufferStrategy(int, BufferCapabilities) + */ +public class ExtendedBufferCapabilities extends BufferCapabilities { + + /** + * Type of synchronization on vertical retrace. + */ + public static enum VSyncType { + /** + * Use the default v-sync mode appropriate for given BufferStrategy + * and situation. + */ + VSYNC_DEFAULT(0), + + /** + * Synchronize flip on vertical retrace. + */ + VSYNC_ON(1), + + /** + * Do not synchronize flip on vertical retrace. + */ + VSYNC_OFF(2); + + /** + * Used to identify the v-sync type (independent of the constants + * order as opposed to {@code ordinal()}). + */ + public int id() { + return id; + } + + private VSyncType(int id) { + this.id = id; + } + private int id; + } + + private VSyncType vsync; + + /** + * Creates an ExtendedBufferCapabilities object with front/back/flip caps + * from the passed cap, and VSYNC_DEFAULT v-sync mode. + */ + public ExtendedBufferCapabilities(BufferCapabilities caps) { + super(caps.getFrontBufferCapabilities(), + caps.getBackBufferCapabilities(), + caps.getFlipContents()); + + this.vsync = VSyncType.VSYNC_DEFAULT; + } + + /** + * Creates an ExtendedBufferCapabilities instance with front/back/flip caps + * from the passed caps, and VSYNC_DEFAULT v-sync mode. + */ + public ExtendedBufferCapabilities(ImageCapabilities front, + ImageCapabilities back, FlipContents flip) + { + super(front, back, flip); + + this.vsync = VSyncType.VSYNC_DEFAULT; + } + + /** + * Creates an ExtendedBufferCapabilities instance with front/back/flip caps + * from the passed image/flip caps, and the v-sync type. + */ + public ExtendedBufferCapabilities(ImageCapabilities front, + ImageCapabilities back, FlipContents flip, + VSyncType t) + { + super(front, back, flip); + + this.vsync = t; + } + + /** + * Creates an ExtendedBufferCapabilities instance with front/back/flip caps + * from the passed cap, and the passed v-sync mode. + */ + public ExtendedBufferCapabilities(BufferCapabilities caps, VSyncType t) { + super(caps.getFrontBufferCapabilities(), + caps.getBackBufferCapabilities(), + caps.getFlipContents()); + + this.vsync = t; + } + + /** + * Creates an ExtendedBufferCapabilities instance with front/back/flip caps + * from the object, and passed v-sync mode. + */ + public ExtendedBufferCapabilities derive(VSyncType t) { + return new ExtendedBufferCapabilities(this, t); + } + + /** + * Returns the type of v-sync requested by this capabilities instance. + */ + public VSyncType getVSync() { + return vsync; + } + + @Override + public final boolean isPageFlipping() { + return true; + } +} diff --git a/src/share/native/sun/font/AccelGlyphCache.c b/src/share/native/sun/font/AccelGlyphCache.c index abd2d881a..2a54fbf44 100644 --- a/src/share/native/sun/font/AccelGlyphCache.c +++ b/src/share/native/sun/font/AccelGlyphCache.c @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2008 Sun Microsystems Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,6 +45,19 @@ * list describing the cache as new glyphs are added. Platform specific * glyph caching code is responsible for actually creating the accelerated * memory surface that will contain the individual glyph images. + * + * Each glyph contains a reference to a list of cell infos - one per glyph + * cache. There may be multiple glyph caches (for example, one per graphics + * adapter), so if the glyph is cached on two devices its cell list will + * consists of two elements corresponding to different glyph caches. + * + * The platform-specific glyph caching code is supposed to use + * GetCellInfoForCache method for retrieving cache infos from the glyph's list. + * + * Note that if it is guaranteed that there will be only one global glyph + * cache then it one does not have to use AccelGlyphCache_GetCellInfoForCache + * for retrieving cell info for the glyph, but instead just use the struct's + * field directly. */ GlyphCacheInfo * AccelGlyphCache_Init(jint width, jint height, @@ -86,8 +99,11 @@ AccelGlyphCache_Init(jint width, jint height, * "virtual" glyph cache is available for the glyph image. Platform specific * glyph caching code is responsible for actually caching the glyph image * in the associated accelerated memory surface. + * + * Returns created cell info if it was successfully created and added to the + * cache and glyph's cell lists, NULL otherwise. */ -void +CacheCellInfo * AccelGlyphCache_AddGlyph(GlyphCacheInfo *cache, GlyphInfo *glyph) { CacheCellInfo *cellinfo = NULL; @@ -99,7 +115,7 @@ AccelGlyphCache_AddGlyph(GlyphCacheInfo *cache, GlyphInfo *glyph) if ((glyph->width > cache->cellWidth) || (glyph->height > cache->cellHeight)) { - return; + return NULL; } if (!cache->isFull) { @@ -126,9 +142,8 @@ AccelGlyphCache_AddGlyph(GlyphCacheInfo *cache, GlyphInfo *glyph) // create new CacheCellInfo cellinfo = (CacheCellInfo *)malloc(sizeof(CacheCellInfo)); if (cellinfo == NULL) { - glyph->cellInfo = NULL; J2dTraceLn(J2D_TRACE_ERROR, "could not allocate CellInfo"); - return; + return NULL; } cellinfo->cacheInfo = cache; @@ -136,6 +151,8 @@ AccelGlyphCache_AddGlyph(GlyphCacheInfo *cache, GlyphInfo *glyph) cellinfo->timesRendered = 0; cellinfo->x = x; cellinfo->y = y; + cellinfo->leftOff = 0; + cellinfo->rightOff = 0; cellinfo->tx1 = (jfloat)cellinfo->x / cache->width; cellinfo->ty1 = (jfloat)cellinfo->y / cache->height; cellinfo->tx2 = cellinfo->tx1 + ((jfloat)w / cache->width); @@ -152,6 +169,7 @@ AccelGlyphCache_AddGlyph(GlyphCacheInfo *cache, GlyphInfo *glyph) // add the new cell to the end of the list cache->tail = cellinfo; cellinfo->next = NULL; + cellinfo->nextGCI = NULL; } } @@ -210,9 +228,9 @@ AccelGlyphCache_AddGlyph(GlyphCacheInfo *cache, GlyphInfo *glyph) cache->Flush(); } - // if the cell is occupied, notify the base glyph that its - // cached version is about to be kicked out - cellinfo->glyphInfo->cellInfo = NULL; + // if the cell is occupied, notify the base glyph that the + // cached version for this cache is about to be kicked out + AccelGlyphCache_RemoveCellInfo(cellinfo->glyphInfo, cellinfo); } // update cellinfo with glyph's occupied region information @@ -221,8 +239,9 @@ AccelGlyphCache_AddGlyph(GlyphCacheInfo *cache, GlyphInfo *glyph) cellinfo->ty2 = cellinfo->ty1 + ((jfloat)h / cache->height); } - // update the glyph's reference to its cache cell - glyph->cellInfo = cellinfo; + // add cache cell to the glyph's cells list + AccelGlyphCache_AddCellInfo(glyph, cellinfo); + return cellinfo; } /** @@ -251,10 +270,145 @@ AccelGlyphCache_Invalidate(GlyphCacheInfo *cache) while (cellinfo != NULL) { if (cellinfo->glyphInfo != NULL) { // if the cell is occupied, notify the base glyph that its - // cached version is about to be invalidated - cellinfo->glyphInfo->cellInfo = NULL; - cellinfo->glyphInfo = NULL; + // cached version for this cache is about to be invalidated + AccelGlyphCache_RemoveCellInfo(cellinfo->glyphInfo, cellinfo); } cellinfo = cellinfo->next; } } + +/** + * Invalidates and frees all cells and the cache itself. The "cache" pointer + * becomes invalid after this function returns. + */ +void +AccelGlyphCache_Free(GlyphCacheInfo *cache) +{ + CacheCellInfo *cellinfo; + + J2dTraceLn(J2D_TRACE_INFO, "AccelGlyphCache_Free"); + + if (cache == NULL) { + return; + } + + // flush any pending vertices that may be depending on the current + // glyph cache + if (cache->Flush != NULL) { + cache->Flush(); + } + + while (cache->head != NULL) { + cellinfo = cache->head; + if (cellinfo->glyphInfo != NULL) { + // if the cell is occupied, notify the base glyph that its + // cached version for this cache is about to be invalidated + AccelGlyphCache_RemoveCellInfo(cellinfo->glyphInfo, cellinfo); + } + cache->head = cellinfo->next; + free(cellinfo); + } + free(cache); +} + +/** + * Add cell info to the head of the glyph's list of cached cells. + */ +void +AccelGlyphCache_AddCellInfo(GlyphInfo *glyph, CacheCellInfo *cellInfo) +{ + // assert (glyph != NULL && cellInfo != NULL) + J2dTraceLn(J2D_TRACE_INFO, "AccelGlyphCache_AddCellInfo"); + J2dTraceLn2(J2D_TRACE_VERBOSE, " glyph 0x%x: adding cell 0x%x to the list", + glyph, cellInfo); + + cellInfo->glyphInfo = glyph; + cellInfo->nextGCI = glyph->cellInfo; + glyph->cellInfo = cellInfo; +} + +/** + * Removes cell info from the glyph's list of cached cells. + */ +void +AccelGlyphCache_RemoveCellInfo(GlyphInfo *glyph, CacheCellInfo *cellInfo) +{ + CacheCellInfo *currCellInfo = glyph->cellInfo; + CacheCellInfo *prevInfo = NULL; + // assert (glyph!= NULL && glyph->cellInfo != NULL && cellInfo != NULL) + J2dTraceLn(J2D_TRACE_INFO, "AccelGlyphCache_RemoveCellInfo"); + do { + if (currCellInfo == cellInfo) { + J2dTraceLn2(J2D_TRACE_VERBOSE, + " glyph 0x%x: removing cell 0x%x from glyph's list", + glyph, currCellInfo); + if (prevInfo == NULL) { // it's the head, chop-chop + glyph->cellInfo = currCellInfo->nextGCI; + } else { + prevInfo->nextGCI = currCellInfo->nextGCI; + } + currCellInfo->glyphInfo = NULL; + currCellInfo->nextGCI = NULL; + return; + } + prevInfo = currCellInfo; + currCellInfo = currCellInfo->nextGCI; + } while (currCellInfo != NULL); + J2dTraceLn2(J2D_TRACE_WARNING, "AccelGlyphCache_RemoveCellInfo: "\ + "no cell 0x%x in glyph 0x%x's cell list", + cellInfo, glyph); +} + +/** + * Removes cell info from the glyph's list of cached cells. + */ +JNIEXPORT void +AccelGlyphCache_RemoveAllCellInfos(GlyphInfo *glyph) +{ + CacheCellInfo *currCell, *prevCell; + + J2dTraceLn(J2D_TRACE_INFO, "AccelGlyphCache_RemoveAllCellInfos"); + + if (glyph == NULL || glyph->cellInfo == NULL) { + return; + } + + // invalidate all of this glyph's accelerated cache cells + currCell = glyph->cellInfo; + do { + currCell->glyphInfo = NULL; + prevCell = currCell; + currCell = currCell->nextGCI; + prevCell->nextGCI = NULL; + } while (currCell != NULL); + + glyph->cellInfo = NULL; +} + +/** + * Returns cell info associated with particular cache from the glyph's list of + * cached cells. + */ +CacheCellInfo * +AccelGlyphCache_GetCellInfoForCache(GlyphInfo *glyph, GlyphCacheInfo *cache) +{ + // assert (glyph != NULL && cache != NULL) + J2dTraceLn(J2D_TRACE_VERBOSE2, "AccelGlyphCache_GetCellInfoForCache"); + + if (glyph->cellInfo != NULL) { + CacheCellInfo *cellInfo = glyph->cellInfo; + do { + if (cellInfo->cacheInfo == cache) { + J2dTraceLn3(J2D_TRACE_VERBOSE2, + " glyph 0x%x: found cell 0x%x for cache 0x%x", + glyph, cellInfo, cache); + return cellInfo; + } + cellInfo = cellInfo->nextGCI; + } while (cellInfo != NULL); + } + J2dTraceLn2(J2D_TRACE_VERBOSE2, " glyph 0x%x: no cell for cache 0x%x", + glyph, cache); + return NULL; +} + diff --git a/src/share/native/sun/font/AccelGlyphCache.h b/src/share/native/sun/font/AccelGlyphCache.h index fa62dc044..3f2c3e724 100644 --- a/src/share/native/sun/font/AccelGlyphCache.h +++ b/src/share/native/sun/font/AccelGlyphCache.h @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2008 Sun Microsystems Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,10 @@ #ifndef AccelGlyphCache_h_Included #define AccelGlyphCache_h_Included +#ifdef __cplusplus +extern "C" { +#endif + #include "jni.h" #include "fontscalerdefs.h" @@ -48,10 +52,18 @@ typedef struct { struct _CacheCellInfo { GlyphCacheInfo *cacheInfo; struct GlyphInfo *glyphInfo; + // next cell info in the cache's list CacheCellInfo *next; + // REMIND: find better name? + // next cell info in the glyph's cell list (next Glyph Cache Info) + CacheCellInfo *nextGCI; jint timesRendered; jint x; jint y; + // number of pixels from the left or right edge not considered touched + // by the glyph + jint leftOff; + jint rightOff; jfloat tx1; jfloat ty1; jfloat tx2; @@ -62,9 +74,24 @@ GlyphCacheInfo * AccelGlyphCache_Init(jint width, jint height, jint cellWidth, jint cellHeight, FlushFunc *func); -void +CacheCellInfo * AccelGlyphCache_AddGlyph(GlyphCacheInfo *cache, struct GlyphInfo *glyph); void AccelGlyphCache_Invalidate(GlyphCacheInfo *cache); +void +AccelGlyphCache_AddCellInfo(struct GlyphInfo *glyph, CacheCellInfo *cellInfo); +void +AccelGlyphCache_RemoveCellInfo(struct GlyphInfo *glyph, CacheCellInfo *cellInfo); +CacheCellInfo * +AccelGlyphCache_GetCellInfoForCache(struct GlyphInfo *glyph, + GlyphCacheInfo *cache); +JNIEXPORT void +AccelGlyphCache_RemoveAllCellInfos(struct GlyphInfo *glyph); +void +AccelGlyphCache_Free(GlyphCacheInfo *cache); + +#ifdef __cplusplus +}; +#endif #endif /* AccelGlyphCache_h_Included */ diff --git a/src/share/native/sun/font/sunFont.c b/src/share/native/sun/font/sunFont.c index 7c00561f6..af8aa6698 100644 --- a/src/share/native/sun/font/sunFont.c +++ b/src/share/native/sun/font/sunFont.c @@ -1,5 +1,5 @@ /* - * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,6 +35,8 @@ #include "sun_font_StrikeCache.h" static void *theNullScalerContext = NULL; +extern void AccelGlyphCache_RemoveAllCellInfos(GlyphInfo *glyph); + JNIEXPORT jlong JNICALL Java_sun_font_NullFontScaler_getNullScalerContext @@ -294,7 +296,7 @@ JNIEXPORT void JNICALL Java_sun_font_StrikeCache_freeIntMemory GlyphInfo *ginfo = (GlyphInfo *)ptrs[i]; if (ginfo->cellInfo != NULL) { // invalidate this glyph's accelerated cache cell - ginfo->cellInfo->glyphInfo = NULL; + AccelGlyphCache_RemoveAllCellInfos(ginfo); } free((void*)ginfo); } @@ -324,8 +326,7 @@ JNIEXPORT void JNICALL Java_sun_font_StrikeCache_freeLongMemory if (ptrs[i] != 0L) { GlyphInfo *ginfo = (GlyphInfo *) jlong_to_ptr(ptrs[i]); if (ginfo->cellInfo != NULL) { - // invalidate this glyph's accelerated cache cell - ginfo->cellInfo->glyphInfo = NULL; + AccelGlyphCache_RemoveAllCellInfos(ginfo); } free((void*)ginfo); } diff --git a/src/share/native/sun/java2d/ShaderList.c b/src/share/native/sun/java2d/ShaderList.c new file mode 100644 index 000000000..8831f2abd --- /dev/null +++ b/src/share/native/sun/java2d/ShaderList.c @@ -0,0 +1,143 @@ +/* + * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +#include <malloc.h> +#include <string.h> + +#include "ShaderList.h" +#include "Trace.h" + +/** + * Creates a new ShaderInfo that wraps the given fragment program handle + * and related data and stores it at the front of the provided ShaderList. + * If the addition causes the ShaderList to outgrow its defined capacity, + * the least-recently used item in the list (including its fragment program + * object) will be disposed. + */ +void +ShaderList_AddProgram(ShaderList *programList, + jlong programID, + jint compType, jint compMode, jint flags) +{ + ShaderInfo *info; + + J2dTraceLn(J2D_TRACE_INFO, "ShaderList_AddProgram"); + + // create new ShaderInfo + info = (ShaderInfo *)malloc(sizeof(ShaderInfo)); + if (info == NULL) { + J2dTraceLn(J2D_TRACE_ERROR, + "OGLContext_AddProgram: could not allocate ShaderInfo"); + return; + } + + // fill in the information + info->next = programList->head; + info->programID = programID; + info->compType = compType; + info->compMode = compMode; + info->flags = flags; + + // insert it at the head of the list + programList->head = info; + + // run through the list and see if we need to delete the least + // recently used item + { + int i = 1; + ShaderInfo *prev = NULL; + ShaderInfo *curr = info->next; + while (curr != NULL) { + if (i >= programList->maxItems) { + prev->next = NULL; + programList->dispose(curr->programID); + free(curr); + break; + } + i++; + prev = curr; + curr = curr->next; + } + } +} + +/** + * Locates a fragment program handle given a list of shader programs + * (ShaderInfos), using the provided composite state and flags as search + * parameters. The "flags" parameter is a bitwise-or'd value that helps + * differentiate one program for another; the interpretation of this value + * varies depending on the type of shader (BufImgOp, Paint, etc) but here + * it is only used to find another ShaderInfo with that same "flags" value. + * If no matching program can be located, this method returns 0. + */ +jlong +ShaderList_FindProgram(ShaderList *programList, + jint compType, jint compMode, jint flags) +{ + ShaderInfo *prev = NULL; + ShaderInfo *info = programList->head; + + J2dTraceLn(J2D_TRACE_INFO, "ShaderList_FindProgram"); + + while (info != NULL) { + if (compType == info->compType && + compMode == info->compMode && + flags == info->flags) + { + // it's a match: move it to the front of the list (if it's not + // there already) and patch up the links + if (info != programList->head) { + prev->next = info->next; + info->next = programList->head; + programList->head = info; + } + return info->programID; + } + prev = info; + info = info->next; + } + return 0; +} + +/** + * Disposes all entries (and their associated shader program objects) + * contained in the given ShaderList. + */ +void +ShaderList_Dispose(ShaderList *programList) +{ + ShaderInfo *info = programList->head; + + J2dTraceLn(J2D_TRACE_INFO, "ShaderList_Dispose"); + + while (info != NULL) { + ShaderInfo *tmp = info->next; + programList->dispose(info->programID); + free(info); + info = tmp; + } + + programList->head = NULL; +} diff --git a/src/share/native/sun/java2d/ShaderList.h b/src/share/native/sun/java2d/ShaderList.h new file mode 100644 index 000000000..f46190fcd --- /dev/null +++ b/src/share/native/sun/java2d/ShaderList.h @@ -0,0 +1,85 @@ +/* + * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +#ifndef ShaderList_h_Included +#define ShaderList_h_Included + +#ifdef __cplusplus +extern "C" { +#endif + +#include "jni.h" +#include "jlong.h" + +typedef void (ShaderDisposeFunc)(jlong programID); + +/** + * The following structures are used to maintain a list of fragment program + * objects and their associated attributes. Each logical shader (e.g. + * RadialGradientPaint shader, ConvolveOp shader) can have a number of + * different variants depending on a number of factors, such as whether + * antialiasing is enabled or the current composite mode. Since the number + * of possible combinations of these factors is in the hundreds, we need + * some way to create fragment programs on an as-needed basis, and also + * keep them in a limited sized cache to avoid creating too many objects. + * + * The ShaderInfo structure keeps a reference to the fragment program's + * handle, as well as some other values that help differentiate one ShaderInfo + * from another. ShaderInfos can be chained together to form a linked list. + * + * The ShaderList structure acts as a cache for ShaderInfos, placing + * most-recently used items at the front, and removing items from the + * cache when its size exceeds the "maxItems" limit. + */ +typedef struct _ShaderInfo ShaderInfo; + +typedef struct { + ShaderInfo *head; + ShaderDisposeFunc *dispose; + jint maxItems; +} ShaderList; + +struct _ShaderInfo { + ShaderInfo *next; + jlong programID; + jint compType; + jint compMode; + jint flags; +}; + +void ShaderList_AddProgram(ShaderList *programList, + jlong programID, + jint compType, jint compMode, + jint flags); +jlong ShaderList_FindProgram(ShaderList *programList, + jint compType, jint compMode, + jint flags); +void ShaderList_Dispose(ShaderList *programList); + +#ifdef __cplusplus +}; +#endif + +#endif /* ShaderList_h_Included */ diff --git a/src/share/native/sun/java2d/Trace.h b/src/share/native/sun/java2d/Trace.h index bc2596db0..f50dd9366 100644 --- a/src/share/native/sun/java2d/Trace.h +++ b/src/share/native/sun/java2d/Trace.h @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2008 Sun Microsystems Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -62,12 +62,18 @@ J2dTraceInit(); #define J2dTrace3(level, string, arg1, arg2, arg3) #define J2dTrace4(level, string, arg1, arg2, arg3, arg4) #define J2dTrace5(level, string, arg1, arg2, arg3, arg4, arg5) +#define J2dTrace6(level, string, arg1, arg2, arg3, arg4, arg5, arg6) +#define J2dTrace7(level, string, arg1, arg2, arg3, arg4, arg5, arg6, arg7) +#define J2dTrace8(level, string, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) #define J2dTraceLn(level, string) #define J2dTraceLn1(level, string, arg1) #define J2dTraceLn2(level, string, arg1, arg2) #define J2dTraceLn3(level, string, arg1, arg2, arg3) #define J2dTraceLn4(level, string, arg1, arg2, arg3, arg4) #define J2dTraceLn5(level, string, arg1, arg2, arg3, arg4, arg5) +#define J2dTraceLn6(level, string, arg1, arg2, arg3, arg4, arg5, arg6) +#define J2dTraceLn7(level, string, arg1, arg2, arg3, arg4, arg5, arg6, arg7) +#define J2dTraceLn8(level, string, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) #else /* DEBUG */ #define J2dTrace(level, string) { \ J2dTraceImpl(level, JNI_FALSE, string); \ @@ -87,6 +93,15 @@ J2dTraceInit(); #define J2dTrace5(level, string, arg1, arg2, arg3, arg4, arg5) { \ J2dTraceImpl(level, JNI_FALSE, string, arg1, arg2, arg3, arg4, arg5); \ } +#define J2dTrace6(level, string, arg1, arg2, arg3, arg4, arg5, arg6) { \ + J2dTraceImpl(level, JNI_FALSE, string, arg1, arg2, arg3, arg4, arg5, arg6); \ + } +#define J2dTrace7(level, string, arg1, arg2, arg3, arg4, arg5, arg6, arg7) { \ + J2dTraceImpl(level, JNI_FALSE, string, arg1, arg2, arg3, arg4, arg5, arg6, arg7); \ + } +#define J2dTrace8(level, string, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) { \ + J2dTraceImpl(level, JNI_FALSE, string, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); \ + } #define J2dTraceLn(level, string) { \ J2dTraceImpl(level, JNI_TRUE, string); \ } @@ -105,6 +120,15 @@ J2dTraceInit(); #define J2dTraceLn5(level, string, arg1, arg2, arg3, arg4, arg5) { \ J2dTraceImpl(level, JNI_TRUE, string, arg1, arg2, arg3, arg4, arg5); \ } +#define J2dTraceLn6(level, string, arg1, arg2, arg3, arg4, arg5, arg6) { \ + J2dTraceImpl(level, JNI_TRUE, string, arg1, arg2, arg3, arg4, arg5, arg6); \ + } +#define J2dTraceLn7(level, string, arg1, arg2, arg3, arg4, arg5, arg6, arg7) { \ + J2dTraceImpl(level, JNI_TRUE, string, arg1, arg2, arg3, arg4, arg5, arg6, arg7); \ + } +#define J2dTraceLn8(level, string, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) { \ + J2dTraceImpl(level, JNI_TRUE, string, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); \ + } #endif /* DEBUG */ diff --git a/src/share/native/sun/java2d/loops/BlitBg.c b/src/share/native/sun/java2d/loops/BlitBg.c index c5bccf24a..4c7e1f353 100644 --- a/src/share/native/sun/java2d/loops/BlitBg.c +++ b/src/share/native/sun/java2d/loops/BlitBg.c @@ -1,5 +1,5 @@ /* - * Copyright 2000-2003 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2008 Sun Microsystems Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,12 +31,12 @@ /* * Class: sun_java2d_loops_BlitBg * Method: BlitBg - * Signature: (Lsun/java2d/SurfaceData;Lsun/java2d/SurfaceData;Ljava/awt/Composite;Ljava/awt/Color;IIIIII)V + * Signature: (Lsun/java2d/SurfaceData;Lsun/java2d/SurfaceData;Ljava/awt/Composite;IIIIIII)V */ JNIEXPORT void JNICALL Java_sun_java2d_loops_BlitBg_BlitBg (JNIEnv *env, jobject self, jobject srcData, jobject dstData, - jobject comp, jobject clip, jobject bgColor, + jobject comp, jobject clip, jint bgColor, jint srcx, jint srcy, jint dstx, jint dsty, jint width, jint height) { SurfaceDataOps *srcOps; @@ -93,7 +93,7 @@ JNIEXPORT void JNICALL Java_sun_java2d_loops_BlitBg_BlitBg Region_IntersectBounds(&clipInfo, &dstInfo.bounds); if (!Region_IsEmpty(&clipInfo)) { - jint bgpixel = GrPrim_ColorGetRGB(env, bgColor); + jint bgpixel = bgColor; srcOps->GetRasInfo(env, srcOps, &srcInfo); dstOps->GetRasInfo(env, dstOps, &dstInfo); if (pPrim->pDstType->pixelFor) { diff --git a/src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.c b/src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.c index a36a28857..0240920b8 100644 --- a/src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.c +++ b/src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.c @@ -1,5 +1,5 @@ /* - * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2008 Sun Microsystems Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,7 +50,6 @@ static jfieldID eargbID; static jfieldID clipRegionID; static jfieldID compositeID; static jfieldID lcdTextContrastID; -static jfieldID valueID; static jfieldID xorPixelID; static jfieldID xorColorID; static jfieldID alphaMaskID; @@ -64,6 +63,8 @@ static jfieldID m10ID; static jfieldID m11ID; static jfieldID m12ID; +static jmethodID getRgbID; + static jboolean InitPrimTypes(JNIEnv *env); static jboolean InitSurfaceTypes(JNIEnv *env, jclass SurfaceType); static jboolean InitCompositeTypes(JNIEnv *env, jclass CompositeType); @@ -114,7 +115,7 @@ Java_sun_java2d_loops_GraphicsPrimitiveMgr_initIDs "Ljava/awt/Composite;"); lcdTextContrastID = (*env)->GetFieldID(env, SG2D, "lcdTextContrast", "I"); - valueID = (*env)->GetFieldID(env, Color, "value", "I"); + getRgbID = (*env)->GetMethodID(env, Color, "getRGB", "()I"); xorPixelID = (*env)->GetFieldID(env, XORComp, "xorPixel", "I"); xorColorID = (*env)->GetFieldID(env, XORComp, "xorColor", "Ljava/awt/Color;"); @@ -138,7 +139,6 @@ Java_sun_java2d_loops_GraphicsPrimitiveMgr_initIDs sg2dStrokeHintID = (*env)->GetFieldID(env, SG2D, "strokeHint", "I"); fid = (*env)->GetStaticFieldID(env, SHints, "INTVAL_STROKE_PURE", "I"); sunHints_INTVAL_STROKE_PURE = (*env)->GetStaticIntField(env, SHints, fid); - } void GrPrim_RefineBounds(SurfaceDataBounds *bounds, jint transX, jint transY, @@ -467,7 +467,7 @@ GrPrim_CompGetXorColor(JNIEnv *env, jobject comp) jint rgb; color = (*env)->GetObjectField(env, comp, xorColorID); - rgb = (*env)->GetIntField(env, color, valueID); + rgb = (*env)->CallIntMethod(env, color, getRgbID); (*env)->DeleteLocalRef(env, color); return rgb; @@ -492,11 +492,6 @@ GrPrim_Sg2dGetEaRGB(JNIEnv *env, jobject sg2d) return (*env)->GetIntField(env, sg2d, eargbID); } -jint GrPrim_ColorGetRGB(JNIEnv *env, jobject color) -{ - return (*env)->GetIntField(env, color, valueID); -} - JNIEXPORT jint JNICALL GrPrim_Sg2dGetLCDTextContrast(JNIEnv *env, jobject sg2d) { diff --git a/src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h b/src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h index 2d5676322..4845e3ae9 100644 --- a/src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h +++ b/src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h @@ -1,5 +1,5 @@ /* - * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2008 Sun Microsystems Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -501,7 +501,6 @@ extern JNIEXPORT jint JNICALL GrPrim_Sg2dGetEaRGB(JNIEnv *env, jobject sg2d); extern JNIEXPORT jint JNICALL GrPrim_Sg2dGetLCDTextContrast(JNIEnv *env, jobject sg2d); -extern jint GrPrim_ColorGetRGB(JNIEnv *env, jobject color); /* * Data structure and functions to retrieve and use diff --git a/src/share/native/sun/java2d/opengl/OGLContext.c b/src/share/native/sun/java2d/opengl/OGLContext.c index 33bc3e827..66ad30cda 100644 --- a/src/share/native/sun/java2d/opengl/OGLContext.c +++ b/src/share/native/sun/java2d/opengl/OGLContext.c @@ -1,5 +1,5 @@ /* - * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2004-2008 Sun Microsystems Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -852,28 +852,58 @@ OGLContext_GetExtensionInfo(JNIEnv *env, jint *caps) J2dTraceLn(J2D_TRACE_INFO, "OGLContext_GetExtensionInfo"); + *caps |= CAPS_TEXNONSQUARE; if (OGLContext_IsExtensionAvailable(e, "GL_ARB_multitexture")) { - *caps |= sun_java2d_opengl_OGLContext_CAPS_EXT_MULTITEXTURE; + *caps |= CAPS_MULTITEXTURE; } if (OGLContext_IsExtensionAvailable(e, "GL_ARB_texture_non_power_of_two")){ - *caps |= sun_java2d_opengl_OGLContext_CAPS_EXT_TEXNONPOW2; + *caps |= CAPS_TEXNONPOW2; } - if (OGLContext_IsExtensionAvailable(e, "GL_ARB_texture_rectangle")) { - *caps |= sun_java2d_opengl_OGLContext_CAPS_EXT_TEXRECT; + // 6656574: Use of the GL_ARB_texture_rectangle extension by Java 2D + // complicates any third-party libraries that try to interact with + // the OGL pipeline (and we've run into driver bugs in the past related + // to this extension), so for now we will disable its use by default (unless + // forced). We will still make use of the GL_ARB_texture_non_power_of_two + // extension when available, which is the better choice going forward + // anyway. + if (OGLContext_IsExtensionAvailable(e, "GL_ARB_texture_rectangle") && + getenv("J2D_OGL_TEXRECT") != NULL) + { + *caps |= CAPS_EXT_TEXRECT; } if (OGLContext_IsFBObjectExtensionAvailable(env, e)) { - *caps |= sun_java2d_opengl_OGLContext_CAPS_EXT_FBOBJECT; + *caps |= CAPS_EXT_FBOBJECT; } if (OGLContext_IsLCDShaderSupportAvailable(env, fragShaderAvail)) { - *caps |= sun_java2d_opengl_OGLContext_CAPS_EXT_LCD_SHADER; + *caps |= CAPS_EXT_LCD_SHADER | CAPS_PS20; } if (OGLContext_IsBIOpShaderSupportAvailable(env, fragShaderAvail)) { - *caps |= sun_java2d_opengl_OGLContext_CAPS_EXT_BIOP_SHADER; + *caps |= CAPS_EXT_BIOP_SHADER | CAPS_PS20; } if (OGLContext_IsGradShaderSupportAvailable(env, fragShaderAvail)) { - *caps |= sun_java2d_opengl_OGLContext_CAPS_EXT_GRAD_SHADER; + *caps |= CAPS_EXT_GRAD_SHADER | CAPS_PS20; + } + if (OGLContext_IsExtensionAvailable(e, "GL_NV_fragment_program")) { + // this is an Nvidia board, at least PS 2.0, but we can't + // use the "max instructions" heuristic since GeForce FX + // boards report 1024 even though they're only PS 2.0, + // so we'll check the following, which does imply PS 3.0 + if (OGLContext_IsExtensionAvailable(e, "GL_NV_fragment_program2")) { + *caps |= CAPS_PS30; + } + } else { + // for all other boards, we look at the "max instructions" + // count reported by the GL_ARB_fragment_program extension + // as a heuristic for detecting PS 3.0 compatible hardware + if (OGLContext_IsExtensionAvailable(e, "GL_ARB_fragment_program")) { + GLint instr; + j2d_glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, + GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &instr); + if (instr > 512) { + *caps |= CAPS_PS30; + } + } } - // stuff vendor descriptor in the upper bits of the caps if (vendor != NULL) { if (strncmp(vendor, "ATI", 3) == 0) { @@ -883,8 +913,10 @@ OGLContext_GetExtensionInfo(JNIEnv *env, jint *caps) } else if (strncmp(vendor, "Sun", 3) == 0) { vcap = OGLC_VENDOR_SUN; } + // REMIND: new in 7 - check if needs fixing + *caps |= ((vcap & OGLC_VCAP_MASK) << OGLC_VCAP_OFFSET); } - *caps |= ((vcap & OGLC_VCAP_MASK) << OGLC_VCAP_OFFSET); + } /** @@ -983,4 +1015,49 @@ OGLContext_CreateFragmentProgram(const char *fragmentShaderSource) return fragmentProgram; } +/* + * Class: sun_java2d_opengl_OGLContext + * Method: getOGLIdString + * Signature: ()Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_sun_java2d_opengl_OGLContext_getOGLIdString + (JNIEnv *env, jclass oglcc) +{ + char *vendor, *renderer, *version; + char *pAdapterId; + jobject ret = NULL; + int len; + + J2dTraceLn(J2D_TRACE_INFO, "OGLContext_getOGLIdString"); + + vendor = (char*)j2d_glGetString(GL_VENDOR); + if (vendor == NULL) { + vendor = "Unknown Vendor"; + } + renderer = (char*)j2d_glGetString(GL_RENDERER); + if (renderer == NULL) { + renderer = "Unknown Renderer"; + } + version = (char*)j2d_glGetString(GL_VERSION); + if (version == NULL) { + version = "unknown version"; + } + + // 'vendor renderer (version)0' + len = strlen(vendor) + 1 + strlen(renderer) + 1 + 1+strlen(version)+1 + 1; + pAdapterId = malloc(len); + if (pAdapterId != NULL) { + + jio_snprintf(pAdapterId, len, "%s %s (%s)", vendor, renderer, version); + + J2dTraceLn1(J2D_TRACE_VERBOSE, " id=%s", pAdapterId); + + ret = JNU_NewStringPlatform(env, pAdapterId); + + free(pAdapterId); + } + + return ret; +} + #endif /* !HEADLESS */ diff --git a/src/share/native/sun/java2d/opengl/OGLContext.h b/src/share/native/sun/java2d/opengl/OGLContext.h index 0e0236f1d..d8605a7a0 100644 --- a/src/share/native/sun/java2d/opengl/OGLContext.h +++ b/src/share/native/sun/java2d/opengl/OGLContext.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2004-2008 Sun Microsystems Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ #include "sun_java2d_pipe_BufferedContext.h" #include "sun_java2d_opengl_OGLContext.h" +#include "sun_java2d_opengl_OGLContext_OGLContextCaps.h" #include "j2d_md.h" #include "J2D_GL/gl.h" @@ -96,13 +97,50 @@ typedef struct { sun_java2d_pipe_BufferedContext_USE_MASK /** + * See OGLContext.java for more on these flags. + */ +#define CAPS_EMPTY \ + sun_java2d_opengl_OGLContext_OGLContextCaps_CAPS_EMPTY +#define CAPS_RT_PLAIN_ALPHA \ + sun_java2d_opengl_OGLContext_OGLContextCaps_CAPS_RT_PLAIN_ALPHA +#define CAPS_RT_TEXTURE_ALPHA \ + sun_java2d_opengl_OGLContext_OGLContextCaps_CAPS_RT_TEXTURE_ALPHA +#define CAPS_RT_TEXTURE_OPAQUE \ + sun_java2d_opengl_OGLContext_OGLContextCaps_CAPS_RT_TEXTURE_OPAQUE +#define CAPS_MULTITEXTURE \ + sun_java2d_opengl_OGLContext_OGLContextCaps_CAPS_MULTITEXTURE +#define CAPS_TEXNONPOW2 \ + sun_java2d_opengl_OGLContext_OGLContextCaps_CAPS_TEXNONPOW2 +#define CAPS_TEXNONSQUARE \ + sun_java2d_opengl_OGLContext_OGLContextCaps_CAPS_TEXNONSQUARE +#define CAPS_PS20 \ + sun_java2d_opengl_OGLContext_OGLContextCaps_CAPS_PS20 +#define CAPS_PS30 \ + sun_java2d_opengl_OGLContext_OGLContextCaps_CAPS_PS30 +#define LAST_SHARED_CAP \ + sun_java2d_opengl_OGLContext_OGLContextCaps_LAST_SHARED_CAP +#define CAPS_EXT_FBOBJECT \ + sun_java2d_opengl_OGLContext_OGLContextCaps_CAPS_EXT_FBOBJECT +#define CAPS_STORED_ALPHA \ + sun_java2d_opengl_OGLContext_OGLContextCaps_CAPS_STORED_ALPHA +#define CAPS_DOUBLEBUFFERED \ + sun_java2d_opengl_OGLContext_OGLContextCaps_CAPS_DOUBLEBUFFERED +#define CAPS_EXT_LCD_SHADER \ + sun_java2d_opengl_OGLContext_OGLContextCaps_CAPS_EXT_LCD_SHADER +#define CAPS_EXT_BIOP_SHADER \ + sun_java2d_opengl_OGLContext_OGLContextCaps_CAPS_EXT_BIOP_SHADER +#define CAPS_EXT_GRAD_SHADER \ + sun_java2d_opengl_OGLContext_OGLContextCaps_CAPS_EXT_GRAD_SHADER +#define CAPS_EXT_TEXRECT \ + sun_java2d_opengl_OGLContext_OGLContextCaps_CAPS_EXT_TEXRECT + +/** * Evaluates to true if the given capability bitmask is present for the * given OGLContext. Note that only the constant name needs to be passed as * a parameter, as this macro will automatically prepend the full package * and class name to the constant name. */ -#define OGLC_IS_CAP_PRESENT(oglc, cap) \ - (((oglc)->caps & (sun_java2d_opengl_OGLContext_##cap)) != 0) +#define OGLC_IS_CAP_PRESENT(oglc, cap) (((oglc)->caps & (cap)) != 0) /** * At startup we will embed one of the following values in the caps field diff --git a/src/share/native/sun/java2d/opengl/OGLFuncs.h b/src/share/native/sun/java2d/opengl/OGLFuncs.h index 3d22a0c5c..e902da8c6 100644 --- a/src/share/native/sun/java2d/opengl/OGLFuncs.h +++ b/src/share/native/sun/java2d/opengl/OGLFuncs.h @@ -1,5 +1,5 @@ /* - * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2008 Sun Microsystems Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -91,8 +91,12 @@ typedef void (GLAPIENTRY *glPixelStoreiType)(GLenum pname, GLint param); typedef void (GLAPIENTRY *glPixelTransferfType)(GLenum pname, GLfloat param); typedef void (GLAPIENTRY *glPixelZoomType)(GLfloat xfactor, GLfloat yfactor); typedef void (GLAPIENTRY *glPolygonOffsetType)(GLfloat factor, GLfloat units); +typedef void (GLAPIENTRY *glPopAttribType)(void); +typedef void (GLAPIENTRY *glPopClientAttribType)(void); typedef void (GLAPIENTRY *glPopMatrixType)(void); typedef void (GLAPIENTRY *glPrioritizeTexturesType)(GLsizei n, const GLuint *textures, const GLclampf *priorities); +typedef void (GLAPIENTRY *glPushAttribType)(GLbitfield); +typedef void (GLAPIENTRY *glPushClientAttribType)(GLbitfield); typedef void (GLAPIENTRY *glPushMatrixType)(void); typedef void (GLAPIENTRY *glRasterPos2iType)(GLint x, GLint y); typedef void (GLAPIENTRY *glReadBufferType)(GLenum mode); @@ -155,8 +159,10 @@ typedef void (GLAPIENTRY *glUniform2fARBType)(GLint, GLfloat, GLfloat); typedef void (GLAPIENTRY *glUniform3fARBType)(GLint, GLfloat, GLfloat, GLfloat); typedef void (GLAPIENTRY *glUniform3fvARBType)(GLint, GLsizei, const GLfloat *); typedef void (GLAPIENTRY *glUniform4fARBType)(GLint, GLfloat, GLfloat, GLfloat, GLfloat); +typedef void (GLAPIENTRY *glUniform4fvARBType)(GLint, GLsizei, const GLfloat *); typedef GLint (GLAPIENTRY *glGetUniformLocationARBType)(GLhandleARB, const GLcharARB *); typedef void (GLAPIENTRY *glGetInfoLogARBType)(GLhandleARB, GLsizei, GLsizei *, GLcharARB *); +typedef void (GLAPIENTRY *glGetProgramivARBType)(GLenum, GLenum, GLint *); typedef void (GLAPIENTRY *glGetObjectParameterivARBType)(GLhandleARB, GLenum, GLint *); typedef GLhandleARB (GLAPIENTRY *glCreateProgramObjectARBType)(void); typedef void (GLAPIENTRY *glAttachObjectARBType)(GLhandleARB, GLhandleARB); @@ -243,8 +249,12 @@ typedef void (GLAPIENTRY *glDeleteObjectARBType)(GLhandleARB); OGL_##action##_FUNC(glPixelTransferf); \ OGL_##action##_FUNC(glPixelZoom); \ OGL_##action##_FUNC(glPolygonOffset); \ + OGL_##action##_FUNC(glPopAttrib); \ + OGL_##action##_FUNC(glPopClientAttrib); \ OGL_##action##_FUNC(glPopMatrix); \ OGL_##action##_FUNC(glPrioritizeTextures); \ + OGL_##action##_FUNC(glPushAttrib); \ + OGL_##action##_FUNC(glPushClientAttrib); \ OGL_##action##_FUNC(glPushMatrix); \ OGL_##action##_FUNC(glRasterPos2i); \ OGL_##action##_FUNC(glReadBuffer); \ @@ -298,7 +308,9 @@ typedef void (GLAPIENTRY *glDeleteObjectARBType)(GLhandleARB); OGL_##action##_EXT_FUNC(glUniform3fARB); \ OGL_##action##_EXT_FUNC(glUniform3fvARB); \ OGL_##action##_EXT_FUNC(glUniform4fARB); \ + OGL_##action##_EXT_FUNC(glUniform4fvARB); \ OGL_##action##_EXT_FUNC(glGetUniformLocationARB); \ + OGL_##action##_EXT_FUNC(glGetProgramivARB); \ OGL_##action##_EXT_FUNC(glGetInfoLogARB); \ OGL_##action##_EXT_FUNC(glGetObjectParameterivARB); \ OGL_##action##_EXT_FUNC(glDeleteObjectARB); diff --git a/src/share/native/sun/java2d/opengl/OGLRenderQueue.c b/src/share/native/sun/java2d/opengl/OGLRenderQueue.c index 0ded24d51..2143e0c9a 100644 --- a/src/share/native/sun/java2d/opengl/OGLRenderQueue.c +++ b/src/share/native/sun/java2d/opengl/OGLRenderQueue.c @@ -1,5 +1,5 @@ /* - * Copyright 2005-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-2008 Sun Microsystems Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -88,8 +88,9 @@ Java_sun_java2d_opengl_OGLRenderQueue_flushBuffer while (b < end) { jint opcode = NEXT_INT(b); - J2dTraceLn1(J2D_TRACE_VERBOSE, - "OGLRenderQueue_flushBuffer: opcode=%d", opcode); + J2dTraceLn2(J2D_TRACE_VERBOSE, + "OGLRenderQueue_flushBuffer: opcode=%d, rem=%d", + opcode, (end-b)); switch (opcode) { @@ -148,6 +149,40 @@ Java_sun_java2d_opengl_OGLRenderQueue_flushBuffer SKIP_BYTES(b, count * BYTES_PER_SCANLINE); } break; + case sun_java2d_pipe_BufferedOpCodes_DRAW_PARALLELOGRAM: + { + jfloat x11 = NEXT_FLOAT(b); + jfloat y11 = NEXT_FLOAT(b); + jfloat dx21 = NEXT_FLOAT(b); + jfloat dy21 = NEXT_FLOAT(b); + jfloat dx12 = NEXT_FLOAT(b); + jfloat dy12 = NEXT_FLOAT(b); + jfloat lwr21 = NEXT_FLOAT(b); + jfloat lwr12 = NEXT_FLOAT(b); + OGLRenderer_DrawParallelogram(oglc, + x11, y11, + dx21, dy21, + dx12, dy12, + lwr21, lwr12); + } + break; + case sun_java2d_pipe_BufferedOpCodes_DRAW_AAPARALLELOGRAM: + { + jfloat x11 = NEXT_FLOAT(b); + jfloat y11 = NEXT_FLOAT(b); + jfloat dx21 = NEXT_FLOAT(b); + jfloat dy21 = NEXT_FLOAT(b); + jfloat dx12 = NEXT_FLOAT(b); + jfloat dy12 = NEXT_FLOAT(b); + jfloat lwr21 = NEXT_FLOAT(b); + jfloat lwr12 = NEXT_FLOAT(b); + OGLRenderer_DrawAAParallelogram(oglc, dstOps, + x11, y11, + dx21, dy21, + dx12, dy12, + lwr21, lwr12); + } + break; // fill ops case sun_java2d_pipe_BufferedOpCodes_FILL_RECT: @@ -166,6 +201,34 @@ Java_sun_java2d_opengl_OGLRenderQueue_flushBuffer SKIP_BYTES(b, count * BYTES_PER_SPAN); } break; + case sun_java2d_pipe_BufferedOpCodes_FILL_PARALLELOGRAM: + { + jfloat x11 = NEXT_FLOAT(b); + jfloat y11 = NEXT_FLOAT(b); + jfloat dx21 = NEXT_FLOAT(b); + jfloat dy21 = NEXT_FLOAT(b); + jfloat dx12 = NEXT_FLOAT(b); + jfloat dy12 = NEXT_FLOAT(b); + OGLRenderer_FillParallelogram(oglc, + x11, y11, + dx21, dy21, + dx12, dy12); + } + break; + case sun_java2d_pipe_BufferedOpCodes_FILL_AAPARALLELOGRAM: + { + jfloat x11 = NEXT_FLOAT(b); + jfloat y11 = NEXT_FLOAT(b); + jfloat dx21 = NEXT_FLOAT(b); + jfloat dy21 = NEXT_FLOAT(b); + jfloat dx12 = NEXT_FLOAT(b); + jfloat dy12 = NEXT_FLOAT(b); + OGLRenderer_FillAAParallelogram(oglc, dstOps, + x11, y11, + dx21, dy21, + dx12, dy12); + } + break; // text-related ops case sun_java2d_pipe_BufferedOpCodes_DRAW_GLYPH_LIST: @@ -438,6 +501,31 @@ Java_sun_java2d_opengl_OGLRenderQueue_flushBuffer dstOps = NULL; } break; + case sun_java2d_pipe_BufferedOpCodes_SAVE_STATE: + { + j2d_glPushAttrib(GL_ALL_ATTRIB_BITS); + j2d_glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS); + j2d_glMatrixMode(GL_MODELVIEW); + j2d_glPushMatrix(); + j2d_glMatrixMode(GL_PROJECTION); + j2d_glPushMatrix(); + j2d_glMatrixMode(GL_TEXTURE); + j2d_glPushMatrix(); + } + break; + + case sun_java2d_pipe_BufferedOpCodes_RESTORE_STATE: + { + j2d_glPopAttrib(); + j2d_glPopClientAttrib(); + j2d_glMatrixMode(GL_MODELVIEW); + j2d_glPopMatrix(); + j2d_glMatrixMode(GL_PROJECTION); + j2d_glPopMatrix(); + j2d_glMatrixMode(GL_TEXTURE); + j2d_glPopMatrix(); + } + break; case sun_java2d_pipe_BufferedOpCodes_SYNC: { sync = JNI_TRUE; @@ -691,6 +779,9 @@ OGLRenderQueue_CheckPreviousOp(jint op) return; } + J2dTraceLn1(J2D_TRACE_VERBOSE, + "OGLRenderQueue_CheckPreviousOp: new op=%d", op); + switch (previousOp) { case GL_TEXTURE_2D: case GL_TEXTURE_RECTANGLE_ARB: @@ -718,6 +809,9 @@ OGLRenderQueue_CheckPreviousOp(jint op) case OGL_STATE_GLYPH_OP: OGLTR_DisableGlyphVertexCache(oglc); break; + case OGL_STATE_PGRAM_OP: + OGLRenderer_DisableAAParallelogramProgram(); + break; case OGL_STATE_RESET: case OGL_STATE_CHANGE: // No-op @@ -745,6 +839,9 @@ OGLRenderQueue_CheckPreviousOp(jint op) case OGL_STATE_GLYPH_OP: OGLTR_EnableGlyphVertexCache(oglc); break; + case OGL_STATE_PGRAM_OP: + OGLRenderer_EnableAAParallelogramProgram(); + break; case OGL_STATE_RESET: case OGL_STATE_CHANGE: // No-op diff --git a/src/share/native/sun/java2d/opengl/OGLRenderQueue.h b/src/share/native/sun/java2d/opengl/OGLRenderQueue.h index e70d74015..743ee7216 100644 --- a/src/share/native/sun/java2d/opengl/OGLRenderQueue.h +++ b/src/share/native/sun/java2d/opengl/OGLRenderQueue.h @@ -1,5 +1,5 @@ /* - * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-2008 Sun Microsystems Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -90,6 +90,13 @@ #define OGL_STATE_GLYPH_OP -4 /* + * Parameter passed to the CHECK_PREVIOUS_OP() macro to indicate that the + * following operation represents an operation that renders a + * parallelogram via a fragment program (see OGLRenderer). + */ +#define OGL_STATE_PGRAM_OP -5 + +/* * Initializes the "previous operation" state to its default value. */ #define INIT_PREVIOUS_OP() previousOp = OGL_STATE_RESET diff --git a/src/share/native/sun/java2d/opengl/OGLRenderer.c b/src/share/native/sun/java2d/opengl/OGLRenderer.c index 93b1a6e65..a070ba513 100644 --- a/src/share/native/sun/java2d/opengl/OGLRenderer.c +++ b/src/share/native/sun/java2d/opengl/OGLRenderer.c @@ -1,5 +1,5 @@ /* - * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2008 Sun Microsystems Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ #include <jlong.h> #include <jni_util.h> +#include <math.h> #include "sun_java2d_opengl_OGLRenderer.h" @@ -326,4 +327,486 @@ OGLRenderer_FillSpans(OGLContext *oglc, jint spanCount, jint *spans) } } +#define FILL_PGRAM(fx11, fy11, dx21, dy21, dx12, dy12) \ + do { \ + j2d_glVertex2f(fx11, fy11); \ + j2d_glVertex2f(fx11 + dx21, fy11 + dy21); \ + j2d_glVertex2f(fx11 + dx21 + dx12, fy11 + dy21 + dy12); \ + j2d_glVertex2f(fx11 + dx12, fy11 + dy12); \ + } while (0) + +void +OGLRenderer_FillParallelogram(OGLContext *oglc, + jfloat fx11, jfloat fy11, + jfloat dx21, jfloat dy21, + jfloat dx12, jfloat dy12) +{ + J2dTraceLn6(J2D_TRACE_INFO, + "OGLRenderer_FillParallelogram " + "(x=%6.2f y=%6.2f " + "dx1=%6.2f dy1=%6.2f " + "dx2=%6.2f dy2=%6.2f)", + fx11, fy11, + dx21, dy21, + dx12, dy12); + + RETURN_IF_NULL(oglc); + + CHECK_PREVIOUS_OP(GL_QUADS); + + FILL_PGRAM(fx11, fy11, dx21, dy21, dx12, dy12); +} + +void +OGLRenderer_DrawParallelogram(OGLContext *oglc, + jfloat fx11, jfloat fy11, + jfloat dx21, jfloat dy21, + jfloat dx12, jfloat dy12, + jfloat lwr21, jfloat lwr12) +{ + // dx,dy for line width in the "21" and "12" directions. + jfloat ldx21 = dx21 * lwr21; + jfloat ldy21 = dy21 * lwr21; + jfloat ldx12 = dx12 * lwr12; + jfloat ldy12 = dy12 * lwr12; + + // calculate origin of the outer parallelogram + jfloat ox11 = fx11 - (ldx21 + ldx12) / 2.0f; + jfloat oy11 = fy11 - (ldy21 + ldy12) / 2.0f; + + J2dTraceLn8(J2D_TRACE_INFO, + "OGLRenderer_DrawParallelogram " + "(x=%6.2f y=%6.2f " + "dx1=%6.2f dy1=%6.2f lwr1=%6.2f " + "dx2=%6.2f dy2=%6.2f lwr2=%6.2f)", + fx11, fy11, + dx21, dy21, lwr21, + dx12, dy12, lwr12); + + RETURN_IF_NULL(oglc); + + CHECK_PREVIOUS_OP(GL_QUADS); + + // Only need to generate 4 quads if the interior still + // has a hole in it (i.e. if the line width ratio was + // less than 1.0) + if (lwr21 < 1.0f && lwr12 < 1.0f) { + // Note: "TOP", "BOTTOM", "LEFT" and "RIGHT" here are + // relative to whether the dxNN variables are positive + // and negative. The math works fine regardless of + // their signs, but for conceptual simplicity the + // comments will refer to the sides as if the dxNN + // were all positive. "TOP" and "BOTTOM" segments + // are defined by the dxy21 deltas. "LEFT" and "RIGHT" + // segments are defined by the dxy12 deltas. + + // Each segment includes its starting corner and comes + // to just short of the following corner. Thus, each + // corner is included just once and the only lengths + // needed are the original parallelogram delta lengths + // and the "line width deltas". The sides will cover + // the following relative territories: + // + // T T T T T R + // L R + // L R + // L R + // L R + // L B B B B B + + // TOP segment, to left side of RIGHT edge + // "width" of original pgram, "height" of hor. line size + fx11 = ox11; + fy11 = oy11; + FILL_PGRAM(fx11, fy11, dx21, dy21, ldx12, ldy12); + + // RIGHT segment, to top of BOTTOM edge + // "width" of vert. line size , "height" of original pgram + fx11 = ox11 + dx21; + fy11 = oy11 + dy21; + FILL_PGRAM(fx11, fy11, ldx21, ldy21, dx12, dy12); + + // BOTTOM segment, from right side of LEFT edge + // "width" of original pgram, "height" of hor. line size + fx11 = ox11 + dx12 + ldx21; + fy11 = oy11 + dy12 + ldy21; + FILL_PGRAM(fx11, fy11, dx21, dy21, ldx12, ldy12); + + // LEFT segment, from bottom of TOP edge + // "width" of vert. line size , "height" of inner pgram + fx11 = ox11 + ldx12; + fy11 = oy11 + ldy12; + FILL_PGRAM(fx11, fy11, ldx21, ldy21, dx12, dy12); + } else { + // The line width ratios were large enough to consume + // the entire hole in the middle of the parallelogram + // so we can just issue one large quad for the outer + // parallelogram. + dx21 += ldx21; + dy21 += ldy21; + dx12 += ldx12; + dy12 += ldy12; + FILL_PGRAM(ox11, oy11, dx21, dy21, dx12, dy12); + } +} + +static GLhandleARB aaPgramProgram = 0; + +/* + * This shader fills the space between an outer and inner parallelogram. + * It can be used to draw an outline by specifying both inner and outer + * values. It fills pixels by estimating what portion falls inside the + * outer shape, and subtracting an estimate of what portion falls inside + * the inner shape. Specifying both inner and outer values produces a + * standard "wide outline". Specifying an inner shape that falls far + * outside the outer shape allows the same shader to fill the outer + * shape entirely since pixels that fall within the outer shape are never + * inside the inner shape and so they are filled based solely on their + * coverage of the outer shape. + * + * The setup code renders this shader over the bounds of the outer + * shape (or the only shape in the case of a fill operation) and + * sets the texture 0 coordinates so that 0,0=>0,1=>1,1=>1,0 in those + * texture coordinates map to the four corners of the parallelogram. + * Similarly the texture 1 coordinates map the inner shape to the + * unit square as well, but in a different coordinate system. + * + * When viewed in the texture coordinate systems the parallelograms + * we are filling are unit squares, but the pixels have then become + * tiny parallelograms themselves. Both of the texture coordinate + * systems are affine transforms so the rate of change in X and Y + * of the texture coordinates are essentially constants and happen + * to correspond to the size and direction of the slanted sides of + * the distorted pixels relative to the "square mapped" boundary + * of the parallelograms. + * + * The shader uses the dFdx() and dFdy() functions to measure the "rate + * of change" of these texture coordinates and thus gets an accurate + * measure of the size and shape of a pixel relative to the two + * parallelograms. It then uses the bounds of the size and shape + * of a pixel to intersect with the unit square to estimate the + * coverage of the pixel. Unfortunately, without a lot more work + * to calculate the exact area of intersection between a unit + * square (the original parallelogram) and a parallelogram (the + * distorted pixel), this shader only approximates the pixel + * coverage, but emperically the estimate is very useful and + * produces visually pleasing results, if not theoretically accurate. + */ +static const char *aaPgramShaderSource = + "void main() {" + // Calculate the vectors for the "legs" of the pixel parallelogram + // for the outer parallelogram. + " vec2 oleg1 = dFdx(gl_TexCoord[0].st);" + " vec2 oleg2 = dFdy(gl_TexCoord[0].st);" + // Calculate the bounds of the distorted pixel parallelogram. + " vec2 corner = gl_TexCoord[0].st - (oleg1+oleg2)/2.0;" + " vec2 omin = min(corner, corner+oleg1);" + " omin = min(omin, corner+oleg2);" + " omin = min(omin, corner+oleg1+oleg2);" + " vec2 omax = max(corner, corner+oleg1);" + " omax = max(omax, corner+oleg2);" + " omax = max(omax, corner+oleg1+oleg2);" + // Calculate the vectors for the "legs" of the pixel parallelogram + // for the inner parallelogram. + " vec2 ileg1 = dFdx(gl_TexCoord[1].st);" + " vec2 ileg2 = dFdy(gl_TexCoord[1].st);" + // Calculate the bounds of the distorted pixel parallelogram. + " corner = gl_TexCoord[1].st - (ileg1+ileg2)/2.0;" + " vec2 imin = min(corner, corner+ileg1);" + " imin = min(imin, corner+ileg2);" + " imin = min(imin, corner+ileg1+ileg2);" + " vec2 imax = max(corner, corner+ileg1);" + " imax = max(imax, corner+ileg2);" + " imax = max(imax, corner+ileg1+ileg2);" + // Clamp the bounds of the parallelograms to the unit square to + // estimate the intersection of the pixel parallelogram with + // the unit square. The ratio of the 2 rectangle areas is a + // reasonable estimate of the proportion of coverage. + " vec2 o1 = clamp(omin, 0.0, 1.0);" + " vec2 o2 = clamp(omax, 0.0, 1.0);" + " float oint = (o2.y-o1.y)*(o2.x-o1.x);" + " float oarea = (omax.y-omin.y)*(omax.x-omin.x);" + " vec2 i1 = clamp(imin, 0.0, 1.0);" + " vec2 i2 = clamp(imax, 0.0, 1.0);" + " float iint = (i2.y-i1.y)*(i2.x-i1.x);" + " float iarea = (imax.y-imin.y)*(imax.x-imin.x);" + // Proportion of pixel in outer shape minus the proportion + // of pixel in the inner shape == the coverage of the pixel + // in the area between the two. + " float coverage = oint/oarea - iint / iarea;" + " gl_FragColor = gl_Color * coverage;" + "}"; + +#define ADJUST_PGRAM(V1, DV, V2) \ + do { \ + if ((DV) >= 0) { \ + (V2) += (DV); \ + } else { \ + (V1) += (DV); \ + } \ + } while (0) + +// Invert the following transform: +// DeltaT(0, 0) == (0, 0) +// DeltaT(1, 0) == (DX1, DY1) +// DeltaT(0, 1) == (DX2, DY2) +// DeltaT(1, 1) == (DX1+DX2, DY1+DY2) +// TM00 = DX1, TM01 = DX2, (TM02 = X11) +// TM10 = DY1, TM11 = DY2, (TM12 = Y11) +// Determinant = TM00*TM11 - TM01*TM10 +// = DX1*DY2 - DX2*DY1 +// Inverse is: +// IM00 = TM11/det, IM01 = -TM01/det +// IM10 = -TM10/det, IM11 = TM00/det +// IM02 = (TM01 * TM12 - TM11 * TM02) / det, +// IM12 = (TM10 * TM02 - TM00 * TM12) / det, + +#define DECLARE_MATRIX(MAT) \ + jfloat MAT ## 00, MAT ## 01, MAT ## 02, MAT ## 10, MAT ## 11, MAT ## 12 + +#define GET_INVERTED_MATRIX(MAT, X11, Y11, DX1, DY1, DX2, DY2, RET_CODE) \ + do { \ + jfloat det = DX1*DY2 - DX2*DY1; \ + if (det == 0) { \ + RET_CODE; \ + } \ + MAT ## 00 = DY2/det; \ + MAT ## 01 = -DX2/det; \ + MAT ## 10 = -DY1/det; \ + MAT ## 11 = DX1/det; \ + MAT ## 02 = (DX2 * Y11 - DY2 * X11) / det; \ + MAT ## 12 = (DY1 * X11 - DX1 * Y11) / det; \ + } while (0) + +#define TRANSFORM(MAT, TX, TY, X, Y) \ + do { \ + TX = (X) * MAT ## 00 + (Y) * MAT ## 01 + MAT ## 02; \ + TY = (X) * MAT ## 10 + (Y) * MAT ## 11 + MAT ## 12; \ + } while (0) + +void +OGLRenderer_FillAAParallelogram(OGLContext *oglc, OGLSDOps *dstOps, + jfloat fx11, jfloat fy11, + jfloat dx21, jfloat dy21, + jfloat dx12, jfloat dy12) +{ + DECLARE_MATRIX(om); + // parameters for parallelogram bounding box + jfloat bx11, by11, bx22, by22; + // parameters for uv texture coordinates of parallelogram corners + jfloat u11, v11, u12, v12, u21, v21, u22, v22; + + J2dTraceLn6(J2D_TRACE_INFO, + "OGLRenderer_FillAAParallelogram " + "(x=%6.2f y=%6.2f " + "dx1=%6.2f dy1=%6.2f " + "dx2=%6.2f dy2=%6.2f)", + fx11, fy11, + dx21, dy21, + dx12, dy12); + + RETURN_IF_NULL(oglc); + RETURN_IF_NULL(dstOps); + + GET_INVERTED_MATRIX(om, fx11, fy11, dx21, dy21, dx12, dy12, + return); + + CHECK_PREVIOUS_OP(OGL_STATE_PGRAM_OP); + + bx11 = bx22 = fx11; + by11 = by22 = fy11; + ADJUST_PGRAM(bx11, dx21, bx22); + ADJUST_PGRAM(by11, dy21, by22); + ADJUST_PGRAM(bx11, dx12, bx22); + ADJUST_PGRAM(by11, dy12, by22); + bx11 = (jfloat) floor(bx11); + by11 = (jfloat) floor(by11); + bx22 = (jfloat) ceil(bx22); + by22 = (jfloat) ceil(by22); + + TRANSFORM(om, u11, v11, bx11, by11); + TRANSFORM(om, u21, v21, bx22, by11); + TRANSFORM(om, u12, v12, bx11, by22); + TRANSFORM(om, u22, v22, bx22, by22); + + j2d_glBegin(GL_QUADS); + j2d_glMultiTexCoord2fARB(GL_TEXTURE0_ARB, u11, v11); + j2d_glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 5.f, 5.f); + j2d_glVertex2f(bx11, by11); + j2d_glMultiTexCoord2fARB(GL_TEXTURE0_ARB, u21, v21); + j2d_glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 6.f, 5.f); + j2d_glVertex2f(bx22, by11); + j2d_glMultiTexCoord2fARB(GL_TEXTURE0_ARB, u22, v22); + j2d_glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 6.f, 6.f); + j2d_glVertex2f(bx22, by22); + j2d_glMultiTexCoord2fARB(GL_TEXTURE0_ARB, u12, v12); + j2d_glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 5.f, 6.f); + j2d_glVertex2f(bx11, by22); + j2d_glEnd(); +} + +void +OGLRenderer_FillAAParallelogramInnerOuter(OGLContext *oglc, OGLSDOps *dstOps, + jfloat ox11, jfloat oy11, + jfloat ox21, jfloat oy21, + jfloat ox12, jfloat oy12, + jfloat ix11, jfloat iy11, + jfloat ix21, jfloat iy21, + jfloat ix12, jfloat iy12) +{ + DECLARE_MATRIX(om); + DECLARE_MATRIX(im); + // parameters for parallelogram bounding box + jfloat bx11, by11, bx22, by22; + // parameters for uv texture coordinates of outer parallelogram corners + jfloat ou11, ov11, ou12, ov12, ou21, ov21, ou22, ov22; + // parameters for uv texture coordinates of inner parallelogram corners + jfloat iu11, iv11, iu12, iv12, iu21, iv21, iu22, iv22; + + RETURN_IF_NULL(oglc); + RETURN_IF_NULL(dstOps); + + GET_INVERTED_MATRIX(im, ix11, iy11, ix21, iy21, ix12, iy12, + // inner parallelogram is degenerate + // therefore it encloses no area + // fill outer + OGLRenderer_FillAAParallelogram(oglc, dstOps, + ox11, oy11, + ox21, oy21, + ox12, oy12); + return); + GET_INVERTED_MATRIX(om, ox11, oy11, ox21, oy21, ox12, oy12, + return); + + CHECK_PREVIOUS_OP(OGL_STATE_PGRAM_OP); + + bx11 = bx22 = ox11; + by11 = by22 = oy11; + ADJUST_PGRAM(bx11, ox21, bx22); + ADJUST_PGRAM(by11, oy21, by22); + ADJUST_PGRAM(bx11, ox12, bx22); + ADJUST_PGRAM(by11, oy12, by22); + bx11 = (jfloat) floor(bx11); + by11 = (jfloat) floor(by11); + bx22 = (jfloat) ceil(bx22); + by22 = (jfloat) ceil(by22); + + TRANSFORM(om, ou11, ov11, bx11, by11); + TRANSFORM(om, ou21, ov21, bx22, by11); + TRANSFORM(om, ou12, ov12, bx11, by22); + TRANSFORM(om, ou22, ov22, bx22, by22); + + TRANSFORM(im, iu11, iv11, bx11, by11); + TRANSFORM(im, iu21, iv21, bx22, by11); + TRANSFORM(im, iu12, iv12, bx11, by22); + TRANSFORM(im, iu22, iv22, bx22, by22); + + j2d_glBegin(GL_QUADS); + j2d_glMultiTexCoord2fARB(GL_TEXTURE0_ARB, ou11, ov11); + j2d_glMultiTexCoord2fARB(GL_TEXTURE1_ARB, iu11, iv11); + j2d_glVertex2f(bx11, by11); + j2d_glMultiTexCoord2fARB(GL_TEXTURE0_ARB, ou21, ov21); + j2d_glMultiTexCoord2fARB(GL_TEXTURE1_ARB, iu21, iv21); + j2d_glVertex2f(bx22, by11); + j2d_glMultiTexCoord2fARB(GL_TEXTURE0_ARB, ou22, ov22); + j2d_glMultiTexCoord2fARB(GL_TEXTURE1_ARB, iu22, iv22); + j2d_glVertex2f(bx22, by22); + j2d_glMultiTexCoord2fARB(GL_TEXTURE0_ARB, ou12, ov12); + j2d_glMultiTexCoord2fARB(GL_TEXTURE1_ARB, iu12, iv12); + j2d_glVertex2f(bx11, by22); + j2d_glEnd(); +} + +void +OGLRenderer_DrawAAParallelogram(OGLContext *oglc, OGLSDOps *dstOps, + jfloat fx11, jfloat fy11, + jfloat dx21, jfloat dy21, + jfloat dx12, jfloat dy12, + jfloat lwr21, jfloat lwr12) +{ + // dx,dy for line width in the "21" and "12" directions. + jfloat ldx21, ldy21, ldx12, ldy12; + // parameters for "outer" parallelogram + jfloat ofx11, ofy11, odx21, ody21, odx12, ody12; + // parameters for "inner" parallelogram + jfloat ifx11, ify11, idx21, idy21, idx12, idy12; + + J2dTraceLn8(J2D_TRACE_INFO, + "OGLRenderer_DrawAAParallelogram " + "(x=%6.2f y=%6.2f " + "dx1=%6.2f dy1=%6.2f lwr1=%6.2f " + "dx2=%6.2f dy2=%6.2f lwr2=%6.2f)", + fx11, fy11, + dx21, dy21, lwr21, + dx12, dy12, lwr12); + + RETURN_IF_NULL(oglc); + RETURN_IF_NULL(dstOps); + + // calculate true dx,dy for line widths from the "line width ratios" + ldx21 = dx21 * lwr21; + ldy21 = dy21 * lwr21; + ldx12 = dx12 * lwr12; + ldy12 = dy12 * lwr12; + + // calculate coordinates of the outer parallelogram + ofx11 = fx11 - (ldx21 + ldx12) / 2.0f; + ofy11 = fy11 - (ldy21 + ldy12) / 2.0f; + odx21 = dx21 + ldx21; + ody21 = dy21 + ldy21; + odx12 = dx12 + ldx12; + ody12 = dy12 + ldy12; + + // Only process the inner parallelogram if the line width ratio + // did not consume the entire interior of the parallelogram + // (i.e. if the width ratio was less than 1.0) + if (lwr21 < 1.0f && lwr12 < 1.0f) { + // calculate coordinates of the inner parallelogram + ifx11 = fx11 + (ldx21 + ldx12) / 2.0f; + ify11 = fy11 + (ldy21 + ldy12) / 2.0f; + idx21 = dx21 - ldx21; + idy21 = dy21 - ldy21; + idx12 = dx12 - ldx12; + idy12 = dy12 - ldy12; + + OGLRenderer_FillAAParallelogramInnerOuter(oglc, dstOps, + ofx11, ofy11, + odx21, ody21, + odx12, ody12, + ifx11, ify11, + idx21, idy21, + idx12, idy12); + } else { + OGLRenderer_FillAAParallelogram(oglc, dstOps, + ofx11, ofy11, + odx21, ody21, + odx12, ody12); + } +} + +void +OGLRenderer_EnableAAParallelogramProgram() +{ + J2dTraceLn(J2D_TRACE_INFO, "OGLRenderer_EnableAAParallelogramProgram"); + + if (aaPgramProgram == 0) { + aaPgramProgram = OGLContext_CreateFragmentProgram(aaPgramShaderSource); + if (aaPgramProgram == 0) { + J2dRlsTraceLn(J2D_TRACE_ERROR, + "OGLRenderer_EnableAAParallelogramProgram: " + "error creating program"); + return; + } + } + j2d_glUseProgramObjectARB(aaPgramProgram); +} + +void +OGLRenderer_DisableAAParallelogramProgram() +{ + J2dTraceLn(J2D_TRACE_INFO, "OGLRenderer_DisableAAParallelogramProgram"); + + j2d_glUseProgramObjectARB(0); +} + #endif /* !HEADLESS */ diff --git a/src/share/native/sun/java2d/opengl/OGLRenderer.h b/src/share/native/sun/java2d/opengl/OGLRenderer.h index 6b97ba166..78d8dd0e9 100644 --- a/src/share/native/sun/java2d/opengl/OGLRenderer.h +++ b/src/share/native/sun/java2d/opengl/OGLRenderer.h @@ -1,5 +1,5 @@ /* - * Copyright 2005-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-2008 Sun Microsystems Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,9 +46,31 @@ void OGLRenderer_DrawPoly(OGLContext *oglc, jint *xPoints, jint *yPoints); void OGLRenderer_DrawScanlines(OGLContext *oglc, jint count, jint *scanlines); +void OGLRenderer_DrawParallelogram(OGLContext *oglc, + jfloat fx11, jfloat fy11, + jfloat dx21, jfloat dy21, + jfloat dx12, jfloat dy12, + jfloat lw21, jfloat lw12); +void OGLRenderer_DrawAAParallelogram(OGLContext *oglc, OGLSDOps *dstOps, + jfloat fx11, jfloat fy11, + jfloat dx21, jfloat dy21, + jfloat dx12, jfloat dy12, + jfloat lw21, jfloat lw12); + void OGLRenderer_FillRect(OGLContext *oglc, jint x, jint y, jint w, jint h); void OGLRenderer_FillSpans(OGLContext *oglc, jint count, jint *spans); +void OGLRenderer_FillParallelogram(OGLContext *oglc, + jfloat fx11, jfloat fy11, + jfloat dx21, jfloat dy21, + jfloat dx12, jfloat dy12); +void OGLRenderer_FillAAParallelogram(OGLContext *oglc, OGLSDOps *dstOps, + jfloat fx11, jfloat fy11, + jfloat dx21, jfloat dy21, + jfloat dx12, jfloat dy12); + +void OGLRenderer_EnableAAParallelogramProgram(); +void OGLRenderer_DisableAAParallelogramProgram(); #endif /* OGLRenderer_h_Included */ diff --git a/src/share/native/sun/java2d/opengl/OGLSurfaceData.c b/src/share/native/sun/java2d/opengl/OGLSurfaceData.c index fe9d37ac6..50cbaf3f0 100644 --- a/src/share/native/sun/java2d/opengl/OGLSurfaceData.c +++ b/src/share/native/sun/java2d/opengl/OGLSurfaceData.c @@ -1,5 +1,5 @@ /* - * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2008 Sun Microsystems Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,6 +41,8 @@ extern jlong OGLSD_GetNativeConfigInfo(OGLSDOps *oglsdo); extern jboolean OGLSD_InitOGLWindow(JNIEnv *env, OGLSDOps *oglsdo); extern void OGLSD_DestroyOGLSurface(JNIEnv *env, OGLSDOps *oglsdo); +void OGLSD_SetNativeDimensions(JNIEnv *env, OGLSDOps *oglsdo, jint w, jint h); + /** * This table contains the "pixel formats" for all system memory surfaces * that OpenGL is capable of handling, indexed by the "PF_" constants defined @@ -269,6 +271,9 @@ Java_sun_java2d_opengl_OGLSurfaceData_initTexture return JNI_FALSE; } + OGLSD_SetNativeDimensions(env, oglsdo, + oglsdo->textureWidth, oglsdo->textureHeight); + oglsdo->drawableType = OGLSD_TEXTURE; // other fields (e.g. width, height) are set in OGLSD_InitTextureObject() @@ -427,6 +432,9 @@ Java_sun_java2d_opengl_OGLSurfaceData_initFBObject oglsdo->fbobjectID = fbobjectID; oglsdo->depthID = depthID; + OGLSD_SetNativeDimensions(env, oglsdo, + oglsdo->textureWidth, oglsdo->textureHeight); + // framebuffer objects differ from other OpenGL surfaces in that the // value passed to glRead/DrawBuffer() must be GL_COLOR_ATTACHMENTn_EXT, // rather than GL_FRONT (or GL_BACK) @@ -476,6 +484,8 @@ Java_sun_java2d_opengl_OGLSurfaceData_initFlipBackbuffer // explicitly use BACK_LEFT rather than BACK... oglsdo->activeBuffer = GL_BACK_LEFT; + OGLSD_SetNativeDimensions(env, oglsdo, oglsdo->width, oglsdo->height); + return JNI_TRUE; } @@ -497,6 +507,45 @@ Java_sun_java2d_opengl_OGLSurfaceData_getTextureTarget return (jint)oglsdo->textureTarget; } +JNIEXPORT jint JNICALL +Java_sun_java2d_opengl_OGLSurfaceData_getTextureID + (JNIEnv *env, jobject oglsd, + jlong pData) +{ + OGLSDOps *oglsdo = (OGLSDOps *)jlong_to_ptr(pData); + + J2dTraceLn(J2D_TRACE_INFO, "OGLSurfaceData_getTextureID"); + + if (oglsdo == NULL) { + J2dRlsTraceLn(J2D_TRACE_ERROR, + "OGLSurfaceData_getTextureID: ops are null"); + return 0L; + } + + return (jint)oglsdo->textureID; +} + +/** + * Initializes nativeWidth/Height fields of the surfaceData object with + * passed arguments. + */ +void +OGLSD_SetNativeDimensions(JNIEnv *env, OGLSDOps *oglsdo, + jint width, jint height) +{ + jobject sdObject; + + sdObject = (*env)->NewLocalRef(env, oglsdo->sdOps.sdObject); + if (sdObject == NULL) { + return; + } + + JNU_SetFieldByName(env, NULL, sdObject, "nativeWidth", "I", width); + JNU_SetFieldByName(env, NULL, sdObject, "nativeHeight", "I", height); + + (*env)->DeleteLocalRef(env, sdObject); +} + /** * Disposes of all native resources associated with this surface. */ diff --git a/src/share/native/sun/java2d/opengl/OGLSurfaceData.h b/src/share/native/sun/java2d/opengl/OGLSurfaceData.h index 17205ce06..7d21068bf 100644 --- a/src/share/native/sun/java2d/opengl/OGLSurfaceData.h +++ b/src/share/native/sun/java2d/opengl/OGLSurfaceData.h @@ -1,5 +1,5 @@ /* - * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2008 Sun Microsystems Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ #include "java_awt_image_AffineTransformOp.h" #include "sun_java2d_opengl_OGLSurfaceData.h" +#include "sun_java2d_pipe_hw_AccelSurface.h" #include "J2D_GL/gl.h" #include "SurfaceData.h" @@ -215,12 +216,12 @@ struct _OGLSDOps { * These are shorthand names for the surface type constants defined in * OGLSurfaceData.java. */ -#define OGLSD_UNDEFINED sun_java2d_opengl_OGLSurfaceData_UNDEFINED -#define OGLSD_WINDOW sun_java2d_opengl_OGLSurfaceData_WINDOW -#define OGLSD_PBUFFER sun_java2d_opengl_OGLSurfaceData_PBUFFER -#define OGLSD_TEXTURE sun_java2d_opengl_OGLSurfaceData_TEXTURE -#define OGLSD_FLIP_BACKBUFFER sun_java2d_opengl_OGLSurfaceData_FLIP_BACKBUFFER -#define OGLSD_FBOBJECT sun_java2d_opengl_OGLSurfaceData_FBOBJECT +#define OGLSD_UNDEFINED sun_java2d_pipe_hw_AccelSurface_UNDEFINED +#define OGLSD_WINDOW sun_java2d_pipe_hw_AccelSurface_WINDOW +#define OGLSD_PBUFFER sun_java2d_pipe_hw_AccelSurface_RT_PLAIN +#define OGLSD_TEXTURE sun_java2d_pipe_hw_AccelSurface_TEXTURE +#define OGLSD_FLIP_BACKBUFFER sun_java2d_pipe_hw_AccelSurface_FLIP_BACKBUFFER +#define OGLSD_FBOBJECT sun_java2d_pipe_hw_AccelSurface_RT_TEXTURE /** * These are shorthand names for the filtering method constants used by diff --git a/src/share/native/sun/java2d/pipe/BufferedMaskBlit.c b/src/share/native/sun/java2d/pipe/BufferedMaskBlit.c index 42933cd06..c11172bc6 100644 --- a/src/share/native/sun/java2d/pipe/BufferedMaskBlit.c +++ b/src/share/native/sun/java2d/pipe/BufferedMaskBlit.c @@ -1,5 +1,5 @@ /* - * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,7 +59,6 @@ Java_sun_java2d_pipe_BufferedMaskBlit_enqueueTile { SurfaceDataOps *srcOps = (SurfaceDataOps *)jlong_to_ptr(pSrcOps); SurfaceDataRasInfo srcInfo; - unsigned char *pMask; unsigned char *bbuf; jint *pBuf; @@ -97,13 +96,6 @@ Java_sun_java2d_pipe_BufferedMaskBlit_enqueueTile return bpos; } - pMask = (*env)->GetPrimitiveArrayCritical(env, maskArray, 0); - if (pMask == NULL) { - J2dRlsTraceLn(J2D_TRACE_ERROR, - "BufferedMaskBlit_enqueueTile: cannot lock mask array"); - return bpos; - } - srcInfo.bounds.x1 = srcx; srcInfo.bounds.y1 = srcy; srcInfo.bounds.x2 = srcx + width; @@ -112,8 +104,6 @@ Java_sun_java2d_pipe_BufferedMaskBlit_enqueueTile if (srcOps->Lock(env, srcOps, &srcInfo, SD_LOCK_READ) != SD_SUCCESS) { J2dRlsTraceLn(J2D_TRACE_WARNING, "BufferedMaskBlit_enqueueTile: could not acquire lock"); - (*env)->ReleasePrimitiveArrayCritical(env, maskArray, - pMask, JNI_ABORT); return bpos; } @@ -129,6 +119,15 @@ Java_sun_java2d_pipe_BufferedMaskBlit_enqueueTile PtrCoord(srcInfo.rasBase, srcInfo.bounds.x1, srcInfo.pixelStride, srcInfo.bounds.y1, srcInfo.scanStride); + unsigned char *pMask = + (*env)->GetPrimitiveArrayCritical(env, maskArray, 0); + if (pMask == NULL) { + J2dRlsTraceLn(J2D_TRACE_ERROR, + "BufferedMaskBlit_enqueueTile: cannot lock mask array"); + SurfaceData_InvokeRelease(env, srcOps, &srcInfo); + SurfaceData_InvokeUnlock(env, srcOps, &srcInfo); + return bpos; + } width = srcInfo.bounds.x2 - srcInfo.bounds.x1; height = srcInfo.bounds.y2 - srcInfo.bounds.y1; @@ -166,18 +165,22 @@ Java_sun_java2d_pipe_BufferedMaskBlit_enqueueTile do { jint w = width; do { - jubyte pathA = *pMask++; + jint pathA = *pMask++; if (!pathA) { pBuf[0] = 0; } else { - jint cr, cg, cb, ca; - jubyte r, g, b, a; - LoadIntArgbTo4ByteArgb(pSrc, c, 0, ca, cr, cg, cb); - a = MUL8(ca, pathA); - r = MUL8(cr, a); - g = MUL8(cg, a); - b = MUL8(cb, a); - pBuf[0] = (a << 24) | (r << 16) | (g << 8) | b; + jint pixel = pSrc[0]; + if (pathA == 0xff && (pixel >> 24) + 1 == 0) { + pBuf[0] = pixel; + } else { + jint r, g, b, a; + ExtractIntDcmComponents1234(pixel, a, r, g, b); + a = MUL8(pathA, a); + r = MUL8(a, r); + g = MUL8(a, g); + b = MUL8(a, b); + pBuf[0] = (a << 24) | (r << 16) | (g << 8) | b; + } } pSrc = PtrAddBytes(pSrc, srcPixelStride); pBuf++; @@ -191,17 +194,17 @@ Java_sun_java2d_pipe_BufferedMaskBlit_enqueueTile do { jint w = width; do { - jubyte pathA = *pMask++; + jint pathA = *pMask++; if (!pathA) { pBuf[0] = 0; } else if (pathA == 0xff) { pBuf[0] = pSrc[0]; } else { - jubyte r, g, b, a; - a = MUL8((pSrc[0] >> 24) & 0xff, pathA); - r = MUL8((pSrc[0] >> 16) & 0xff, pathA); - g = MUL8((pSrc[0] >> 8) & 0xff, pathA); - b = MUL8((pSrc[0] >> 0) & 0xff, pathA); + jint r, g, b, a; + a = MUL8(pathA, (pSrc[0] >> 24) & 0xff); + r = MUL8(pathA, (pSrc[0] >> 16) & 0xff); + g = MUL8(pathA, (pSrc[0] >> 8) & 0xff); + b = MUL8(pathA, (pSrc[0] >> 0) & 0xff); pBuf[0] = (a << 24) | (r << 16) | (g << 8) | b; } pSrc = PtrAddBytes(pSrc, srcPixelStride); @@ -216,17 +219,18 @@ Java_sun_java2d_pipe_BufferedMaskBlit_enqueueTile do { jint w = width; do { - jubyte pathA = *pMask++; + jint pathA = *pMask++; if (!pathA) { pBuf[0] = 0; + } else if (pathA == 0xff) { + pBuf[0] = pSrc[0] | 0xff000000; } else { - jint cr, cg, cb; - jubyte r, g, b, a; - LoadIntRgbTo3ByteRgb(pSrc, c, 0, cr, cg, cb); + jint r, g, b, a; + LoadIntRgbTo3ByteRgb(pSrc, c, 0, r, g, b); a = pathA; - r = MUL8(cr, a); - g = MUL8(cg, a); - b = MUL8(cb, a); + r = MUL8(a, r); + g = MUL8(a, g); + b = MUL8(a, b); pBuf[0] = (a << 24) | (r << 16) | (g << 8) | b; } pSrc = PtrAddBytes(pSrc, srcPixelStride); @@ -241,17 +245,16 @@ Java_sun_java2d_pipe_BufferedMaskBlit_enqueueTile do { jint w = width; do { - jubyte pathA = *pMask++; + jint pathA = *pMask++; if (!pathA) { pBuf[0] = 0; } else { - jint cr, cg, cb; - jubyte r, g, b, a; - LoadIntBgrTo3ByteRgb(pSrc, c, 0, cr, cg, cb); + jint r, g, b, a; + LoadIntBgrTo3ByteRgb(pSrc, c, 0, r, g, b); a = pathA; - r = MUL8(cr, a); - g = MUL8(cg, a); - b = MUL8(cb, a); + r = MUL8(a, r); + g = MUL8(a, g); + b = MUL8(a, b); pBuf[0] = (a << 24) | (r << 16) | (g << 8) | b; } pSrc = PtrAddBytes(pSrc, srcPixelStride); @@ -269,14 +272,14 @@ Java_sun_java2d_pipe_BufferedMaskBlit_enqueueTile // increment current byte position bpos += width * height * sizeof(jint); + + (*env)->ReleasePrimitiveArrayCritical(env, maskArray, + pMask, JNI_ABORT); } SurfaceData_InvokeRelease(env, srcOps, &srcInfo); } SurfaceData_InvokeUnlock(env, srcOps, &srcInfo); - (*env)->ReleasePrimitiveArrayCritical(env, maskArray, - pMask, JNI_ABORT); - // return the current byte position return bpos; } |