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.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 = (String) 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 = (String) 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 = 268 (String) java.security.AccessController.doPrivileged( 269 new sun.security.action.GetPropertyAction("sun.java2d.pmoffscreen")); 270 if (prop != null) { 271 // true iff prop==true, false otherwise 272 accelerationEnabled = Boolean.valueOf(prop); 273 } else { 274 boolean isDisplayLocal = false; 275 GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); 276 if (ge instanceof SunGraphicsEnvironment) { 277 isDisplayLocal = ((SunGraphicsEnvironment) ge).isDisplayLocal(); 278 } 279 280 // EXA based drivers tend to place pixmaps in VRAM, slowing down readbacks. 281 // Don't use pixmaps if dga is available, 282 // or we are local and shared memory Pixmaps are not available. 283 accelerationEnabled = 284 !(isDgaAvailable() || (isDisplayLocal && !isShmPMAvailable())); 285 } 286 } 287 } 288 return accelerationEnabled.booleanValue(); 289 } 290 291 @Override 292 public SurfaceDataProxy makeProxyFor(SurfaceData srcData) { 293 return X11SurfaceDataProxy.createProxy(srcData, graphicsConfig); 294 } 295 296 public void validatePipe(SunGraphics2D sg2d) { 297 if (sg2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON && 298 sg2d.paintState <= sg2d.PAINT_ALPHACOLOR && 299 (sg2d.compositeState <= sg2d.COMP_ISCOPY || 300 sg2d.compositeState == sg2d.COMP_XOR)) 301 { 302 if (x11txpipe == null) { 303 /* 304 * Note: this is thread-safe since x11txpipe is the 305 * second of the two pipes constructed in makePipes(). 306 * In the rare case we are racing against another 307 * thread making new pipes, setting lazypipe is a 308 * safe alternative to waiting for the other thread. 309 */ 310 sg2d.drawpipe = lazypipe; 311 sg2d.fillpipe = lazypipe; 312 sg2d.shapepipe = lazypipe; 313 sg2d.imagepipe = lazypipe; 314 sg2d.textpipe = lazypipe; 315 return; 316 } 317 318 if (sg2d.clipState == sg2d.CLIP_SHAPE) { 319 // Do this to init textpipe correctly; we will override the 320 // other non-text pipes below 321 // REMIND: we should clean this up eventually instead of 322 // having this work duplicated. 323 super.validatePipe(sg2d); 324 } else { 325 switch (sg2d.textAntialiasHint) { 326 327 case SunHints.INTVAL_TEXT_ANTIALIAS_DEFAULT: 328 /* equating to OFF which it is for us */ 329 case SunHints.INTVAL_TEXT_ANTIALIAS_OFF: 330 // Use X11 pipe even if DGA is available since DGA 331 // text slows everything down when mixed with X11 calls 332 if (sg2d.compositeState == sg2d.COMP_ISCOPY) { 333 sg2d.textpipe = x11textpipe; 334 } else { 335 sg2d.textpipe = solidTextRenderer; 336 } 337 break; 338 339 case SunHints.INTVAL_TEXT_ANTIALIAS_ON: 340 // Remind: may use Xrender for these when composite is 341 // copy as above, or if remote X11. 342 sg2d.textpipe = aaTextRenderer; 343 break; 344 345 default: 346 switch (sg2d.getFontInfo().aaHint) { 347 348 case SunHints.INTVAL_TEXT_ANTIALIAS_LCD_HRGB: 349 case SunHints.INTVAL_TEXT_ANTIALIAS_LCD_VRGB: 350 sg2d.textpipe = lcdTextRenderer; 351 break; 352 353 case SunHints.INTVAL_TEXT_ANTIALIAS_OFF: 354 // Use X11 pipe even if DGA is available since DGA 355 // text slows everything down when mixed with X11 calls 356 if (sg2d.compositeState == sg2d.COMP_ISCOPY) { 357 sg2d.textpipe = x11textpipe; 358 } else { 359 sg2d.textpipe = solidTextRenderer; 360 } 361 break; 362 363 case SunHints.INTVAL_TEXT_ANTIALIAS_ON: 364 sg2d.textpipe = aaTextRenderer; 365 break; 366 367 default: 368 sg2d.textpipe = solidTextRenderer; 369 } 370 } 371 } 372 373 if (sg2d.transformState >= sg2d.TRANSFORM_TRANSLATESCALE) { 374 sg2d.drawpipe = x11txpipe; 375 sg2d.fillpipe = x11txpipe; 376 } else if (sg2d.strokeState != sg2d.STROKE_THIN){ 377 sg2d.drawpipe = x11txpipe; 378 sg2d.fillpipe = x11pipe; 379 } else { 380 sg2d.drawpipe = x11pipe; 381 sg2d.fillpipe = x11pipe; 382 } 383 sg2d.shapepipe = x11pipe; 384 sg2d.imagepipe = imagepipe; 385 386 // This is needed for AA text. 387 // Note that even an X11TextRenderer can dispatch AA text 388 // if a GlyphVector overrides the AA setting. 389 // We use getRenderLoops() rather than setting solidloops 390 // directly so that we get the appropriate loops in XOR mode. 391 if (sg2d.loops == null) { 392 // assert(some pipe will always be a LoopBasedPipe) 393 sg2d.loops = getRenderLoops(sg2d); 394 } 395 } else { 396 super.validatePipe(sg2d); 397 } 398 } 399 400 public RenderLoops getRenderLoops(SunGraphics2D sg2d) { 401 if (sg2d.paintState <= sg2d.PAINT_ALPHACOLOR && 402 sg2d.compositeState <= sg2d.COMP_ISCOPY) 403 { 404 return solidloops; 405 } 406 return super.getRenderLoops(sg2d); 407 } 408 409 public GraphicsConfiguration getDeviceConfiguration() { 410 return graphicsConfig; 411 } 412 413 /** 414 * Method for instantiating a Window SurfaceData 415 */ 416 public static X11WindowSurfaceData createData(X11ComponentPeer peer) { 417 X11GraphicsConfig gc = getGC(peer); 418 return new X11WindowSurfaceData(peer, gc, gc.getSurfaceType()); 419 } 420 421 /** 422 * Method for instantiating a Pixmap SurfaceData (offscreen) 423 */ 424 public static X11PixmapSurfaceData createData(X11GraphicsConfig gc, 425 int width, int height, 426 ColorModel cm, Image image, 427 long drawable, 428 int transparency) 429 { 430 return new X11PixmapSurfaceData(gc, width, height, image, 431 getSurfaceType(gc, transparency, true), 432 cm, drawable, transparency); 433 } 434 435 // /** 436 // * Initializes the native Ops pointer. 437 // */ 438 // private native void initOps(X11ComponentPeer peer, 439 // X11GraphicsConfig gc, int depth); 440 441 protected X11SurfaceData(X11ComponentPeer peer, 442 X11GraphicsConfig gc, 443 SurfaceType sType, 444 ColorModel cm) { 445 super(sType, cm); 446 this.peer = peer; 447 this.graphicsConfig = gc; 448 this.solidloops = graphicsConfig.getSolidLoops(sType); 449 this.depth = cm.getPixelSize(); 450 initOps(peer, graphicsConfig, depth); 451 if (isAccelerationEnabled()) { 452 setBlitProxyKey(gc.getProxyKey()); 453 } 454 } 455 456 public static X11GraphicsConfig getGC(X11ComponentPeer peer) { 457 if (peer != null) { 458 return (X11GraphicsConfig) peer.getGraphicsConfiguration(); 459 } else { 460 GraphicsEnvironment env = 461 GraphicsEnvironment.getLocalGraphicsEnvironment(); 462 GraphicsDevice gd = env.getDefaultScreenDevice(); 463 return (X11GraphicsConfig)gd.getDefaultConfiguration(); 464 } 465 } 466 467 /** 468 * Returns a boolean indicating whether or not a copyArea from 469 * the given rectangle source coordinates might be incomplete 470 * and result in X11 GraphicsExposure events being generated 471 * from XCopyArea. 472 * This method allows the SurfaceData copyArea method to determine 473 * if it needs to set the GraphicsExposures attribute of the X11 GC 474 * to True or False to receive or avoid the events. 475 * @return true if there is any chance that an XCopyArea from the 476 * given source coordinates could produce any X11 477 * Exposure events. 478 */ 479 public abstract boolean canSourceSendExposures(int x, int y, int w, int h); 480 481 public boolean copyArea(SunGraphics2D sg2d, 482 int x, int y, int w, int h, int dx, int dy) 483 { 484 if (x11pipe == null) { 485 if (!isDrawableValid()) { 486 return true; 487 } 488 makePipes(); 489 } 490 CompositeType comptype = sg2d.imageComp; 491 if (sg2d.transformState < sg2d.TRANSFORM_TRANSLATESCALE && 492 (CompositeType.SrcOverNoEa.equals(comptype) || 493 CompositeType.SrcNoEa.equals(comptype))) 494 { 495 x += sg2d.transX; 496 y += sg2d.transY; 497 SunToolkit.awtLock(); 498 try { 499 boolean needExposures = canSourceSendExposures(x, y, w, h); 500 long xgc = getBlitGC(sg2d.getCompClip(), needExposures); 501 x11pipe.devCopyArea(getNativeOps(), xgc, 502 x, y, 503 x + dx, y + dy, 504 w, h); 505 } finally { 506 SunToolkit.awtUnlock(); 507 } 508 return true; 509 } 510 return false; 511 } 512 513 public static SurfaceType getSurfaceType(X11GraphicsConfig gc, 514 int transparency) 515 { 516 return getSurfaceType(gc, transparency, false); 517 } 518 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 }