1 /*
2  * Copyright (c) 2003, 2015, 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.opengl;
27 
28 import java.awt.AlphaComposite;
29 import java.awt.Composite;
30 import java.awt.Transparency;
31 import java.awt.geom.AffineTransform;
32 import java.awt.image.AffineTransformOp;
33 import java.awt.image.BufferedImage;
34 import java.awt.image.BufferedImageOp;
35 import java.lang.ref.WeakReference;
36 import sun.java2d.SurfaceData;
37 import sun.java2d.loops.Blit;
38 import sun.java2d.loops.CompositeType;
39 import sun.java2d.loops.GraphicsPrimitive;
40 import sun.java2d.loops.GraphicsPrimitiveMgr;
41 import sun.java2d.loops.ScaledBlit;
42 import sun.java2d.loops.SurfaceType;
43 import sun.java2d.loops.TransformBlit;
44 import sun.java2d.pipe.Region;
45 import sun.java2d.pipe.RenderBuffer;
46 import sun.java2d.pipe.RenderQueue;
47 import static sun.java2d.pipe.BufferedOpCodes.*;
48 import java.lang.annotation.Native;
49 
50 final class OGLBlitLoops {
51 
register()52     static void register() {
53         Blit blitIntArgbPreToSurface =
54             new OGLSwToSurfaceBlit(SurfaceType.IntArgbPre,
55                                    OGLSurfaceData.PF_INT_ARGB_PRE);
56         Blit blitIntArgbPreToTexture =
57             new OGLSwToTextureBlit(SurfaceType.IntArgbPre,
58                                    OGLSurfaceData.PF_INT_ARGB_PRE);
59         TransformBlit transformBlitIntArgbPreToSurface =
60             new OGLSwToSurfaceTransform(SurfaceType.IntArgbPre,
61                                         OGLSurfaceData.PF_INT_ARGB_PRE);
62         OGLSurfaceToSwBlit blitSurfaceToIntArgbPre =
63             new OGLSurfaceToSwBlit(SurfaceType.IntArgbPre,
64                                    OGLSurfaceData.PF_INT_ARGB_PRE);
65 
66         GraphicsPrimitive[] primitives = {
67             // surface->surface ops
68             new OGLSurfaceToSurfaceBlit(),
69             new OGLSurfaceToSurfaceScale(),
70             new OGLSurfaceToSurfaceTransform(),
71 
72             // render-to-texture surface->surface ops
73             new OGLRTTSurfaceToSurfaceBlit(),
74             new OGLRTTSurfaceToSurfaceScale(),
75             new OGLRTTSurfaceToSurfaceTransform(),
76 
77             // surface->sw ops
78             new OGLSurfaceToSwBlit(SurfaceType.IntArgb,
79                                    OGLSurfaceData.PF_INT_ARGB),
80             blitSurfaceToIntArgbPre,
81 
82             // sw->surface ops
83             blitIntArgbPreToSurface,
84             new OGLSwToSurfaceBlit(SurfaceType.IntRgb,
85                                    OGLSurfaceData.PF_INT_RGB),
86             new OGLSwToSurfaceBlit(SurfaceType.IntRgbx,
87                                    OGLSurfaceData.PF_INT_RGBX),
88             new OGLSwToSurfaceBlit(SurfaceType.IntBgr,
89                                    OGLSurfaceData.PF_INT_BGR),
90             new OGLSwToSurfaceBlit(SurfaceType.IntBgrx,
91                                    OGLSurfaceData.PF_INT_BGRX),
92             new OGLSwToSurfaceBlit(SurfaceType.ThreeByteBgr,
93                                    OGLSurfaceData.PF_3BYTE_BGR),
94             new OGLSwToSurfaceBlit(SurfaceType.Ushort565Rgb,
95                                    OGLSurfaceData.PF_USHORT_565_RGB),
96             new OGLSwToSurfaceBlit(SurfaceType.Ushort555Rgb,
97                                    OGLSurfaceData.PF_USHORT_555_RGB),
98             new OGLSwToSurfaceBlit(SurfaceType.Ushort555Rgbx,
99                                    OGLSurfaceData.PF_USHORT_555_RGBX),
100             new OGLSwToSurfaceBlit(SurfaceType.ByteGray,
101                                    OGLSurfaceData.PF_BYTE_GRAY),
102             new OGLSwToSurfaceBlit(SurfaceType.UshortGray,
103                                    OGLSurfaceData.PF_USHORT_GRAY),
104             new OGLGeneralBlit(OGLSurfaceData.OpenGLSurface,
105                                CompositeType.AnyAlpha,
106                                blitIntArgbPreToSurface),
107 
108             new OGLAnyCompositeBlit(OGLSurfaceData.OpenGLSurface,
109                                     blitSurfaceToIntArgbPre,
110                                     blitSurfaceToIntArgbPre,
111                                     blitIntArgbPreToSurface),
112             new OGLAnyCompositeBlit(SurfaceType.Any,
113                                     null,
114                                     blitSurfaceToIntArgbPre,
115                                     blitIntArgbPreToSurface),
116 
117             new OGLSwToSurfaceScale(SurfaceType.IntRgb,
118                                     OGLSurfaceData.PF_INT_RGB),
119             new OGLSwToSurfaceScale(SurfaceType.IntRgbx,
120                                     OGLSurfaceData.PF_INT_RGBX),
121             new OGLSwToSurfaceScale(SurfaceType.IntBgr,
122                                     OGLSurfaceData.PF_INT_BGR),
123             new OGLSwToSurfaceScale(SurfaceType.IntBgrx,
124                                     OGLSurfaceData.PF_INT_BGRX),
125             new OGLSwToSurfaceScale(SurfaceType.ThreeByteBgr,
126                                     OGLSurfaceData.PF_3BYTE_BGR),
127             new OGLSwToSurfaceScale(SurfaceType.Ushort565Rgb,
128                                     OGLSurfaceData.PF_USHORT_565_RGB),
129             new OGLSwToSurfaceScale(SurfaceType.Ushort555Rgb,
130                                     OGLSurfaceData.PF_USHORT_555_RGB),
131             new OGLSwToSurfaceScale(SurfaceType.Ushort555Rgbx,
132                                     OGLSurfaceData.PF_USHORT_555_RGBX),
133             new OGLSwToSurfaceScale(SurfaceType.ByteGray,
134                                     OGLSurfaceData.PF_BYTE_GRAY),
135             new OGLSwToSurfaceScale(SurfaceType.UshortGray,
136                                     OGLSurfaceData.PF_USHORT_GRAY),
137             new OGLSwToSurfaceScale(SurfaceType.IntArgbPre,
138                                     OGLSurfaceData.PF_INT_ARGB_PRE),
139 
140             new OGLSwToSurfaceTransform(SurfaceType.IntRgb,
141                                         OGLSurfaceData.PF_INT_RGB),
142             new OGLSwToSurfaceTransform(SurfaceType.IntRgbx,
143                                         OGLSurfaceData.PF_INT_RGBX),
144             new OGLSwToSurfaceTransform(SurfaceType.IntBgr,
145                                         OGLSurfaceData.PF_INT_BGR),
146             new OGLSwToSurfaceTransform(SurfaceType.IntBgrx,
147                                         OGLSurfaceData.PF_INT_BGRX),
148             new OGLSwToSurfaceTransform(SurfaceType.ThreeByteBgr,
149                                         OGLSurfaceData.PF_3BYTE_BGR),
150             new OGLSwToSurfaceTransform(SurfaceType.Ushort565Rgb,
151                                         OGLSurfaceData.PF_USHORT_565_RGB),
152             new OGLSwToSurfaceTransform(SurfaceType.Ushort555Rgb,
153                                         OGLSurfaceData.PF_USHORT_555_RGB),
154             new OGLSwToSurfaceTransform(SurfaceType.Ushort555Rgbx,
155                                         OGLSurfaceData.PF_USHORT_555_RGBX),
156             new OGLSwToSurfaceTransform(SurfaceType.ByteGray,
157                                         OGLSurfaceData.PF_BYTE_GRAY),
158             new OGLSwToSurfaceTransform(SurfaceType.UshortGray,
159                                         OGLSurfaceData.PF_USHORT_GRAY),
160             transformBlitIntArgbPreToSurface,
161 
162             new OGLGeneralTransformedBlit(transformBlitIntArgbPreToSurface),
163 
164             // texture->surface ops
165             new OGLTextureToSurfaceBlit(),
166             new OGLTextureToSurfaceScale(),
167             new OGLTextureToSurfaceTransform(),
168 
169             // sw->texture ops
170             blitIntArgbPreToTexture,
171             new OGLSwToTextureBlit(SurfaceType.IntRgb,
172                                    OGLSurfaceData.PF_INT_RGB),
173             new OGLSwToTextureBlit(SurfaceType.IntRgbx,
174                                    OGLSurfaceData.PF_INT_RGBX),
175             new OGLSwToTextureBlit(SurfaceType.IntBgr,
176                                    OGLSurfaceData.PF_INT_BGR),
177             new OGLSwToTextureBlit(SurfaceType.IntBgrx,
178                                    OGLSurfaceData.PF_INT_BGRX),
179             new OGLSwToTextureBlit(SurfaceType.ThreeByteBgr,
180                                    OGLSurfaceData.PF_3BYTE_BGR),
181             new OGLSwToTextureBlit(SurfaceType.Ushort565Rgb,
182                                    OGLSurfaceData.PF_USHORT_565_RGB),
183             new OGLSwToTextureBlit(SurfaceType.Ushort555Rgb,
184                                    OGLSurfaceData.PF_USHORT_555_RGB),
185             new OGLSwToTextureBlit(SurfaceType.Ushort555Rgbx,
186                                    OGLSurfaceData.PF_USHORT_555_RGBX),
187             new OGLSwToTextureBlit(SurfaceType.ByteGray,
188                                    OGLSurfaceData.PF_BYTE_GRAY),
189             new OGLSwToTextureBlit(SurfaceType.UshortGray,
190                                    OGLSurfaceData.PF_USHORT_GRAY),
191             new OGLGeneralBlit(OGLSurfaceData.OpenGLTexture,
192                                CompositeType.SrcNoEa,
193                                blitIntArgbPreToTexture),
194         };
195         GraphicsPrimitiveMgr.register(primitives);
196     }
197 
198     /**
199      * The following offsets are used to pack the parameters in
200      * createPackedParams().  (They are also used at the native level when
201      * unpacking the params.)
202      */
203     @Native private static final int OFFSET_SRCTYPE = 16;
204     @Native private static final int OFFSET_HINT    =  8;
205     @Native private static final int OFFSET_TEXTURE =  3;
206     @Native private static final int OFFSET_RTT     =  2;
207     @Native private static final int OFFSET_XFORM   =  1;
208     @Native private static final int OFFSET_ISOBLIT =  0;
209 
210     /**
211      * Packs the given parameters into a single int value in order to save
212      * space on the rendering queue.
213      */
createPackedParams(boolean isoblit, boolean texture, boolean rtt, boolean xform, int hint, int srctype)214     private static int createPackedParams(boolean isoblit, boolean texture,
215                                           boolean rtt, boolean xform,
216                                           int hint, int srctype)
217     {
218         return
219             ((srctype           << OFFSET_SRCTYPE) |
220              (hint              << OFFSET_HINT   ) |
221              ((texture ? 1 : 0) << OFFSET_TEXTURE) |
222              ((rtt     ? 1 : 0) << OFFSET_RTT    ) |
223              ((xform   ? 1 : 0) << OFFSET_XFORM  ) |
224              ((isoblit ? 1 : 0) << OFFSET_ISOBLIT));
225     }
226 
227     /**
228      * Enqueues a BLIT operation with the given parameters.  Note that the
229      * RenderQueue lock must be held before calling this method.
230      */
enqueueBlit(RenderQueue rq, SurfaceData src, SurfaceData dst, int packedParams, int sx1, int sy1, int sx2, int sy2, double dx1, double dy1, double dx2, double dy2)231     private static void enqueueBlit(RenderQueue rq,
232                                     SurfaceData src, SurfaceData dst,
233                                     int packedParams,
234                                     int sx1, int sy1,
235                                     int sx2, int sy2,
236                                     double dx1, double dy1,
237                                     double dx2, double dy2)
238     {
239         // assert rq.lock.isHeldByCurrentThread();
240         RenderBuffer buf = rq.getBuffer();
241         rq.ensureCapacityAndAlignment(72, 24);
242         buf.putInt(BLIT);
243         buf.putInt(packedParams);
244         buf.putInt(sx1).putInt(sy1);
245         buf.putInt(sx2).putInt(sy2);
246         buf.putDouble(dx1).putDouble(dy1);
247         buf.putDouble(dx2).putDouble(dy2);
248         buf.putLong(src.getNativeOps());
249         buf.putLong(dst.getNativeOps());
250     }
251 
Blit(SurfaceData srcData, SurfaceData dstData, Composite comp, Region clip, AffineTransform xform, int hint, int sx1, int sy1, int sx2, int sy2, double dx1, double dy1, double dx2, double dy2, int srctype, boolean texture)252     static void Blit(SurfaceData srcData, SurfaceData dstData,
253                      Composite comp, Region clip,
254                      AffineTransform xform, int hint,
255                      int sx1, int sy1,
256                      int sx2, int sy2,
257                      double dx1, double dy1,
258                      double dx2, double dy2,
259                      int srctype, boolean texture)
260     {
261         int ctxflags = 0;
262         if (srcData.getTransparency() == Transparency.OPAQUE) {
263             ctxflags |= OGLContext.SRC_IS_OPAQUE;
264         }
265 
266         OGLRenderQueue rq = OGLRenderQueue.getInstance();
267         rq.lock();
268         try {
269             // make sure the RenderQueue keeps a hard reference to the
270             // source (sysmem) SurfaceData to prevent it from being
271             // disposed while the operation is processed on the QFT
272             rq.addReference(srcData);
273 
274             OGLSurfaceData oglDst = (OGLSurfaceData)dstData;
275             if (texture) {
276                 // make sure we have a current context before uploading
277                 // the sysmem data to the texture object
278                 OGLGraphicsConfig gc = oglDst.getOGLGraphicsConfig();
279                 OGLContext.setScratchSurface(gc);
280             } else {
281                 OGLContext.validateContext(oglDst, oglDst,
282                                            clip, comp, xform, null, null,
283                                            ctxflags);
284             }
285 
286             int packedParams = createPackedParams(false, texture,
287                                                   false, xform != null,
288                                                   hint, srctype);
289             enqueueBlit(rq, srcData, dstData,
290                         packedParams,
291                         sx1, sy1, sx2, sy2,
292                         dx1, dy1, dx2, dy2);
293 
294             // always flush immediately, since we (currently) have no means
295             // of tracking changes to the system memory surface
296             rq.flushNow();
297         } finally {
298             rq.unlock();
299         }
300     }
301 
302     /**
303      * Note: The srcImg and biop parameters are only used when invoked
304      * from the OGLBufImgOps.renderImageWithOp() method; in all other cases,
305      * this method can be called with null values for those two parameters,
306      * and they will be effectively ignored.
307      */
IsoBlit(SurfaceData srcData, SurfaceData dstData, BufferedImage srcImg, BufferedImageOp biop, Composite comp, Region clip, AffineTransform xform, int hint, int sx1, int sy1, int sx2, int sy2, double dx1, double dy1, double dx2, double dy2, boolean texture)308     static void IsoBlit(SurfaceData srcData, SurfaceData dstData,
309                         BufferedImage srcImg, BufferedImageOp biop,
310                         Composite comp, Region clip,
311                         AffineTransform xform, int hint,
312                         int sx1, int sy1,
313                         int sx2, int sy2,
314                         double dx1, double dy1,
315                         double dx2, double dy2,
316                         boolean texture)
317     {
318         int ctxflags = 0;
319         if (srcData.getTransparency() == Transparency.OPAQUE) {
320             ctxflags |= OGLContext.SRC_IS_OPAQUE;
321         }
322 
323         OGLRenderQueue rq = OGLRenderQueue.getInstance();
324         rq.lock();
325         try {
326             OGLSurfaceData oglSrc = (OGLSurfaceData)srcData;
327             OGLSurfaceData oglDst = (OGLSurfaceData)dstData;
328             int srctype = oglSrc.getType();
329             boolean rtt;
330             OGLSurfaceData srcCtxData;
331             if (srctype == OGLSurfaceData.TEXTURE) {
332                 // the source is a regular texture object; we substitute
333                 // the destination surface for the purposes of making a
334                 // context current
335                 rtt = false;
336                 srcCtxData = oglDst;
337             } else {
338                 // the source is a pbuffer, backbuffer, or render-to-texture
339                 // surface; we set rtt to true to differentiate this kind
340                 // of surface from a regular texture object
341                 rtt = true;
342                 if (srctype == OGLSurfaceData.FBOBJECT) {
343                     srcCtxData = oglDst;
344                 } else {
345                     srcCtxData = oglSrc;
346                 }
347             }
348 
349             OGLContext.validateContext(srcCtxData, oglDst,
350                                        clip, comp, xform, null, null,
351                                        ctxflags);
352 
353             if (biop != null) {
354                 OGLBufImgOps.enableBufImgOp(rq, oglSrc, srcImg, biop);
355             }
356 
357             int packedParams = createPackedParams(true, texture,
358                                                   rtt, xform != null,
359                                                   hint, 0 /*unused*/);
360             enqueueBlit(rq, srcData, dstData,
361                         packedParams,
362                         sx1, sy1, sx2, sy2,
363                         dx1, dy1, dx2, dy2);
364 
365             if (biop != null) {
366                 OGLBufImgOps.disableBufImgOp(rq, biop);
367             }
368 
369             if (rtt && oglDst.isOnScreen()) {
370                 // we only have to flush immediately when copying from a
371                 // (non-texture) surface to the screen; otherwise Swing apps
372                 // might appear unresponsive until the auto-flush completes
373                 rq.flushNow();
374             }
375         } finally {
376             rq.unlock();
377         }
378     }
379 }
380 
381 class OGLSurfaceToSurfaceBlit extends Blit {
382 
OGLSurfaceToSurfaceBlit()383     OGLSurfaceToSurfaceBlit() {
384         super(OGLSurfaceData.OpenGLSurface,
385               CompositeType.AnyAlpha,
386               OGLSurfaceData.OpenGLSurface);
387     }
388 
Blit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx, int sy, int dx, int dy, int w, int h)389     public void Blit(SurfaceData src, SurfaceData dst,
390                      Composite comp, Region clip,
391                      int sx, int sy, int dx, int dy, int w, int h)
392     {
393         OGLBlitLoops.IsoBlit(src, dst,
394                              null, null,
395                              comp, clip, null,
396                              AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
397                              sx, sy, sx+w, sy+h,
398                              dx, dy, dx+w, dy+h,
399                              false);
400     }
401 }
402 
403 class OGLSurfaceToSurfaceScale extends ScaledBlit {
404 
OGLSurfaceToSurfaceScale()405     OGLSurfaceToSurfaceScale() {
406         super(OGLSurfaceData.OpenGLSurface,
407               CompositeType.AnyAlpha,
408               OGLSurfaceData.OpenGLSurface);
409     }
410 
Scale(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx1, int sy1, int sx2, int sy2, double dx1, double dy1, double dx2, double dy2)411     public void Scale(SurfaceData src, SurfaceData dst,
412                       Composite comp, Region clip,
413                       int sx1, int sy1,
414                       int sx2, int sy2,
415                       double dx1, double dy1,
416                       double dx2, double dy2)
417     {
418         OGLBlitLoops.IsoBlit(src, dst,
419                              null, null,
420                              comp, clip, null,
421                              AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
422                              sx1, sy1, sx2, sy2,
423                              dx1, dy1, dx2, dy2,
424                              false);
425     }
426 }
427 
428 class OGLSurfaceToSurfaceTransform extends TransformBlit {
429 
OGLSurfaceToSurfaceTransform()430     OGLSurfaceToSurfaceTransform() {
431         super(OGLSurfaceData.OpenGLSurface,
432               CompositeType.AnyAlpha,
433               OGLSurfaceData.OpenGLSurface);
434     }
435 
Transform(SurfaceData src, SurfaceData dst, Composite comp, Region clip, AffineTransform at, int hint, int sx, int sy, int dx, int dy, int w, int h)436     public void Transform(SurfaceData src, SurfaceData dst,
437                           Composite comp, Region clip,
438                           AffineTransform at, int hint,
439                           int sx, int sy, int dx, int dy,
440                           int w, int h)
441     {
442         OGLBlitLoops.IsoBlit(src, dst,
443                              null, null,
444                              comp, clip, at, hint,
445                              sx, sy, sx+w, sy+h,
446                              dx, dy, dx+w, dy+h,
447                              false);
448     }
449 }
450 
451 class OGLRTTSurfaceToSurfaceBlit extends Blit {
452 
OGLRTTSurfaceToSurfaceBlit()453     OGLRTTSurfaceToSurfaceBlit() {
454         super(OGLSurfaceData.OpenGLSurfaceRTT,
455               CompositeType.AnyAlpha,
456               OGLSurfaceData.OpenGLSurface);
457     }
458 
Blit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx, int sy, int dx, int dy, int w, int h)459     public void Blit(SurfaceData src, SurfaceData dst,
460                      Composite comp, Region clip,
461                      int sx, int sy, int dx, int dy, int w, int h)
462     {
463         OGLBlitLoops.IsoBlit(src, dst,
464                              null, null,
465                              comp, clip, null,
466                              AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
467                              sx, sy, sx+w, sy+h,
468                              dx, dy, dx+w, dy+h,
469                              true);
470     }
471 }
472 
473 class OGLRTTSurfaceToSurfaceScale extends ScaledBlit {
474 
OGLRTTSurfaceToSurfaceScale()475     OGLRTTSurfaceToSurfaceScale() {
476         super(OGLSurfaceData.OpenGLSurfaceRTT,
477               CompositeType.AnyAlpha,
478               OGLSurfaceData.OpenGLSurface);
479     }
480 
Scale(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx1, int sy1, int sx2, int sy2, double dx1, double dy1, double dx2, double dy2)481     public void Scale(SurfaceData src, SurfaceData dst,
482                       Composite comp, Region clip,
483                       int sx1, int sy1,
484                       int sx2, int sy2,
485                       double dx1, double dy1,
486                       double dx2, double dy2)
487     {
488         OGLBlitLoops.IsoBlit(src, dst,
489                              null, null,
490                              comp, clip, null,
491                              AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
492                              sx1, sy1, sx2, sy2,
493                              dx1, dy1, dx2, dy2,
494                              true);
495     }
496 }
497 
498 class OGLRTTSurfaceToSurfaceTransform extends TransformBlit {
499 
OGLRTTSurfaceToSurfaceTransform()500     OGLRTTSurfaceToSurfaceTransform() {
501         super(OGLSurfaceData.OpenGLSurfaceRTT,
502               CompositeType.AnyAlpha,
503               OGLSurfaceData.OpenGLSurface);
504     }
505 
Transform(SurfaceData src, SurfaceData dst, Composite comp, Region clip, AffineTransform at, int hint, int sx, int sy, int dx, int dy, int w, int h)506     public void Transform(SurfaceData src, SurfaceData dst,
507                           Composite comp, Region clip,
508                           AffineTransform at, int hint,
509                           int sx, int sy, int dx, int dy, int w, int h)
510     {
511         OGLBlitLoops.IsoBlit(src, dst,
512                              null, null,
513                              comp, clip, at, hint,
514                              sx, sy, sx+w, sy+h,
515                              dx, dy, dx+w, dy+h,
516                              true);
517     }
518 }
519 
520 final class OGLSurfaceToSwBlit extends Blit {
521 
522     private final int typeval;
523     private WeakReference<SurfaceData> srcTmp;
524 
525     // destination will actually be ArgbPre or Argb
OGLSurfaceToSwBlit(final SurfaceType dstType,final int typeval)526     OGLSurfaceToSwBlit(final SurfaceType dstType,final int typeval) {
527         super(OGLSurfaceData.OpenGLSurface,
528               CompositeType.SrcNoEa,
529               dstType);
530         this.typeval = typeval;
531     }
532 
complexClipBlit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx, int sy, int dx, int dy, int w, int h)533     private synchronized void complexClipBlit(SurfaceData src, SurfaceData dst,
534                                               Composite comp, Region clip,
535                                               int sx, int sy, int dx, int dy,
536                                               int w, int h) {
537         SurfaceData cachedSrc = null;
538         if (srcTmp != null) {
539             // use cached intermediate surface, if available
540             cachedSrc = srcTmp.get();
541         }
542 
543         // We can convert argb_pre data from OpenGL surface in two places:
544         // - During OpenGL surface -> SW blit
545         // - During SW -> SW blit
546         // The first one is faster when we use opaque OGL surface, because in
547         // this case we simply skip conversion and use color components as is.
548         // Because of this we align intermediate buffer type with type of
549         // destination not source.
550         final int type = typeval == OGLSurfaceData.PF_INT_ARGB_PRE ?
551                          BufferedImage.TYPE_INT_ARGB_PRE :
552                          BufferedImage.TYPE_INT_ARGB;
553 
554         src = convertFrom(this, src, sx, sy, w, h, cachedSrc, type);
555 
556         // copy intermediate SW to destination SW using complex clip
557         final Blit performop = Blit.getFromCache(src.getSurfaceType(),
558                                                  CompositeType.SrcNoEa,
559                                                  dst.getSurfaceType());
560         performop.Blit(src, dst, comp, clip, 0, 0, dx, dy, w, h);
561 
562         if (src != cachedSrc) {
563             // cache the intermediate surface
564             srcTmp = new WeakReference<>(src);
565         }
566     }
567 
Blit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx, int sy, int dx, int dy, int w, int h)568     public void Blit(SurfaceData src, SurfaceData dst,
569                      Composite comp, Region clip,
570                      int sx, int sy, int dx, int dy,
571                      int w, int h)
572     {
573         if (clip != null) {
574             clip = clip.getIntersectionXYWH(dx, dy, w, h);
575             // At the end this method will flush the RenderQueue, we should exit
576             // from it as soon as possible.
577             if (clip.isEmpty()) {
578                 return;
579             }
580             sx += clip.getLoX() - dx;
581             sy += clip.getLoY() - dy;
582             dx = clip.getLoX();
583             dy = clip.getLoY();
584             w = clip.getWidth();
585             h = clip.getHeight();
586 
587             if (!clip.isRectangular()) {
588                 complexClipBlit(src, dst, comp, clip, sx, sy, dx, dy, w, h);
589                 return;
590             }
591         }
592 
593         OGLRenderQueue rq = OGLRenderQueue.getInstance();
594         rq.lock();
595         try {
596             // make sure the RenderQueue keeps a hard reference to the
597             // destination (sysmem) SurfaceData to prevent it from being
598             // disposed while the operation is processed on the QFT
599             rq.addReference(dst);
600 
601             RenderBuffer buf = rq.getBuffer();
602             OGLContext.validateContext((OGLSurfaceData)src);
603 
604             rq.ensureCapacityAndAlignment(48, 32);
605             buf.putInt(SURFACE_TO_SW_BLIT);
606             buf.putInt(sx).putInt(sy);
607             buf.putInt(dx).putInt(dy);
608             buf.putInt(w).putInt(h);
609             buf.putInt(typeval);
610             buf.putLong(src.getNativeOps());
611             buf.putLong(dst.getNativeOps());
612 
613             // always flush immediately
614             rq.flushNow();
615         } finally {
616             rq.unlock();
617         }
618     }
619 }
620 
621 class OGLSwToSurfaceBlit extends Blit {
622 
623     private int typeval;
624 
OGLSwToSurfaceBlit(SurfaceType srcType, int typeval)625     OGLSwToSurfaceBlit(SurfaceType srcType, int typeval) {
626         super(srcType,
627               CompositeType.AnyAlpha,
628               OGLSurfaceData.OpenGLSurface);
629         this.typeval = typeval;
630     }
631 
Blit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx, int sy, int dx, int dy, int w, int h)632     public void Blit(SurfaceData src, SurfaceData dst,
633                      Composite comp, Region clip,
634                      int sx, int sy, int dx, int dy, int w, int h)
635     {
636         OGLBlitLoops.Blit(src, dst,
637                           comp, clip, null,
638                           AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
639                           sx, sy, sx+w, sy+h,
640                           dx, dy, dx+w, dy+h,
641                           typeval, false);
642     }
643 }
644 
645 class OGLSwToSurfaceScale extends ScaledBlit {
646 
647     private int typeval;
648 
OGLSwToSurfaceScale(SurfaceType srcType, int typeval)649     OGLSwToSurfaceScale(SurfaceType srcType, int typeval) {
650         super(srcType,
651               CompositeType.AnyAlpha,
652               OGLSurfaceData.OpenGLSurface);
653         this.typeval = typeval;
654     }
655 
Scale(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx1, int sy1, int sx2, int sy2, double dx1, double dy1, double dx2, double dy2)656     public void Scale(SurfaceData src, SurfaceData dst,
657                       Composite comp, Region clip,
658                       int sx1, int sy1,
659                       int sx2, int sy2,
660                       double dx1, double dy1,
661                       double dx2, double dy2)
662     {
663         OGLBlitLoops.Blit(src, dst,
664                           comp, clip, null,
665                           AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
666                           sx1, sy1, sx2, sy2,
667                           dx1, dy1, dx2, dy2,
668                           typeval, false);
669     }
670 }
671 
672 class OGLSwToSurfaceTransform extends TransformBlit {
673 
674     private int typeval;
675 
OGLSwToSurfaceTransform(SurfaceType srcType, int typeval)676     OGLSwToSurfaceTransform(SurfaceType srcType, int typeval) {
677         super(srcType,
678               CompositeType.AnyAlpha,
679               OGLSurfaceData.OpenGLSurface);
680         this.typeval = typeval;
681     }
682 
Transform(SurfaceData src, SurfaceData dst, Composite comp, Region clip, AffineTransform at, int hint, int sx, int sy, int dx, int dy, int w, int h)683     public void Transform(SurfaceData src, SurfaceData dst,
684                           Composite comp, Region clip,
685                           AffineTransform at, int hint,
686                           int sx, int sy, int dx, int dy, int w, int h)
687     {
688         OGLBlitLoops.Blit(src, dst,
689                           comp, clip, at, hint,
690                           sx, sy, sx+w, sy+h,
691                           dx, dy, dx+w, dy+h,
692                           typeval, false);
693     }
694 }
695 
696 class OGLSwToTextureBlit extends Blit {
697 
698     private int typeval;
699 
OGLSwToTextureBlit(SurfaceType srcType, int typeval)700     OGLSwToTextureBlit(SurfaceType srcType, int typeval) {
701         super(srcType,
702               CompositeType.SrcNoEa,
703               OGLSurfaceData.OpenGLTexture);
704         this.typeval = typeval;
705     }
706 
Blit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx, int sy, int dx, int dy, int w, int h)707     public void Blit(SurfaceData src, SurfaceData dst,
708                      Composite comp, Region clip,
709                      int sx, int sy, int dx, int dy, int w, int h)
710     {
711         OGLBlitLoops.Blit(src, dst,
712                           comp, clip, null,
713                           AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
714                           sx, sy, sx+w, sy+h,
715                           dx, dy, dx+w, dy+h,
716                           typeval, true);
717     }
718 }
719 
720 class OGLTextureToSurfaceBlit extends Blit {
721 
OGLTextureToSurfaceBlit()722     OGLTextureToSurfaceBlit() {
723         super(OGLSurfaceData.OpenGLTexture,
724               CompositeType.AnyAlpha,
725               OGLSurfaceData.OpenGLSurface);
726     }
727 
Blit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx, int sy, int dx, int dy, int w, int h)728     public void Blit(SurfaceData src, SurfaceData dst,
729                      Composite comp, Region clip,
730                      int sx, int sy, int dx, int dy, int w, int h)
731     {
732         OGLBlitLoops.IsoBlit(src, dst,
733                              null, null,
734                              comp, clip, null,
735                              AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
736                              sx, sy, sx+w, sy+h,
737                              dx, dy, dx+w, dy+h,
738                              true);
739     }
740 }
741 
742 class OGLTextureToSurfaceScale extends ScaledBlit {
743 
OGLTextureToSurfaceScale()744     OGLTextureToSurfaceScale() {
745         super(OGLSurfaceData.OpenGLTexture,
746               CompositeType.AnyAlpha,
747               OGLSurfaceData.OpenGLSurface);
748     }
749 
Scale(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx1, int sy1, int sx2, int sy2, double dx1, double dy1, double dx2, double dy2)750     public void Scale(SurfaceData src, SurfaceData dst,
751                       Composite comp, Region clip,
752                       int sx1, int sy1,
753                       int sx2, int sy2,
754                       double dx1, double dy1,
755                       double dx2, double dy2)
756     {
757         OGLBlitLoops.IsoBlit(src, dst,
758                              null, null,
759                              comp, clip, null,
760                              AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
761                              sx1, sy1, sx2, sy2,
762                              dx1, dy1, dx2, dy2,
763                              true);
764     }
765 }
766 
767 class OGLTextureToSurfaceTransform extends TransformBlit {
768 
OGLTextureToSurfaceTransform()769     OGLTextureToSurfaceTransform() {
770         super(OGLSurfaceData.OpenGLTexture,
771               CompositeType.AnyAlpha,
772               OGLSurfaceData.OpenGLSurface);
773     }
774 
Transform(SurfaceData src, SurfaceData dst, Composite comp, Region clip, AffineTransform at, int hint, int sx, int sy, int dx, int dy, int w, int h)775     public void Transform(SurfaceData src, SurfaceData dst,
776                           Composite comp, Region clip,
777                           AffineTransform at, int hint,
778                           int sx, int sy, int dx, int dy,
779                           int w, int h)
780     {
781         OGLBlitLoops.IsoBlit(src, dst,
782                              null, null,
783                              comp, clip, at, hint,
784                              sx, sy, sx+w, sy+h,
785                              dx, dy, dx+w, dy+h,
786                              true);
787     }
788 }
789 
790 /**
791  * This general Blit implementation converts any source surface to an
792  * intermediate IntArgbPre surface, and then uses the more specific
793  * IntArgbPre->OpenGLSurface/Texture loop to get the intermediate
794  * (premultiplied) surface down to OpenGL using simple blit.
795  */
796 class OGLGeneralBlit extends Blit {
797 
798     private final Blit performop;
799     private WeakReference<SurfaceData> srcTmp;
800 
OGLGeneralBlit(SurfaceType dstType, CompositeType compType, Blit performop)801     OGLGeneralBlit(SurfaceType dstType,
802                    CompositeType compType,
803                    Blit performop)
804     {
805         super(SurfaceType.Any, compType, dstType);
806         this.performop = performop;
807     }
808 
Blit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx, int sy, int dx, int dy, int w, int h)809     public synchronized void Blit(SurfaceData src, SurfaceData dst,
810                                   Composite comp, Region clip,
811                                   int sx, int sy, int dx, int dy,
812                                   int w, int h)
813     {
814         Blit convertsrc = Blit.getFromCache(src.getSurfaceType(),
815                                             CompositeType.SrcNoEa,
816                                             SurfaceType.IntArgbPre);
817 
818         SurfaceData cachedSrc = null;
819         if (srcTmp != null) {
820             // use cached intermediate surface, if available
821             cachedSrc = srcTmp.get();
822         }
823 
824         // convert source to IntArgbPre
825         src = convertFrom(convertsrc, src, sx, sy, w, h,
826                           cachedSrc, BufferedImage.TYPE_INT_ARGB_PRE);
827 
828         // copy IntArgbPre intermediate surface to OpenGL surface
829         performop.Blit(src, dst, comp, clip,
830                        0, 0, dx, dy, w, h);
831 
832         if (src != cachedSrc) {
833             // cache the intermediate surface
834             srcTmp = new WeakReference<>(src);
835         }
836     }
837 }
838 
839 /**
840  * This general TransformedBlit implementation converts any source surface to an
841  * intermediate IntArgbPre surface, and then uses the more specific
842  * IntArgbPre->OpenGLSurface/Texture loop to get the intermediate
843  * (premultiplied) surface down to OpenGL using simple transformBlit.
844  */
845 final class OGLGeneralTransformedBlit extends TransformBlit {
846 
847     private final TransformBlit performop;
848     private WeakReference<SurfaceData> srcTmp;
849 
OGLGeneralTransformedBlit(final TransformBlit performop)850     OGLGeneralTransformedBlit(final TransformBlit performop) {
851         super(SurfaceType.Any, CompositeType.AnyAlpha,
852               OGLSurfaceData.OpenGLSurface);
853         this.performop = performop;
854     }
855 
856     @Override
Transform(SurfaceData src, SurfaceData dst, Composite comp, Region clip, AffineTransform at, int hint, int srcx, int srcy, int dstx, int dsty, int width, int height)857     public synchronized void Transform(SurfaceData src, SurfaceData dst,
858                                        Composite comp, Region clip,
859                                        AffineTransform at, int hint, int srcx,
860                                        int srcy, int dstx, int dsty, int width,
861                                        int height){
862         Blit convertsrc = Blit.getFromCache(src.getSurfaceType(),
863                                             CompositeType.SrcNoEa,
864                                             SurfaceType.IntArgbPre);
865         // use cached intermediate surface, if available
866         final SurfaceData cachedSrc = srcTmp != null ? srcTmp.get() : null;
867         // convert source to IntArgbPre
868         src = convertFrom(convertsrc, src, srcx, srcy, width, height, cachedSrc,
869                           BufferedImage.TYPE_INT_ARGB_PRE);
870 
871         // transform IntArgbPre intermediate surface to OpenGL surface
872         performop.Transform(src, dst, comp, clip, at, hint, 0, 0, dstx, dsty,
873                             width, height);
874 
875         if (src != cachedSrc) {
876             // cache the intermediate surface
877             srcTmp = new WeakReference<>(src);
878         }
879     }
880 }
881 
882 /**
883  * This general OGLAnyCompositeBlit implementation can convert any source/target
884  * surface to an intermediate surface using convertsrc/convertdst loops, applies
885  * necessary composite operation, and then uses convertresult loop to get the
886  * intermediate surface down to OpenGL.
887  */
888 final class OGLAnyCompositeBlit extends Blit {
889 
890     private WeakReference<SurfaceData> dstTmp;
891     private WeakReference<SurfaceData> srcTmp;
892     private final Blit convertsrc;
893     private final Blit convertdst;
894     private final Blit convertresult;
895 
OGLAnyCompositeBlit(SurfaceType srctype, Blit convertsrc, Blit convertdst, Blit convertresult)896     OGLAnyCompositeBlit(SurfaceType srctype, Blit convertsrc, Blit convertdst,
897                         Blit convertresult) {
898         super(srctype, CompositeType.Any, OGLSurfaceData.OpenGLSurface);
899         this.convertsrc = convertsrc;
900         this.convertdst = convertdst;
901         this.convertresult = convertresult;
902     }
903 
Blit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx, int sy, int dx, int dy, int w, int h)904     public synchronized void Blit(SurfaceData src, SurfaceData dst,
905                                   Composite comp, Region clip,
906                                   int sx, int sy, int dx, int dy,
907                                   int w, int h)
908     {
909         if (convertsrc != null) {
910             SurfaceData cachedSrc = null;
911             if (srcTmp != null) {
912                 // use cached intermediate surface, if available
913                 cachedSrc = srcTmp.get();
914             }
915             // convert source to IntArgbPre
916             src = convertFrom(convertsrc, src, sx, sy, w, h, cachedSrc,
917                               BufferedImage.TYPE_INT_ARGB_PRE);
918             if (src != cachedSrc) {
919                 // cache the intermediate surface
920                 srcTmp = new WeakReference<>(src);
921             }
922         }
923 
924         SurfaceData cachedDst = null;
925 
926         if (dstTmp != null) {
927             // use cached intermediate surface, if available
928             cachedDst = dstTmp.get();
929         }
930 
931         // convert destination to IntArgbPre
932         SurfaceData dstBuffer = convertFrom(convertdst, dst, dx, dy, w, h,
933                           cachedDst, BufferedImage.TYPE_INT_ARGB_PRE);
934         Region bufferClip =
935                 clip == null ? null : clip.getTranslatedRegion(-dx, -dy);
936 
937         Blit performop = Blit.getFromCache(src.getSurfaceType(),
938                 CompositeType.Any, dstBuffer.getSurfaceType());
939         performop.Blit(src, dstBuffer, comp, bufferClip, sx, sy, 0, 0, w, h);
940 
941         if (dstBuffer != cachedDst) {
942             // cache the intermediate surface
943             dstTmp = new WeakReference<>(dstBuffer);
944         }
945         // now blit the buffer back to the destination
946         convertresult.Blit(dstBuffer, dst, AlphaComposite.Src, clip, 0, 0, dx,
947                            dy, w, h);
948     }
949 }
950