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