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