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