001: /*
002: * Copyright 2000-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.windows;
027:
028: import java.awt.GraphicsConfiguration;
029: import java.awt.Image;
030: import java.awt.Rectangle;
031: import java.awt.Transparency;
032: import java.awt.color.ColorSpace;
033: import java.awt.image.ColorModel;
034: import java.awt.image.ComponentColorModel;
035: import java.awt.image.DirectColorModel;
036: import java.awt.image.IndexColorModel;
037: import java.awt.image.Raster;
038:
039: import sun.awt.SunHints;
040: import sun.awt.Win32GraphicsConfig;
041: import sun.awt.Win32GraphicsDevice;
042: import sun.awt.image.SurfaceManager;
043: import sun.awt.image.SunVolatileImage;
044: import sun.awt.image.WritableRasterNative;
045: import sun.java2d.SunGraphics2D;
046: import sun.java2d.SurfaceData;
047: import sun.java2d.SurfaceDataProxy;
048: import sun.java2d.loops.CompositeType;
049: import sun.java2d.pipe.PixelToShapeConverter;
050: import sun.java2d.loops.GraphicsPrimitive;
051: import sun.java2d.loops.SurfaceType;
052: import sun.java2d.loops.RenderLoops;
053: import sun.java2d.pipe.Region;
054:
055: /**
056: * Win32OffScreenSurfaceData
057: *
058: * This class implements a hardware-accelerated video memory surface. It uses
059: * a custom renderer (DDRenderer) to render via DirectDraw into the
060: * surface and uses a custom Blit loop (DDBlitLoops) to copy between
061: * two hardware-accelerated surfaces (including the screen).
062: */
063: public class Win32OffScreenSurfaceData extends SurfaceData {
064:
065: protected int width;
066: protected int height;
067: protected int transparency;
068:
069: protected GraphicsConfiguration graphicsConfig;
070: protected Image image;
071: protected RenderLoops solidloops;
072: private boolean ddSurfacePunted = false;
073:
074: private static native void initIDs();
075:
076: static {
077: initIDs();
078: // REMIND: This isn't really thought-out; if the user doesn't have or
079: // doesn't want ddraw then we should not even have this surface type
080: // in the loop
081: if (WindowsFlags.isDDEnabled()
082: && WindowsFlags.isDDOffscreenEnabled()) {
083: if (WindowsFlags.isDDBlitEnabled()) {
084: // Register out hardware-accelerated Blit loops
085: DDBlitLoops.register();
086: }
087: if (WindowsFlags.isDDScaleEnabled()) {
088: DDScaleLoops.register();
089: }
090: }
091: }
092:
093: public static SurfaceType getSurfaceType(ColorModel cm,
094: int transparency) {
095: boolean transparent = (transparency == Transparency.BITMASK);
096: switch (cm.getPixelSize()) {
097: case 32:
098: case 24:
099: if (cm instanceof DirectColorModel) {
100: if (((DirectColorModel) cm).getRedMask() == 0xff0000) {
101: return transparent ? Win32SurfaceData.IntRgbDD_BM
102: : Win32SurfaceData.IntRgbDD;
103: } else {
104: return transparent ? Win32SurfaceData.IntRgbxDD_BM
105: : Win32SurfaceData.IntRgbxDD;
106: }
107: } else {
108: return transparent ? Win32SurfaceData.ThreeByteBgrDD_BM
109: : Win32SurfaceData.ThreeByteBgrDD;
110: }
111: case 15:
112: return transparent ? Win32SurfaceData.Ushort555RgbDD_BM
113: : Win32SurfaceData.Ushort555RgbDD;
114: case 16:
115: if ((cm instanceof DirectColorModel)
116: && (((DirectColorModel) cm).getBlueMask() == 0x3e)) {
117: return transparent ? Win32SurfaceData.Ushort555RgbxDD_BM
118: : Win32SurfaceData.Ushort555RgbxDD;
119: } else {
120: return transparent ? Win32SurfaceData.Ushort565RgbDD_BM
121: : Win32SurfaceData.Ushort565RgbDD;
122: }
123: case 8:
124: if (cm.getColorSpace().getType() == ColorSpace.TYPE_GRAY
125: && cm instanceof ComponentColorModel) {
126: return transparent ? Win32SurfaceData.ByteGrayDD_BM
127: : Win32SurfaceData.ByteGrayDD;
128: } else if (cm instanceof IndexColorModel
129: && isOpaqueGray((IndexColorModel) cm)) {
130: return transparent ? Win32SurfaceData.Index8GrayDD_BM
131: : Win32SurfaceData.Index8GrayDD;
132: } else {
133: return transparent ? Win32SurfaceData.ByteIndexedDD_BM
134: : Win32SurfaceData.ByteIndexedOpaqueDD;
135: }
136: default:
137: throw new sun.java2d.InvalidPipeException(
138: "Unsupported bit " + "depth: " + cm.getPixelSize());
139: }
140: }
141:
142: @Override
143: public SurfaceDataProxy makeProxyFor(SurfaceData srcData) {
144: Win32GraphicsConfig wgc = (Win32GraphicsConfig) graphicsConfig;
145: return Win32SurfaceDataProxy.createProxy(srcData, wgc);
146: }
147:
148: public static Win32OffScreenSurfaceData createData(int width,
149: int height, ColorModel cm, Win32GraphicsConfig gc,
150: Image image, int transparency) {
151: // Win32OSD doesn't support acceleration of translucent images
152: if (transparency == Transparency.TRANSLUCENT) {
153: return null;
154: }
155:
156: Win32GraphicsDevice gd = (Win32GraphicsDevice) gc.getDevice();
157: if (!gd.isOffscreenAccelerationEnabled()) {
158: // If acceleration for this type of image is disabled on this
159: // device, do not create an accelerated surface type
160: return null;
161: }
162:
163: return new Win32OffScreenSurfaceData(width, height,
164: getSurfaceType(cm, transparency), cm, gc, image,
165: transparency, gd.getScreen());
166: }
167:
168: protected static DDRenderer ddPipe;
169: protected static PixelToShapeConverter ddTxPipe;
170:
171: static {
172: ddPipe = new DDRenderer();
173: if (GraphicsPrimitive.tracingEnabled()) {
174: ddPipe = ddPipe.traceWrapDD();
175: }
176: ddTxPipe = new PixelToShapeConverter(ddPipe);
177: }
178:
179: public void validatePipe(SunGraphics2D sg2d) {
180: if (sg2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON
181: && sg2d.paintState <= sg2d.PAINT_ALPHACOLOR
182: && sg2d.compositeState <= sg2d.COMP_ISCOPY
183: && sg2d.clipState != sg2d.CLIP_SHAPE
184: && transparency != Transparency.TRANSLUCENT) {
185: PixelToShapeConverter txPipe;
186: DDRenderer nontxPipe;
187: txPipe = ddTxPipe;
188: nontxPipe = ddPipe;
189: sg2d.imagepipe = imagepipe;
190: if (sg2d.transformState >= sg2d.TRANSFORM_TRANSLATESCALE) {
191: sg2d.drawpipe = txPipe;
192: sg2d.fillpipe = txPipe;
193: } else if (sg2d.strokeState != sg2d.STROKE_THIN) {
194: sg2d.drawpipe = txPipe;
195: sg2d.fillpipe = nontxPipe;
196: } else {
197: sg2d.drawpipe = nontxPipe;
198: sg2d.fillpipe = nontxPipe;
199: }
200: sg2d.shapepipe = nontxPipe;
201: switch (sg2d.textAntialiasHint) {
202:
203: case SunHints.INTVAL_TEXT_ANTIALIAS_DEFAULT:
204: /* equate DEFAULT to OFF which it is for us */
205: case SunHints.INTVAL_TEXT_ANTIALIAS_OFF:
206: sg2d.textpipe = solidTextRenderer;
207: break;
208:
209: case SunHints.INTVAL_TEXT_ANTIALIAS_ON:
210: sg2d.textpipe = aaTextRenderer;
211: break;
212:
213: default:
214: switch (sg2d.getFontInfo().aaHint) {
215:
216: case SunHints.INTVAL_TEXT_ANTIALIAS_LCD_HRGB:
217: case SunHints.INTVAL_TEXT_ANTIALIAS_LCD_VRGB:
218: sg2d.textpipe = lcdTextRenderer;
219: break;
220:
221: case SunHints.INTVAL_TEXT_ANTIALIAS_ON:
222: sg2d.textpipe = aaTextRenderer;
223: break;
224:
225: default:
226: sg2d.textpipe = solidTextRenderer;
227: }
228: }
229: // This is needed for AA text.
230: // Note that even a SolidTextRenderer can dispatch AA text
231: // if a GlyphVector overrides the AA setting.
232: sg2d.loops = solidloops;
233: } else {
234: super .validatePipe(sg2d);
235: }
236: }
237:
238: public static boolean isDDScaleEnabled() {
239: return WindowsFlags.isDDScaleEnabled();
240: }
241:
242: private WritableRasterNative wrn = null;
243:
244: public synchronized Raster getRaster(int x, int y, int w, int h) {
245: if (wrn == null) {
246: wrn = WritableRasterNative.createNativeRaster(
247: getColorModel(), this , width, height);
248: if (wrn == null) {
249: throw new InternalError(
250: "Unable to create native raster");
251: }
252: }
253:
254: return wrn;
255: }
256:
257: public RenderLoops getRenderLoops(SunGraphics2D sg2d) {
258: if (sg2d.paintState <= sg2d.PAINT_ALPHACOLOR
259: && sg2d.compositeState <= sg2d.COMP_ISCOPY) {
260: return solidloops;
261: }
262: return super .getRenderLoops(sg2d);
263: }
264:
265: public GraphicsConfiguration getDeviceConfiguration() {
266: return graphicsConfig;
267: }
268:
269: /**
270: * Initializes the native Ops pointer.
271: */
272: private native void initOps(int depth, int transparency);
273:
274: /**
275: * This native method creates the offscreen surface in video memory and
276: * (if necessary) initializes DirectDraw
277: */
278: private native void initSurface(int depth, int width, int height,
279: int screen, boolean isVolatile, int transparency);
280:
281: public native void restoreSurface();
282:
283: /**
284: * Non-public constructor. Use createData() to create an object.
285: *
286: * This constructor is used to house the common construction
287: * code shared between the creation of Win32OSSD objects
288: * and subclasses of Win32OSSD (such as D3DSurfaceData
289: * and WinBackBufferSurfaceData).
290: *
291: * It calls the common constructor in the parent, and then
292: * initializes other shared Win32 data.
293: */
294: protected Win32OffScreenSurfaceData(int width, int height,
295: SurfaceType sType, ColorModel cm, GraphicsConfiguration gc,
296: Image image, int transparency) {
297: super (sType, cm);
298: this .width = width;
299: this .height = height;
300: this .graphicsConfig = gc;
301: this .image = image;
302: this .transparency = transparency;
303: this .solidloops = ((Win32GraphicsConfig) graphicsConfig)
304: .getSolidLoops(sType);
305: initOps(cm.getPixelSize(), transparency);
306: }
307:
308: /**
309: * Private constructor. Use createData() to create an object.
310: *
311: * This constructor calls the common constructor above and then
312: * performs the specific initialization of the Win32Surface.
313: */
314: private Win32OffScreenSurfaceData(int width, int height,
315: SurfaceType sType, ColorModel cm, Win32GraphicsConfig gc,
316: Image image, int transparency, int screen) {
317: this (width, height, sType, cm, gc, image, transparency);
318: initSurface(cm.getPixelSize(), width, height, screen,
319: (image instanceof SunVolatileImage), transparency);
320: setBlitProxyKey(gc.getProxyKey());
321: }
322:
323: /**
324: * Need this since the surface data is created with
325: * the color model of the target GC, which is always
326: * opaque. But in SunGraphics2D.blitSD we choose loops
327: * based on the transparency on the source SD, so
328: * we could choose wrong loop (blit instead of blitbg,
329: * for example, which will cause problems in transparent
330: * case).
331: */
332: public int getTransparency() {
333: return transparency;
334: }
335:
336: /**
337: * When someone asks for a new surface data, we punt to our
338: * container image which will attempt to restore the contents
339: * of this surface or, failing that, will return null.
340: */
341: public SurfaceData getReplacement() {
342: return restoreContents(image);
343: }
344:
345: public Rectangle getBounds() {
346: return new Rectangle(width, height);
347: }
348:
349: protected native void nativeInvalidate();
350:
351: public void invalidate() {
352: if (isValid()) {
353: synchronized (this ) {
354: wrn = null;
355: }
356: nativeInvalidate();
357: super .invalidate();
358: }
359: }
360:
361: public native void setTransparentPixel(int pixel);
362:
363: public native void flush();
364:
365: /**
366: * Returns true if the native representation of this image has been
367: * moved into ddraw system memory. This happens when many reads
368: * or read-modify-write operations are requested of that surface.
369: * If we have moved that surface into system memory, we should note that
370: * here so that someone wanting to copy something to this surface will
371: * take that into account during that copy.
372: */
373: public boolean surfacePunted() {
374: return ddSurfacePunted;
375: }
376:
377: protected void markSurfaceLost() {
378: synchronized (this ) {
379: wrn = null;
380: }
381: setSurfaceLost(true);
382: if (image != null) {
383: // Inform the Volatile that it lost its accelerated surface
384: SurfaceManager sMgr = SurfaceManager.getManager(image);
385: sMgr.acceleratedSurfaceLost();
386: }
387: }
388:
389: /**
390: * This method is called from the native code if an unrecoverable
391: * error has been detected.
392: *
393: * Marks the surface lost, and notifies the surface manager
394: * that the DirectDraw acceleration for the corresponding image
395: * should be disabled.
396: */
397: protected void disableDD() {
398: markSurfaceLost();
399: if (image != null) {
400: SurfaceManager sMgr = SurfaceManager.getManager(image);
401: // REMIND: yes, this is not pretty; the accelerationEnabled property
402: // should be pulled up to SurfaceManager some day.
403: if (sMgr instanceof WinVolatileSurfaceManager) {
404: ((WinVolatileSurfaceManager) sMgr)
405: .setAccelerationEnabled(false);
406: }
407: }
408: setBlitProxyKey(null);
409: }
410:
411: /**
412: * Returns destination Image associated with this SurfaceData.
413: */
414: public Object getDestination() {
415: return image;
416: }
417:
418: @Override
419: public boolean copyArea(SunGraphics2D sg2d, int x, int y, int w,
420: int h, int dx, int dy) {
421: CompositeType comptype = sg2d.imageComp;
422: if (sg2d.transformState < sg2d.TRANSFORM_TRANSLATESCALE
423: && sg2d.clipState != sg2d.CLIP_SHAPE
424: && (CompositeType.SrcOverNoEa.equals(comptype) || CompositeType.SrcNoEa
425: .equals(comptype))) {
426: x += sg2d.transX;
427: y += sg2d.transY;
428: int dstx1 = x + dx;
429: int dsty1 = y + dy;
430: int dstx2 = dstx1 + w;
431: int dsty2 = dsty1 + h;
432: Region clip = sg2d.getCompClip();
433: if (dstx1 < clip.getLoX())
434: dstx1 = clip.getLoX();
435: if (dsty1 < clip.getLoY())
436: dsty1 = clip.getLoY();
437: if (dstx2 > clip.getHiX())
438: dstx2 = clip.getHiX();
439: if (dsty2 > clip.getHiY())
440: dsty2 = clip.getHiY();
441: if (dstx1 < dstx2 && dsty1 < dsty2) {
442: ddPipe.devCopyArea(this , dstx1 - dx, dsty1 - dy, dx,
443: dy, dstx2 - dstx1, dsty2 - dsty1);
444: }
445: return true;
446: }
447: return false;
448: }
449: }
|