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 initIDs()69 private static native void initIDs(); 70 XRInitSurface(int depth, int width, int height, long drawable, int pictFormat)71 protected native void XRInitSurface(int depth, int width, int height, 72 long drawable, int pictFormat); 73 initXRPicture(long xsdo, int pictForm)74 native void initXRPicture(long xsdo, int pictForm); 75 freeXSDOPicture(long xsdo)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 getRaster(int x, int y, int w, int h)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 initXRSurfaceData()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 */ isXRDrawableValid()117 protected boolean isXRDrawableValid() { 118 try { 119 SunToolkit.awtLock(); 120 return isDrawableValid(); 121 } finally { 122 SunToolkit.awtUnlock(); 123 } 124 } 125 126 @Override makeProxyFor(SurfaceData srcData)127 public SurfaceDataProxy makeProxyFor(SurfaceData srcData) { 128 return XRSurfaceDataProxy.createProxy(srcData, graphicsConfig); 129 } 130 131 @Override validatePipe(SunGraphics2D sg2d)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 getTextPipe(SunGraphics2D sg2d)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 getMaskFill(SunGraphics2D sg2d)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 getRenderLoops(SunGraphics2D sg2d)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 getDeviceConfiguration()237 public GraphicsConfiguration getDeviceConfiguration() { 238 return graphicsConfig; 239 } 240 241 /** 242 * Method for instantiating a Window SurfaceData 243 */ createData(X11ComponentPeer peer)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 */ createData(XRGraphicsConfig gc, int width, int height, ColorModel cm, Image image, long drawable, int transparency, boolean isTexture)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 XRSurfaceData(X11ComponentPeer peer, XRGraphicsConfig gc, SurfaceType sType, ColorModel cm, int depth, int transparency)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 XRSurfaceData(XRBackend renderQueue)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 */ initXRender(int pictureFormat)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 getGC(X11ComponentPeer peer)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 */ canSourceSendExposures(int x, int y, int w, int h)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 */ validateCopyAreaGC(Region gcClip, boolean needExposures)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 copyArea(SunGraphics2D sg2d, int x, int y, int w, int h, int dx, int dy)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 */ getSurfaceType(XRGraphicsConfig gc, int transparency)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 invalidate()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 */ validateAsSource(AffineTransform sxForm, int repeat, int filter)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 */ validateAsDestination(SunGraphics2D sg2d, Region clip)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 makePipes()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 XRWindowSurfaceData(X11ComponentPeer peer, XRGraphicsConfig gc, SurfaceType sType)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 getReplacement()576 public SurfaceData getReplacement() { 577 return peer.getSurfaceData(); 578 } 579 getBounds()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 canSourceSendExposures(int x, int y, int w, int h)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 */ getDestination()596 public Object getDestination() { 597 return peer.getTarget(); 598 } 599 invalidate()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 getDefaultScaleX()612 public double getDefaultScaleX() { 613 return scale; 614 } 615 616 @Override getDefaultScaleY()617 public double getDefaultScaleY() { 618 return scale; 619 } 620 } 621 622 public static class XRInternalSurfaceData extends XRSurfaceData { XRInternalSurfaceData(XRBackend renderQueue, int pictXid)623 public XRInternalSurfaceData(XRBackend renderQueue, int pictXid) { 624 super(renderQueue); 625 this.picture = pictXid; 626 this.transformInUse = false; 627 } 628 canSourceSendExposures(int x, int y, int w, int h)629 public boolean canSourceSendExposures(int x, int y, int w, int h) { 630 return false; 631 } 632 getBounds()633 public Rectangle getBounds() { 634 return null; 635 } 636 getDestination()637 public Object getDestination() { 638 return null; 639 } 640 getReplacement()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 XRPixmapSurfaceData(XRGraphicsConfig gc, int width, int height, Image image, SurfaceType sType, ColorModel cm, long drawable, int transparency, int pictFormat, int depth, boolean isTexture)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 initSurface(int depth, int width, int height, long drawable, int pictFormat)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 getReplacement()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 */ getTransparency()690 public int getTransparency() { 691 return transparency; 692 } 693 getBounds()694 public Rectangle getBounds() { 695 return new Rectangle(width, height); 696 } 697 698 @Override canSourceSendExposures(int x, int y, int w, int h)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 flush()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 */ getDestination()719 public Object getDestination() { 720 return offscreenImage; 721 } 722 723 @Override getDefaultScaleX()724 public double getDefaultScaleX() { 725 return scale; 726 } 727 728 @Override getDefaultScaleY()729 public double getDefaultScaleY() { 730 return scale; 731 } 732 } 733 getGC()734 public long getGC() { 735 return xgc; 736 } 737 738 public static class LazyPipe extends ValidatePipe { validate(SunGraphics2D sg2d)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 getPicture()749 public int getPicture() { 750 return picture; 751 } 752 getXid()753 public int getXid() { 754 return xid; 755 } 756 getGraphicsConfig()757 public XRGraphicsConfig getGraphicsConfig() { 758 return graphicsConfig; 759 } 760 setStaticSrcTx(AffineTransform staticSrcTx)761 public void setStaticSrcTx(AffineTransform staticSrcTx) { 762 this.staticSrcTx = staticSrcTx; 763 } 764 } 765