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