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, boolean tryDGA); 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 // If a screen magnifier is present, don't attempt to use DGA 217 String magPresent = java.security.AccessController.doPrivileged 218 (new sun.security.action.GetPropertyAction("javax.accessibility.screen_magnifier_present")); 219 boolean tryDGA = magPresent == null || !"true".equals(magPresent); 220 221 initIDs(XORComposite.class, tryDGA); 222 223 String xtextpipe = java.security.AccessController.doPrivileged 224 (new sun.security.action.GetPropertyAction("sun.java2d.xtextpipe")); 225 if (xtextpipe == null || "true".startsWith(xtextpipe)) { 226 if ("true".equals(xtextpipe)) { 227 // Only verbose if they use the full string "true" 228 System.out.println("using X11 text renderer"); 229 } 230 x11textpipe = new X11TextRenderer(); 231 if (GraphicsPrimitive.tracingEnabled()) { 232 x11textpipe = ((X11TextRenderer) x11textpipe).traceWrap(); 233 } 234 } else { 235 if ("false".equals(xtextpipe)) { 236 // Only verbose if they use the full string "false" 237 System.out.println("using DGA text renderer"); 238 } 239 x11textpipe = solidTextRenderer; 240 } 241 242 dgaAvailable = isDgaAvailable(); 243 244 if (isAccelerationEnabled()) { 245 X11PMBlitLoops.register(); 246 X11PMBlitBgLoops.register(); 247 } 248 } 249 } 250 251 /** 252 * Returns true if we can use DGA on any of the screens 253 */ 254 public static native boolean isDgaAvailable(); 255 256 /** 257 * Returns true if shared memory pixmaps are available 258 */ 259 private static native boolean isShmPMAvailable(); 260 261 public static boolean isAccelerationEnabled() { 262 if (accelerationEnabled == null) { 263 264 if (GraphicsEnvironment.isHeadless()) { 265 accelerationEnabled = Boolean.FALSE; 266 } else { 267 String prop = java.security.AccessController.doPrivileged( 268 new sun.security.action.GetPropertyAction("sun.java2d.pmoffscreen")); 269 if (prop != null) { 270 // true iff prop==true, false otherwise 271 accelerationEnabled = Boolean.valueOf(prop); 272 } else { 273 boolean isDisplayLocal = false; 274 GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); 275 if (ge instanceof SunGraphicsEnvironment) { 276 isDisplayLocal = ((SunGraphicsEnvironment) ge).isDisplayLocal(); 277 } 278 279 // EXA based drivers tend to place pixmaps in VRAM, slowing down readbacks. 280 // Don't use pixmaps if dga is available, 281 // or we are local and shared memory Pixmaps are not available. 282 accelerationEnabled = 283 !(isDgaAvailable() || (isDisplayLocal && !isShmPMAvailable())); 284 } 285 } 286 } 287 return accelerationEnabled.booleanValue(); 288 } 289 290 @Override 291 public SurfaceDataProxy makeProxyFor(SurfaceData srcData) { 292 return X11SurfaceDataProxy.createProxy(srcData, graphicsConfig); 293 } 294 295 public void validatePipe(SunGraphics2D sg2d) { 296 if (sg2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON && 297 sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR && 298 (sg2d.compositeState <= SunGraphics2D.COMP_ISCOPY || 299 sg2d.compositeState == SunGraphics2D.COMP_XOR)) 300 { 301 if (x11txpipe == null) { 302 /* 303 * Note: this is thread-safe since x11txpipe is the 304 * second of the two pipes constructed in makePipes(). 305 * In the rare case we are racing against another 306 * thread making new pipes, setting lazypipe is a 307 * safe alternative to waiting for the other thread. 308 */ 309 sg2d.drawpipe = lazypipe; 310 sg2d.fillpipe = lazypipe; 311 sg2d.shapepipe = lazypipe; 312 sg2d.imagepipe = lazypipe; 313 sg2d.textpipe = lazypipe; 314 return; 315 } 316 317 if (sg2d.clipState == SunGraphics2D.CLIP_SHAPE) { 318 // Do this to init textpipe correctly; we will override the 319 // other non-text pipes below 320 // REMIND: we should clean this up eventually instead of 321 // having this work duplicated. 322 super.validatePipe(sg2d); 323 } else { 324 switch (sg2d.textAntialiasHint) { 325 326 case SunHints.INTVAL_TEXT_ANTIALIAS_DEFAULT: 327 /* equating to OFF which it is for us */ 328 case SunHints.INTVAL_TEXT_ANTIALIAS_OFF: 329 // Use X11 pipe even if DGA is available since DGA 330 // text slows everything down when mixed with X11 calls 331 if (sg2d.compositeState == SunGraphics2D.COMP_ISCOPY) { 332 sg2d.textpipe = x11textpipe; 333 } else { 334 sg2d.textpipe = solidTextRenderer; 335 } 336 break; 337 338 case SunHints.INTVAL_TEXT_ANTIALIAS_ON: 339 // Remind: may use Xrender for these when composite is 340 // copy as above, or if remote X11. 341 sg2d.textpipe = aaTextRenderer; 342 break; 343 344 default: 345 switch (sg2d.getFontInfo().aaHint) { 346 347 case SunHints.INTVAL_TEXT_ANTIALIAS_LCD_HRGB: 348 case SunHints.INTVAL_TEXT_ANTIALIAS_LCD_VRGB: 349 sg2d.textpipe = lcdTextRenderer; 350 break; 351 352 case SunHints.INTVAL_TEXT_ANTIALIAS_OFF: 353 // Use X11 pipe even if DGA is available since DGA 354 // text slows everything down when mixed with X11 calls 355 if (sg2d.compositeState == SunGraphics2D.COMP_ISCOPY) { 356 sg2d.textpipe = x11textpipe; 357 } else { 358 sg2d.textpipe = solidTextRenderer; 359 } 360 break; 361 362 case SunHints.INTVAL_TEXT_ANTIALIAS_ON: 363 sg2d.textpipe = aaTextRenderer; 364 break; 365 366 default: 367 sg2d.textpipe = solidTextRenderer; 368 } 369 } 370 } 371 372 if (sg2d.transformState >= SunGraphics2D.TRANSFORM_TRANSLATESCALE) { 373 sg2d.drawpipe = x11txpipe; 374 sg2d.fillpipe = x11txpipe; 375 } else if (sg2d.strokeState != SunGraphics2D.STROKE_THIN){ 376 sg2d.drawpipe = x11txpipe; 377 sg2d.fillpipe = x11pipe; 378 } else { 379 sg2d.drawpipe = x11pipe; 380 sg2d.fillpipe = x11pipe; 381 } 382 sg2d.shapepipe = x11pipe; 383 sg2d.imagepipe = imagepipe; 384 385 // This is needed for AA text. 386 // Note that even an X11TextRenderer can dispatch AA text 387 // if a GlyphVector overrides the AA setting. 388 // We use getRenderLoops() rather than setting solidloops 389 // directly so that we get the appropriate loops in XOR mode. 390 if (sg2d.loops == null) { 391 // assert(some pipe will always be a LoopBasedPipe) 392 sg2d.loops = getRenderLoops(sg2d); 393 } 394 } else { 395 super.validatePipe(sg2d); 396 } 397 } 398 399 public RenderLoops getRenderLoops(SunGraphics2D sg2d) { 400 if (sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR && 401 sg2d.compositeState <= SunGraphics2D.COMP_ISCOPY) 402 { 403 return solidloops; 404 } 405 return super.getRenderLoops(sg2d); 406 } 407 408 public GraphicsConfiguration getDeviceConfiguration() { 409 return graphicsConfig; 410 } 411 412 /** 413 * Method for instantiating a Window SurfaceData 414 */ 415 public static X11WindowSurfaceData createData(X11ComponentPeer peer) { 416 X11GraphicsConfig gc = getGC(peer); 417 return new X11WindowSurfaceData(peer, gc, gc.getSurfaceType()); 418 } 419 420 /** 421 * Method for instantiating a Pixmap SurfaceData (offscreen) 422 */ 423 public static X11PixmapSurfaceData createData(X11GraphicsConfig gc, 424 int width, int height, 425 ColorModel cm, Image image, 426 long drawable, 427 int transparency) 428 { 429 return new X11PixmapSurfaceData(gc, width, height, image, 430 getSurfaceType(gc, transparency, true), 431 cm, drawable, transparency); 432 } 433 434 // /** 435 // * Initializes the native Ops pointer. 436 // */ 437 // private native void initOps(X11ComponentPeer peer, 438 // X11GraphicsConfig gc, int depth); 439 440 protected X11SurfaceData(X11ComponentPeer peer, 441 X11GraphicsConfig gc, 442 SurfaceType sType, 443 ColorModel cm) { 444 super(sType, cm); 445 this.peer = peer; 446 this.graphicsConfig = gc; 447 this.solidloops = graphicsConfig.getSolidLoops(sType); 448 this.depth = cm.getPixelSize(); 449 initOps(peer, graphicsConfig, depth); 450 if (isAccelerationEnabled()) { 451 setBlitProxyKey(gc.getProxyKey()); 452 } 453 } 454 455 public static X11GraphicsConfig getGC(X11ComponentPeer peer) { 456 if (peer != null) { 457 return (X11GraphicsConfig) peer.getGraphicsConfiguration(); 458 } else { 459 GraphicsEnvironment env = 460 GraphicsEnvironment.getLocalGraphicsEnvironment(); 461 GraphicsDevice gd = env.getDefaultScreenDevice(); 462 return (X11GraphicsConfig)gd.getDefaultConfiguration(); 463 } 464 } 465 466 /** 467 * Returns a boolean indicating whether or not a copyArea from 468 * the given rectangle source coordinates might be incomplete 469 * and result in X11 GraphicsExposure events being generated 470 * from XCopyArea. 471 * This method allows the SurfaceData copyArea method to determine 472 * if it needs to set the GraphicsExposures attribute of the X11 GC 473 * to True or False to receive or avoid the events. 474 * @return true if there is any chance that an XCopyArea from the 475 * given source coordinates could produce any X11 476 * Exposure events. 477 */ 478 public abstract boolean canSourceSendExposures(int x, int y, int w, int h); 479 480 public boolean copyArea(SunGraphics2D sg2d, 481 int x, int y, int w, int h, int dx, int dy) 482 { 483 if (x11pipe == null) { 484 if (!isDrawableValid()) { 485 return true; 486 } 487 makePipes(); 488 } 489 CompositeType comptype = sg2d.imageComp; 490 if (sg2d.transformState < SunGraphics2D.TRANSFORM_TRANSLATESCALE && 491 (CompositeType.SrcOverNoEa.equals(comptype) || 492 CompositeType.SrcNoEa.equals(comptype))) 493 { 494 SunToolkit.awtLock(); 495 try { 496 boolean needExposures = canSourceSendExposures(x, y, w, h); 497 long xgc = getBlitGC(sg2d.getCompClip(), needExposures); 498 x11pipe.devCopyArea(getNativeOps(), xgc, 499 x, y, 500 x + dx, y + dy, 501 w, h); 502 } finally { 503 SunToolkit.awtUnlock(); 504 } 505 return true; 506 } 507 return false; 508 } 509 510 public static SurfaceType getSurfaceType(X11GraphicsConfig gc, 511 int transparency) 512 { 513 return getSurfaceType(gc, transparency, false); 514 } 515 516 @SuppressWarnings("fallthrough") 517 public static SurfaceType getSurfaceType(X11GraphicsConfig gc, 518 int transparency, 519 boolean pixmapSurface) 520 { 521 boolean transparent = (transparency == Transparency.BITMASK); 522 SurfaceType sType; 523 ColorModel cm = gc.getColorModel(); 524 switch (cm.getPixelSize()) { 525 case 24: 526 if (gc.getBitsPerPixel() == 24) { 527 if (cm instanceof DirectColorModel) { 528 // 4517321: We will always use ThreeByteBgr for 24 bpp 529 // surfaces, regardless of the pixel masks reported by 530 // X11. Despite ambiguity in the X11 spec in how 24 bpp 531 // surfaces are treated, it appears that the best 532 // SurfaceType for these configurations (including 533 // some Matrox Millenium and ATI Radeon boards) is 534 // ThreeByteBgr. 535 sType = transparent ? X11SurfaceData.ThreeByteBgrX11_BM : X11SurfaceData.ThreeByteBgrX11; 536 } else { 537 throw new sun.java2d.InvalidPipeException("Unsupported bit " + 538 "depth/cm combo: " + 539 cm.getPixelSize() + 540 ", " + cm); 541 } 542 break; 543 } 544 // Fall through for 32 bit case 545 case 32: 546 if (cm instanceof DirectColorModel) { 547 if (((SunToolkit)java.awt.Toolkit.getDefaultToolkit() 548 ).isTranslucencyCapable(gc) && !pixmapSurface) 549 { 550 sType = X11SurfaceData.IntArgbPreX11; 551 } else { 552 if (((DirectColorModel)cm).getRedMask() == 0xff0000) { 553 sType = transparent ? X11SurfaceData.IntRgbX11_BM : 554 X11SurfaceData.IntRgbX11; 555 } else { 556 sType = transparent ? X11SurfaceData.IntBgrX11_BM : 557 X11SurfaceData.IntBgrX11; 558 } 559 } 560 } else if (cm instanceof ComponentColorModel) { 561 sType = X11SurfaceData.FourByteAbgrPreX11; 562 } else { 563 564 throw new sun.java2d.InvalidPipeException("Unsupported bit " + 565 "depth/cm combo: " + 566 cm.getPixelSize() + 567 ", " + cm); 568 } 569 break; 570 case 15: 571 sType = transparent ? X11SurfaceData.UShort555RgbX11_BM : X11SurfaceData.UShort555RgbX11; 572 break; 573 case 16: 574 if ((cm instanceof DirectColorModel) && 575 (((DirectColorModel)cm).getGreenMask() == 0x3e0)) 576 { 577 // fix for 4352984: Riva128 on Linux 578 sType = transparent ? X11SurfaceData.UShort555RgbX11_BM : X11SurfaceData.UShort555RgbX11; 579 } else { 580 sType = transparent ? X11SurfaceData.UShort565RgbX11_BM : X11SurfaceData.UShort565RgbX11; 581 } 582 break; 583 case 12: 584 if (cm instanceof IndexColorModel) { 585 sType = transparent ? 586 X11SurfaceData.UShortIndexedX11_BM : 587 X11SurfaceData.UShortIndexedX11; 588 } else { 589 throw new sun.java2d.InvalidPipeException("Unsupported bit " + 590 "depth: " + 591 cm.getPixelSize() + 592 " cm="+cm); 593 } 594 break; 595 case 8: 596 if (cm.getColorSpace().getType() == ColorSpace.TYPE_GRAY && 597 cm instanceof ComponentColorModel) { 598 sType = transparent ? X11SurfaceData.ByteGrayX11_BM : X11SurfaceData.ByteGrayX11; 599 } else if (cm instanceof IndexColorModel && 600 isOpaqueGray((IndexColorModel)cm)) { 601 sType = transparent ? X11SurfaceData.Index8GrayX11_BM : X11SurfaceData.Index8GrayX11; 602 } else { 603 sType = transparent ? X11SurfaceData.ByteIndexedX11_BM : X11SurfaceData.ByteIndexedOpaqueX11; 604 } 605 break; 606 default: 607 throw new sun.java2d.InvalidPipeException("Unsupported bit " + 608 "depth: " + 609 cm.getPixelSize()); 610 } 611 return sType; 612 } 613 614 public void invalidate() { 615 if (isValid()) { 616 setInvalid(); 617 super.invalidate(); 618 } 619 } 620 621 /** 622 * The following methods and variables are used to keep the Java-level 623 * context state in sync with the native X11 GC associated with this 624 * X11SurfaceData object. 625 */ 626 627 private static native void XSetCopyMode(long xgc); 628 private static native void XSetXorMode(long xgc); 629 private static native void XSetForeground(long xgc, int pixel); 630 631 private long xgc; 632 private Region validatedClip; 633 private XORComposite validatedXorComp; 634 private int xorpixelmod; 635 private int validatedPixel; 636 private boolean validatedExposures = true; 637 638 public final long getRenderGC(Region clip, 639 int compState, Composite comp, 640 int pixel) 641 { 642 return getGC(clip, compState, comp, pixel, validatedExposures); 643 } 644 645 public final long getBlitGC(Region clip, boolean needExposures) { 646 return getGC(clip, SunGraphics2D.COMP_ISCOPY, null, 647 validatedPixel, needExposures); 648 } 649 650 final long getGC(Region clip, 651 int compState, Composite comp, 652 int pixel, boolean needExposures) 653 { 654 // assert SunToolkit.isAWTLockHeldByCurrentThread(); 655 656 if (!isValid()) { 657 throw new InvalidPipeException("bounds changed"); 658 } 659 660 // validate clip 661 if (clip != validatedClip) { 662 validatedClip = clip; 663 if (clip != null) { 664 XSetClip(xgc, 665 clip.getLoX(), clip.getLoY(), 666 clip.getHiX(), clip.getHiY(), 667 (clip.isRectangular() ? null : clip)); 668 } else { 669 XResetClip(xgc); 670 } 671 } 672 673 // validate composite 674 if (compState == SunGraphics2D.COMP_ISCOPY) { 675 if (validatedXorComp != null) { 676 validatedXorComp = null; 677 xorpixelmod = 0; 678 XSetCopyMode(xgc); 679 } 680 } else { 681 if (validatedXorComp != comp) { 682 validatedXorComp = (XORComposite)comp; 683 xorpixelmod = validatedXorComp.getXorPixel(); 684 XSetXorMode(xgc); 685 } 686 } 687 688 // validate pixel 689 pixel ^= xorpixelmod; 690 if (pixel != validatedPixel) { 691 validatedPixel = pixel; 692 XSetForeground(xgc, pixel); 693 } 694 695 if (validatedExposures != needExposures) { 696 validatedExposures = needExposures; 697 XSetGraphicsExposures(xgc, needExposures); 698 } 699 700 return xgc; 701 } 702 703 public synchronized void makePipes() { 704 if (x11pipe == null) { 705 SunToolkit.awtLock(); 706 try { 707 xgc = XCreateGC(getNativeOps()); 708 } finally { 709 SunToolkit.awtUnlock(); 710 } 711 x11pipe = X11Renderer.getInstance(); 712 x11txpipe = new PixelToShapeConverter(x11pipe); 713 } 714 } 715 716 public static class X11WindowSurfaceData extends X11SurfaceData { 717 public X11WindowSurfaceData(X11ComponentPeer peer, 718 X11GraphicsConfig gc, 719 SurfaceType sType) { 720 super(peer, gc, sType, peer.getColorModel()); 721 if (isDrawableValid()) { 722 makePipes(); 723 } 724 } 725 726 public SurfaceData getReplacement() { 727 return peer.getSurfaceData(); 728 } 729 730 public Rectangle getBounds() { 731 Rectangle r = peer.getBounds(); 732 r.x = r.y = 0; 733 return r; 734 } 735 736 @Override 737 public boolean canSourceSendExposures(int x, int y, int w, int h) { 738 return true; 739 } 740 741 /** 742 * Returns destination Component associated with this SurfaceData. 743 */ 744 public Object getDestination() { 745 return peer.getTarget(); 746 } 747 } 748 749 public static class X11PixmapSurfaceData extends X11SurfaceData { 750 751 Image offscreenImage; 752 int width; 753 int height; 754 int transparency; 755 756 public X11PixmapSurfaceData(X11GraphicsConfig gc, 757 int width, int height, 758 Image image, 759 SurfaceType sType, ColorModel cm, 760 long drawable, int transparency) 761 { 762 super(null, gc, sType, cm); 763 this.width = width; 764 this.height = height; 765 offscreenImage = image; 766 this.transparency = transparency; 767 initSurface(depth, width, height, drawable); 768 makePipes(); 769 } 770 771 public SurfaceData getReplacement() { 772 return restoreContents(offscreenImage); 773 } 774 775 /** 776 * Need this since the surface data is created with 777 * the color model of the target GC, which is always 778 * opaque. But in SunGraphics2D.blitSD we choose loops 779 * based on the transparency on the source SD, so 780 * it could choose wrong loop (blit instead of blitbg, 781 * for example). 782 */ 783 public int getTransparency() { 784 return transparency; 785 } 786 787 public Rectangle getBounds() { 788 return new Rectangle(width, height); 789 } 790 791 @Override 792 public boolean canSourceSendExposures(int x, int y, int w, int h) { 793 return (x < 0 || y < 0 || (x+w) > width || (y+h) > height); 794 } 795 796 public void flush() { 797 /* 798 * We need to invalidate the surface before disposing the 799 * native Drawable and GC. This way if an application tries 800 * to render to an already flushed X11SurfaceData, we will notice 801 * in the validate() method above that it has been invalidated, 802 * and we will avoid using those native resources that have 803 * already been disposed. 804 */ 805 invalidate(); 806 flushNativeSurface(); 807 } 808 809 /** 810 * Returns destination Image associated with this SurfaceData. 811 */ 812 public Object getDestination() { 813 return offscreenImage; 814 } 815 } 816 817 private static LazyPipe lazypipe = new LazyPipe(); 818 819 public static class LazyPipe extends ValidatePipe { 820 public boolean validate(SunGraphics2D sg2d) { 821 X11SurfaceData xsd = (X11SurfaceData) sg2d.surfaceData; 822 if (!xsd.isDrawableValid()) { 823 return false; 824 } 825 xsd.makePipes(); 826 return super.validate(sg2d); 827 } 828 } 829 }