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