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