1/*
2 * Copyright (c) 2007, 2014, 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
26package sun.java2d.d3d;
27
28import java.awt.Composite;
29import java.awt.Transparency;
30import java.awt.geom.AffineTransform;
31import java.awt.image.AffineTransformOp;
32import java.awt.image.BufferedImage;
33import java.awt.image.BufferedImageOp;
34import java.lang.ref.WeakReference;
35import java.lang.annotation.Native;
36import sun.java2d.ScreenUpdateManager;
37import sun.java2d.SurfaceData;
38import sun.java2d.loops.Blit;
39import sun.java2d.loops.CompositeType;
40import sun.java2d.loops.GraphicsPrimitive;
41import sun.java2d.loops.GraphicsPrimitiveMgr;
42import sun.java2d.loops.ScaledBlit;
43import sun.java2d.loops.SurfaceType;
44import sun.java2d.loops.TransformBlit;
45import sun.java2d.pipe.Region;
46import sun.java2d.pipe.RenderBuffer;
47import sun.java2d.pipe.RenderQueue;
48import static sun.java2d.pipe.BufferedOpCodes.*;
49import sun.java2d.windows.GDIWindowSurfaceData;
50
51final class D3DBlitLoops {
52
53    static void register() {
54        Blit blitIntArgbPreToSurface =
55            new D3DSwToSurfaceBlit(SurfaceType.IntArgbPre,
56                                   D3DSurfaceData.ST_INT_ARGB_PRE);
57        Blit blitIntArgbPreToTexture =
58            new D3DSwToTextureBlit(SurfaceType.IntArgbPre,
59                                   D3DSurfaceData.ST_INT_ARGB_PRE);
60        TransformBlit transformBlitIntArgbPreToSurface =
61            new D3DSwToSurfaceTransform(SurfaceType.IntArgbPre,
62                                        D3DSurfaceData.ST_INT_ARGB_PRE);
63        GraphicsPrimitive[] primitives = {
64            // prevent D3DSurface -> Screen blits
65            new D3DSurfaceToGDIWindowSurfaceBlit(),
66            new D3DSurfaceToGDIWindowSurfaceScale(),
67            new D3DSurfaceToGDIWindowSurfaceTransform(),
68
69            // surface->surface ops
70            new D3DSurfaceToSurfaceBlit(),
71            new D3DSurfaceToSurfaceScale(),
72            new D3DSurfaceToSurfaceTransform(),
73
74            // render-to-texture surface->surface ops
75            new D3DRTTSurfaceToSurfaceBlit(),
76            new D3DRTTSurfaceToSurfaceScale(),
77            new D3DRTTSurfaceToSurfaceTransform(),
78
79            // surface->sw ops
80            new D3DSurfaceToSwBlit(SurfaceType.IntArgb,
81                                   D3DSurfaceData.ST_INT_ARGB),
82
83            // sw->surface ops
84            blitIntArgbPreToSurface,
85            new D3DSwToSurfaceBlit(SurfaceType.IntArgb,
86                                   D3DSurfaceData.ST_INT_ARGB),
87            new D3DSwToSurfaceBlit(SurfaceType.IntRgb,
88                                   D3DSurfaceData.ST_INT_RGB),
89            new D3DSwToSurfaceBlit(SurfaceType.IntBgr,
90                                   D3DSurfaceData.ST_INT_BGR),
91            new D3DSwToSurfaceBlit(SurfaceType.ThreeByteBgr,
92                                   D3DSurfaceData.ST_3BYTE_BGR),
93            new D3DSwToSurfaceBlit(SurfaceType.Ushort565Rgb,
94                                   D3DSurfaceData.ST_USHORT_565_RGB),
95            new D3DSwToSurfaceBlit(SurfaceType.Ushort555Rgb,
96                                   D3DSurfaceData.ST_USHORT_555_RGB),
97            new D3DSwToSurfaceBlit(SurfaceType.ByteIndexed,
98                                   D3DSurfaceData.ST_BYTE_INDEXED),
99            // REMIND: we don't have a native sw loop to back this loop up
100//            new D3DSwToSurfaceBlit(SurfaceType.ByteIndexedBm,
101//                                   D3DSurfaceData.ST_BYTE_INDEXED_BM),
102            new D3DGeneralBlit(D3DSurfaceData.D3DSurface,
103                               CompositeType.AnyAlpha,
104                               blitIntArgbPreToSurface),
105
106            new D3DSwToSurfaceScale(SurfaceType.IntArgb,
107                                    D3DSurfaceData.ST_INT_ARGB),
108            new D3DSwToSurfaceScale(SurfaceType.IntArgbPre,
109                                    D3DSurfaceData.ST_INT_ARGB_PRE),
110            new D3DSwToSurfaceScale(SurfaceType.IntRgb,
111                                    D3DSurfaceData.ST_INT_RGB),
112            new D3DSwToSurfaceScale(SurfaceType.IntBgr,
113                                    D3DSurfaceData.ST_INT_BGR),
114            new D3DSwToSurfaceScale(SurfaceType.ThreeByteBgr,
115                                    D3DSurfaceData.ST_3BYTE_BGR),
116            new D3DSwToSurfaceScale(SurfaceType.Ushort565Rgb,
117                                    D3DSurfaceData.ST_USHORT_565_RGB),
118            new D3DSwToSurfaceScale(SurfaceType.Ushort555Rgb,
119                                    D3DSurfaceData.ST_USHORT_555_RGB),
120            new D3DSwToSurfaceScale(SurfaceType.ByteIndexed,
121                                    D3DSurfaceData.ST_BYTE_INDEXED),
122            // REMIND: we don't have a native sw loop to back this loop up
123//            new D3DSwToSurfaceScale(SurfaceType.ByteIndexedBm,
124//                                    D3DSurfaceData.ST_BYTE_INDEXED_BM),
125
126            new D3DSwToSurfaceTransform(SurfaceType.IntArgb,
127                                        D3DSurfaceData.ST_INT_ARGB),
128            new D3DSwToSurfaceTransform(SurfaceType.IntRgb,
129                                        D3DSurfaceData.ST_INT_RGB),
130            new D3DSwToSurfaceTransform(SurfaceType.IntBgr,
131                                        D3DSurfaceData.ST_INT_BGR),
132            new D3DSwToSurfaceTransform(SurfaceType.ThreeByteBgr,
133                                        D3DSurfaceData.ST_3BYTE_BGR),
134            new D3DSwToSurfaceTransform(SurfaceType.Ushort565Rgb,
135                                        D3DSurfaceData.ST_USHORT_565_RGB),
136            new D3DSwToSurfaceTransform(SurfaceType.Ushort555Rgb,
137                                        D3DSurfaceData.ST_USHORT_555_RGB),
138            new D3DSwToSurfaceTransform(SurfaceType.ByteIndexed,
139                                        D3DSurfaceData.ST_BYTE_INDEXED),
140            // REMIND: we don't have a native sw loop to back this loop up
141//            new D3DSwToSurfaceTransform(SurfaceType.ByteIndexedBm,
142//                                        D3DSurfaceData.ST_BYTE_INDEXED_BM),
143            transformBlitIntArgbPreToSurface,
144
145            new D3DGeneralTransformedBlit(transformBlitIntArgbPreToSurface),
146
147            // texture->surface ops
148            new D3DTextureToSurfaceBlit(),
149            new D3DTextureToSurfaceScale(),
150            new D3DTextureToSurfaceTransform(),
151
152            // sw->texture ops
153            blitIntArgbPreToTexture,
154            new D3DSwToTextureBlit(SurfaceType.IntRgb,
155                                   D3DSurfaceData.ST_INT_RGB),
156            new D3DSwToTextureBlit(SurfaceType.IntArgb,
157                                   D3DSurfaceData.ST_INT_ARGB),
158            new D3DSwToTextureBlit(SurfaceType.IntBgr,
159                                   D3DSurfaceData.ST_INT_BGR),
160            new D3DSwToTextureBlit(SurfaceType.ThreeByteBgr,
161                                   D3DSurfaceData.ST_3BYTE_BGR),
162            new D3DSwToTextureBlit(SurfaceType.Ushort565Rgb,
163                                   D3DSurfaceData.ST_USHORT_565_RGB),
164            new D3DSwToTextureBlit(SurfaceType.Ushort555Rgb,
165                                   D3DSurfaceData.ST_USHORT_555_RGB),
166            new D3DSwToTextureBlit(SurfaceType.ByteIndexed,
167                                   D3DSurfaceData.ST_BYTE_INDEXED),
168            // REMIND: we don't have a native sw loop to back this loop up
169//            new D3DSwToTextureBlit(SurfaceType.ByteIndexedBm,
170//                                   D3DSurfaceData.ST_BYTE_INDEXED_BM),
171            new D3DGeneralBlit(D3DSurfaceData.D3DTexture,
172                               CompositeType.SrcNoEa,
173                               blitIntArgbPreToTexture),
174        };
175        GraphicsPrimitiveMgr.register(primitives);
176    }
177
178    /**
179     * The following offsets are used to pack the parameters in
180     * createPackedParams().  (They are also used at the native level when
181     * unpacking the params.)
182     */
183    @Native private static final int OFFSET_SRCTYPE = 16;
184    @Native private static final int OFFSET_HINT    =  8;
185    @Native private static final int OFFSET_TEXTURE =  3;
186    @Native private static final int OFFSET_RTT     =  2;
187    @Native private static final int OFFSET_XFORM   =  1;
188    @Native private static final int OFFSET_ISOBLIT =  0;
189
190    /**
191     * Packs the given parameters into a single int value in order to save
192     * space on the rendering queue.
193     */
194    private static int createPackedParams(boolean isoblit, boolean texture,
195                                          boolean rtt, boolean xform,
196                                          int hint, int srctype)
197    {
198        return
199            ((srctype           << OFFSET_SRCTYPE) |
200             (hint              << OFFSET_HINT   ) |
201             ((texture ? 1 : 0) << OFFSET_TEXTURE) |
202             ((rtt     ? 1 : 0) << OFFSET_RTT    ) |
203             ((xform   ? 1 : 0) << OFFSET_XFORM  ) |
204             ((isoblit ? 1 : 0) << OFFSET_ISOBLIT));
205    }
206
207    /**
208     * Enqueues a BLIT operation with the given parameters.  Note that the
209     * RenderQueue lock must be held before calling this method.
210     */
211    private static void enqueueBlit(RenderQueue rq,
212                                    SurfaceData src, SurfaceData dst,
213                                    int packedParams,
214                                    int sx1, int sy1,
215                                    int sx2, int sy2,
216                                    double dx1, double dy1,
217                                    double dx2, double dy2)
218    {
219        // assert rq.lock.isHeldByCurrentThread();
220        RenderBuffer buf = rq.getBuffer();
221        rq.ensureCapacityAndAlignment(72, 24);
222        buf.putInt(BLIT);
223        buf.putInt(packedParams);
224        buf.putInt(sx1).putInt(sy1);
225        buf.putInt(sx2).putInt(sy2);
226        buf.putDouble(dx1).putDouble(dy1);
227        buf.putDouble(dx2).putDouble(dy2);
228        buf.putLong(src.getNativeOps());
229        buf.putLong(dst.getNativeOps());
230    }
231
232    static void Blit(SurfaceData srcData, SurfaceData dstData,
233                     Composite comp, Region clip,
234                     AffineTransform xform, int hint,
235                     int sx1, int sy1,
236                     int sx2, int sy2,
237                     double dx1, double dy1,
238                     double dx2, double dy2,
239                     int srctype, boolean texture)
240    {
241        int ctxflags = 0;
242        if (srcData.getTransparency() == Transparency.OPAQUE) {
243            ctxflags |= D3DContext.SRC_IS_OPAQUE;
244        }
245
246        D3DSurfaceData d3dDst = (D3DSurfaceData)dstData;
247        D3DRenderQueue rq = D3DRenderQueue.getInstance();
248        rq.lock();
249        try {
250            // make sure the RenderQueue keeps a hard reference to the
251            // source (sysmem) SurfaceData to prevent it from being
252            // disposed while the operation is processed on the QFT
253            rq.addReference(srcData);
254
255            if (texture) {
256                // make sure we have a current context before uploading
257                // the sysmem data to the texture object
258                D3DContext.setScratchSurface(d3dDst.getContext());
259            } else {
260                D3DContext.validateContext(d3dDst, d3dDst,
261                                           clip, comp, xform, null, null,
262                                           ctxflags);
263            }
264
265            int packedParams = createPackedParams(false, texture,
266                                                  false, xform != null,
267                                                  hint, srctype);
268            enqueueBlit(rq, srcData, dstData,
269                        packedParams,
270                        sx1, sy1, sx2, sy2,
271                        dx1, dy1, dx2, dy2);
272
273            // always flush immediately, since we (currently) have no means
274            // of tracking changes to the system memory surface
275            rq.flushNow();
276        } finally {
277            rq.unlock();
278        }
279
280        if (d3dDst.getType() == D3DSurfaceData.WINDOW) {
281            // flush immediately when copying to the screen to improve
282            // responsiveness of applications using VI or BI backbuffers
283            D3DScreenUpdateManager mgr =
284                (D3DScreenUpdateManager)ScreenUpdateManager.getInstance();
285            mgr.runUpdateNow();
286        }
287    }
288
289    /**
290     * Note: The srcImg and biop parameters are only used when invoked
291     * from the D3DBufImgOps.renderImageWithOp() method; in all other cases,
292     * this method can be called with null values for those two parameters,
293     * and they will be effectively ignored.
294     */
295    static void IsoBlit(SurfaceData srcData, SurfaceData dstData,
296                        BufferedImage srcImg, BufferedImageOp biop,
297                        Composite comp, Region clip,
298                        AffineTransform xform, int hint,
299                        int sx1, int sy1,
300                        int sx2, int sy2,
301                        double dx1, double dy1,
302                        double dx2, double dy2,
303                        boolean texture)
304    {
305        int ctxflags = 0;
306        if (srcData.getTransparency() == Transparency.OPAQUE) {
307            ctxflags |= D3DContext.SRC_IS_OPAQUE;
308        }
309
310        D3DSurfaceData d3dDst = (D3DSurfaceData)dstData;
311        D3DRenderQueue rq = D3DRenderQueue.getInstance();
312        boolean rtt = false;
313        rq.lock();
314        try {
315            D3DSurfaceData d3dSrc = (D3DSurfaceData)srcData;
316            int srctype = d3dSrc.getType();
317            D3DSurfaceData srcCtxData = d3dSrc;
318            if (srctype == D3DSurfaceData.TEXTURE) {
319                rtt = false;
320            } else {
321                // the source is a backbuffer, or render-to-texture
322                // surface; we set rtt to true to differentiate this kind
323                // of surface from a regular texture object
324                rtt = true;
325            }
326
327            D3DContext.validateContext(srcCtxData, d3dDst,
328                                       clip, comp, xform, null, null,
329                                       ctxflags);
330
331            if (biop != null) {
332                D3DBufImgOps.enableBufImgOp(rq, d3dSrc, srcImg, biop);
333            }
334
335            int packedParams = createPackedParams(true, texture,
336                                                  rtt, xform != null,
337                                                  hint, 0 /*unused*/);
338            enqueueBlit(rq, srcData, dstData,
339                        packedParams,
340                        sx1, sy1, sx2, sy2,
341                        dx1, dy1, dx2, dy2);
342
343            if (biop != null) {
344                D3DBufImgOps.disableBufImgOp(rq, biop);
345            }
346        } finally {
347            rq.unlock();
348        }
349
350        if (rtt && (d3dDst.getType() == D3DSurfaceData.WINDOW)) {
351            // we only have to flush immediately when copying from a
352            // (non-texture) surface to the screen; otherwise Swing apps
353            // might appear unresponsive until the auto-flush completes
354            D3DScreenUpdateManager mgr =
355                (D3DScreenUpdateManager)ScreenUpdateManager.getInstance();
356            mgr.runUpdateNow();
357        }
358    }
359}
360
361class D3DSurfaceToSurfaceBlit extends Blit {
362
363    D3DSurfaceToSurfaceBlit() {
364        super(D3DSurfaceData.D3DSurface,
365              CompositeType.AnyAlpha,
366              D3DSurfaceData.D3DSurface);
367    }
368
369    public void Blit(SurfaceData src, SurfaceData dst,
370                     Composite comp, Region clip,
371                     int sx, int sy, int dx, int dy, int w, int h)
372    {
373        D3DBlitLoops.IsoBlit(src, dst,
374                             null, null,
375                             comp, clip, null,
376                             AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
377                             sx, sy, sx+w, sy+h,
378                             dx, dy, dx+w, dy+h,
379                             false);
380    }
381}
382
383class D3DSurfaceToSurfaceScale extends ScaledBlit {
384
385    D3DSurfaceToSurfaceScale() {
386        super(D3DSurfaceData.D3DSurface,
387              CompositeType.AnyAlpha,
388              D3DSurfaceData.D3DSurface);
389    }
390
391    public void Scale(SurfaceData src, SurfaceData dst,
392                      Composite comp, Region clip,
393                      int sx1, int sy1,
394                      int sx2, int sy2,
395                      double dx1, double dy1,
396                      double dx2, double dy2)
397    {
398        D3DBlitLoops.IsoBlit(src, dst,
399                             null, null,
400                             comp, clip, null,
401                             AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
402                             sx1, sy1, sx2, sy2,
403                             dx1, dy1, dx2, dy2,
404                             false);
405    }
406}
407
408class D3DSurfaceToSurfaceTransform extends TransformBlit {
409
410    D3DSurfaceToSurfaceTransform() {
411        super(D3DSurfaceData.D3DSurface,
412              CompositeType.AnyAlpha,
413              D3DSurfaceData.D3DSurface);
414    }
415
416    public void Transform(SurfaceData src, SurfaceData dst,
417                          Composite comp, Region clip,
418                          AffineTransform at, int hint,
419                          int sx, int sy, int dx, int dy,
420                          int w, int h)
421    {
422        D3DBlitLoops.IsoBlit(src, dst,
423                             null, null,
424                             comp, clip, at, hint,
425                             sx, sy, sx+w, sy+h,
426                             dx, dy, dx+w, dy+h,
427                             false);
428    }
429}
430
431class D3DRTTSurfaceToSurfaceBlit extends Blit {
432
433    D3DRTTSurfaceToSurfaceBlit() {
434        super(D3DSurfaceData.D3DSurfaceRTT,
435              CompositeType.AnyAlpha,
436              D3DSurfaceData.D3DSurface);
437    }
438
439    public void Blit(SurfaceData src, SurfaceData dst,
440                     Composite comp, Region clip,
441                     int sx, int sy, int dx, int dy, int w, int h)
442    {
443        D3DBlitLoops.IsoBlit(src, dst,
444                             null, null,
445                             comp, clip, null,
446                             AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
447                             sx, sy, sx+w, sy+h,
448                             dx, dy, dx+w, dy+h,
449                             true);
450    }
451}
452
453class D3DRTTSurfaceToSurfaceScale extends ScaledBlit {
454
455    D3DRTTSurfaceToSurfaceScale() {
456        super(D3DSurfaceData.D3DSurfaceRTT,
457              CompositeType.AnyAlpha,
458              D3DSurfaceData.D3DSurface);
459    }
460
461    public void Scale(SurfaceData src, SurfaceData dst,
462                      Composite comp, Region clip,
463                      int sx1, int sy1,
464                      int sx2, int sy2,
465                      double dx1, double dy1,
466                      double dx2, double dy2)
467    {
468        D3DBlitLoops.IsoBlit(src, dst,
469                             null, null,
470                             comp, clip, null,
471                             AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
472                             sx1, sy1, sx2, sy2,
473                             dx1, dy1, dx2, dy2,
474                             true);
475    }
476}
477
478class D3DRTTSurfaceToSurfaceTransform extends TransformBlit {
479
480    D3DRTTSurfaceToSurfaceTransform() {
481        super(D3DSurfaceData.D3DSurfaceRTT,
482              CompositeType.AnyAlpha,
483              D3DSurfaceData.D3DSurface);
484    }
485
486    public void Transform(SurfaceData src, SurfaceData dst,
487                          Composite comp, Region clip,
488                          AffineTransform at, int hint,
489                          int sx, int sy, int dx, int dy, int w, int h)
490    {
491        D3DBlitLoops.IsoBlit(src, dst,
492                             null, null,
493                             comp, clip, at, hint,
494                             sx, sy, sx+w, sy+h,
495                             dx, dy, dx+w, dy+h,
496                             true);
497    }
498}
499
500class D3DSurfaceToSwBlit extends Blit {
501
502    private int typeval;
503    private WeakReference<SurfaceData> srcTmp;
504
505    // REMIND: destination will actually be opaque/premultiplied...
506    D3DSurfaceToSwBlit(SurfaceType dstType, int typeval) {
507        super(D3DSurfaceData.D3DSurface,
508              CompositeType.SrcNoEa,
509              dstType);
510        this.typeval = typeval;
511    }
512
513    /*
514     * Clip value is ignored in D3D SurfaceToSw blit.
515     * Root Cause: The native interfaces to D3D use StretchRect API followed
516     * by custom copy of pixels from Surface to Sysmem. As a result, clipping
517     * in D3DSurfaceToSw works 'only' for Rect clips, provided, proper srcX,
518     * srcY, dstX, dstY, width and height are passed to native interfaces.
519     * Non rect clips (For example: Shape clips) are ignored completely.
520     *
521     * Solution: There are three solutions possible to fix this issue.
522     * 1. Convert the entire Surface to Sysmem and perform regular Blit.
523     *    An optimized version of this is to take up the conversion only
524     *    when Shape clips are needed. Existing native interface will suffice
525     *    for supporting Rect clips.
526     * 2. With help of existing classes we could perform SwToSurface,
527     *    SurfaceToSurface (implements clip) and SurfaceToSw (complete copy)
528     *    in order.
529     * 3. Modify the native D3D interface to accept clip and perform same logic
530     *    as the second approach but at native side.
531     *
532     * Upon multiple experiments, the first approach has been found to be
533     * faster than the others as it deploys 1-draw/copy operation for rect clip
534     * and 2-draw/copy operations for shape clip compared to 3-draws/copy
535     * operations deployed by the remaining approaches.
536     *
537     * complexClipBlit method helps to convert or copy the contents from
538     * D3DSurface onto Sysmem and perform a regular Blit with the clip
539     * information as required. This method is used when non-rectangular
540     * clip is needed.
541     */
542    private synchronized void complexClipBlit(SurfaceData src, SurfaceData dst,
543                                              Composite comp, Region clip,
544                                              int sx, int sy, int dx, int dy,
545                                              int w, int h) {
546        SurfaceData cachedSrc = null;
547        if (srcTmp != null) {
548            // use cached intermediate surface, if available
549            cachedSrc = srcTmp.get();
550        }
551
552        // Type- indicates the pixel format of Sysmem based BufferedImage.
553        // Native d3d interfaces support on the fly conversion of pixels from
554        // d3d surface to destination sysmem memory of type IntARGB only.
555        final int type = BufferedImage.TYPE_INT_ARGB;
556        src = convertFrom(this, src, sx, sy, w, h, cachedSrc, type);
557
558        // copy intermediate SW to destination SW using complex clip
559        final Blit performop = Blit.getFromCache(src.getSurfaceType(),
560                                                 CompositeType.SrcNoEa,
561                                                 dst.getSurfaceType());
562        performop.Blit(src, dst, comp, clip, 0, 0, dx, dy, w, h);
563
564        if (src != cachedSrc) {
565            // cache the intermediate surface
566            srcTmp = new WeakReference<>(src);
567        }
568    }
569
570    public void Blit(SurfaceData src, SurfaceData dst,
571                     Composite comp, Region clip,
572                     int sx, int sy, int dx, int dy,
573                     int w, int h)
574    {
575        if (clip != null) {
576            clip = clip.getIntersectionXYWH(dx, dy, w, h);
577            // At the end this method will flush the RenderQueue, we should exit
578            // from it as soon as possible.
579            if (clip.isEmpty()) {
580                return;
581            }
582
583            // Adjust final dst(x,y) and src(x,y) based on the clip. The
584            // logic is that, when clip limits drawing on the destination,
585            // corresponding pixels from the src should be skipped.
586            sx += clip.getLoX() - dx;
587            sy += clip.getLoY() - dy;
588            dx = clip.getLoX();
589            dy = clip.getLoY();
590            w = clip.getWidth();
591            h = clip.getHeight();
592
593            // Check if the clip is Rectangular. For non-rectangular clips
594            // complexClipBlit will convert Surface To Sysmem and perform
595            // regular Blit.
596            if (!clip.isRectangular()) {
597                complexClipBlit(src, dst, comp, clip,
598                                sx, sy, dx, dy,
599                                w, h);
600                return;
601            }
602        }
603
604        D3DRenderQueue rq = D3DRenderQueue.getInstance();
605        rq.lock();
606        try {
607            // make sure the RenderQueue keeps a hard reference to the
608            // destination (sysmem) SurfaceData to prevent it from being
609            // disposed while the operation is processed on the QFT
610            rq.addReference(dst);
611
612            RenderBuffer buf = rq.getBuffer();
613            D3DContext.setScratchSurface(((D3DSurfaceData)src).getContext());
614
615            rq.ensureCapacityAndAlignment(48, 32);
616            buf.putInt(SURFACE_TO_SW_BLIT);
617            buf.putInt(sx).putInt(sy);
618            buf.putInt(dx).putInt(dy);
619            buf.putInt(w).putInt(h);
620            buf.putInt(typeval);
621            buf.putLong(src.getNativeOps());
622            buf.putLong(dst.getNativeOps());
623
624            // always flush immediately
625            rq.flushNow();
626        } finally {
627            rq.unlock();
628        }
629    }
630}
631
632class D3DSwToSurfaceBlit extends Blit {
633
634    private int typeval;
635
636    D3DSwToSurfaceBlit(SurfaceType srcType, int typeval) {
637        super(srcType,
638              CompositeType.AnyAlpha,
639              D3DSurfaceData.D3DSurface);
640        this.typeval = typeval;
641    }
642
643    public void Blit(SurfaceData src, SurfaceData dst,
644                     Composite comp, Region clip,
645                     int sx, int sy, int dx, int dy, int w, int h)
646    {
647        D3DBlitLoops.Blit(src, dst,
648                          comp, clip, null,
649                          AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
650                          sx, sy, sx+w, sy+h,
651                          dx, dy, dx+w, dy+h,
652                          typeval, false);
653    }
654}
655
656class D3DSwToSurfaceScale extends ScaledBlit {
657
658    private int typeval;
659
660    D3DSwToSurfaceScale(SurfaceType srcType, int typeval) {
661        super(srcType,
662              CompositeType.AnyAlpha,
663              D3DSurfaceData.D3DSurface);
664        this.typeval = typeval;
665    }
666
667    public void Scale(SurfaceData src, SurfaceData dst,
668                      Composite comp, Region clip,
669                      int sx1, int sy1,
670                      int sx2, int sy2,
671                      double dx1, double dy1,
672                      double dx2, double dy2)
673    {
674        D3DBlitLoops.Blit(src, dst,
675                          comp, clip, null,
676                          AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
677                          sx1, sy1, sx2, sy2,
678                          dx1, dy1, dx2, dy2,
679                          typeval, false);
680    }
681}
682
683class D3DSwToSurfaceTransform extends TransformBlit {
684
685    private int typeval;
686
687    D3DSwToSurfaceTransform(SurfaceType srcType, int typeval) {
688        super(srcType,
689              CompositeType.AnyAlpha,
690              D3DSurfaceData.D3DSurface);
691        this.typeval = typeval;
692    }
693
694    public void Transform(SurfaceData src, SurfaceData dst,
695                          Composite comp, Region clip,
696                          AffineTransform at, int hint,
697                          int sx, int sy, int dx, int dy, int w, int h)
698    {
699        D3DBlitLoops.Blit(src, dst,
700                          comp, clip, at, hint,
701                          sx, sy, sx+w, sy+h,
702                          dx, dy, dx+w, dy+h,
703                          typeval, false);
704    }
705}
706
707class D3DSwToTextureBlit extends Blit {
708
709    private int typeval;
710
711    D3DSwToTextureBlit(SurfaceType srcType, int typeval) {
712        super(srcType,
713              CompositeType.SrcNoEa,
714              D3DSurfaceData.D3DTexture);
715        this.typeval = typeval;
716    }
717
718    public void Blit(SurfaceData src, SurfaceData dst,
719                     Composite comp, Region clip,
720                     int sx, int sy, int dx, int dy, int w, int h)
721    {
722        D3DBlitLoops.Blit(src, dst,
723                          comp, clip, null,
724                          AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
725                          sx, sy, sx+w, sy+h,
726                          dx, dy, dx+w, dy+h,
727                          typeval, true);
728    }
729}
730
731class D3DTextureToSurfaceBlit extends Blit {
732
733    D3DTextureToSurfaceBlit() {
734        super(D3DSurfaceData.D3DTexture,
735              CompositeType.AnyAlpha,
736              D3DSurfaceData.D3DSurface);
737    }
738
739    public void Blit(SurfaceData src, SurfaceData dst,
740                     Composite comp, Region clip,
741                     int sx, int sy, int dx, int dy, int w, int h)
742    {
743        D3DBlitLoops.IsoBlit(src, dst,
744                             null, null,
745                             comp, clip, null,
746                             AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
747                             sx, sy, sx+w, sy+h,
748                             dx, dy, dx+w, dy+h,
749                             true);
750    }
751}
752
753class D3DTextureToSurfaceScale extends ScaledBlit {
754
755    D3DTextureToSurfaceScale() {
756        super(D3DSurfaceData.D3DTexture,
757              CompositeType.AnyAlpha,
758              D3DSurfaceData.D3DSurface);
759    }
760
761    public void Scale(SurfaceData src, SurfaceData dst,
762                      Composite comp, Region clip,
763                      int sx1, int sy1,
764                      int sx2, int sy2,
765                      double dx1, double dy1,
766                      double dx2, double dy2)
767    {
768        D3DBlitLoops.IsoBlit(src, dst,
769                             null, null,
770                             comp, clip, null,
771                             AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
772                             sx1, sy1, sx2, sy2,
773                             dx1, dy1, dx2, dy2,
774                             true);
775    }
776}
777
778class D3DTextureToSurfaceTransform extends TransformBlit {
779
780    D3DTextureToSurfaceTransform() {
781        super(D3DSurfaceData.D3DTexture,
782              CompositeType.AnyAlpha,
783              D3DSurfaceData.D3DSurface);
784    }
785
786    public void Transform(SurfaceData src, SurfaceData dst,
787                          Composite comp, Region clip,
788                          AffineTransform at, int hint,
789                          int sx, int sy, int dx, int dy,
790                          int w, int h)
791    {
792        D3DBlitLoops.IsoBlit(src, dst,
793                             null, null,
794                             comp, clip, at, hint,
795                             sx, sy, sx+w, sy+h,
796                             dx, dy, dx+w, dy+h,
797                             true);
798    }
799}
800
801/**
802 * This general Blit implementation converts any source surface to an
803 * intermediate IntArgbPre surface, and then uses the more specific
804 * IntArgbPre->D3DSurface/Texture loop to get the intermediate
805 * (premultiplied) surface down to D3D using simple blit.
806 */
807class D3DGeneralBlit extends Blit {
808
809    private final Blit performop;
810    private WeakReference<SurfaceData> srcTmp;
811
812    D3DGeneralBlit(SurfaceType dstType,
813                   CompositeType compType,
814                   Blit performop)
815    {
816        super(SurfaceType.Any, compType, dstType);
817        this.performop = performop;
818    }
819
820    public synchronized void Blit(SurfaceData src, SurfaceData dst,
821                                  Composite comp, Region clip,
822                                  int sx, int sy, int dx, int dy,
823                                  int w, int h)
824    {
825        Blit convertsrc = Blit.getFromCache(src.getSurfaceType(),
826                                            CompositeType.SrcNoEa,
827                                            SurfaceType.IntArgbPre);
828
829        SurfaceData cachedSrc = null;
830        if (srcTmp != null) {
831            // use cached intermediate surface, if available
832            cachedSrc = srcTmp.get();
833        }
834
835        // convert source to IntArgbPre
836        src = convertFrom(convertsrc, src, sx, sy, w, h,
837                          cachedSrc, BufferedImage.TYPE_INT_ARGB_PRE);
838
839        // copy IntArgbPre intermediate surface to D3D surface
840        performop.Blit(src, dst, comp, clip,
841                       0, 0, dx, dy, w, h);
842
843        if (src != cachedSrc) {
844            // cache the intermediate surface
845            srcTmp = new WeakReference<>(src);
846        }
847    }
848}
849
850/**
851 * This general TransformedBlit implementation converts any source surface to an
852 * intermediate IntArgbPre surface, and then uses the more specific
853 * IntArgbPre->D3DSurface/Texture loop to get the intermediate
854 * (premultiplied) surface down to D3D using simple transformBlit.
855 */
856final class D3DGeneralTransformedBlit extends TransformBlit {
857
858    private final TransformBlit performop;
859    private WeakReference<SurfaceData> srcTmp;
860
861    D3DGeneralTransformedBlit(final TransformBlit performop) {
862        super(SurfaceType.Any, CompositeType.AnyAlpha,
863                D3DSurfaceData.D3DSurface);
864        this.performop = performop;
865    }
866
867    @Override
868    public synchronized void Transform(SurfaceData src, SurfaceData dst,
869                                       Composite comp, Region clip,
870                                       AffineTransform at, int hint, int srcx,
871                                       int srcy, int dstx, int dsty, int width,
872                                       int height){
873        Blit convertsrc = Blit.getFromCache(src.getSurfaceType(),
874                                            CompositeType.SrcNoEa,
875                                            SurfaceType.IntArgbPre);
876        // use cached intermediate surface, if available
877        final SurfaceData cachedSrc = srcTmp != null ? srcTmp.get() : null;
878        // convert source to IntArgbPre
879        src = convertFrom(convertsrc, src, srcx, srcy, width, height, cachedSrc,
880                          BufferedImage.TYPE_INT_ARGB_PRE);
881
882        // transform IntArgbPre intermediate surface to D3D surface
883        performop.Transform(src, dst, comp, clip, at, hint, 0, 0, dstx, dsty,
884                            width, height);
885
886        if (src != cachedSrc) {
887            // cache the intermediate surface
888            srcTmp = new WeakReference<>(src);
889        }
890    }
891}
892
893/*
894 * The following classes prohibit copying D3DSurfaces to the screen
895 * (the D3D->sysmem->GDI path is known to be very very slow).
896 *
897 * Note: we used to disable hw acceleration for the surafce manager associated
898 * with the source surface in these loops but it proved to be too cautious.
899 *
900 * In most cases d3d->screen copy happens only during some transitional
901 * period where the accelerated destination surface is being recreated or
902 * restored (for example, when Swing's backbuffer VI is copied to the screen
903 * but the D3DScreenSurfaceManager couldn't restore its surface).
904 *
905 * An exception is if for some reason we could not enable accelerated on-screen
906 * rendering for this window for some permanent reason (like window being too
907 * small, or a present BufferStrategy).
908 *
909 * This meant that we'd disable hw acceleration after the first failure
910 * completely (at least until the src image is recreated which in case of
911 * Swing back-buffer happens only after resize).
912 *
913 * Now we delegate to the VISM to figure out if the acceleration needs to
914 * be disabled or if we can wait for a while until the onscreen accelerated
915 * can resume (by marking the source surface lost and making sure the
916 * VISM has a chance to use the backup surface).
917 *
918 */
919
920class D3DSurfaceToGDIWindowSurfaceBlit extends Blit {
921
922    D3DSurfaceToGDIWindowSurfaceBlit() {
923        super(D3DSurfaceData.D3DSurface,
924              CompositeType.AnyAlpha,
925              GDIWindowSurfaceData.AnyGdi);
926    }
927    @Override
928    public void Blit(SurfaceData src, SurfaceData dst,
929                     Composite comp, Region clip,
930                     int sx, int sy, int dx, int dy, int w, int h)
931    {
932        // see comment above
933        D3DVolatileSurfaceManager.handleVItoScreenOp(src, dst);
934    }
935
936}
937
938class D3DSurfaceToGDIWindowSurfaceScale extends ScaledBlit {
939
940    D3DSurfaceToGDIWindowSurfaceScale() {
941        super(D3DSurfaceData.D3DSurface,
942              CompositeType.AnyAlpha,
943              GDIWindowSurfaceData.AnyGdi);
944    }
945    @Override
946    public void Scale(SurfaceData src, SurfaceData dst,
947                      Composite comp, Region clip,
948                      int sx1, int sy1,
949                      int sx2, int sy2,
950                      double dx1, double dy1,
951                      double dx2, double dy2)
952    {
953        // see comment above
954        D3DVolatileSurfaceManager.handleVItoScreenOp(src, dst);
955    }
956}
957
958class D3DSurfaceToGDIWindowSurfaceTransform extends TransformBlit {
959
960    D3DSurfaceToGDIWindowSurfaceTransform() {
961        super(D3DSurfaceData.D3DSurface,
962              CompositeType.AnyAlpha,
963              GDIWindowSurfaceData.AnyGdi);
964    }
965    @Override
966    public void Transform(SurfaceData src, SurfaceData dst,
967                          Composite comp, Region clip,
968                          AffineTransform at, int hint,
969                          int sx, int sy, int dx, int dy,
970                          int w, int h)
971    {
972        // see comment above
973        D3DVolatileSurfaceManager.handleVItoScreenOp(src, dst);
974    }
975}
976