blob: 2dd7a183b955621bbb97388354fe86a8fea7e94c [file] [log] [blame]
/*
* 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();
}
}