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