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 ((CompositeType.SrcOverNoEa.equals(comptype) || 491 CompositeType.SrcNoEa.equals(comptype))) 492 { 493 SunToolkit.awtLock(); 494 try { 495 boolean needExposures = canSourceSendExposures(x, y, w, h); 496 long xgc = getBlitGC(sg2d.getCompClip(), needExposures); 497 x11pipe.devCopyArea(getNativeOps(), xgc, 498 x, y, 499 x + dx, y + dy, 500 w, h); 501 } finally { 502 SunToolkit.awtUnlock(); 503 } 504 return true; 505 } 506 return false; 507 } 508 509 public static SurfaceType getSurfaceType(X11GraphicsConfig gc, 510 int transparency) 511 { 512 return getSurfaceType(gc, transparency, false); 513 } 514 515 @SuppressWarnings("fallthrough") 516 public static SurfaceType getSurfaceType(X11GraphicsConfig gc, 517 int transparency, 518 boolean pixmapSurface) 519 { 520 boolean transparent = (transparency == Transparency.BITMASK); 521 SurfaceType sType; 522 ColorModel cm = gc.getColorModel(); 523 switch (cm.getPixelSize()) { 524 case 24: 525 if (gc.getBitsPerPixel() == 24) { 526 if (cm instanceof DirectColorModel) { 527 // 4517321: We will always use ThreeByteBgr for 24 bpp 528 // surfaces, regardless of the pixel masks reported by 529 // X11. Despite ambiguity in the X11 spec in how 24 bpp 530 // surfaces are treated, it appears that the best 531 // SurfaceType for these configurations (including 532 // some Matrox Millenium and ATI Radeon boards) is 533 // ThreeByteBgr. 534 sType = transparent ? X11SurfaceData.ThreeByteBgrX11_BM : X11SurfaceData.ThreeByteBgrX11; 535 } else { 536 throw new sun.java2d.InvalidPipeException("Unsupported bit " + 537 "depth/cm combo: " + 538 cm.getPixelSize() + 539 ", " + cm); 540 } 541 break; 542 } 543 // Fall through for 32 bit case 544 case 32: 545 if (cm instanceof DirectColorModel) { 546 if (((SunToolkit)java.awt.Toolkit.getDefaultToolkit() 547 ).isTranslucencyCapable(gc) && !pixmapSurface) 548 { 549 sType = X11SurfaceData.IntArgbPreX11; 550 } else { 551 if (((DirectColorModel)cm).getRedMask() == 0xff0000) { 552 sType = transparent ? X11SurfaceData.IntRgbX11_BM : 553 X11SurfaceData.IntRgbX11; 554 } else { 555 sType = transparent ? X11SurfaceData.IntBgrX11_BM : 556 X11SurfaceData.IntBgrX11; 557 } 558 } 559 } else if (cm instanceof ComponentColorModel) { 560 sType = X11SurfaceData.FourByteAbgrPreX11; 561 } else { 562 563 throw new sun.java2d.InvalidPipeException("Unsupported bit " + 564 "depth/cm combo: " + 565 cm.getPixelSize() + 566 ", " + cm); 567 } 568 break; 569 case 15: 570 sType = transparent ? X11SurfaceData.UShort555RgbX11_BM : X11SurfaceData.UShort555RgbX11; 571 break; 572 case 16: 573 if ((cm instanceof DirectColorModel) && 574 (((DirectColorModel)cm).getGreenMask() == 0x3e0)) 575 { 576 // fix for 4352984: Riva128 on Linux 577 sType = transparent ? X11SurfaceData.UShort555RgbX11_BM : X11SurfaceData.UShort555RgbX11; 578 } else { 579 sType = transparent ? X11SurfaceData.UShort565RgbX11_BM : X11SurfaceData.UShort565RgbX11; 580 } 581 break; 582 case 12: 583 if (cm instanceof IndexColorModel) { 584 sType = transparent ? 585 X11SurfaceData.UShortIndexedX11_BM : 586 X11SurfaceData.UShortIndexedX11; 587 } else { 588 throw new sun.java2d.InvalidPipeException("Unsupported bit " + 589 "depth: " + 590 cm.getPixelSize() + 591 " cm="+cm); 592 } 593 break; 594 case 8: 595 if (cm.getColorSpace().getType() == ColorSpace.TYPE_GRAY && 596 cm instanceof ComponentColorModel) { 597 sType = transparent ? X11SurfaceData.ByteGrayX11_BM : X11SurfaceData.ByteGrayX11; 598 } else if (cm instanceof IndexColorModel && 599 isOpaqueGray((IndexColorModel)cm)) { 600 sType = transparent ? X11SurfaceData.Index8GrayX11_BM : X11SurfaceData.Index8GrayX11; 601 } else { 602 sType = transparent ? X11SurfaceData.ByteIndexedX11_BM : X11SurfaceData.ByteIndexedOpaqueX11; 603 } 604 break; 605 default: 606 throw new sun.java2d.InvalidPipeException("Unsupported bit " + 607 "depth: " + 608 cm.getPixelSize()); 609 } 610 return sType; 611 } 612 613 public void invalidate() { 614 if (isValid()) { 615 setInvalid(); 616 super.invalidate(); 617 } 618 } 619 620 /** 621 * The following methods and variables are used to keep the Java-level 622 * context state in sync with the native X11 GC associated with this 623 * X11SurfaceData object. 624 */ 625 626 private static native void XSetCopyMode(long xgc); 627 private static native void XSetXorMode(long xgc); 628 private static native void XSetForeground(long xgc, int pixel); 629 630 private long xgc; 631 private Region validatedClip; 632 private XORComposite validatedXorComp; 633 private int xorpixelmod; 634 private int validatedPixel; 635 private boolean validatedExposures = true; 636 637 public final long getRenderGC(Region clip, 638 int compState, Composite comp, 639 int pixel) 640 { 641 return getGC(clip, compState, comp, pixel, validatedExposures); 642 } 643 644 public final long getBlitGC(Region clip, boolean needExposures) { 645 return getGC(clip, SunGraphics2D.COMP_ISCOPY, null, 646 validatedPixel, needExposures); 647 } 648 649 final long getGC(Region clip, 650 int compState, Composite comp, 651 int pixel, boolean needExposures) 652 { 653 // assert SunToolkit.isAWTLockHeldByCurrentThread(); 654 655 if (!isValid()) { 656 throw new InvalidPipeException("bounds changed"); 657 } 658 659 // validate clip 660 if (clip != validatedClip) { 661 validatedClip = clip; 662 if (clip != null) { 663 XSetClip(xgc, 664 clip.getLoX(), clip.getLoY(), 665 clip.getHiX(), clip.getHiY(), 666 (clip.isRectangular() ? null : clip)); 667 } else { 668 XResetClip(xgc); 669 } 670 } 671 672 // validate composite 673 if (compState == SunGraphics2D.COMP_ISCOPY) { 674 if (validatedXorComp != null) { 675 validatedXorComp = null; 676 xorpixelmod = 0; 677 XSetCopyMode(xgc); 678 } 679 } else { 680 if (validatedXorComp != comp) { 681 validatedXorComp = (XORComposite)comp; 682 xorpixelmod = validatedXorComp.getXorPixel(); 683 XSetXorMode(xgc); 684 } 685 } 686 687 // validate pixel 688 pixel ^= xorpixelmod; 689 if (pixel != validatedPixel) { 690 validatedPixel = pixel; 691 XSetForeground(xgc, pixel); 692 } 693 694 if (validatedExposures != needExposures) { 695 validatedExposures = needExposures; 696 XSetGraphicsExposures(xgc, needExposures); 697 } 698 699 return xgc; 700 } 701 702 public synchronized void makePipes() { 703 if (x11pipe == null) { 704 SunToolkit.awtLock(); 705 try { 706 xgc = XCreateGC(getNativeOps()); 707 } finally { 708 SunToolkit.awtUnlock(); 709 } 710 x11pipe = X11Renderer.getInstance(); 711 x11txpipe = new PixelToShapeConverter(x11pipe); 712 } 713 } 714 715 public static class X11WindowSurfaceData extends X11SurfaceData { 716 public X11WindowSurfaceData(X11ComponentPeer peer, 717 X11GraphicsConfig gc, 718 SurfaceType sType) { 719 super(peer, gc, sType, peer.getColorModel()); 720 if (isDrawableValid()) { 721 makePipes(); 722 } 723 } 724 725 public SurfaceData getReplacement() { 726 return peer.getSurfaceData(); 727 } 728 729 public Rectangle getBounds() { 730 Rectangle r = peer.getBounds(); 731 r.x = r.y = 0; 732 return r; 733 } 734 735 @Override 736 public boolean canSourceSendExposures(int x, int y, int w, int h) { 737 return true; 738 } 739 740 /** 741 * Returns destination Component associated with this SurfaceData. 742 */ 743 public Object getDestination() { 744 return peer.getTarget(); 745 } 746 } 747 748 public static class X11PixmapSurfaceData extends X11SurfaceData { 749 750 Image offscreenImage; 751 int width; 752 int height; 753 int transparency; 754 755 public X11PixmapSurfaceData(X11GraphicsConfig gc, 756 int width, int height, 757 Image image, 758 SurfaceType sType, ColorModel cm, 759 long drawable, int transparency) 760 { 761 super(null, gc, sType, cm); 762 this.width = width; 763 this.height = height; 764 offscreenImage = image; 765 this.transparency = transparency; 766 initSurface(depth, width, height, drawable); 767 makePipes(); 768 } 769 770 public SurfaceData getReplacement() { 771 return restoreContents(offscreenImage); 772 } 773 774 /** 775 * Need this since the surface data is created with 776 * the color model of the target GC, which is always 777 * opaque. But in SunGraphics2D.blitSD we choose loops 778 * based on the transparency on the source SD, so 779 * it could choose wrong loop (blit instead of blitbg, 780 * for example). 781 */ 782 public int getTransparency() { 783 return transparency; 784 } 785 786 public Rectangle getBounds() { 787 return new Rectangle(width, height); 788 } 789 790 @Override 791 public boolean canSourceSendExposures(int x, int y, int w, int h) { 792 return (x < 0 || y < 0 || (x+w) > width || (y+h) > height); 793 } 794 795 public void flush() { 796 /* 797 * We need to invalidate the surface before disposing the 798 * native Drawable and GC. This way if an application tries 799 * to render to an already flushed X11SurfaceData, we will notice 800 * in the validate() method above that it has been invalidated, 801 * and we will avoid using those native resources that have 802 * already been disposed. 803 */ 804 invalidate(); 805 flushNativeSurface(); 806 } 807 808 /** 809 * Returns destination Image associated with this SurfaceData. 810 */ 811 public Object getDestination() { 812 return offscreenImage; 813 } 814 } 815 816 private static LazyPipe lazypipe = new LazyPipe(); 817 818 public static class LazyPipe extends ValidatePipe { 819 public boolean validate(SunGraphics2D sg2d) { 820 X11SurfaceData xsd = (X11SurfaceData) sg2d.surfaceData; 821 if (!xsd.isDrawableValid()) { 822 return false; 823 } 824 xsd.makePipes(); 825 return super.validate(sg2d); 826 } 827 } 828 }