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