| /* |
| * 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(); |
| } |
| } |