jdk/src/windows/classes/sun/java2d/d3d/D3DSurfaceData.java
changeset 2 90ce3da70b43
child 887 0aab8d3fa11a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/windows/classes/sun/java2d/d3d/D3DSurfaceData.java	Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,457 @@
+/*
+ * Copyright 2005-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.d3d;
+
+import java.awt.AlphaComposite;
+import java.awt.GraphicsConfiguration;
+import java.awt.Image;
+import java.awt.Transparency;
+import java.awt.image.ColorModel;
+import java.awt.image.DirectColorModel;
+import sun.awt.SunHints;
+import sun.awt.Win32GraphicsConfig;
+import sun.awt.Win32GraphicsDevice;
+import sun.awt.image.SurfaceManager;
+import sun.java2d.InvalidPipeException;
+import sun.java2d.SunGraphics2D;
+import sun.java2d.SurfaceData;
+import sun.java2d.SurfaceDataProxy;
+import sun.java2d.loops.GraphicsPrimitive;
+import sun.java2d.loops.SurfaceType;
+import sun.java2d.pipe.PixelToShapeConverter;
+import sun.java2d.pipe.TextPipe;
+import sun.java2d.windows.Win32OffScreenSurfaceData;
+import sun.java2d.windows.Win32SurfaceData;
+import sun.java2d.windows.WinVolatileSurfaceManager;
+import sun.java2d.windows.WindowsFlags;
+
+import static sun.java2d.windows.Win32SurfaceData.*;
+
+public class D3DSurfaceData extends Win32OffScreenSurfaceData {
+
+    // properties of a surface
+    /**
+     * This property is used for a back-buffer surface
+     */
+    public static final int D3D_ATTACHED_SURFACE = (1 << 15);
+    /**
+     * A surface with this property can be used as a Direct3D rendering
+     * destination.
+     */
+    public static final int D3D_RENDER_TARGET    = (1 << 16);
+
+    public static final int
+        D3D_INVALID_SURFACE    = 0;
+    /**
+     * Surface is a Direct3D plain surface (not a texture).
+     * Plain surface can be used as render target.
+     * VolatileImages typically use plain surfaces as their hardware
+     * accelerated surfaces.
+     */
+    public static final int
+        D3D_PLAIN_SURFACE      = (1 << 0) | D3D_RENDER_TARGET;
+    /**
+     * Direct3D texture. Mostly used for cached accelerated surfaces.
+     * Surfaces of this type can be copied from using hardware acceleration
+     * by using texture mapping.
+     */
+    public static final int
+        D3D_TEXTURE_SURFACE    = (1 << 1);
+    /**
+     * Direct3D Backbuffer surface - an attached surface. Used for
+     * multibuffered BufferStrategies.
+     */
+    public static final int
+        D3D_BACKBUFFER_SURFACE = D3D_PLAIN_SURFACE | D3D_ATTACHED_SURFACE;
+    /**
+     * Render-to-texture. A texture which can also be a render target.
+     * Combines the benefits of textures (fast copies-from) and
+     * backbuffers or plain surfaces (hw-accelerated rendering to the surface)
+     */
+    public static final int
+        D3D_RTT_SURFACE        = D3D_TEXTURE_SURFACE | D3D_RENDER_TARGET;
+
+    // supported texture pixel formats
+    public static final int PF_INVALID         =  0;
+    public static final int PF_INT_ARGB        =  1;
+    public static final int PF_INT_RGB         =  2;
+    public static final int PF_INT_RGBX        =  3;
+    public static final int PF_INT_BGR         =  4;
+    public static final int PF_USHORT_565_RGB  =  5;
+    public static final int PF_USHORT_555_RGB  =  6;
+    public static final int PF_USHORT_555_RGBX =  7;
+    public static final int PF_INT_ARGB_PRE    =  8;
+    public static final int PF_USHORT_4444_ARGB=  9;
+
+    public static final String
+        DESC_INT_ARGB_D3D         = "Integer ARGB D3D with translucency";
+    public static final String
+        DESC_USHORT_4444_ARGB_D3D = "UShort 4444 ARGB D3D with translucency";
+
+    /**
+     * Surface type for texture destination.  We cannot render textures to
+     * the screen because Direct3D is not clipped by the window's clip list,
+     * so we only enable the texture blit loops for copies to offscreen
+     * accelerated surfaces.
+     */
+    public static final String
+        DESC_DEST_D3D           = "D3D render target";
+
+    public static final SurfaceType D3DSurface =
+        SurfaceType.Any.deriveSubType("Direct3D Surface");
+    public static final SurfaceType D3DTexture =
+        D3DSurface.deriveSubType("Direct3D Texture");
+
+    /**
+     * D3D destination surface types (derive from offscreen dd surfaces).
+     * Note that all of these surfaces have the same surface description;
+     * we do not care about the depth of the surface since texture ops
+     * support multiple depths.
+     */
+    public static final SurfaceType IntRgbD3D =
+        IntRgbDD.deriveSubType(DESC_DEST_D3D);
+
+    public static final SurfaceType IntRgbxD3D =
+        IntRgbxDD.deriveSubType(DESC_DEST_D3D);
+
+    public static final SurfaceType Ushort565RgbD3D =
+        Ushort565RgbDD.deriveSubType(DESC_DEST_D3D);
+
+    public static final SurfaceType Ushort555RgbxD3D =
+        Ushort555RgbxDD.deriveSubType(DESC_DEST_D3D);
+
+    public static final SurfaceType Ushort555RgbD3D =
+        Ushort555RgbDD.deriveSubType(DESC_DEST_D3D);
+
+    // REMIND: Is it possible to have d3d accelerated on this type of surface?
+    public static final SurfaceType ThreeByteBgrD3D =
+        ThreeByteBgrDD.deriveSubType(DESC_DEST_D3D);
+
+    public static final SurfaceType IntArgbD3D =
+        SurfaceType.IntArgb.deriveSubType(DESC_INT_ARGB_D3D);
+
+    public static final SurfaceType Ushort4444ArgbD3D =
+        SurfaceType.Ushort4444Argb.deriveSubType(DESC_USHORT_4444_ARGB_D3D);
+
+    // Textures we can render to using d3d
+    public static final SurfaceType IntRgbD3D_RTT =
+        IntRgbD3D.deriveSubType(DESC_DEST_D3D);
+
+    public static final SurfaceType IntRgbxD3D_RTT =
+        IntRgbxD3D.deriveSubType(DESC_DEST_D3D);
+
+    public static final SurfaceType Ushort565RgbD3D_RTT =
+        Ushort565RgbD3D.deriveSubType(DESC_DEST_D3D);
+
+    public static final SurfaceType Ushort555RgbxD3D_RTT =
+        Ushort555RgbxD3D.deriveSubType(DESC_DEST_D3D);
+
+    public static final SurfaceType Ushort555RgbD3D_RTT =
+        Ushort555RgbD3D.deriveSubType(DESC_DEST_D3D);
+
+    public static final SurfaceType Ushort4444ArgbD3D_RTT =
+        Ushort4444ArgbD3D.deriveSubType(DESC_DEST_D3D);
+
+    public static final SurfaceType IntArgbD3D_RTT =
+        IntArgbD3D.deriveSubType(DESC_DEST_D3D);
+
+    public static final SurfaceType ThreeByteBgrD3D_RTT =
+        ThreeByteBgrD3D.deriveSubType(DESC_DEST_D3D);
+
+    // the type of this surface - texture, plain, back-buffer
+    protected int type;
+    protected int pixelFormat;
+
+    private D3DContext d3dContext;
+
+    protected static D3DRenderer d3dPipe;
+    protected static PixelToShapeConverter d3dTxPipe;
+    protected static D3DTextRenderer d3dTextPipe;
+    protected static D3DDrawImage d3dDrawImagePipe;
+
+    private native void initOps(int depth, int transparency);
+
+    static {
+        if (WindowsFlags.isD3DEnabled()) {
+            D3DBlitLoops.register();
+            D3DMaskFill.register();
+        }
+
+        d3dPipe = new D3DRenderer();
+        d3dTxPipe = new PixelToShapeConverter(d3dPipe);
+        d3dTextPipe = new D3DTextRenderer();
+        d3dDrawImagePipe = new D3DDrawImage();
+
+        if (GraphicsPrimitive.tracingEnabled()) {
+            d3dPipe = d3dPipe.traceWrapD3D();
+            d3dTextPipe = d3dTextPipe.traceWrap();
+        }
+    }
+
+    @Override
+    public SurfaceDataProxy makeProxyFor(SurfaceData srcData) {
+        //D3D may be eliminated soon so no Proxy was created for it...
+        //return D3DSurfaceDataProxy.createProxy(srcData, graphicsConfig);
+        return SurfaceDataProxy.UNCACHED;
+    }
+
+    /**
+     * Non-public constructor.  Use createData() to create an object.
+     *
+     * This constructor is used to house the common construction
+     * code shared between the creation of D3DSurfaceData objects
+     * and subclasses of D3DSurfaceData (such as D3DBackBufferSD).
+     *
+     * It calls the common constructor in the parent, and then
+     * initializes other shared D3D data.
+     */
+    protected D3DSurfaceData(int width, int height,
+                             int d3dSurfaceType,
+                             SurfaceType sType, ColorModel cm,
+                             GraphicsConfiguration gc,
+                             Image image, int transparency)
+    {
+        super(width, height, sType, cm, gc, image, transparency);
+        this.type = d3dSurfaceType;
+    }
+
+    /**
+     * Private constructor.  Use createData() to create an object.
+     *
+     * This constructor calls the common constructor above and then
+     * performs the specific initialization of the D3DSurface.
+     */
+    private D3DSurfaceData(int width, int height,
+                           int d3dSurfaceType,
+                           SurfaceType sType, ColorModel cm,
+                           GraphicsConfiguration gc,
+                           Image image, int transparency,
+                           int screen)
+    {
+        this(width, height, d3dSurfaceType, sType, cm, gc, image, transparency);
+        pixelFormat = initSurface(width, height, screen,
+                                  null /*parent SurfaceData*/);
+    }
+
+    public static D3DSurfaceData createData(int width, int height,
+                                            int d3dSurfaceType,
+                                            ColorModel cm,
+                                            GraphicsConfiguration gc,
+                                            Image image)
+    {
+        Win32GraphicsDevice gd = (Win32GraphicsDevice)gc.getDevice();
+        // After a display change ddInstance may not be
+        // recreated yet, and in this case isD3DEnabledOnDevice will
+        // return false, until someone attempted to recreate the
+        // primary.
+        if (!gd.isD3DEnabledOnDevice()) {
+            return null;
+        }
+
+        return new D3DSurfaceData(width, height,
+                                  d3dSurfaceType,
+                                  getSurfaceType(gc, cm, d3dSurfaceType),
+                                  cm, gc, image,
+                                  cm.getTransparency(), gd.getScreen());
+    }
+
+    int getPixelFormat() {
+        return pixelFormat;
+    }
+
+    static SurfaceType getSurfaceType(GraphicsConfiguration gc,
+                                      ColorModel cm,
+                                      int d3dSurfaceType)
+    {
+        if (d3dSurfaceType == D3D_TEXTURE_SURFACE) {
+            // for non-rtt textures we have only one surface type
+            return D3DTexture;
+        } else {
+            int pixelSize = cm.getPixelSize();
+            Win32GraphicsDevice gd = (Win32GraphicsDevice)gc.getDevice();
+            int transparency = cm.getTransparency();
+
+            // We'll attempt to use render-to-texture if render target is
+            // requested, but it's not a back-buffer and we support RTT
+            // for this configuration.
+            boolean useRTT =
+                ((d3dSurfaceType & D3D_RENDER_TARGET) != 0) &&
+                ((d3dSurfaceType & D3D_BACKBUFFER_SURFACE) == 0) &&
+                gd.getD3DContext().isRTTSupported();
+
+            // if there's no RTT available, we can't accelerate non-opaque
+            // surfaces, so we return null.
+            if (transparency == Transparency.TRANSLUCENT ||
+                transparency == Transparency.BITMASK)
+            {
+                if (pixelSize == 16) {
+                    return useRTT ? Ushort4444ArgbD3D_RTT :
+                        null/*Ushort4444ArgbD3D*/;
+                } else {
+                    return useRTT ? IntArgbD3D_RTT : null/*IntArgbD3D*/;
+                }
+            } else {
+                // it's an opaque surface, either a VI or a back-buffer
+                switch (pixelSize) {
+                case 32:
+                case 24:
+                    if (cm instanceof DirectColorModel) {
+                        if (((DirectColorModel)cm).getRedMask() == 0xff0000) {
+                            return useRTT ? IntRgbD3D_RTT : IntRgbD3D;
+                        } else {
+                            return useRTT ? IntRgbxD3D_RTT : IntRgbxD3D;
+                        }
+                    } else {
+                        return useRTT ? ThreeByteBgrD3D_RTT : ThreeByteBgrD3D;
+                    }
+                case 15:
+                    return useRTT ? Ushort555RgbD3D_RTT : Ushort555RgbD3D;
+                case 16:
+                    if ((cm instanceof DirectColorModel) &&
+                        (((DirectColorModel)cm).getBlueMask() == 0x3e))
+                    {
+                        return useRTT ? Ushort555RgbxD3D_RTT : Ushort555RgbxD3D;
+                    } else {
+                        return useRTT ? Ushort565RgbD3D_RTT : Ushort565RgbD3D;
+                    }
+                case 8: // not supported
+                default:
+                    throw new sun.java2d.InvalidPipeException("Unsupported bit " +
+                                                              "depth: " +
+                                                              cm.getPixelSize());
+                }
+            }
+        }
+    }
+
+    private native int initOffScreenSurface(long pCtx,
+                                            long pData, long parentPdata,
+                                            int width, int height,
+                                            int type, int screen);
+
+    protected int initSurface(int width, int height, int screen,
+                              Win32SurfaceData parentData)
+    {
+        int pFormat = PF_INVALID;
+
+        synchronized (D3DContext.LOCK) {
+            long pData = getNativeOps();
+            long pDataParent = 0L;
+            if (parentData != null) {
+                pDataParent = parentData.getNativeOps();
+            }
+            D3DContext d3dContext = getContext();
+            long pCtx = d3dContext.getNativeContext();
+            // native context could be 0 if the context is currently invalid,
+            // so attempt to revalidate
+            if (pCtx == 0) {
+                d3dContext.reinitNativeContext();
+                pCtx = d3dContext.getNativeContext();
+            }
+            if (pData != 0 && pCtx != 0) {
+                pFormat = initOffScreenSurface(pCtx,
+                                               pData, pDataParent,
+                                               width, height, type, screen);
+            } else {
+                // if the context can't be restored, give up for now.
+                throw new InvalidPipeException("D3DSD.initSurface: pData " +
+                                               "or pCtx is null");
+            }
+        }
+        return pFormat;
+    }
+
+    @Override
+    public void validatePipe(SunGraphics2D sg2d) {
+        // we don't support COMP_XOR yet..
+        if (sg2d.compositeState < sg2d.COMP_XOR) {
+            TextPipe textpipe;
+            boolean validated = false;
+
+            if (((sg2d.compositeState <= sg2d.COMP_ISCOPY &&
+                  sg2d.paintState <= sg2d.PAINT_ALPHACOLOR) ||
+                 (sg2d.compositeState == sg2d.COMP_ALPHA &&
+                  sg2d.paintState <= sg2d.PAINT_ALPHACOLOR &&
+                  (((AlphaComposite)sg2d.composite).getRule() ==
+                   AlphaComposite.SRC_OVER))) &&
+                sg2d.textAntialiasHint <= SunHints.INTVAL_TEXT_ANTIALIAS_GASP)
+            {
+                // D3DTextRenderer handles both AA and non-AA text, but
+                // only works if composite is SrcNoEa or SrcOver
+                textpipe = d3dTextPipe;
+            } else {
+                // do this to initialize textpipe correctly; we will attempt
+                // to override the non-text pipes below
+                super.validatePipe(sg2d);
+                textpipe = sg2d.textpipe;
+                validated = true;
+            }
+
+            if (sg2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON &&
+                sg2d.paintState <= sg2d.PAINT_ALPHACOLOR)
+            {
+                sg2d.drawpipe =
+                    sg2d.strokeState == sg2d.STROKE_THIN ? d3dPipe : d3dTxPipe;
+                sg2d.fillpipe = d3dPipe;
+                sg2d.shapepipe = d3dPipe;
+            } else if (!validated) {
+                super.validatePipe(sg2d);
+            }
+            // install the text pipe based on our earlier decision
+            sg2d.textpipe = textpipe;
+        } else {
+            super.validatePipe(sg2d);
+        }
+
+        // always override the image pipe with the specialized D3D pipe
+        sg2d.imagepipe = d3dDrawImagePipe;
+    }
+
+    /**
+     * Disables D3D acceleration on the surface manager of this surfaceData
+     * object. This can happen when we encounter a hard error in rendering a D3D
+     * primitive (for example, if we were unable to set a surface as D3D target
+     * surface).
+     * Upon next validation the SurfaceManager will create a non-D3D surface.
+     */
+    public void disableD3D() {
+        markSurfaceLost();
+        SurfaceManager sMgr = SurfaceManager.getManager(image);
+        if (sMgr instanceof WinVolatileSurfaceManager) {
+            ((WinVolatileSurfaceManager)sMgr).setD3DAccelerationEnabled(false);
+        }
+    }
+
+    @Override
+    public boolean surfacePunted() {
+        // Punting is disabled for D3D surfaces
+        return false;
+    }
+
+    D3DContext getContext() {
+        return ((Win32GraphicsDevice)graphicsConfig.getDevice()).getD3DContext();
+    }
+}