/* * Copyright 2000-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.GraphicsConfiguration; import java.awt.Image; import java.awt.Rectangle; import java.awt.Transparency; import java.awt.color.ColorSpace; import java.awt.image.ColorModel; import java.awt.image.ComponentColorModel; import java.awt.image.DirectColorModel; import java.awt.image.IndexColorModel; import java.awt.image.Raster; import sun.awt.SunHints; import sun.awt.Win32GraphicsConfig; import sun.awt.Win32GraphicsDevice; import sun.awt.image.SurfaceManager; import sun.awt.image.SunVolatileImage; import sun.awt.image.WritableRasterNative; import sun.java2d.SunGraphics2D; import sun.java2d.SurfaceData; import sun.java2d.SurfaceDataProxy; import sun.java2d.loops.CompositeType; import sun.java2d.pipe.PixelToShapeConverter; import sun.java2d.loops.GraphicsPrimitive; import sun.java2d.loops.SurfaceType; import sun.java2d.loops.RenderLoops; import sun.java2d.pipe.Region; /** * Win32OffScreenSurfaceData * * This class implements a hardware-accelerated video memory surface. It uses * a custom renderer (DDRenderer) to render via DirectDraw into the * surface and uses a custom Blit loop (DDBlitLoops) to copy between * two hardware-accelerated surfaces (including the screen). */ public class Win32OffScreenSurfaceData extends SurfaceData { protected int width; protected int height; protected int transparency; protected GraphicsConfiguration graphicsConfig; protected Image image; protected RenderLoops solidloops; private boolean ddSurfacePunted = false; private static native void initIDs(); static { initIDs(); // REMIND: This isn't really thought-out; if the user doesn't have or // doesn't want ddraw then we should not even have this surface type // in the loop if (WindowsFlags.isDDEnabled() && WindowsFlags.isDDOffscreenEnabled()) { if (WindowsFlags.isDDBlitEnabled()) { // Register out hardware-accelerated Blit loops DDBlitLoops.register(); } if (WindowsFlags.isDDScaleEnabled()) { DDScaleLoops.register(); } } } public static SurfaceType getSurfaceType(ColorModel cm, int transparency) { boolean transparent = (transparency == Transparency.BITMASK); switch (cm.getPixelSize()) { case 32: case 24: if (cm instanceof DirectColorModel) { if (((DirectColorModel)cm).getRedMask() == 0xff0000) { return transparent ? Win32SurfaceData.IntRgbDD_BM : Win32SurfaceData.IntRgbDD; } else { return transparent ? Win32SurfaceData.IntRgbxDD_BM : Win32SurfaceData.IntRgbxDD; } } else { return transparent ? Win32SurfaceData.ThreeByteBgrDD_BM : Win32SurfaceData.ThreeByteBgrDD; } case 15: return transparent ? Win32SurfaceData.Ushort555RgbDD_BM : Win32SurfaceData.Ushort555RgbDD; case 16: if ((cm instanceof DirectColorModel) && (((DirectColorModel)cm).getBlueMask() == 0x3e)) { return transparent ? Win32SurfaceData.Ushort555RgbxDD_BM : Win32SurfaceData.Ushort555RgbxDD; } else { return transparent ? Win32SurfaceData.Ushort565RgbDD_BM : Win32SurfaceData.Ushort565RgbDD; } case 8: if (cm.getColorSpace().getType() == ColorSpace.TYPE_GRAY && cm instanceof ComponentColorModel) { return transparent ? Win32SurfaceData.ByteGrayDD_BM : Win32SurfaceData.ByteGrayDD; } else if (cm instanceof IndexColorModel && isOpaqueGray((IndexColorModel)cm)) { return transparent ? Win32SurfaceData.Index8GrayDD_BM : Win32SurfaceData.Index8GrayDD; } else { return transparent ? Win32SurfaceData.ByteIndexedDD_BM : Win32SurfaceData.ByteIndexedOpaqueDD; } default: throw new sun.java2d.InvalidPipeException("Unsupported bit " + "depth: " + cm.getPixelSize()); } } @Override public SurfaceDataProxy makeProxyFor(SurfaceData srcData) { Win32GraphicsConfig wgc = (Win32GraphicsConfig) graphicsConfig; return Win32SurfaceDataProxy.createProxy(srcData, wgc); } public static Win32OffScreenSurfaceData createData(int width, int height, ColorModel cm, Win32GraphicsConfig gc, Image image, int transparency) { // Win32OSD doesn't support acceleration of translucent images if (transparency == Transparency.TRANSLUCENT) { return null; } Win32GraphicsDevice gd = (Win32GraphicsDevice)gc.getDevice(); if (!gd.isOffscreenAccelerationEnabled()) { // If acceleration for this type of image is disabled on this // device, do not create an accelerated surface type return null; } return new Win32OffScreenSurfaceData(width, height, getSurfaceType(cm, transparency), cm, gc, image, transparency, gd.getScreen()); } protected static DDRenderer ddPipe; protected static PixelToShapeConverter ddTxPipe; static { ddPipe = new DDRenderer(); if (GraphicsPrimitive.tracingEnabled()) { ddPipe = ddPipe.traceWrapDD(); } ddTxPipe = new PixelToShapeConverter(ddPipe); } public void validatePipe(SunGraphics2D sg2d) { if (sg2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON && sg2d.paintState <= sg2d.PAINT_ALPHACOLOR && sg2d.compositeState <= sg2d.COMP_ISCOPY && sg2d.clipState != sg2d.CLIP_SHAPE && transparency != Transparency.TRANSLUCENT) { PixelToShapeConverter txPipe; DDRenderer nontxPipe; txPipe = ddTxPipe; nontxPipe = ddPipe; sg2d.imagepipe = imagepipe; if (sg2d.transformState >= sg2d.TRANSFORM_TRANSLATESCALE) { sg2d.drawpipe = txPipe; sg2d.fillpipe = txPipe; } else if (sg2d.strokeState != sg2d.STROKE_THIN){ sg2d.drawpipe = txPipe; sg2d.fillpipe = nontxPipe; } else { sg2d.drawpipe = nontxPipe; sg2d.fillpipe = nontxPipe; } sg2d.shapepipe = nontxPipe; switch (sg2d.textAntialiasHint) { case SunHints.INTVAL_TEXT_ANTIALIAS_DEFAULT: /* equate DEFAULT to OFF which it is for us */ case SunHints.INTVAL_TEXT_ANTIALIAS_OFF: sg2d.textpipe = solidTextRenderer; break; case SunHints.INTVAL_TEXT_ANTIALIAS_ON: sg2d.textpipe = aaTextRenderer; break; default: switch (sg2d.getFontInfo().aaHint) { case SunHints.INTVAL_TEXT_ANTIALIAS_LCD_HRGB: case SunHints.INTVAL_TEXT_ANTIALIAS_LCD_VRGB: sg2d.textpipe = lcdTextRenderer; break; case SunHints.INTVAL_TEXT_ANTIALIAS_ON: sg2d.textpipe = aaTextRenderer; break; default: sg2d.textpipe = solidTextRenderer; } } // This is needed for AA text. // Note that even a SolidTextRenderer can dispatch AA text // if a GlyphVector overrides the AA setting. sg2d.loops = solidloops; } else { super.validatePipe(sg2d); } } public static boolean isDDScaleEnabled() { return WindowsFlags.isDDScaleEnabled(); } private WritableRasterNative wrn = null; public synchronized Raster getRaster(int x, int y, int w, int h) { if (wrn == null) { wrn = WritableRasterNative.createNativeRaster(getColorModel(), this, width, height); if (wrn == null) { throw new InternalError("Unable to create native raster"); } } return wrn; } public RenderLoops getRenderLoops(SunGraphics2D sg2d) { if (sg2d.paintState <= sg2d.PAINT_ALPHACOLOR && sg2d.compositeState <= sg2d.COMP_ISCOPY) { return solidloops; } return super.getRenderLoops(sg2d); } public GraphicsConfiguration getDeviceConfiguration() { return graphicsConfig; } /** * Initializes the native Ops pointer. */ private native void initOps(int depth, int transparency); /** * This native method creates the offscreen surface in video memory and * (if necessary) initializes DirectDraw */ private native void initSurface(int depth, int width, int height, int screen, boolean isVolatile, int transparency); public native void restoreSurface(); /** * Non-public constructor. Use createData() to create an object. * * This constructor is used to house the common construction * code shared between the creation of Win32OSSD objects * and subclasses of Win32OSSD (such as D3DSurfaceData * and WinBackBufferSurfaceData). * * It calls the common constructor in the parent, and then * initializes other shared Win32 data. */ protected Win32OffScreenSurfaceData(int width, int height, SurfaceType sType, ColorModel cm, GraphicsConfiguration gc, Image image, int transparency) { super(sType, cm); this.width = width; this.height = height; this.graphicsConfig = gc; this.image = image; this.transparency = transparency; this.solidloops = ((Win32GraphicsConfig)graphicsConfig).getSolidLoops(sType); initOps(cm.getPixelSize(), transparency); } /** * Private constructor. Use createData() to create an object. * * This constructor calls the common constructor above and then * performs the specific initialization of the Win32Surface. */ private Win32OffScreenSurfaceData(int width, int height, SurfaceType sType, ColorModel cm, Win32GraphicsConfig gc, Image image, int transparency, int screen) { this(width, height, sType, cm, gc, image, transparency); initSurface(cm.getPixelSize(), width, height, screen, (image instanceof SunVolatileImage), transparency); setBlitProxyKey(gc.getProxyKey()); } /** * Need this since the surface data is created with * the color model of the target GC, which is always * opaque. But in SunGraphics2D.blitSD we choose loops * based on the transparency on the source SD, so * we could choose wrong loop (blit instead of blitbg, * for example, which will cause problems in transparent * case). */ public int getTransparency() { return transparency; } /** * When someone asks for a new surface data, we punt to our * container image which will attempt to restore the contents * of this surface or, failing that, will return null. */ public SurfaceData getReplacement() { return restoreContents(image); } public Rectangle getBounds() { return new Rectangle(width, height); } protected native void nativeInvalidate(); public void invalidate() { if (isValid()) { synchronized (this) { wrn = null; } nativeInvalidate(); super.invalidate(); } } public native void setTransparentPixel(int pixel); public native void flush(); /** * Returns true if the native representation of this image has been * moved into ddraw system memory. This happens when many reads * or read-modify-write operations are requested of that surface. * If we have moved that surface into system memory, we should note that * here so that someone wanting to copy something to this surface will * take that into account during that copy. */ public boolean surfacePunted() { return ddSurfacePunted; } protected void markSurfaceLost() { synchronized (this) { wrn = null; } setSurfaceLost(true); if (image != null) { // Inform the Volatile that it lost its accelerated surface SurfaceManager sMgr = SurfaceManager.getManager(image); sMgr.acceleratedSurfaceLost(); } } /** * This method is called from the native code if an unrecoverable * error has been detected. * * Marks the surface lost, and notifies the surface manager * that the DirectDraw acceleration for the corresponding image * should be disabled. */ protected void disableDD() { markSurfaceLost(); if (image != null) { SurfaceManager sMgr = SurfaceManager.getManager(image); // REMIND: yes, this is not pretty; the accelerationEnabled property // should be pulled up to SurfaceManager some day. if (sMgr instanceof WinVolatileSurfaceManager) { ((WinVolatileSurfaceManager)sMgr).setAccelerationEnabled(false); } } setBlitProxyKey(null); } /** * Returns destination Image associated with this SurfaceData. */ public Object getDestination() { return image; } @Override public boolean copyArea(SunGraphics2D sg2d, int x, int y, int w, int h, int dx, int dy) { CompositeType comptype = sg2d.imageComp; if (sg2d.transformState < sg2d.TRANSFORM_TRANSLATESCALE && sg2d.clipState != sg2d.CLIP_SHAPE && (CompositeType.SrcOverNoEa.equals(comptype) || CompositeType.SrcNoEa.equals(comptype))) { x += sg2d.transX; y += sg2d.transY; int dstx1 = x + dx; int dsty1 = y + dy; int dstx2 = dstx1 + w; int dsty2 = dsty1 + h; Region clip = sg2d.getCompClip(); if (dstx1 < clip.getLoX()) dstx1 = clip.getLoX(); if (dsty1 < clip.getLoY()) dsty1 = clip.getLoY(); if (dstx2 > clip.getHiX()) dstx2 = clip.getHiX(); if (dsty2 > clip.getHiY()) dsty2 = clip.getHiY(); if (dstx1 < dstx2 && dsty1 < dsty2) { ddPipe.devCopyArea(this, dstx1 - dx, dsty1 - dy, dx, dy, dstx2 - dstx1, dsty2 - dsty1); } return true; } return false; } }