1 /* 2 * Copyright (c) 2010, 2013, 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.xr; 27 28 import java.awt.*; 29 import java.awt.geom.*; 30 import java.awt.image.*; 31 import sun.awt.*; 32 import sun.java2d.InvalidPipeException; 33 import sun.java2d.SunGraphics2D; 34 import sun.java2d.SurfaceData; 35 import sun.java2d.SurfaceDataProxy; 36 import sun.java2d.jules.*; 37 import sun.java2d.loops.*; 38 import sun.java2d.pipe.*; 39 import sun.java2d.x11.*; 40 import sun.font.FontManagerNativeLibrary; 41 42 public abstract class XRSurfaceData extends XSurfaceData { 43 X11ComponentPeer peer; 44 XRGraphicsConfig graphicsConfig; 45 XRBackend renderQueue; 46 47 private RenderLoops solidloops; 48 49 protected int depth; 50 initIDs()51 private static native void initIDs(); 52 XRInitSurface(int depth, int width, int height, long drawable, int pictFormat)53 protected native void XRInitSurface(int depth, int width, int height, 54 long drawable, int pictFormat); 55 initXRPicture(long xsdo, int pictForm)56 native void initXRPicture(long xsdo, int pictForm); 57 freeXSDOPicture(long xsdo)58 native void freeXSDOPicture(long xsdo); 59 60 public static final String DESC_BYTE_A8_X11 = "Byte A8 Pixmap"; 61 public static final String DESC_INT_RGB_X11 = "Integer RGB Pixmap"; 62 public static final String DESC_INT_ARGB_X11 = "Integer ARGB-Pre Pixmap"; 63 64 public static final SurfaceType 65 ByteA8X11 = SurfaceType.ByteGray.deriveSubType(DESC_BYTE_A8_X11); 66 public static final SurfaceType 67 IntRgbX11 = SurfaceType.IntRgb.deriveSubType(DESC_INT_RGB_X11); 68 public static final SurfaceType 69 IntArgbPreX11 = SurfaceType.IntArgbPre.deriveSubType(DESC_INT_ARGB_X11); 70 getRaster(int x, int y, int w, int h)71 public Raster getRaster(int x, int y, int w, int h) { 72 throw new InternalError("not implemented yet"); 73 } 74 75 protected XRRenderer xrpipe; 76 protected PixelToShapeConverter xrtxpipe; 77 protected TextPipe xrtextpipe; 78 protected XRDrawImage xrDrawImage; 79 80 protected ShapeDrawPipe aaShapePipe; 81 protected PixelToShapeConverter aaPixelToShapeConv; 82 initXRSurfaceData()83 public static void initXRSurfaceData() { 84 if (!isX11SurfaceDataInitialized()) { 85 FontManagerNativeLibrary.load(); 86 initIDs(); 87 XRPMBlitLoops.register(); 88 XRMaskFill.register(); 89 XRMaskBlit.register(); 90 91 setX11SurfaceDataInitialized(); 92 } 93 } 94 95 /** 96 * Synchronized accessor method for isDrawableValid. 97 */ isXRDrawableValid()98 protected boolean isXRDrawableValid() { 99 try { 100 SunToolkit.awtLock(); 101 return isDrawableValid(); 102 } finally { 103 SunToolkit.awtUnlock(); 104 } 105 } 106 107 @Override makeProxyFor(SurfaceData srcData)108 public SurfaceDataProxy makeProxyFor(SurfaceData srcData) { 109 return XRSurfaceDataProxy.createProxy(srcData, graphicsConfig); 110 } 111 112 @Override validatePipe(SunGraphics2D sg2d)113 public void validatePipe(SunGraphics2D sg2d) { 114 TextPipe textpipe; 115 boolean validated = false; 116 117 /* 118 * The textpipe for now can't handle TexturePaint when extra-alpha is 119 * specified nore XOR mode 120 */ 121 if ((textpipe = getTextPipe(sg2d)) == null) 122 { 123 super.validatePipe(sg2d); 124 textpipe = sg2d.textpipe; 125 validated = true; 126 } 127 128 PixelToShapeConverter txPipe = null; 129 XRRenderer nonTxPipe = null; 130 131 /* 132 * TODO: Can we rely on the GC for ARGB32 surfaces? 133 */ 134 if (sg2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON) { 135 if (sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR) { 136 if (sg2d.compositeState <= SunGraphics2D.COMP_XOR) { 137 txPipe = xrtxpipe; 138 nonTxPipe = xrpipe; 139 } 140 } else if (sg2d.compositeState <= SunGraphics2D.COMP_ALPHA) { 141 if (XRPaints.isValid(sg2d)) { 142 txPipe = xrtxpipe; 143 nonTxPipe = xrpipe; 144 } 145 // custom paints handled by super.validatePipe() below 146 } 147 } 148 149 if (sg2d.antialiasHint == SunHints.INTVAL_ANTIALIAS_ON && 150 JulesPathBuf.isCairoAvailable()) 151 { 152 sg2d.shapepipe = aaShapePipe; 153 sg2d.drawpipe = aaPixelToShapeConv; 154 sg2d.fillpipe = aaPixelToShapeConv; 155 } else { 156 if (txPipe != null) { 157 if (sg2d.transformState >= SunGraphics2D.TRANSFORM_TRANSLATESCALE) { 158 sg2d.drawpipe = txPipe; 159 sg2d.fillpipe = txPipe; 160 } else if (sg2d.strokeState != SunGraphics2D.STROKE_THIN) { 161 sg2d.drawpipe = txPipe; 162 sg2d.fillpipe = nonTxPipe; 163 } else { 164 sg2d.drawpipe = nonTxPipe; 165 sg2d.fillpipe = nonTxPipe; 166 } 167 sg2d.shapepipe = nonTxPipe; 168 } else { 169 if (!validated) { 170 super.validatePipe(sg2d); 171 } 172 } 173 } 174 175 // install the text pipe based on our earlier decision 176 sg2d.textpipe = textpipe; 177 178 // always override the image pipe with the specialized XRender pipe 179 sg2d.imagepipe = xrDrawImage; 180 } 181 getTextPipe(SunGraphics2D sg2d)182 protected TextPipe getTextPipe(SunGraphics2D sg2d) { 183 boolean supportedPaint = sg2d.compositeState <= SunGraphics2D.COMP_ALPHA 184 && (sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR || sg2d.composite == null); 185 186 boolean supportedCompOp = false; 187 if (sg2d.composite instanceof AlphaComposite) { 188 int compRule = ((AlphaComposite) sg2d.composite).getRule(); 189 supportedCompOp = XRUtils.isMaskEvaluated(XRUtils.j2dAlphaCompToXR(compRule)) 190 || (compRule == AlphaComposite.SRC 191 && sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR); 192 } 193 194 return (supportedPaint && supportedCompOp) ? xrtextpipe : null; 195 } 196 getMaskFill(SunGraphics2D sg2d)197 protected MaskFill getMaskFill(SunGraphics2D sg2d) { 198 AlphaComposite aComp = null; 199 if(sg2d.composite != null 200 && sg2d.composite instanceof AlphaComposite) { 201 aComp = (AlphaComposite) sg2d.composite; 202 } 203 204 boolean supportedPaint = sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR 205 || XRPaints.isValid(sg2d); 206 207 boolean supportedCompOp = false; 208 if(aComp != null) { 209 int rule = aComp.getRule(); 210 supportedCompOp = XRUtils.isMaskEvaluated(XRUtils.j2dAlphaCompToXR(rule)); 211 } 212 213 return (supportedPaint && supportedCompOp) ? super.getMaskFill(sg2d) : null; 214 } 215 getRenderLoops(SunGraphics2D sg2d)216 public RenderLoops getRenderLoops(SunGraphics2D sg2d) { 217 if (sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR && 218 sg2d.compositeState <= SunGraphics2D.COMP_ALPHA) 219 { 220 return solidloops; 221 } 222 223 return super.getRenderLoops(sg2d); 224 } 225 getDeviceConfiguration()226 public GraphicsConfiguration getDeviceConfiguration() { 227 return graphicsConfig; 228 } 229 230 /** 231 * Method for instantiating a Window SurfaceData 232 */ createData(X11ComponentPeer peer)233 public static XRWindowSurfaceData createData(X11ComponentPeer peer) { 234 XRGraphicsConfig gc = getGC(peer); 235 return new XRWindowSurfaceData(peer, gc, gc.getSurfaceType()); 236 } 237 238 /** 239 * Method for instantiating a Pixmap SurfaceData (offscreen). 240 * If the surface * is opaque a 24-bit/RGB surface is chosen, 241 * otherwise a 32-bit ARGB surface. 242 */ createData(XRGraphicsConfig gc, int width, int height, ColorModel cm, Image image, long drawable, int transparency)243 public static XRPixmapSurfaceData createData(XRGraphicsConfig gc, 244 int width, int height, 245 ColorModel cm, Image image, 246 long drawable, 247 int transparency) { 248 int depth; 249 // If we have a 32 bit color model for the window it needs 250 // alpha to support translucency of the window so we need 251 // to upgrade what was requested for the surface. 252 if (gc.getColorModel().getPixelSize() == 32) { 253 depth = 32; 254 transparency = Transparency.TRANSLUCENT; 255 } else { 256 depth = transparency > Transparency.OPAQUE ? 32 : 24; 257 } 258 259 if (depth == 24) { 260 cm = new DirectColorModel(depth, 261 0x00FF0000, 0x0000FF00, 0x000000FF); 262 } else { 263 cm = new DirectColorModel(depth, 0x00FF0000, 0x0000FF00, 264 0x000000FF, 0xFF000000); 265 } 266 267 return new XRPixmapSurfaceData 268 (gc, width, height, image, getSurfaceType(gc, transparency), 269 cm, drawable, transparency, 270 XRUtils.getPictureFormatForTransparency(transparency), depth); 271 } 272 XRSurfaceData(X11ComponentPeer peer, XRGraphicsConfig gc, SurfaceType sType, ColorModel cm, int depth, int transparency)273 protected XRSurfaceData(X11ComponentPeer peer, XRGraphicsConfig gc, 274 SurfaceType sType, ColorModel cm, int depth, int transparency) 275 { 276 super(sType, cm); 277 this.peer = peer; 278 this.graphicsConfig = gc; 279 this.solidloops = graphicsConfig.getSolidLoops(sType); 280 this.depth = depth; 281 initOps(peer, graphicsConfig, depth); 282 283 setBlitProxyKey(gc.getProxyKey()); 284 } 285 XRSurfaceData(XRBackend renderQueue)286 protected XRSurfaceData(XRBackend renderQueue) { 287 super(XRSurfaceData.IntRgbX11, 288 new DirectColorModel(24, 0x00FF0000, 0x0000FF00, 0x000000FF)); 289 this.renderQueue = renderQueue; 290 } 291 292 /** 293 * Inits the XRender-data-structures which belong to the XRSurfaceData. 294 * 295 * @param pictureFormat 296 */ initXRender(int pictureFormat)297 public void initXRender(int pictureFormat) { 298 try { 299 SunToolkit.awtLock(); 300 initXRPicture(getNativeOps(), pictureFormat); 301 renderQueue = XRCompositeManager.getInstance(this).getBackend(); 302 maskBuffer = XRCompositeManager.getInstance(this); 303 } catch (Throwable ex) { 304 ex.printStackTrace(); 305 } finally { 306 SunToolkit.awtUnlock(); 307 } 308 } 309 getGC(X11ComponentPeer peer)310 public static XRGraphicsConfig getGC(X11ComponentPeer peer) { 311 if (peer != null) { 312 return (XRGraphicsConfig) peer.getGraphicsConfiguration(); 313 } else { 314 GraphicsEnvironment env = 315 GraphicsEnvironment.getLocalGraphicsEnvironment(); 316 GraphicsDevice gd = env.getDefaultScreenDevice(); 317 return (XRGraphicsConfig) gd.getDefaultConfiguration(); 318 } 319 } 320 321 /** 322 * Returns a boolean indicating whether or not a copyArea from the given 323 * rectangle source coordinates might be incomplete and result in X11 324 * GraphicsExposure events being generated from XCopyArea. This method 325 * allows the SurfaceData copyArea method to determine if it needs to set 326 * the GraphicsExposures attribute of the X11 GC to True or False to receive 327 * or avoid the events. 328 * 329 * @return true if there is any chance that an XCopyArea from the given 330 * source coordinates could produce any X11 Exposure events. 331 */ canSourceSendExposures(int x, int y, int w, int h)332 public abstract boolean canSourceSendExposures(int x, int y, int w, int h); 333 334 /** 335 * CopyArea is implemented using the "old" X11 GC, therefor clip and 336 * needExposures have to be validated against that GC. Pictures and GCs 337 * don't share state. 338 */ validateCopyAreaGC(Region gcClip, boolean needExposures)339 public void validateCopyAreaGC(Region gcClip, boolean needExposures) { 340 if (validatedGCClip != gcClip) { 341 if (gcClip != null) 342 renderQueue.setGCClipRectangles(xgc, gcClip); 343 validatedGCClip = gcClip; 344 } 345 346 if (validatedExposures != needExposures) { 347 validatedExposures = needExposures; 348 renderQueue.setGCExposures(xgc, needExposures); 349 } 350 351 if (validatedXorComp != null) { 352 renderQueue.setGCMode(xgc, true); 353 renderQueue.setGCForeground(xgc, validatedGCForegroundPixel); 354 validatedXorComp = null; 355 } 356 } 357 copyArea(SunGraphics2D sg2d, int x, int y, int w, int h, int dx, int dy)358 public boolean copyArea(SunGraphics2D sg2d, int x, int y, int w, int h, 359 int dx, int dy) { 360 if (xrpipe == null) { 361 if (!isXRDrawableValid()) { 362 return true; 363 } 364 makePipes(); 365 } 366 CompositeType comptype = sg2d.imageComp; 367 if (sg2d.transformState < SunGraphics2D.TRANSFORM_TRANSLATESCALE && 368 (CompositeType.SrcOverNoEa.equals(comptype) || 369 CompositeType.SrcNoEa.equals(comptype))) 370 { 371 x += sg2d.transX; 372 y += sg2d.transY; 373 try { 374 SunToolkit.awtLock(); 375 boolean needExposures = canSourceSendExposures(x, y, w, h); 376 validateCopyAreaGC(sg2d.getCompClip(), needExposures); 377 renderQueue.copyArea(xid, xid, xgc, x, y, w, h, x + dx, y + dy); 378 } finally { 379 SunToolkit.awtUnlock(); 380 } 381 return true; 382 } 383 return false; 384 } 385 386 /** 387 * Returns the XRender SurfaceType which is able to fullfill the specified 388 * transparency requirement. 389 */ getSurfaceType(XRGraphicsConfig gc, int transparency)390 public static SurfaceType getSurfaceType(XRGraphicsConfig gc, 391 int transparency) { 392 SurfaceType sType = null; 393 394 switch (transparency) { 395 case Transparency.OPAQUE: 396 sType = XRSurfaceData.IntRgbX11; 397 break; 398 399 case Transparency.BITMASK: 400 case Transparency.TRANSLUCENT: 401 sType = XRSurfaceData.IntArgbPreX11; 402 break; 403 } 404 405 return sType; 406 } 407 invalidate()408 public void invalidate() { 409 if (isValid()) { 410 setInvalid(); 411 super.invalidate(); 412 } 413 } 414 415 private long xgc; // GC is still used for copyArea 416 private int validatedGCForegroundPixel = 0; 417 private XORComposite validatedXorComp; 418 private int xid; 419 public int picture; 420 public XRCompositeManager maskBuffer; 421 422 private Region validatedClip; 423 private Region validatedGCClip; 424 private boolean validatedExposures = true; 425 426 boolean transformInUse = false; 427 AffineTransform validatedSourceTransform = new AffineTransform(); 428 AffineTransform staticSrcTx = null; 429 int validatedRepeat = XRUtils.RepeatNone; 430 int validatedFilter = XRUtils.FAST; 431 432 /** 433 * Validates an XRSurfaceData when used as source. Note that the clip is 434 * applied when used as source as well as destination. 435 */ validateAsSource(AffineTransform sxForm, int repeat, int filter)436 void validateAsSource(AffineTransform sxForm, int repeat, int filter) { 437 438 if (validatedClip != null) { 439 validatedClip = null; 440 renderQueue.setClipRectangles(picture, null); 441 } 442 443 if (validatedRepeat != repeat && repeat != -1) { 444 validatedRepeat = repeat; 445 renderQueue.setPictureRepeat(picture, repeat); 446 } 447 448 if (sxForm == null) { 449 if (transformInUse) { 450 validatedSourceTransform.setToIdentity(); 451 renderQueue.setPictureTransform(picture, 452 validatedSourceTransform); 453 transformInUse = false; 454 } 455 } else if (!transformInUse || 456 (transformInUse && !sxForm.equals(validatedSourceTransform))) { 457 458 validatedSourceTransform.setTransform(sxForm.getScaleX(), 459 sxForm.getShearY(), 460 sxForm.getShearX(), 461 sxForm.getScaleY(), 462 sxForm.getTranslateX(), 463 sxForm.getTranslateY()); 464 465 AffineTransform srcTransform = validatedSourceTransform; 466 if(staticSrcTx != null) { 467 // Apply static transform set when used as texture or gradient. 468 // Create a copy to not modify validatedSourceTransform as 469 // this would confuse the validation logic. 470 srcTransform = new AffineTransform(validatedSourceTransform); 471 srcTransform.preConcatenate(staticSrcTx); 472 } 473 474 renderQueue.setPictureTransform(picture, srcTransform); 475 transformInUse = true; 476 } 477 478 if (filter != validatedFilter && filter != -1) { 479 renderQueue.setFilter(picture, filter); 480 validatedFilter = filter; 481 } 482 } 483 484 /** 485 * Validates the Surface when used as destination. 486 */ validateAsDestination(SunGraphics2D sg2d, Region clip)487 public void validateAsDestination(SunGraphics2D sg2d, Region clip) { 488 if (!isValid()) { 489 throw new InvalidPipeException("bounds changed"); 490 } 491 492 boolean updateGCClip = false; 493 if (clip != validatedClip) { 494 renderQueue.setClipRectangles(picture, clip); 495 validatedClip = clip; 496 updateGCClip = true; 497 } 498 499 if (sg2d != null && sg2d.compositeState == SunGraphics2D.COMP_XOR) { 500 if (validatedXorComp != sg2d.getComposite()) { 501 validatedXorComp = (XORComposite) sg2d.getComposite(); 502 renderQueue.setGCMode(xgc, false); 503 } 504 505 // validate pixel 506 int pixel = sg2d.pixel; 507 if (validatedGCForegroundPixel != pixel) { 508 int xorpixelmod = validatedXorComp.getXorPixel(); 509 renderQueue.setGCForeground(xgc, pixel ^ xorpixelmod); 510 validatedGCForegroundPixel = pixel; 511 } 512 513 if (updateGCClip) { 514 renderQueue.setGCClipRectangles(xgc, clip); 515 } 516 } 517 } 518 makePipes()519 public synchronized void makePipes() { /* 520 * TODO: Why is this synchronized, 521 * but access not? 522 */ 523 if (xrpipe == null) { 524 try { 525 SunToolkit.awtLock(); 526 xgc = XCreateGC(getNativeOps()); 527 528 xrpipe = new XRRenderer(maskBuffer.getMaskBuffer()); 529 xrtxpipe = new PixelToShapeConverter(xrpipe); 530 xrtextpipe = maskBuffer.getTextRenderer(); 531 xrDrawImage = new XRDrawImage(); 532 533 if (JulesPathBuf.isCairoAvailable()) { 534 aaShapePipe = 535 new JulesShapePipe(XRCompositeManager.getInstance(this)); 536 aaPixelToShapeConv = new PixelToShapeConverter(aaShapePipe); 537 } 538 } finally { 539 SunToolkit.awtUnlock(); 540 } 541 } 542 } 543 544 public static class XRWindowSurfaceData extends XRSurfaceData { XRWindowSurfaceData(X11ComponentPeer peer, XRGraphicsConfig gc, SurfaceType sType)545 public XRWindowSurfaceData(X11ComponentPeer peer, 546 XRGraphicsConfig gc, SurfaceType sType) { 547 super(peer, gc, sType, peer.getColorModel(), 548 peer.getColorModel().getPixelSize(), Transparency.OPAQUE); 549 550 if (isXRDrawableValid()) { 551 initXRender(XRUtils. 552 getPictureFormatForTransparency(Transparency.OPAQUE)); 553 makePipes(); 554 } 555 } 556 getReplacement()557 public SurfaceData getReplacement() { 558 return peer.getSurfaceData(); 559 } 560 getBounds()561 public Rectangle getBounds() { 562 Rectangle r = peer.getBounds(); 563 r.x = r.y = 0; 564 return r; 565 } 566 567 @Override canSourceSendExposures(int x, int y, int w, int h)568 public boolean canSourceSendExposures(int x, int y, int w, int h) { 569 return true; 570 } 571 572 /** 573 * Returns destination Component associated with this SurfaceData. 574 */ getDestination()575 public Object getDestination() { 576 return peer.getTarget(); 577 } 578 invalidate()579 public void invalidate() { 580 try { 581 SunToolkit.awtLock(); 582 freeXSDOPicture(getNativeOps()); 583 }finally { 584 SunToolkit.awtUnlock(); 585 } 586 587 super.invalidate(); 588 } 589 } 590 591 public static class XRInternalSurfaceData extends XRSurfaceData { XRInternalSurfaceData(XRBackend renderQueue, int pictXid)592 public XRInternalSurfaceData(XRBackend renderQueue, int pictXid) { 593 super(renderQueue); 594 this.picture = pictXid; 595 this.transformInUse = false; 596 } 597 canSourceSendExposures(int x, int y, int w, int h)598 public boolean canSourceSendExposures(int x, int y, int w, int h) { 599 return false; 600 } 601 getBounds()602 public Rectangle getBounds() { 603 return null; 604 } 605 getDestination()606 public Object getDestination() { 607 return null; 608 } 609 getReplacement()610 public SurfaceData getReplacement() { 611 return null; 612 } 613 } 614 615 public static class XRPixmapSurfaceData extends XRSurfaceData { 616 Image offscreenImage; 617 int width; 618 int height; 619 int transparency; 620 XRPixmapSurfaceData(XRGraphicsConfig gc, int width, int height, Image image, SurfaceType sType, ColorModel cm, long drawable, int transparency, int pictFormat, int depth)621 public XRPixmapSurfaceData(XRGraphicsConfig gc, int width, int height, 622 Image image, SurfaceType sType, 623 ColorModel cm, long drawable, 624 int transparency, int pictFormat, 625 int depth) { 626 super(null, gc, sType, cm, depth, transparency); 627 this.width = width; 628 this.height = height; 629 offscreenImage = image; 630 this.transparency = transparency; 631 initSurface(depth, width, height, drawable, pictFormat); 632 633 initXRender(pictFormat); 634 makePipes(); 635 } 636 initSurface(int depth, int width, int height, long drawable, int pictFormat)637 public void initSurface(int depth, int width, int height, 638 long drawable, int pictFormat) { 639 try { 640 SunToolkit.awtLock(); 641 XRInitSurface(depth, width, height, drawable, pictFormat); 642 } finally { 643 SunToolkit.awtUnlock(); 644 } 645 } 646 getReplacement()647 public SurfaceData getReplacement() { 648 return restoreContents(offscreenImage); 649 } 650 651 /** 652 * Need this since the surface data is created with the color model of 653 * the target GC, which is always opaque. But in SunGraphics2D.blitSD we 654 * choose loops based on the transparency on the source SD, so it could 655 * choose wrong loop (blit instead of blitbg, for example). 656 */ getTransparency()657 public int getTransparency() { 658 return transparency; 659 } 660 getBounds()661 public Rectangle getBounds() { 662 return new Rectangle(width, height); 663 } 664 665 @Override canSourceSendExposures(int x, int y, int w, int h)666 public boolean canSourceSendExposures(int x, int y, int w, int h) { 667 return (x < 0 || y < 0 || (x + w) > width || (y + h) > height); 668 } 669 flush()670 public void flush() { 671 /* 672 * We need to invalidate the surface before disposing the native 673 * Drawable and Picture. This way if an application tries to render 674 * to an already flushed XRSurfaceData, we will notice in the 675 * validate() method above that it has been invalidated, and we will 676 * avoid using those native resources that have already been 677 * disposed. 678 */ 679 invalidate(); 680 flushNativeSurface(); 681 } 682 683 /** 684 * Returns destination Image associated with this SurfaceData. 685 */ getDestination()686 public Object getDestination() { 687 return offscreenImage; 688 } 689 } 690 getGC()691 public long getGC() { 692 return xgc; 693 } 694 695 public static class LazyPipe extends ValidatePipe { validate(SunGraphics2D sg2d)696 public boolean validate(SunGraphics2D sg2d) { 697 XRSurfaceData xsd = (XRSurfaceData) sg2d.surfaceData; 698 if (!xsd.isXRDrawableValid()) { 699 return false; 700 } 701 xsd.makePipes(); 702 return super.validate(sg2d); 703 } 704 } 705 getPicture()706 public int getPicture() { 707 return picture; 708 } 709 getXid()710 public int getXid() { 711 return xid; 712 } 713 getGraphicsConfig()714 public XRGraphicsConfig getGraphicsConfig() { 715 return graphicsConfig; 716 } 717 setStaticSrcTx(AffineTransform staticSrcTx)718 public void setStaticSrcTx(AffineTransform staticSrcTx) { 719 this.staticSrcTx = staticSrcTx; 720 } 721 } 722