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