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