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 51 private static native void initIDs(); 52 53 protected native void XRInitSurface(int depth, int width, int height, 54 long drawable, int pictFormat); 55 56 native void initXRPicture(long xsdo, int pictForm); 57 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 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 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 */ 98 protected boolean isXRDrawableValid() { 99 try { 100 SunToolkit.awtLock(); 101 return isDrawableValid(); 102 } finally { 103 SunToolkit.awtUnlock(); 104 } 105 } 106 107 @Override 108 public SurfaceDataProxy makeProxyFor(SurfaceData srcData) { 109 return XRSurfaceDataProxy.createProxy(srcData, graphicsConfig); 110 } 111 112 @Override 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 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 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 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 226 public GraphicsConfiguration getDeviceConfiguration() { 227 return graphicsConfig; 228 } 229 230 /** 231 * Method for instantiating a Window SurfaceData 232 */ 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 */ 243 public static XRPixmapSurfaceData createData(XRGraphicsConfig gc, 244 int width, int height, 245 ColorModel cm, Image image, 246 long drawable, 247 int transparency, 248 boolean isTexture) { 249 int depth; 250 // If we have a 32 bit color model for the window it needs 251 // alpha to support translucency of the window so we need 252 // to upgrade what was requested for the surface. 253 if (gc.getColorModel().getPixelSize() == 32) { 254 depth = 32; 255 transparency = Transparency.TRANSLUCENT; 256 } else { 257 depth = transparency > Transparency.OPAQUE ? 32 : 24; 258 } 259 260 if (depth == 24) { 261 cm = new DirectColorModel(depth, 262 0x00FF0000, 0x0000FF00, 0x000000FF); 263 } else { 264 cm = new DirectColorModel(depth, 0x00FF0000, 0x0000FF00, 265 0x000000FF, 0xFF000000); 266 } 267 268 return new XRPixmapSurfaceData 269 (gc, width, height, image, getSurfaceType(gc, transparency), 270 cm, drawable, transparency, 271 XRUtils.getPictureFormatForTransparency(transparency), depth, isTexture); 272 } 273 274 protected XRSurfaceData(X11ComponentPeer peer, XRGraphicsConfig gc, 275 SurfaceType sType, ColorModel cm, int depth, int transparency) 276 { 277 super(sType, cm); 278 this.peer = peer; 279 this.graphicsConfig = gc; 280 this.solidloops = graphicsConfig.getSolidLoops(sType); 281 this.depth = depth; 282 initOps(peer, graphicsConfig, depth); 283 284 setBlitProxyKey(gc.getProxyKey()); 285 } 286 287 protected XRSurfaceData(XRBackend renderQueue) { 288 super(XRSurfaceData.IntRgbX11, 289 new DirectColorModel(24, 0x00FF0000, 0x0000FF00, 0x000000FF)); 290 this.renderQueue = renderQueue; 291 } 292 293 /** 294 * Inits the XRender-data-structures which belong to the XRSurfaceData. 295 * 296 * @param pictureFormat 297 */ 298 public void initXRender(int pictureFormat) { 299 try { 300 SunToolkit.awtLock(); 301 initXRPicture(getNativeOps(), pictureFormat); 302 renderQueue = XRCompositeManager.getInstance(this).getBackend(); 303 maskBuffer = XRCompositeManager.getInstance(this); 304 } catch (Throwable ex) { 305 ex.printStackTrace(); 306 } finally { 307 SunToolkit.awtUnlock(); 308 } 309 } 310 311 public static XRGraphicsConfig getGC(X11ComponentPeer peer) { 312 if (peer != null) { 313 return (XRGraphicsConfig) peer.getGraphicsConfiguration(); 314 } else { 315 GraphicsEnvironment env = 316 GraphicsEnvironment.getLocalGraphicsEnvironment(); 317 GraphicsDevice gd = env.getDefaultScreenDevice(); 318 return (XRGraphicsConfig) gd.getDefaultConfiguration(); 319 } 320 } 321 322 /** 323 * Returns a boolean indicating whether or not a copyArea from the given 324 * rectangle source coordinates might be incomplete and result in X11 325 * GraphicsExposure events being generated from XCopyArea. This method 326 * allows the SurfaceData copyArea method to determine if it needs to set 327 * the GraphicsExposures attribute of the X11 GC to True or False to receive 328 * or avoid the events. 329 * 330 * @return true if there is any chance that an XCopyArea from the given 331 * source coordinates could produce any X11 Exposure events. 332 */ 333 public abstract boolean canSourceSendExposures(int x, int y, int w, int h); 334 335 /** 336 * CopyArea is implemented using the "old" X11 GC, therefor clip and 337 * needExposures have to be validated against that GC. Pictures and GCs 338 * don't share state. 339 */ 340 public void validateCopyAreaGC(Region gcClip, boolean needExposures) { 341 if (validatedGCClip != gcClip) { 342 if (gcClip != null) 343 renderQueue.setGCClipRectangles(xgc, gcClip); 344 validatedGCClip = gcClip; 345 } 346 347 if (validatedExposures != needExposures) { 348 validatedExposures = needExposures; 349 renderQueue.setGCExposures(xgc, needExposures); 350 } 351 352 if (validatedXorComp != null) { 353 renderQueue.setGCMode(xgc, true); 354 renderQueue.setGCForeground(xgc, validatedGCForegroundPixel); 355 validatedXorComp = null; 356 } 357 } 358 359 public boolean copyArea(SunGraphics2D sg2d, int x, int y, int w, int h, 360 int dx, int dy) { 361 if (xrpipe == null) { 362 if (!isXRDrawableValid()) { 363 return true; 364 } 365 makePipes(); 366 } 367 CompositeType comptype = sg2d.imageComp; 368 if (sg2d.transformState < SunGraphics2D.TRANSFORM_TRANSLATESCALE && 369 (CompositeType.SrcOverNoEa.equals(comptype) || 370 CompositeType.SrcNoEa.equals(comptype))) 371 { 372 try { 373 SunToolkit.awtLock(); 374 boolean needExposures = canSourceSendExposures(x, y, w, h); 375 validateCopyAreaGC(sg2d.getCompClip(), needExposures); 376 renderQueue.copyArea(xid, xid, xgc, x, y, w, h, x + dx, y + dy); 377 } finally { 378 SunToolkit.awtUnlock(); 379 } 380 return true; 381 } 382 return false; 383 } 384 385 /** 386 * Returns the XRender SurfaceType which is able to fullfill the specified 387 * transparency requirement. 388 */ 389 public static SurfaceType getSurfaceType(XRGraphicsConfig gc, 390 int transparency) { 391 SurfaceType sType = null; 392 393 switch (transparency) { 394 case Transparency.OPAQUE: 395 sType = XRSurfaceData.IntRgbX11; 396 break; 397 398 case Transparency.BITMASK: 399 case Transparency.TRANSLUCENT: 400 sType = XRSurfaceData.IntArgbPreX11; 401 break; 402 } 403 404 return sType; 405 } 406 407 public void invalidate() { 408 if (isValid()) { 409 setInvalid(); 410 super.invalidate(); 411 } 412 } 413 414 private long xgc; // GC is still used for copyArea 415 private int validatedGCForegroundPixel = 0; 416 private XORComposite validatedXorComp; 417 private int xid; 418 public int picture; 419 public XRCompositeManager maskBuffer; 420 421 private Region validatedClip; 422 private Region validatedGCClip; 423 private boolean validatedExposures = true; 424 425 boolean transformInUse = false; 426 AffineTransform validatedSourceTransform = new AffineTransform(); 427 AffineTransform staticSrcTx = null; 428 int validatedRepeat = XRUtils.RepeatNone; 429 int validatedFilter = XRUtils.FAST; 430 431 /** 432 * Validates an XRSurfaceData when used as source. Note that the clip is 433 * applied when used as source as well as destination. 434 */ 435 void validateAsSource(AffineTransform sxForm, int repeat, int filter) { 436 437 if (validatedClip != null) { 438 validatedClip = null; 439 renderQueue.setClipRectangles(picture, null); 440 } 441 442 if (validatedRepeat != repeat && repeat != -1) { 443 validatedRepeat = repeat; 444 renderQueue.setPictureRepeat(picture, repeat); 445 } 446 447 if (sxForm == null) { 448 if (transformInUse) { 449 validatedSourceTransform.setToIdentity(); 450 renderQueue.setPictureTransform(picture, 451 validatedSourceTransform); 452 transformInUse = false; 453 } 454 } else if (!transformInUse || 455 (transformInUse && !sxForm.equals(validatedSourceTransform))) { 456 457 validatedSourceTransform.setTransform(sxForm.getScaleX(), 458 sxForm.getShearY(), 459 sxForm.getShearX(), 460 sxForm.getScaleY(), 461 sxForm.getTranslateX(), 462 sxForm.getTranslateY()); 463 464 AffineTransform srcTransform = validatedSourceTransform; 465 if(staticSrcTx != null) { 466 // Apply static transform set when used as texture or gradient. 467 // Create a copy to not modify validatedSourceTransform as 468 // this would confuse the validation logic. 469 srcTransform = new AffineTransform(validatedSourceTransform); 470 srcTransform.preConcatenate(staticSrcTx); 471 } 472 473 renderQueue.setPictureTransform(picture, srcTransform); 474 transformInUse = true; 475 } 476 477 if (filter != validatedFilter && filter != -1) { 478 renderQueue.setFilter(picture, filter); 479 validatedFilter = filter; 480 } 481 } 482 483 /** 484 * Validates the Surface when used as destination. 485 */ 486 public void validateAsDestination(SunGraphics2D sg2d, Region clip) { 487 if (!isValid()) { 488 throw new InvalidPipeException("bounds changed"); 489 } 490 491 boolean updateGCClip = false; 492 if (clip != validatedClip) { 493 renderQueue.setClipRectangles(picture, clip); 494 validatedClip = clip; 495 updateGCClip = true; 496 } 497 498 if (sg2d != null && sg2d.compositeState == SunGraphics2D.COMP_XOR) { 499 if (validatedXorComp != sg2d.getComposite()) { 500 validatedXorComp = (XORComposite) sg2d.getComposite(); 501 renderQueue.setGCMode(xgc, false); 502 } 503 504 // validate pixel 505 int pixel = sg2d.pixel; 506 if (validatedGCForegroundPixel != pixel) { 507 int xorpixelmod = validatedXorComp.getXorPixel(); 508 renderQueue.setGCForeground(xgc, pixel ^ xorpixelmod); 509 validatedGCForegroundPixel = pixel; 510 } 511 512 if (updateGCClip) { 513 renderQueue.setGCClipRectangles(xgc, clip); 514 } 515 } 516 } 517 518 public synchronized void makePipes() { /* 519 * TODO: Why is this synchronized, 520 * but access not? 521 */ 522 if (xrpipe == null) { 523 try { 524 SunToolkit.awtLock(); 525 xgc = XCreateGC(getNativeOps()); 526 527 xrpipe = new XRRenderer(maskBuffer.getMaskBuffer()); 528 xrtxpipe = new PixelToShapeConverter(xrpipe); 529 xrtextpipe = maskBuffer.getTextRenderer(); 530 xrDrawImage = new XRDrawImage(); 531 532 if (JulesPathBuf.isCairoAvailable()) { 533 aaShapePipe = 534 new JulesShapePipe(XRCompositeManager.getInstance(this)); 535 aaPixelToShapeConv = new PixelToShapeConverter(aaShapePipe); 536 } 537 } finally { 538 SunToolkit.awtUnlock(); 539 } 540 } 541 } 542 543 public static class XRWindowSurfaceData extends XRSurfaceData { 544 545 protected final int scale; 546 547 public XRWindowSurfaceData(X11ComponentPeer peer, 548 XRGraphicsConfig gc, SurfaceType sType) { 549 super(peer, gc, sType, peer.getColorModel(), 550 peer.getColorModel().getPixelSize(), Transparency.OPAQUE); 551 552 this.scale = gc.getScale(); 553 554 if (isXRDrawableValid()) { 555 // If we have a 32 bit color model for the window it needs 556 // alpha to support translucency of the window so we need 557 // to get the ARGB32 XRender picture format else for 558 // 24 bit colormodel we need RGB24 or OPAQUE pictureformat. 559 if (peer.getColorModel().getPixelSize() == 32) { 560 initXRender(XRUtils. 561 getPictureFormatForTransparency(Transparency.TRANSLUCENT)); 562 } 563 else { 564 initXRender(XRUtils. 565 getPictureFormatForTransparency(Transparency.OPAQUE)); 566 } 567 makePipes(); 568 } 569 } 570 571 public SurfaceData getReplacement() { 572 return peer.getSurfaceData(); 573 } 574 575 public Rectangle getBounds() { 576 Rectangle r = peer.getBounds(); 577 r.x = r.y = 0; 578 r.width *= scale; 579 r.height *= scale; 580 return r; 581 } 582 583 @Override 584 public boolean canSourceSendExposures(int x, int y, int w, int h) { 585 return true; 586 } 587 588 /** 589 * Returns destination Component associated with this SurfaceData. 590 */ 591 public Object getDestination() { 592 return peer.getTarget(); 593 } 594 595 public void invalidate() { 596 try { 597 SunToolkit.awtLock(); 598 freeXSDOPicture(getNativeOps()); 599 }finally { 600 SunToolkit.awtUnlock(); 601 } 602 603 super.invalidate(); 604 } 605 606 @Override 607 public double getDefaultScaleX() { 608 return scale; 609 } 610 611 @Override 612 public double getDefaultScaleY() { 613 return scale; 614 } 615 } 616 617 public static class XRInternalSurfaceData extends XRSurfaceData { 618 public XRInternalSurfaceData(XRBackend renderQueue, int pictXid) { 619 super(renderQueue); 620 this.picture = pictXid; 621 this.transformInUse = false; 622 } 623 624 public boolean canSourceSendExposures(int x, int y, int w, int h) { 625 return false; 626 } 627 628 public Rectangle getBounds() { 629 return null; 630 } 631 632 public Object getDestination() { 633 return null; 634 } 635 636 public SurfaceData getReplacement() { 637 return null; 638 } 639 } 640 641 public static class XRPixmapSurfaceData extends XRSurfaceData { 642 Image offscreenImage; 643 int width; 644 int height; 645 int transparency; 646 private final int scale; 647 648 public XRPixmapSurfaceData(XRGraphicsConfig gc, int width, int height, 649 Image image, SurfaceType sType, 650 ColorModel cm, long drawable, 651 int transparency, int pictFormat, 652 int depth, boolean isTexture) { 653 super(null, gc, sType, cm, depth, transparency); 654 this.scale = isTexture ? 1 : gc.getDevice().getScaleFactor(); 655 this.width = width * scale; 656 this.height = height * scale; 657 offscreenImage = image; 658 this.transparency = transparency; 659 initSurface(depth, this.width, this.height, drawable, pictFormat); 660 661 initXRender(pictFormat); 662 makePipes(); 663 } 664 665 public void initSurface(int depth, int width, int height, 666 long drawable, int pictFormat) { 667 try { 668 SunToolkit.awtLock(); 669 XRInitSurface(depth, width, height, drawable, pictFormat); 670 } finally { 671 SunToolkit.awtUnlock(); 672 } 673 } 674 675 public SurfaceData getReplacement() { 676 return restoreContents(offscreenImage); 677 } 678 679 /** 680 * Need this since the surface data is created with the color model of 681 * the target GC, which is always opaque. But in SunGraphics2D.blitSD we 682 * choose loops based on the transparency on the source SD, so it could 683 * choose wrong loop (blit instead of blitbg, for example). 684 */ 685 public int getTransparency() { 686 return transparency; 687 } 688 689 public Rectangle getBounds() { 690 return new Rectangle(width, height); 691 } 692 693 @Override 694 public boolean canSourceSendExposures(int x, int y, int w, int h) { 695 return (x < 0 || y < 0 || (x + w) > width || (y + h) > height); 696 } 697 698 public void flush() { 699 /* 700 * We need to invalidate the surface before disposing the native 701 * Drawable and Picture. This way if an application tries to render 702 * to an already flushed XRSurfaceData, we will notice in the 703 * validate() method above that it has been invalidated, and we will 704 * avoid using those native resources that have already been 705 * disposed. 706 */ 707 invalidate(); 708 flushNativeSurface(); 709 } 710 711 /** 712 * Returns destination Image associated with this SurfaceData. 713 */ 714 public Object getDestination() { 715 return offscreenImage; 716 } 717 718 @Override 719 public double getDefaultScaleX() { 720 return scale; 721 } 722 723 @Override 724 public double getDefaultScaleY() { 725 return scale; 726 } 727 } 728 729 public long getGC() { 730 return xgc; 731 } 732 733 public static class LazyPipe extends ValidatePipe { 734 public boolean validate(SunGraphics2D sg2d) { 735 XRSurfaceData xsd = (XRSurfaceData) sg2d.surfaceData; 736 if (!xsd.isXRDrawableValid()) { 737 return false; 738 } 739 xsd.makePipes(); 740 return super.validate(sg2d); 741 } 742 } 743 744 public int getPicture() { 745 return picture; 746 } 747 748 public int getXid() { 749 return xid; 750 } 751 752 public XRGraphicsConfig getGraphicsConfig() { 753 return graphicsConfig; 754 } 755 756 public void setStaticSrcTx(AffineTransform staticSrcTx) { 757 this.staticSrcTx = staticSrcTx; 758 } 759 }