001: /*
002: * Copyright 2005-2007 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.java2d.d3d;
027:
028: import java.awt.AlphaComposite;
029: import java.awt.GraphicsConfiguration;
030: import java.awt.Image;
031: import java.awt.Transparency;
032: import java.awt.image.ColorModel;
033: import java.awt.image.DirectColorModel;
034: import sun.awt.SunHints;
035: import sun.awt.Win32GraphicsConfig;
036: import sun.awt.Win32GraphicsDevice;
037: import sun.awt.image.SurfaceManager;
038: import sun.java2d.InvalidPipeException;
039: import sun.java2d.SunGraphics2D;
040: import sun.java2d.SurfaceData;
041: import sun.java2d.SurfaceDataProxy;
042: import sun.java2d.loops.GraphicsPrimitive;
043: import sun.java2d.loops.SurfaceType;
044: import sun.java2d.pipe.PixelToShapeConverter;
045: import sun.java2d.pipe.TextPipe;
046: import sun.java2d.windows.Win32OffScreenSurfaceData;
047: import sun.java2d.windows.Win32SurfaceData;
048: import sun.java2d.windows.WinVolatileSurfaceManager;
049: import sun.java2d.windows.WindowsFlags;
050:
051: import static sun.java2d.windows.Win32SurfaceData.*;
052:
053: public class D3DSurfaceData extends Win32OffScreenSurfaceData {
054:
055: // properties of a surface
056: /**
057: * This property is used for a back-buffer surface
058: */
059: public static final int D3D_ATTACHED_SURFACE = (1 << 15);
060: /**
061: * A surface with this property can be used as a Direct3D rendering
062: * destination.
063: */
064: public static final int D3D_RENDER_TARGET = (1 << 16);
065:
066: public static final int D3D_INVALID_SURFACE = 0;
067: /**
068: * Surface is a Direct3D plain surface (not a texture).
069: * Plain surface can be used as render target.
070: * VolatileImages typically use plain surfaces as their hardware
071: * accelerated surfaces.
072: */
073: public static final int D3D_PLAIN_SURFACE = (1 << 0)
074: | D3D_RENDER_TARGET;
075: /**
076: * Direct3D texture. Mostly used for cached accelerated surfaces.
077: * Surfaces of this type can be copied from using hardware acceleration
078: * by using texture mapping.
079: */
080: public static final int D3D_TEXTURE_SURFACE = (1 << 1);
081: /**
082: * Direct3D Backbuffer surface - an attached surface. Used for
083: * multibuffered BufferStrategies.
084: */
085: public static final int D3D_BACKBUFFER_SURFACE = D3D_PLAIN_SURFACE
086: | D3D_ATTACHED_SURFACE;
087: /**
088: * Render-to-texture. A texture which can also be a render target.
089: * Combines the benefits of textures (fast copies-from) and
090: * backbuffers or plain surfaces (hw-accelerated rendering to the surface)
091: */
092: public static final int D3D_RTT_SURFACE = D3D_TEXTURE_SURFACE
093: | D3D_RENDER_TARGET;
094:
095: // supported texture pixel formats
096: public static final int PF_INVALID = 0;
097: public static final int PF_INT_ARGB = 1;
098: public static final int PF_INT_RGB = 2;
099: public static final int PF_INT_RGBX = 3;
100: public static final int PF_INT_BGR = 4;
101: public static final int PF_USHORT_565_RGB = 5;
102: public static final int PF_USHORT_555_RGB = 6;
103: public static final int PF_USHORT_555_RGBX = 7;
104: public static final int PF_INT_ARGB_PRE = 8;
105: public static final int PF_USHORT_4444_ARGB = 9;
106:
107: public static final String DESC_INT_ARGB_D3D = "Integer ARGB D3D with translucency";
108: public static final String DESC_USHORT_4444_ARGB_D3D = "UShort 4444 ARGB D3D with translucency";
109:
110: /**
111: * Surface type for texture destination. We cannot render textures to
112: * the screen because Direct3D is not clipped by the window's clip list,
113: * so we only enable the texture blit loops for copies to offscreen
114: * accelerated surfaces.
115: */
116: public static final String DESC_DEST_D3D = "D3D render target";
117:
118: public static final SurfaceType D3DSurface = SurfaceType.Any
119: .deriveSubType("Direct3D Surface");
120: public static final SurfaceType D3DTexture = D3DSurface
121: .deriveSubType("Direct3D Texture");
122:
123: /**
124: * D3D destination surface types (derive from offscreen dd surfaces).
125: * Note that all of these surfaces have the same surface description;
126: * we do not care about the depth of the surface since texture ops
127: * support multiple depths.
128: */
129: public static final SurfaceType IntRgbD3D = IntRgbDD
130: .deriveSubType(DESC_DEST_D3D);
131:
132: public static final SurfaceType IntRgbxD3D = IntRgbxDD
133: .deriveSubType(DESC_DEST_D3D);
134:
135: public static final SurfaceType Ushort565RgbD3D = Ushort565RgbDD
136: .deriveSubType(DESC_DEST_D3D);
137:
138: public static final SurfaceType Ushort555RgbxD3D = Ushort555RgbxDD
139: .deriveSubType(DESC_DEST_D3D);
140:
141: public static final SurfaceType Ushort555RgbD3D = Ushort555RgbDD
142: .deriveSubType(DESC_DEST_D3D);
143:
144: // REMIND: Is it possible to have d3d accelerated on this type of surface?
145: public static final SurfaceType ThreeByteBgrD3D = ThreeByteBgrDD
146: .deriveSubType(DESC_DEST_D3D);
147:
148: public static final SurfaceType IntArgbD3D = SurfaceType.IntArgb
149: .deriveSubType(DESC_INT_ARGB_D3D);
150:
151: public static final SurfaceType Ushort4444ArgbD3D = SurfaceType.Ushort4444Argb
152: .deriveSubType(DESC_USHORT_4444_ARGB_D3D);
153:
154: // Textures we can render to using d3d
155: public static final SurfaceType IntRgbD3D_RTT = IntRgbD3D
156: .deriveSubType(DESC_DEST_D3D);
157:
158: public static final SurfaceType IntRgbxD3D_RTT = IntRgbxD3D
159: .deriveSubType(DESC_DEST_D3D);
160:
161: public static final SurfaceType Ushort565RgbD3D_RTT = Ushort565RgbD3D
162: .deriveSubType(DESC_DEST_D3D);
163:
164: public static final SurfaceType Ushort555RgbxD3D_RTT = Ushort555RgbxD3D
165: .deriveSubType(DESC_DEST_D3D);
166:
167: public static final SurfaceType Ushort555RgbD3D_RTT = Ushort555RgbD3D
168: .deriveSubType(DESC_DEST_D3D);
169:
170: public static final SurfaceType Ushort4444ArgbD3D_RTT = Ushort4444ArgbD3D
171: .deriveSubType(DESC_DEST_D3D);
172:
173: public static final SurfaceType IntArgbD3D_RTT = IntArgbD3D
174: .deriveSubType(DESC_DEST_D3D);
175:
176: public static final SurfaceType ThreeByteBgrD3D_RTT = ThreeByteBgrD3D
177: .deriveSubType(DESC_DEST_D3D);
178:
179: // the type of this surface - texture, plain, back-buffer
180: protected int type;
181: protected int pixelFormat;
182:
183: private D3DContext d3dContext;
184:
185: protected static D3DRenderer d3dPipe;
186: protected static PixelToShapeConverter d3dTxPipe;
187: protected static D3DTextRenderer d3dTextPipe;
188: protected static D3DDrawImage d3dDrawImagePipe;
189:
190: private native void initOps(int depth, int transparency);
191:
192: static {
193: if (WindowsFlags.isD3DEnabled()) {
194: D3DBlitLoops.register();
195: D3DMaskFill.register();
196: }
197:
198: d3dPipe = new D3DRenderer();
199: d3dTxPipe = new PixelToShapeConverter(d3dPipe);
200: d3dTextPipe = new D3DTextRenderer();
201: d3dDrawImagePipe = new D3DDrawImage();
202:
203: if (GraphicsPrimitive.tracingEnabled()) {
204: d3dPipe = d3dPipe.traceWrapD3D();
205: d3dTextPipe = d3dTextPipe.traceWrap();
206: }
207: }
208:
209: @Override
210: public SurfaceDataProxy makeProxyFor(SurfaceData srcData) {
211: //D3D may be eliminated soon so no Proxy was created for it...
212: //return D3DSurfaceDataProxy.createProxy(srcData, graphicsConfig);
213: return SurfaceDataProxy.UNCACHED;
214: }
215:
216: /**
217: * Non-public constructor. Use createData() to create an object.
218: *
219: * This constructor is used to house the common construction
220: * code shared between the creation of D3DSurfaceData objects
221: * and subclasses of D3DSurfaceData (such as D3DBackBufferSD).
222: *
223: * It calls the common constructor in the parent, and then
224: * initializes other shared D3D data.
225: */
226: protected D3DSurfaceData(int width, int height, int d3dSurfaceType,
227: SurfaceType sType, ColorModel cm, GraphicsConfiguration gc,
228: Image image, int transparency) {
229: super (width, height, sType, cm, gc, image, transparency);
230: this .type = d3dSurfaceType;
231: }
232:
233: /**
234: * Private constructor. Use createData() to create an object.
235: *
236: * This constructor calls the common constructor above and then
237: * performs the specific initialization of the D3DSurface.
238: */
239: private D3DSurfaceData(int width, int height, int d3dSurfaceType,
240: SurfaceType sType, ColorModel cm, GraphicsConfiguration gc,
241: Image image, int transparency, int screen) {
242: this (width, height, d3dSurfaceType, sType, cm, gc, image,
243: transparency);
244: pixelFormat = initSurface(width, height, screen, null /*parent SurfaceData*/);
245: }
246:
247: public static D3DSurfaceData createData(int width, int height,
248: int d3dSurfaceType, ColorModel cm,
249: GraphicsConfiguration gc, Image image) {
250: Win32GraphicsDevice gd = (Win32GraphicsDevice) gc.getDevice();
251: // After a display change ddInstance may not be
252: // recreated yet, and in this case isD3DEnabledOnDevice will
253: // return false, until someone attempted to recreate the
254: // primary.
255: if (!gd.isD3DEnabledOnDevice()) {
256: return null;
257: }
258:
259: return new D3DSurfaceData(width, height, d3dSurfaceType,
260: getSurfaceType(gc, cm, d3dSurfaceType), cm, gc, image,
261: cm.getTransparency(), gd.getScreen());
262: }
263:
264: int getPixelFormat() {
265: return pixelFormat;
266: }
267:
268: static SurfaceType getSurfaceType(GraphicsConfiguration gc,
269: ColorModel cm, int d3dSurfaceType) {
270: if (d3dSurfaceType == D3D_TEXTURE_SURFACE) {
271: // for non-rtt textures we have only one surface type
272: return D3DTexture;
273: } else {
274: int pixelSize = cm.getPixelSize();
275: Win32GraphicsDevice gd = (Win32GraphicsDevice) gc
276: .getDevice();
277: int transparency = cm.getTransparency();
278:
279: // We'll attempt to use render-to-texture if render target is
280: // requested, but it's not a back-buffer and we support RTT
281: // for this configuration.
282: boolean useRTT = ((d3dSurfaceType & D3D_RENDER_TARGET) != 0)
283: && ((d3dSurfaceType & D3D_BACKBUFFER_SURFACE) == 0)
284: && gd.getD3DContext().isRTTSupported();
285:
286: // if there's no RTT available, we can't accelerate non-opaque
287: // surfaces, so we return null.
288: if (transparency == Transparency.TRANSLUCENT
289: || transparency == Transparency.BITMASK) {
290: if (pixelSize == 16) {
291: return useRTT ? Ushort4444ArgbD3D_RTT : null/*Ushort4444ArgbD3D*/;
292: } else {
293: return useRTT ? IntArgbD3D_RTT : null/*IntArgbD3D*/;
294: }
295: } else {
296: // it's an opaque surface, either a VI or a back-buffer
297: switch (pixelSize) {
298: case 32:
299: case 24:
300: if (cm instanceof DirectColorModel) {
301: if (((DirectColorModel) cm).getRedMask() == 0xff0000) {
302: return useRTT ? IntRgbD3D_RTT : IntRgbD3D;
303: } else {
304: return useRTT ? IntRgbxD3D_RTT : IntRgbxD3D;
305: }
306: } else {
307: return useRTT ? ThreeByteBgrD3D_RTT
308: : ThreeByteBgrD3D;
309: }
310: case 15:
311: return useRTT ? Ushort555RgbD3D_RTT
312: : Ushort555RgbD3D;
313: case 16:
314: if ((cm instanceof DirectColorModel)
315: && (((DirectColorModel) cm).getBlueMask() == 0x3e)) {
316: return useRTT ? Ushort555RgbxD3D_RTT
317: : Ushort555RgbxD3D;
318: } else {
319: return useRTT ? Ushort565RgbD3D_RTT
320: : Ushort565RgbD3D;
321: }
322: case 8: // not supported
323: default:
324: throw new sun.java2d.InvalidPipeException(
325: "Unsupported bit " + "depth: "
326: + cm.getPixelSize());
327: }
328: }
329: }
330: }
331:
332: private native int initOffScreenSurface(long pCtx, long pData,
333: long parentPdata, int width, int height, int type,
334: int screen);
335:
336: protected int initSurface(int width, int height, int screen,
337: Win32SurfaceData parentData) {
338: int pFormat = PF_INVALID;
339:
340: synchronized (D3DContext.LOCK) {
341: long pData = getNativeOps();
342: long pDataParent = 0L;
343: if (parentData != null) {
344: pDataParent = parentData.getNativeOps();
345: }
346: D3DContext d3dContext = getContext();
347: long pCtx = d3dContext.getNativeContext();
348: // native context could be 0 if the context is currently invalid,
349: // so attempt to revalidate
350: if (pCtx == 0) {
351: d3dContext.reinitNativeContext();
352: pCtx = d3dContext.getNativeContext();
353: }
354: if (pData != 0 && pCtx != 0) {
355: pFormat = initOffScreenSurface(pCtx, pData,
356: pDataParent, width, height, type, screen);
357: } else {
358: // if the context can't be restored, give up for now.
359: throw new InvalidPipeException(
360: "D3DSD.initSurface: pData " + "or pCtx is null");
361: }
362: }
363: return pFormat;
364: }
365:
366: @Override
367: public void validatePipe(SunGraphics2D sg2d) {
368: // we don't support COMP_XOR yet..
369: if (sg2d.compositeState < sg2d.COMP_XOR) {
370: TextPipe textpipe;
371: boolean validated = false;
372:
373: if (((sg2d.compositeState <= sg2d.COMP_ISCOPY && sg2d.paintState <= sg2d.PAINT_ALPHACOLOR) || (sg2d.compositeState == sg2d.COMP_ALPHA
374: && sg2d.paintState <= sg2d.PAINT_ALPHACOLOR && (((AlphaComposite) sg2d.composite)
375: .getRule() == AlphaComposite.SRC_OVER)))
376: && sg2d.textAntialiasHint <= SunHints.INTVAL_TEXT_ANTIALIAS_GASP) {
377: // D3DTextRenderer handles both AA and non-AA text, but
378: // only works if composite is SrcNoEa or SrcOver
379: textpipe = d3dTextPipe;
380: } else {
381: // do this to initialize textpipe correctly; we will attempt
382: // to override the non-text pipes below
383: super .validatePipe(sg2d);
384: textpipe = sg2d.textpipe;
385: validated = true;
386: }
387:
388: if (sg2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON
389: && sg2d.paintState <= sg2d.PAINT_ALPHACOLOR) {
390: sg2d.drawpipe = sg2d.strokeState == sg2d.STROKE_THIN ? d3dPipe
391: : d3dTxPipe;
392: sg2d.fillpipe = d3dPipe;
393: sg2d.shapepipe = d3dPipe;
394: } else if (!validated) {
395: super .validatePipe(sg2d);
396: }
397: // install the text pipe based on our earlier decision
398: sg2d.textpipe = textpipe;
399: } else {
400: super .validatePipe(sg2d);
401: }
402:
403: // always override the image pipe with the specialized D3D pipe
404: sg2d.imagepipe = d3dDrawImagePipe;
405: }
406:
407: /**
408: * Disables D3D acceleration on the surface manager of this surfaceData
409: * object. This can happen when we encounter a hard error in rendering a D3D
410: * primitive (for example, if we were unable to set a surface as D3D target
411: * surface).
412: * Upon next validation the SurfaceManager will create a non-D3D surface.
413: */
414: public void disableD3D() {
415: markSurfaceLost();
416: SurfaceManager sMgr = SurfaceManager.getManager(image);
417: if (sMgr instanceof WinVolatileSurfaceManager) {
418: ((WinVolatileSurfaceManager) sMgr)
419: .setD3DAccelerationEnabled(false);
420: }
421: }
422:
423: @Override
424: public boolean surfacePunted() {
425: // Punting is disabled for D3D surfaces
426: return false;
427: }
428:
429: D3DContext getContext() {
430: return ((Win32GraphicsDevice) graphicsConfig.getDevice())
431: .getD3DContext();
432: }
433: }
|