diff -r d958f883b42a -r 2f703334f63f jdk/src/windows/classes/sun/java2d/windows/Win32SurfaceDataProxy.java --- a/jdk/src/windows/classes/sun/java2d/windows/Win32SurfaceDataProxy.java Tue Aug 12 15:16:51 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,434 +0,0 @@ -/* - * Copyright 2007 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.windows; - -import java.awt.Color; -import java.awt.Transparency; -import java.awt.Rectangle; -import java.awt.image.ColorModel; -import java.awt.image.IndexColorModel; -import java.awt.image.DirectColorModel; -import java.awt.image.BufferedImage; -import java.awt.image.DataBuffer; -import java.awt.image.DataBufferInt; - -import sun.awt.Win32GraphicsConfig; -import sun.awt.Win32GraphicsDevice; -import sun.awt.image.BufImgSurfaceData; -import sun.awt.image.SunWritableRaster; -import sun.java2d.SurfaceData; -import sun.java2d.SurfaceDataProxy; -import sun.java2d.SunGraphics2D; -import sun.java2d.StateTracker; -import sun.java2d.InvalidPipeException; -import sun.java2d.loops.CompositeType; - -/** - * The proxy class contains the logic for when to replace a - * SurfaceData with a cached X11 Pixmap and the code to create - * the accelerated surfaces. - */ -public abstract class Win32SurfaceDataProxy extends SurfaceDataProxy { - /** - * Represents the maximum size (width * height) of an image that we should - * scan for an unused color. Any image larger than this would probably - * require too much computation time. - */ - private static final int MAX_SIZE = 65536; - - public static SurfaceDataProxy createProxy(SurfaceData srcData, - Win32GraphicsConfig dstConfig) - { - Win32GraphicsDevice wgd = - (Win32GraphicsDevice) dstConfig.getDevice(); - if (!wgd.isDDEnabledOnDevice() || - srcData instanceof Win32SurfaceData || - srcData instanceof Win32OffScreenSurfaceData) - { - // If they are not on the same screen then we could cache the - // blit by returning an instance of Opaque below, but this - // only happens for VolatileImage blits to the wrong screen - // which we make no promises on so we just punt to UNCACHED... - return UNCACHED; - } - - ColorModel srcCM = srcData.getColorModel(); - int srcTransparency = srcCM.getTransparency(); - - if (srcTransparency == Transparency.OPAQUE) { - return new Opaque(dstConfig); - } else if (srcTransparency == Transparency.BITMASK) { - if (Bitmask.isCompatible(srcCM, srcData)) { - return new Bitmask(dstConfig); - } - } - - return UNCACHED; - } - - int srcTransparency; - Win32GraphicsConfig wgc; - - public Win32SurfaceDataProxy(Win32GraphicsConfig wgc, - int srcTransparency) - { - this.wgc = wgc; - this.srcTransparency = srcTransparency; - activateDisplayListener(); - } - - @Override - public SurfaceData validateSurfaceData(SurfaceData srcData, - SurfaceData cachedData, - int w, int h) - { - if (cachedData == null || - !cachedData.isValid() || - cachedData.isSurfaceLost()) - { - // use the device's color model for ddraw surfaces - ColorModel dstScreenCM = wgc.getDeviceColorModel(); - try { - cachedData = - Win32OffScreenSurfaceData.createData(w, h, - dstScreenCM, - wgc, null, - srcTransparency); - } catch (InvalidPipeException e) { - Win32GraphicsDevice wgd = (Win32GraphicsDevice) wgc.getDevice(); - if (!wgd.isDDEnabledOnDevice()) { - invalidate(); - flush(); - return null; - } - } - } - return cachedData; - } - - /** - * Proxy for opaque source images. - */ - public static class Opaque extends Win32SurfaceDataProxy { - static int TXMAX = - (WindowsFlags.isDDScaleEnabled() - ? SunGraphics2D.TRANSFORM_TRANSLATESCALE - : SunGraphics2D.TRANSFORM_ANY_TRANSLATE); - - public Opaque(Win32GraphicsConfig wgc) { - super(wgc, Transparency.OPAQUE); - } - - @Override - public boolean isSupportedOperation(SurfaceData srcData, - int txtype, - CompositeType comp, - Color bgColor) - { - // we save a read from video memory for compositing - // operations by copying from the buffered image sd - return (txtype <= TXMAX && - (CompositeType.SrcOverNoEa.equals(comp) || - CompositeType.SrcNoEa.equals(comp))); - } - } - - /** - * Proxy for bitmask transparent source images. - * This proxy can accelerate unscaled SrcOver copies with no bgColor. - * - * Note that this proxy plays some games with returning the srcData - * from the validate method. It needs to do this since the conditions - * for caching an accelerated copy depend on many factors that can - * change over time, including: - * - * - the depth of the display - * - the availability of a transparent pixel - */ - public static class Bitmask extends Win32SurfaceDataProxy { - /** - * Tests a source image ColorModel and SurfaceData to - * see if they are of an appropriate size and type to - * perform our transparent pixel searches. - * - * Note that some dynamic factors may occur which prevent - * us from finding or using a transparent pixel. These - * are detailed above in the class comments. We do not - * test those conditions here, but rely on the Bitmask - * proxy to verify those conditions on the fly. - */ - public static boolean isCompatible(ColorModel srcCM, - SurfaceData srcData) - { - if (srcCM instanceof IndexColorModel) { - return true; - } else if (srcCM instanceof DirectColorModel) { - return isCompatibleDCM((DirectColorModel) srcCM, srcData); - } - - return false; - } - - /** - * Tests a given DirectColorModel to make sure it is - * compatible with the assumptions we make when scanning - * a DCM image for a transparent pixel. - */ - public static boolean isCompatibleDCM(DirectColorModel dcm, - SurfaceData srcData) - { - // The BISD restriction is because we need to - // examine the pixels to find a tranparent color - if (!(srcData instanceof BufImgSurfaceData)) { - return false; - } - - // The size restriction prevents us from wasting too - // much time scanning large images for unused pixel values. - Rectangle bounds = srcData.getBounds(); - // Using division instead of multiplication avoids overflow - if (bounds.width <= 0 || - MAX_SIZE / bounds.width < bounds.height) - { - return false; - } - - // Below we use the pixels from the data buffer to map - // directly to pixel values using the dstData.pixelFor() - // method so the pixel format must be compatible with - // ARGB or we could end up with bad results. We assume - // here that the destination is opaque and so only the - // red, green, and blue masks matter. - // These new checks for RGB masks are more correct, - // but potentially reject the acceleration of some images - // that we used to allow just because we cannot prove - // that they will work OK. If we ever had an INT_BGR - // image for instance, would that have really failed here? - // 565 and 555 screens will both keep equal numbers of - // bits of red and blue, but will differ in the amount of - // green they keep so INT_BGR might be safe, but if anyone - // ever created an INT_RBG image then 555 and 565 might - // differ in whether they thought a transparent pixel - // was available. Also, are there any other strange - // screen formats where bizarre orderings of the RGB - // would cause the tests below to make mistakes? - return ((dcm.getPixelSize() == 25) && - (dcm.getTransferType() == DataBuffer.TYPE_INT) && - (dcm.getRedMask() == 0x00ff0000) && - (dcm.getGreenMask() == 0x0000ff00) && - (dcm.getBlueMask() == 0x000000ff)); - } - - int transPixel; - Color transColor; - - // The real accelerated surface - only used when we can find - // a transparent color. - SurfaceData accelData; - - public Bitmask(Win32GraphicsConfig wgc) { - super(wgc, Transparency.BITMASK); - } - - @Override - public boolean isSupportedOperation(SurfaceData srcData, - int txtype, - CompositeType comp, - Color bgColor) - { - // We have accelerated loops only for blits with SrcOverNoEa - // (no blit bg loops or blit loops with SrcNoEa) - return (CompositeType.SrcOverNoEa.equals(comp) && - bgColor == null && - txtype < SunGraphics2D.TRANSFORM_TRANSLATESCALE); - } - - /** - * Note that every time we update the surface we may or may - * not find a transparent pixel depending on what was modified - * in the source image since the last time we looked. - * Our validation method saves the accelerated surface aside - * in a different field so we can switch back and forth between - * the accelerated version and null depending on whether we - * find a transparent pixel. - * Note that we also override getRetryTracker() and return a - * tracker that tracks the source pixels so that we do not - * try to revalidate until there are new pixels to be scanned. - */ - @Override - public SurfaceData validateSurfaceData(SurfaceData srcData, - SurfaceData cachedData, - int w, int h) - { - // Evaluate the dest screen pixel size every time - ColorModel dstScreenCM = wgc.getDeviceColorModel(); - if (dstScreenCM.getPixelSize() <= 8) { - return null; - } - accelData = super.validateSurfaceData(srcData, accelData, w, h); - return (accelData != null && - findTransparentPixel(srcData, accelData)) - ? accelData - : null; - } - - @Override - public StateTracker getRetryTracker(SurfaceData srcData) { - // If we failed to validate, it is permanent until the - // next change to srcData... - return srcData.getStateTracker(); - } - - @Override - public void updateSurfaceData(SurfaceData srcData, - SurfaceData dstData, - int w, int h) - { - updateSurfaceDataBg(srcData, dstData, w, h, transColor); - } - - /** - * Invoked when the cached surface should be dropped. - * Overrides the base class implementation so we can invalidate - * the accelData field instead of the cachedSD field. - */ - @Override - public synchronized void flush() { - SurfaceData accelData = this.accelData; - if (accelData != null) { - this.accelData = null; - accelData.flush(); - } - super.flush(); - } - - /** - * The following constants determine the size of the histograms - * used when searching for an unused color - */ - private static final int ICM_HISTOGRAM_SIZE = 256; - private static final int ICM_HISTOGRAM_MASK = ICM_HISTOGRAM_SIZE - 1; - private static final int DCM_HISTOGRAM_SIZE = 1024; - private static final int DCM_HISTOGRAM_MASK = DCM_HISTOGRAM_SIZE - 1; - - /** - * Attempts to find an unused pixel value in the image and if - * successful, sets up the DirectDraw surface so that it uses - * this value as its color key. - */ - public boolean findTransparentPixel(SurfaceData srcData, - SurfaceData accelData) - { - ColorModel srcCM = srcData.getColorModel(); - boolean success = false; - - if (srcCM instanceof IndexColorModel) { - success = findUnusedPixelICM((IndexColorModel) srcCM, - accelData); - } else if (srcCM instanceof DirectColorModel) { - success = findUnusedPixelDCM((BufImgSurfaceData) srcData, - accelData); - } - - if (success) { - int rgb = accelData.rgbFor(transPixel); - transColor = new Color(rgb); - Win32OffScreenSurfaceData wossd = - (Win32OffScreenSurfaceData) accelData; - wossd.setTransparentPixel(transPixel); - } else { - transColor = null; - } - return success; - } - - /** - * Attempts to find an unused pixel value in the color map of an - * IndexColorModel. If successful, it returns that value (in the - * ColorModel of the destination surface) or null otherwise. - */ - private boolean findUnusedPixelICM(IndexColorModel icm, - SurfaceData accelData) { - int mapsize = icm.getMapSize(); - int[] histogram = new int[ICM_HISTOGRAM_SIZE]; - int[] cmap = new int[mapsize]; - icm.getRGBs(cmap); - - // load up the histogram - for (int i = 0; i < mapsize; i++) { - int pixel = accelData.pixelFor(cmap[i]); - histogram[pixel & ICM_HISTOGRAM_MASK]++; - } - - // find an empty histo-bucket - for (int j = 0; j < histogram.length; j++) { - if (histogram[j] == 0) { - transPixel = j; - return true; - } - } - - return false; - } - - /** - * Attempts to find an unused pixel value in an image with a - * 25-bit DirectColorModel and a DataBuffer of TYPE_INT. - * If successful, it returns that value (in the ColorModel - * of the destination surface) or null otherwise. - */ - private boolean findUnusedPixelDCM(BufImgSurfaceData bisd, - SurfaceData accelData) - { - BufferedImage bimg = (BufferedImage) bisd.getDestination(); - DataBufferInt db = - (DataBufferInt) bimg.getRaster().getDataBuffer(); - int[] pixels = SunWritableRaster.stealData(db, 0); - int[] histogram = new int[DCM_HISTOGRAM_SIZE]; - - // load up the histogram - // REMIND: we could possibly make this faster by keeping track - // of the unique colors found, and only doing a pixelFor() - // when we come across a new unique color - // REMIND: We are assuming pixels are in ARGB format. Is that - // a safe assumption here? - for (int i = 0; i < pixels.length; i++) { - int pixel = accelData.pixelFor(pixels[i]); - histogram[pixel & DCM_HISTOGRAM_MASK]++; - } - - // find an empty histo-bucket - for (int j = 0; j < histogram.length; j++) { - if (histogram[j] == 0) { - transPixel = j; - return true; - } - } - - return false; - } - } -}