001: /*
002: * Copyright 1999-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.x11;
027:
028: import java.awt.GraphicsDevice;
029: import java.awt.GraphicsEnvironment;
030: import java.awt.Color;
031: import java.awt.Composite;
032: import java.awt.Rectangle;
033: import java.awt.GraphicsConfiguration;
034: import java.awt.Image;
035: import java.awt.color.ColorSpace;
036: import java.awt.Transparency;
037: import java.awt.image.BufferedImage;
038: import java.awt.image.ColorModel;
039: import java.awt.image.ComponentColorModel;
040: import java.awt.image.DirectColorModel;
041: import java.awt.image.IndexColorModel;
042: import java.awt.image.Raster;
043: import java.awt.peer.ComponentPeer;
044:
045: import sun.awt.SunHints;
046: import sun.awt.SunToolkit;
047: import sun.awt.X11ComponentPeer;
048: import sun.awt.X11GraphicsConfig;
049: import sun.awt.image.PixelConverter;
050: import sun.font.X11TextRenderer;
051: import sun.java2d.InvalidPipeException;
052: import sun.java2d.SunGraphics2D;
053: import sun.java2d.SurfaceData;
054: import sun.java2d.SurfaceDataProxy;
055: import sun.java2d.loops.SurfaceType;
056: import sun.java2d.loops.CompositeType;
057: import sun.java2d.loops.RenderLoops;
058: import sun.java2d.loops.GraphicsPrimitive;
059: import sun.java2d.loops.XORComposite;
060: import sun.java2d.loops.Blit;
061: import sun.java2d.pipe.ValidatePipe;
062: import sun.java2d.pipe.PixelToShapeConverter;
063: import sun.java2d.pipe.TextPipe;
064: import sun.java2d.pipe.Region;
065:
066: public abstract class X11SurfaceData extends SurfaceData {
067: X11ComponentPeer peer;
068: X11GraphicsConfig graphicsConfig;
069: private RenderLoops solidloops;
070:
071: protected int depth;
072:
073: private static native void initIDs(Class xorComp, boolean tryDGA);
074:
075: protected native void initSurface(int depth, int width, int height,
076: long drawable);
077:
078: native boolean isDrawableValid();
079:
080: protected native void flushNativeSurface();
081:
082: public static final String DESC_INT_BGR_X11 = "Integer BGR Pixmap";
083: public static final String DESC_INT_RGB_X11 = "Integer RGB Pixmap";
084: public static final String DESC_BYTE_IND_OPQ_X11 = "Byte Indexed Opaque Pixmap";
085:
086: public static final String DESC_INT_BGR_X11_BM = "Integer BGR Pixmap with 1-bit transp";
087: public static final String DESC_INT_RGB_X11_BM = "Integer RGB Pixmap with 1-bit transp";
088: public static final String DESC_BYTE_IND_X11_BM = "Byte Indexed Pixmap with 1-bit transp";
089:
090: public static final String DESC_BYTE_GRAY_X11 = "Byte Gray Opaque Pixmap";
091: public static final String DESC_INDEX8_GRAY_X11 = "Index8 Gray Opaque Pixmap";
092:
093: public static final String DESC_BYTE_GRAY_X11_BM = "Byte Gray Opaque Pixmap with 1-bit transp";
094: public static final String DESC_INDEX8_GRAY_X11_BM = "Index8 Gray Opaque Pixmap with 1-bit transp";
095:
096: public static final String DESC_3BYTE_RGB_X11 = "3 Byte RGB Pixmap";
097: public static final String DESC_3BYTE_BGR_X11 = "3 Byte BGR Pixmap";
098:
099: public static final String DESC_3BYTE_RGB_X11_BM = "3 Byte RGB Pixmap with 1-bit transp";
100: public static final String DESC_3BYTE_BGR_X11_BM = "3 Byte BGR Pixmap with 1-bit transp";
101:
102: public static final String DESC_USHORT_555_RGB_X11 = "Ushort 555 RGB Pixmap";
103: public static final String DESC_USHORT_565_RGB_X11 = "Ushort 565 RGB Pixmap";
104:
105: public static final String DESC_USHORT_555_RGB_X11_BM = "Ushort 555 RGB Pixmap with 1-bit transp";
106: public static final String DESC_USHORT_565_RGB_X11_BM = "Ushort 565 RGB Pixmap with 1-bit transp";
107: public static final String DESC_USHORT_INDEXED_X11 = "Ushort Indexed Pixmap";
108:
109: public static final String DESC_USHORT_INDEXED_X11_BM = "Ushort Indexed Pixmap with 1-bit transp";
110:
111: public static final SurfaceType IntBgrX11 = SurfaceType.IntBgr
112: .deriveSubType(DESC_INT_BGR_X11);
113: public static final SurfaceType IntRgbX11 = SurfaceType.IntRgb
114: .deriveSubType(DESC_INT_RGB_X11);
115:
116: public static final SurfaceType ThreeByteRgbX11 = SurfaceType.ThreeByteRgb
117: .deriveSubType(DESC_3BYTE_RGB_X11);
118: public static final SurfaceType ThreeByteBgrX11 = SurfaceType.ThreeByteBgr
119: .deriveSubType(DESC_3BYTE_BGR_X11);
120:
121: public static final SurfaceType UShort555RgbX11 = SurfaceType.Ushort555Rgb
122: .deriveSubType(DESC_USHORT_555_RGB_X11);
123: public static final SurfaceType UShort565RgbX11 = SurfaceType.Ushort565Rgb
124: .deriveSubType(DESC_USHORT_565_RGB_X11);
125:
126: public static final SurfaceType UShortIndexedX11 = SurfaceType.UshortIndexed
127: .deriveSubType(DESC_USHORT_INDEXED_X11);
128:
129: public static final SurfaceType ByteIndexedOpaqueX11 = SurfaceType.ByteIndexedOpaque
130: .deriveSubType(DESC_BYTE_IND_OPQ_X11);
131:
132: public static final SurfaceType ByteGrayX11 = SurfaceType.ByteGray
133: .deriveSubType(DESC_BYTE_GRAY_X11);
134: public static final SurfaceType Index8GrayX11 = SurfaceType.Index8Gray
135: .deriveSubType(DESC_INDEX8_GRAY_X11);
136:
137: // Bitmap surface types
138: public static final SurfaceType IntBgrX11_BM = SurfaceType.Custom
139: .deriveSubType(DESC_INT_BGR_X11_BM,
140: PixelConverter.Xbgr.instance);
141: public static final SurfaceType IntRgbX11_BM = SurfaceType.Custom
142: .deriveSubType(DESC_INT_RGB_X11_BM,
143: PixelConverter.Xrgb.instance);
144:
145: public static final SurfaceType ThreeByteRgbX11_BM = SurfaceType.Custom
146: .deriveSubType(DESC_3BYTE_RGB_X11_BM,
147: PixelConverter.Xbgr.instance);
148: public static final SurfaceType ThreeByteBgrX11_BM = SurfaceType.Custom
149: .deriveSubType(DESC_3BYTE_BGR_X11_BM,
150: PixelConverter.Xrgb.instance);
151:
152: public static final SurfaceType UShort555RgbX11_BM = SurfaceType.Custom
153: .deriveSubType(DESC_USHORT_555_RGB_X11_BM,
154: PixelConverter.Ushort555Rgb.instance);
155: public static final SurfaceType UShort565RgbX11_BM = SurfaceType.Custom
156: .deriveSubType(DESC_USHORT_565_RGB_X11_BM,
157: PixelConverter.Ushort565Rgb.instance);
158:
159: public static final SurfaceType UShortIndexedX11_BM = SurfaceType.Custom
160: .deriveSubType(DESC_USHORT_INDEXED_X11_BM);
161:
162: public static final SurfaceType ByteIndexedX11_BM = SurfaceType.Custom
163: .deriveSubType(DESC_BYTE_IND_X11_BM);
164:
165: public static final SurfaceType ByteGrayX11_BM = SurfaceType.Custom
166: .deriveSubType(DESC_BYTE_GRAY_X11_BM);
167: public static final SurfaceType Index8GrayX11_BM = SurfaceType.Custom
168: .deriveSubType(DESC_INDEX8_GRAY_X11_BM);
169:
170: private static Boolean accelerationEnabled = null;
171:
172: public Raster getRaster(int x, int y, int w, int h) {
173: throw new InternalError("not implemented yet");
174: }
175:
176: protected X11Renderer x11pipe;
177: protected PixelToShapeConverter x11txpipe;
178: protected static TextPipe x11textpipe;
179: protected static boolean dgaAvailable;
180:
181: static {
182: if (!GraphicsEnvironment.isHeadless()) {
183: // If a screen magnifier is present, don't attempt to use DGA
184: String magPresent = (String) java.security.AccessController
185: .doPrivileged(new sun.security.action.GetPropertyAction(
186: "javax.accessibility.screen_magnifier_present"));
187: boolean tryDGA = magPresent == null
188: || !"true".equals(magPresent);
189:
190: initIDs(XORComposite.class, tryDGA);
191:
192: String xtextpipe = (String) java.security.AccessController
193: .doPrivileged(new sun.security.action.GetPropertyAction(
194: "sun.java2d.xtextpipe"));
195: if (xtextpipe == null || "true".startsWith(xtextpipe)) {
196: if ("true".equals(xtextpipe)) {
197: // Only verbose if they use the full string "true"
198: System.out.println("using X11 text renderer");
199: }
200: x11textpipe = new X11TextRenderer();
201: if (GraphicsPrimitive.tracingEnabled()) {
202: x11textpipe = ((X11TextRenderer) x11textpipe)
203: .traceWrap();
204: }
205: } else {
206: if ("false".equals(xtextpipe)) {
207: // Only verbose if they use the full string "false"
208: System.out.println("using DGA text renderer");
209: }
210: x11textpipe = solidTextRenderer;
211: }
212:
213: dgaAvailable = isDgaAvailable();
214:
215: if (isAccelerationEnabled()) {
216: X11PMBlitLoops.register();
217: X11PMBlitBgLoops.register();
218: }
219: }
220: }
221:
222: /**
223: * Returns true if we can use DGA on any of the screens
224: */
225: public static native boolean isDgaAvailable();
226:
227: public static boolean isAccelerationEnabled() {
228: if (accelerationEnabled == null) {
229:
230: if (GraphicsEnvironment.isHeadless()) {
231: accelerationEnabled = Boolean.FALSE;
232: } else {
233: String prop = (String) java.security.AccessController
234: .doPrivileged(new sun.security.action.GetPropertyAction(
235: "sun.java2d.pmoffscreen"));
236: if (prop != null) {
237: // true iff prop==true, false otherwise
238: accelerationEnabled = Boolean.valueOf(prop);
239: } else {
240: // use pixmaps if there is no dga, no matter local or remote
241: accelerationEnabled = Boolean
242: .valueOf(!isDgaAvailable());
243: }
244: }
245: }
246: return accelerationEnabled.booleanValue();
247: }
248:
249: @Override
250: public SurfaceDataProxy makeProxyFor(SurfaceData srcData) {
251: return X11SurfaceDataProxy.createProxy(srcData, graphicsConfig);
252: }
253:
254: public void validatePipe(SunGraphics2D sg2d) {
255: if (sg2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON
256: && sg2d.paintState <= sg2d.PAINT_ALPHACOLOR
257: && (sg2d.compositeState <= sg2d.COMP_ISCOPY || sg2d.compositeState == sg2d.COMP_XOR)) {
258: if (x11txpipe == null) {
259: /*
260: * Note: this is thread-safe since x11txpipe is the
261: * second of the two pipes constructed in makePipes().
262: * In the rare case we are racing against another
263: * thread making new pipes, setting lazypipe is a
264: * safe alternative to waiting for the other thread.
265: */
266: sg2d.drawpipe = lazypipe;
267: sg2d.fillpipe = lazypipe;
268: sg2d.shapepipe = lazypipe;
269: sg2d.imagepipe = lazypipe;
270: sg2d.textpipe = lazypipe;
271: return;
272: }
273:
274: if (sg2d.clipState == sg2d.CLIP_SHAPE) {
275: // Do this to init textpipe correctly; we will override the
276: // other non-text pipes below
277: // REMIND: we should clean this up eventually instead of
278: // having this work duplicated.
279: super .validatePipe(sg2d);
280: } else {
281: switch (sg2d.textAntialiasHint) {
282:
283: case SunHints.INTVAL_TEXT_ANTIALIAS_DEFAULT:
284: /* equating to OFF which it is for us */
285: case SunHints.INTVAL_TEXT_ANTIALIAS_OFF:
286: // Use X11 pipe even if DGA is available since DGA
287: // text slows everything down when mixed with X11 calls
288: if (sg2d.compositeState == sg2d.COMP_ISCOPY) {
289: sg2d.textpipe = x11textpipe;
290: } else {
291: sg2d.textpipe = solidTextRenderer;
292: }
293: break;
294:
295: case SunHints.INTVAL_TEXT_ANTIALIAS_ON:
296: // Remind: may use Xrender for these when composite is
297: // copy as above, or if remote X11.
298: sg2d.textpipe = aaTextRenderer;
299: break;
300:
301: default:
302: switch (sg2d.getFontInfo().aaHint) {
303:
304: case SunHints.INTVAL_TEXT_ANTIALIAS_LCD_HRGB:
305: case SunHints.INTVAL_TEXT_ANTIALIAS_LCD_VRGB:
306: sg2d.textpipe = lcdTextRenderer;
307: break;
308:
309: case SunHints.INTVAL_TEXT_ANTIALIAS_OFF:
310: // Use X11 pipe even if DGA is available since DGA
311: // text slows everything down when mixed with X11 calls
312: if (sg2d.compositeState == sg2d.COMP_ISCOPY) {
313: sg2d.textpipe = x11textpipe;
314: } else {
315: sg2d.textpipe = solidTextRenderer;
316: }
317: break;
318:
319: case SunHints.INTVAL_TEXT_ANTIALIAS_ON:
320: sg2d.textpipe = aaTextRenderer;
321: break;
322:
323: default:
324: sg2d.textpipe = solidTextRenderer;
325: }
326: }
327: }
328:
329: if (sg2d.transformState >= sg2d.TRANSFORM_TRANSLATESCALE) {
330: sg2d.drawpipe = x11txpipe;
331: sg2d.fillpipe = x11txpipe;
332: } else if (sg2d.strokeState != sg2d.STROKE_THIN) {
333: sg2d.drawpipe = x11txpipe;
334: sg2d.fillpipe = x11pipe;
335: } else {
336: sg2d.drawpipe = x11pipe;
337: sg2d.fillpipe = x11pipe;
338: }
339: sg2d.shapepipe = x11pipe;
340: sg2d.imagepipe = imagepipe;
341:
342: // This is needed for AA text.
343: // Note that even an X11TextRenderer can dispatch AA text
344: // if a GlyphVector overrides the AA setting.
345: // We use getRenderLoops() rather than setting solidloops
346: // directly so that we get the appropriate loops in XOR mode.
347: sg2d.loops = getRenderLoops(sg2d);
348: } else {
349: super .validatePipe(sg2d);
350: }
351: }
352:
353: public RenderLoops getRenderLoops(SunGraphics2D sg2d) {
354: if (sg2d.paintState <= sg2d.PAINT_ALPHACOLOR
355: && sg2d.compositeState <= sg2d.COMP_ISCOPY) {
356: return solidloops;
357: }
358: return super .getRenderLoops(sg2d);
359: }
360:
361: public GraphicsConfiguration getDeviceConfiguration() {
362: return graphicsConfig;
363: }
364:
365: /**
366: * Method for instantiating a Window SurfaceData
367: */
368: public static X11WindowSurfaceData createData(X11ComponentPeer peer) {
369: X11GraphicsConfig gc = getGC(peer);
370: return new X11WindowSurfaceData(peer, gc, gc.getSurfaceType());
371: }
372:
373: /**
374: * Method for instantiating a Pixmap SurfaceData (offscreen)
375: */
376: public static X11PixmapSurfaceData createData(X11GraphicsConfig gc,
377: int width, int height, ColorModel cm, Image image,
378: long drawable, int transparency) {
379: return new X11PixmapSurfaceData(gc, width, height, image,
380: getSurfaceType(gc, transparency), cm, drawable,
381: transparency);
382: }
383:
384: /**
385: * Initializes the native Ops pointer.
386: */
387: private native void initOps(X11ComponentPeer peer,
388: X11GraphicsConfig gc, int depth);
389:
390: protected X11SurfaceData(X11ComponentPeer peer,
391: X11GraphicsConfig gc, SurfaceType sType, ColorModel cm) {
392: super (sType, cm);
393: this .peer = peer;
394: this .graphicsConfig = gc;
395: this .solidloops = graphicsConfig.getSolidLoops(sType);
396: this .depth = cm.getPixelSize();
397: initOps(peer, graphicsConfig, depth);
398: if (isAccelerationEnabled()) {
399: setBlitProxyKey(gc.getProxyKey());
400: }
401: }
402:
403: public static X11GraphicsConfig getGC(X11ComponentPeer peer) {
404: if (peer != null) {
405: return (X11GraphicsConfig) peer.getGraphicsConfiguration();
406: } else {
407: GraphicsEnvironment env = GraphicsEnvironment
408: .getLocalGraphicsEnvironment();
409: GraphicsDevice gd = env.getDefaultScreenDevice();
410: return (X11GraphicsConfig) gd.getDefaultConfiguration();
411: }
412: }
413:
414: /**
415: * Returns a boolean indicating whether or not a copyArea from
416: * the given rectangle source coordinates might be incomplete
417: * and result in X11 GraphicsExposure events being generated
418: * from XCopyArea.
419: * This method allows the SurfaceData copyArea method to determine
420: * if it needs to set the GraphicsExposures attribute of the X11 GC
421: * to True or False to receive or avoid the events.
422: * @return true if there is any chance that an XCopyArea from the
423: * given source coordinates could produce any X11
424: * Exposure events.
425: */
426: public abstract boolean canSourceSendExposures(int x, int y, int w,
427: int h);
428:
429: public boolean copyArea(SunGraphics2D sg2d, int x, int y, int w,
430: int h, int dx, int dy) {
431: if (x11pipe == null) {
432: if (!isDrawableValid()) {
433: return true;
434: }
435: makePipes();
436: }
437: CompositeType comptype = sg2d.imageComp;
438: if (sg2d.transformState < sg2d.TRANSFORM_TRANSLATESCALE
439: && (CompositeType.SrcOverNoEa.equals(comptype) || CompositeType.SrcNoEa
440: .equals(comptype))) {
441: x += sg2d.transX;
442: y += sg2d.transY;
443: SunToolkit.awtLock();
444: try {
445: boolean needExposures = canSourceSendExposures(x, y, w,
446: h);
447: long xgc = getBlitGC(sg2d.getCompClip(), needExposures);
448: x11pipe.devCopyArea(getNativeOps(), xgc, x, y, x + dx,
449: y + dy, w, h);
450: } finally {
451: SunToolkit.awtUnlock();
452: }
453: return true;
454: }
455: return false;
456: }
457:
458: public static SurfaceType getSurfaceType(X11GraphicsConfig gc,
459: int transparency) {
460: boolean transparent = (transparency == Transparency.BITMASK);
461: SurfaceType sType;
462: ColorModel cm = gc.getColorModel();
463: switch (cm.getPixelSize()) {
464: case 24:
465: if (gc.getBitsPerPixel() == 24) {
466: if (cm instanceof DirectColorModel) {
467: // 4517321: We will always use ThreeByteBgr for 24 bpp
468: // surfaces, regardless of the pixel masks reported by
469: // X11. Despite ambiguity in the X11 spec in how 24 bpp
470: // surfaces are treated, it appears that the best
471: // SurfaceType for these configurations (including
472: // some Matrox Millenium and ATI Radeon boards) is
473: // ThreeByteBgr.
474: sType = transparent ? X11SurfaceData.ThreeByteBgrX11_BM
475: : X11SurfaceData.ThreeByteBgrX11;
476: } else {
477: throw new sun.java2d.InvalidPipeException(
478: "Unsupported bit " + "depth/cm combo: "
479: + cm.getPixelSize() + ", " + cm);
480: }
481: break;
482: }
483: // Fall through for 32 bit case
484: case 32:
485: if (cm instanceof DirectColorModel) {
486: if (((DirectColorModel) cm).getRedMask() == 0xff0000) {
487: sType = transparent ? X11SurfaceData.IntRgbX11_BM
488: : X11SurfaceData.IntRgbX11;
489: } else {
490: sType = transparent ? X11SurfaceData.IntBgrX11_BM
491: : X11SurfaceData.IntBgrX11;
492: }
493: } else {
494: throw new sun.java2d.InvalidPipeException(
495: "Unsupported bit " + "depth/cm combo: "
496: + cm.getPixelSize() + ", " + cm);
497: }
498: break;
499: case 15:
500: sType = transparent ? X11SurfaceData.UShort555RgbX11_BM
501: : X11SurfaceData.UShort555RgbX11;
502: break;
503: case 16:
504: if ((cm instanceof DirectColorModel)
505: && (((DirectColorModel) cm).getGreenMask() == 0x3e0)) {
506: // fix for 4352984: Riva128 on Linux
507: sType = transparent ? X11SurfaceData.UShort555RgbX11_BM
508: : X11SurfaceData.UShort555RgbX11;
509: } else {
510: sType = transparent ? X11SurfaceData.UShort565RgbX11_BM
511: : X11SurfaceData.UShort565RgbX11;
512: }
513: break;
514: case 12:
515: if (cm instanceof IndexColorModel) {
516: sType = transparent ? X11SurfaceData.UShortIndexedX11_BM
517: : X11SurfaceData.UShortIndexedX11;
518: } else {
519: throw new sun.java2d.InvalidPipeException(
520: "Unsupported bit " + "depth: "
521: + cm.getPixelSize() + " cm=" + cm);
522: }
523: break;
524: case 8:
525: if (cm.getColorSpace().getType() == ColorSpace.TYPE_GRAY
526: && cm instanceof ComponentColorModel) {
527: sType = transparent ? X11SurfaceData.ByteGrayX11_BM
528: : X11SurfaceData.ByteGrayX11;
529: } else if (cm instanceof IndexColorModel
530: && isOpaqueGray((IndexColorModel) cm)) {
531: sType = transparent ? X11SurfaceData.Index8GrayX11_BM
532: : X11SurfaceData.Index8GrayX11;
533: } else {
534: sType = transparent ? X11SurfaceData.ByteIndexedX11_BM
535: : X11SurfaceData.ByteIndexedOpaqueX11;
536: }
537: break;
538: default:
539: throw new sun.java2d.InvalidPipeException(
540: "Unsupported bit " + "depth: " + cm.getPixelSize());
541: }
542: return sType;
543: }
544:
545: public native void setInvalid();
546:
547: public void invalidate() {
548: if (isValid()) {
549: setInvalid();
550: super .invalidate();
551: }
552: }
553:
554: /**
555: * The following methods and variables are used to keep the Java-level
556: * context state in sync with the native X11 GC associated with this
557: * X11SurfaceData object.
558: */
559:
560: private static native long XCreateGC(long pXSData);
561:
562: private static native void XResetClip(long xgc);
563:
564: private static native void XSetClip(long xgc, int lox, int loy,
565: int hix, int hiy, Region complexclip);
566:
567: private static native void XSetCopyMode(long xgc);
568:
569: private static native void XSetXorMode(long xgc);
570:
571: private static native void XSetForeground(long xgc, int pixel);
572:
573: private static native void XSetGraphicsExposures(long xgc,
574: boolean needExposures);
575:
576: private long xgc;
577: private Region validatedClip;
578: private XORComposite validatedXorComp;
579: private int xorpixelmod;
580: private int validatedPixel;
581: private boolean validatedExposures = true;
582:
583: public final long getRenderGC(Region clip, int compState,
584: Composite comp, int pixel) {
585: return getGC(clip, compState, comp, pixel, validatedExposures);
586: }
587:
588: public final long getBlitGC(Region clip, boolean needExposures) {
589: return getGC(clip, SunGraphics2D.COMP_ISCOPY, null,
590: validatedPixel, needExposures);
591: }
592:
593: final long getGC(Region clip, int compState, Composite comp,
594: int pixel, boolean needExposures) {
595: // assert SunToolkit.isAWTLockHeldByCurrentThread();
596:
597: if (!isValid()) {
598: throw new InvalidPipeException("bounds changed");
599: }
600:
601: // validate clip
602: if (clip != validatedClip) {
603: validatedClip = clip;
604: if (clip != null) {
605: XSetClip(xgc, clip.getLoX(), clip.getLoY(), clip
606: .getHiX(), clip.getHiY(),
607: (clip.isRectangular() ? null : clip));
608: } else {
609: XResetClip(xgc);
610: }
611: }
612:
613: // validate composite
614: if (compState == SunGraphics2D.COMP_ISCOPY) {
615: if (validatedXorComp != null) {
616: validatedXorComp = null;
617: xorpixelmod = 0;
618: XSetCopyMode(xgc);
619: }
620: } else {
621: if (validatedXorComp != comp) {
622: validatedXorComp = (XORComposite) comp;
623: xorpixelmod = validatedXorComp.getXorPixel();
624: XSetXorMode(xgc);
625: }
626: }
627:
628: // validate pixel
629: pixel ^= xorpixelmod;
630: if (pixel != validatedPixel) {
631: validatedPixel = pixel;
632: XSetForeground(xgc, pixel);
633: }
634:
635: if (validatedExposures != needExposures) {
636: validatedExposures = needExposures;
637: XSetGraphicsExposures(xgc, needExposures);
638: }
639:
640: return xgc;
641: }
642:
643: public synchronized void makePipes() {
644: if (x11pipe == null) {
645: SunToolkit.awtLock();
646: try {
647: xgc = XCreateGC(getNativeOps());
648: } finally {
649: SunToolkit.awtUnlock();
650: }
651: x11pipe = X11Renderer.getInstance();
652: x11txpipe = new PixelToShapeConverter(x11pipe);
653: }
654: }
655:
656: public static class X11WindowSurfaceData extends X11SurfaceData {
657: public X11WindowSurfaceData(X11ComponentPeer peer,
658: X11GraphicsConfig gc, SurfaceType sType) {
659: super (peer, gc, sType, peer.getColorModel());
660: if (isDrawableValid()) {
661: makePipes();
662: }
663: }
664:
665: public SurfaceData getReplacement() {
666: return peer.getSurfaceData();
667: }
668:
669: public Rectangle getBounds() {
670: Rectangle r = peer.getBounds();
671: r.x = r.y = 0;
672: return r;
673: }
674:
675: @Override
676: public boolean canSourceSendExposures(int x, int y, int w, int h) {
677: return true;
678: }
679:
680: /**
681: * Returns destination Component associated with this SurfaceData.
682: */
683: public Object getDestination() {
684: return peer.getTarget();
685: }
686: }
687:
688: public static class X11PixmapSurfaceData extends X11SurfaceData {
689:
690: Image offscreenImage;
691: int width;
692: int height;
693: int transparency;
694:
695: public X11PixmapSurfaceData(X11GraphicsConfig gc, int width,
696: int height, Image image, SurfaceType sType,
697: ColorModel cm, long drawable, int transparency) {
698: super (null, gc, sType, cm);
699: this .width = width;
700: this .height = height;
701: offscreenImage = image;
702: this .transparency = transparency;
703: initSurface(depth, width, height, drawable);
704: makePipes();
705: }
706:
707: public SurfaceData getReplacement() {
708: return restoreContents(offscreenImage);
709: }
710:
711: /**
712: * Need this since the surface data is created with
713: * the color model of the target GC, which is always
714: * opaque. But in SunGraphics2D.blitSD we choose loops
715: * based on the transparency on the source SD, so
716: * it could choose wrong loop (blit instead of blitbg,
717: * for example).
718: */
719: public int getTransparency() {
720: return transparency;
721: }
722:
723: public Rectangle getBounds() {
724: return new Rectangle(width, height);
725: }
726:
727: @Override
728: public boolean canSourceSendExposures(int x, int y, int w, int h) {
729: return (x < 0 || y < 0 || (x + w) > width || (y + h) > height);
730: }
731:
732: public void flush() {
733: /*
734: * We need to invalidate the surface before disposing the
735: * native Drawable and GC. This way if an application tries
736: * to render to an already flushed X11SurfaceData, we will notice
737: * in the validate() method above that it has been invalidated,
738: * and we will avoid using those native resources that have
739: * already been disposed.
740: */
741: invalidate();
742: flushNativeSurface();
743: }
744:
745: /**
746: * Returns destination Image associated with this SurfaceData.
747: */
748: public Object getDestination() {
749: return offscreenImage;
750: }
751: }
752:
753: private static LazyPipe lazypipe = new LazyPipe();
754:
755: public static class LazyPipe extends ValidatePipe {
756: public boolean validate(SunGraphics2D sg2d) {
757: X11SurfaceData xsd = (X11SurfaceData) sg2d.surfaceData;
758: if (!xsd.isDrawableValid()) {
759: return false;
760: }
761: xsd.makePipes();
762: return super.validate(sg2d);
763: }
764: }
765: }
|