1 /*
   2  * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package sun.java2d.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 class OGLBlitLoops {
  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 
  60         GraphicsPrimitive[] primitives = {
  61             // surface->surface ops
  62             new OGLSurfaceToSurfaceBlit(),
  63             new OGLSurfaceToSurfaceScale(),
  64             new OGLSurfaceToSurfaceTransform(),
  65 
  66             // render-to-texture surface->surface ops
  67             new OGLRTTSurfaceToSurfaceBlit(),
  68             new OGLRTTSurfaceToSurfaceScale(),
  69             new OGLRTTSurfaceToSurfaceTransform(),
  70 
  71             // surface->sw ops
  72             new OGLSurfaceToSwBlit(SurfaceType.IntArgb,
  73                                    OGLSurfaceData.PF_INT_ARGB),
  74 
  75             // sw->surface ops
  76             blitIntArgbPreToSurface,
  77             new OGLSwToSurfaceBlit(SurfaceType.IntRgb,
  78                                    OGLSurfaceData.PF_INT_RGB),
  79             new OGLSwToSurfaceBlit(SurfaceType.IntRgbx,
  80                                    OGLSurfaceData.PF_INT_RGBX),
  81             new OGLSwToSurfaceBlit(SurfaceType.IntBgr,
  82                                    OGLSurfaceData.PF_INT_BGR),
  83             new OGLSwToSurfaceBlit(SurfaceType.IntBgrx,
  84                                    OGLSurfaceData.PF_INT_BGRX),
  85             new OGLSwToSurfaceBlit(SurfaceType.ThreeByteBgr,
  86                                    OGLSurfaceData.PF_3BYTE_BGR),
  87             new OGLSwToSurfaceBlit(SurfaceType.Ushort565Rgb,
  88                                    OGLSurfaceData.PF_USHORT_565_RGB),
  89             new OGLSwToSurfaceBlit(SurfaceType.Ushort555Rgb,
  90                                    OGLSurfaceData.PF_USHORT_555_RGB),
  91             new OGLSwToSurfaceBlit(SurfaceType.Ushort555Rgbx,
  92                                    OGLSurfaceData.PF_USHORT_555_RGBX),
  93             new OGLSwToSurfaceBlit(SurfaceType.ByteGray,
  94                                    OGLSurfaceData.PF_BYTE_GRAY),
  95             new OGLSwToSurfaceBlit(SurfaceType.UshortGray,
  96                                    OGLSurfaceData.PF_USHORT_GRAY),
  97             new OGLGeneralBlit(OGLSurfaceData.OpenGLSurface,
  98                                CompositeType.AnyAlpha,
  99                                blitIntArgbPreToSurface),
 100 
 101             new OGLAnyCompositeBlit(OGLSurfaceData.OpenGLSurface),
 102 
 103             new OGLSwToSurfaceScale(SurfaceType.IntRgb,
 104                                     OGLSurfaceData.PF_INT_RGB),
 105             new OGLSwToSurfaceScale(SurfaceType.IntRgbx,
 106                                     OGLSurfaceData.PF_INT_RGBX),
 107             new OGLSwToSurfaceScale(SurfaceType.IntBgr,
 108                                     OGLSurfaceData.PF_INT_BGR),
 109             new OGLSwToSurfaceScale(SurfaceType.IntBgrx,
 110                                     OGLSurfaceData.PF_INT_BGRX),
 111             new OGLSwToSurfaceScale(SurfaceType.ThreeByteBgr,
 112                                     OGLSurfaceData.PF_3BYTE_BGR),
 113             new OGLSwToSurfaceScale(SurfaceType.Ushort565Rgb,
 114                                     OGLSurfaceData.PF_USHORT_565_RGB),
 115             new OGLSwToSurfaceScale(SurfaceType.Ushort555Rgb,
 116                                     OGLSurfaceData.PF_USHORT_555_RGB),
 117             new OGLSwToSurfaceScale(SurfaceType.Ushort555Rgbx,
 118                                     OGLSurfaceData.PF_USHORT_555_RGBX),
 119             new OGLSwToSurfaceScale(SurfaceType.ByteGray,
 120                                     OGLSurfaceData.PF_BYTE_GRAY),
 121             new OGLSwToSurfaceScale(SurfaceType.UshortGray,
 122                                     OGLSurfaceData.PF_USHORT_GRAY),
 123             new OGLSwToSurfaceScale(SurfaceType.IntArgbPre,
 124                                     OGLSurfaceData.PF_INT_ARGB_PRE),
 125 
 126             new OGLSwToSurfaceTransform(SurfaceType.IntRgb,
 127                                         OGLSurfaceData.PF_INT_RGB),
 128             new OGLSwToSurfaceTransform(SurfaceType.IntRgbx,
 129                                         OGLSurfaceData.PF_INT_RGBX),
 130             new OGLSwToSurfaceTransform(SurfaceType.IntBgr,
 131                                         OGLSurfaceData.PF_INT_BGR),
 132             new OGLSwToSurfaceTransform(SurfaceType.IntBgrx,
 133                                         OGLSurfaceData.PF_INT_BGRX),
 134             new OGLSwToSurfaceTransform(SurfaceType.ThreeByteBgr,
 135                                         OGLSurfaceData.PF_3BYTE_BGR),
 136             new OGLSwToSurfaceTransform(SurfaceType.Ushort565Rgb,
 137                                         OGLSurfaceData.PF_USHORT_565_RGB),
 138             new OGLSwToSurfaceTransform(SurfaceType.Ushort555Rgb,
 139                                         OGLSurfaceData.PF_USHORT_555_RGB),
 140             new OGLSwToSurfaceTransform(SurfaceType.Ushort555Rgbx,
 141                                         OGLSurfaceData.PF_USHORT_555_RGBX),
 142             new OGLSwToSurfaceTransform(SurfaceType.ByteGray,
 143                                         OGLSurfaceData.PF_BYTE_GRAY),
 144             new OGLSwToSurfaceTransform(SurfaceType.UshortGray,
 145                                         OGLSurfaceData.PF_USHORT_GRAY),
 146             new OGLSwToSurfaceTransform(SurfaceType.IntArgbPre,
 147                                         OGLSurfaceData.PF_INT_ARGB_PRE),
 148 
 149             // texture->surface ops
 150             new OGLTextureToSurfaceBlit(),
 151             new OGLTextureToSurfaceScale(),
 152             new OGLTextureToSurfaceTransform(),
 153 
 154             // sw->texture ops
 155             blitIntArgbPreToTexture,
 156             new OGLSwToTextureBlit(SurfaceType.IntRgb,
 157                                    OGLSurfaceData.PF_INT_RGB),
 158             new OGLSwToTextureBlit(SurfaceType.IntRgbx,
 159                                    OGLSurfaceData.PF_INT_RGBX),
 160             new OGLSwToTextureBlit(SurfaceType.IntBgr,
 161                                    OGLSurfaceData.PF_INT_BGR),
 162             new OGLSwToTextureBlit(SurfaceType.IntBgrx,
 163                                    OGLSurfaceData.PF_INT_BGRX),
 164             new OGLSwToTextureBlit(SurfaceType.ThreeByteBgr,
 165                                    OGLSurfaceData.PF_3BYTE_BGR),
 166             new OGLSwToTextureBlit(SurfaceType.Ushort565Rgb,
 167                                    OGLSurfaceData.PF_USHORT_565_RGB),
 168             new OGLSwToTextureBlit(SurfaceType.Ushort555Rgb,
 169                                    OGLSurfaceData.PF_USHORT_555_RGB),
 170             new OGLSwToTextureBlit(SurfaceType.Ushort555Rgbx,
 171                                    OGLSurfaceData.PF_USHORT_555_RGBX),
 172             new OGLSwToTextureBlit(SurfaceType.ByteGray,
 173                                    OGLSurfaceData.PF_BYTE_GRAY),
 174             new OGLSwToTextureBlit(SurfaceType.UshortGray,
 175                                    OGLSurfaceData.PF_USHORT_GRAY),
 176             new OGLGeneralBlit(OGLSurfaceData.OpenGLTexture,
 177                                CompositeType.SrcNoEa,
 178                                blitIntArgbPreToTexture),
 179 
 180             new OGLAnyCompositeBlit(OGLSurfaceData.OpenGLTexture),
 181 
 182         };
 183         GraphicsPrimitiveMgr.register(primitives);
 184     }
 185 
 186     /**
 187      * The following offsets are used to pack the parameters in
 188      * createPackedParams().  (They are also used at the native level when
 189      * unpacking the params.)
 190      */
 191     @Native private static final int OFFSET_SRCTYPE = 16;
 192     @Native private static final int OFFSET_HINT    =  8;
 193     @Native private static final int OFFSET_TEXTURE =  3;
 194     @Native private static final int OFFSET_RTT     =  2;
 195     @Native private static final int OFFSET_XFORM   =  1;
 196     @Native private static final int OFFSET_ISOBLIT =  0;
 197 
 198     /**
 199      * Packs the given parameters into a single int value in order to save
 200      * space on the rendering queue.
 201      */
 202     private static int createPackedParams(boolean isoblit, boolean texture,
 203                                           boolean rtt, boolean xform,
 204                                           int hint, int srctype)
 205     {
 206         return
 207             ((srctype           << OFFSET_SRCTYPE) |
 208              (hint              << OFFSET_HINT   ) |
 209              ((texture ? 1 : 0) << OFFSET_TEXTURE) |
 210              ((rtt     ? 1 : 0) << OFFSET_RTT    ) |
 211              ((xform   ? 1 : 0) << OFFSET_XFORM  ) |
 212              ((isoblit ? 1 : 0) << OFFSET_ISOBLIT));
 213     }
 214 
 215     /**
 216      * Enqueues a BLIT operation with the given parameters.  Note that the
 217      * RenderQueue lock must be held before calling this method.
 218      */
 219     private static void enqueueBlit(RenderQueue rq,
 220                                     SurfaceData src, SurfaceData dst,
 221                                     int packedParams,
 222                                     int sx1, int sy1,
 223                                     int sx2, int sy2,
 224                                     double dx1, double dy1,
 225                                     double dx2, double dy2)
 226     {
 227         // assert rq.lock.isHeldByCurrentThread();
 228         RenderBuffer buf = rq.getBuffer();
 229         rq.ensureCapacityAndAlignment(72, 24);
 230         buf.putInt(BLIT);
 231         buf.putInt(packedParams);
 232         buf.putInt(sx1).putInt(sy1);
 233         buf.putInt(sx2).putInt(sy2);
 234         buf.putDouble(dx1).putDouble(dy1);
 235         buf.putDouble(dx2).putDouble(dy2);
 236         buf.putLong(src.getNativeOps());
 237         buf.putLong(dst.getNativeOps());
 238     }
 239 
 240     static void Blit(SurfaceData srcData, SurfaceData dstData,
 241                      Composite comp, Region clip,
 242                      AffineTransform xform, int hint,
 243                      int sx1, int sy1,
 244                      int sx2, int sy2,
 245                      double dx1, double dy1,
 246                      double dx2, double dy2,
 247                      int srctype, boolean texture)
 248     {
 249         int ctxflags = 0;
 250         if (srcData.getTransparency() == Transparency.OPAQUE) {
 251             ctxflags |= OGLContext.SRC_IS_OPAQUE;
 252         }
 253 
 254         OGLRenderQueue rq = OGLRenderQueue.getInstance();
 255         rq.lock();
 256         try {
 257             // make sure the RenderQueue keeps a hard reference to the
 258             // source (sysmem) SurfaceData to prevent it from being
 259             // disposed while the operation is processed on the QFT
 260             rq.addReference(srcData);
 261 
 262             OGLSurfaceData oglDst = (OGLSurfaceData)dstData;
 263             if (texture) {
 264                 // make sure we have a current context before uploading
 265                 // the sysmem data to the texture object
 266                 OGLGraphicsConfig gc = oglDst.getOGLGraphicsConfig();
 267                 OGLContext.setScratchSurface(gc);
 268             } else {
 269                 OGLContext.validateContext(oglDst, oglDst,
 270                                            clip, comp, xform, null, null,
 271                                            ctxflags);
 272             }
 273 
 274             int packedParams = createPackedParams(false, texture,
 275                                                   false, xform != null,
 276                                                   hint, srctype);
 277             enqueueBlit(rq, srcData, dstData,
 278                         packedParams,
 279                         sx1, sy1, sx2, sy2,
 280                         dx1, dy1, dx2, dy2);
 281 
 282             // always flush immediately, since we (currently) have no means
 283             // of tracking changes to the system memory surface
 284             rq.flushNow();
 285         } finally {
 286             rq.unlock();
 287         }
 288     }
 289 
 290     /**
 291      * Note: The srcImg and biop parameters are only used when invoked
 292      * from the OGLBufImgOps.renderImageWithOp() method; in all other cases,
 293      * this method can be called with null values for those two parameters,
 294      * and they will be effectively ignored.
 295      */
 296     static void IsoBlit(SurfaceData srcData, SurfaceData dstData,
 297                         BufferedImage srcImg, BufferedImageOp biop,
 298                         Composite comp, Region clip,
 299                         AffineTransform xform, int hint,
 300                         int sx1, int sy1,
 301                         int sx2, int sy2,
 302                         double dx1, double dy1,
 303                         double dx2, double dy2,
 304                         boolean texture)
 305     {
 306         int ctxflags = 0;
 307         if (srcData.getTransparency() == Transparency.OPAQUE) {
 308             ctxflags |= OGLContext.SRC_IS_OPAQUE;
 309         }
 310 
 311         OGLRenderQueue rq = OGLRenderQueue.getInstance();
 312         rq.lock();
 313         try {
 314             OGLSurfaceData oglSrc = (OGLSurfaceData)srcData;
 315             OGLSurfaceData oglDst = (OGLSurfaceData)dstData;
 316             int srctype = oglSrc.getType();
 317             boolean rtt;
 318             OGLSurfaceData srcCtxData;
 319             if (srctype == OGLSurfaceData.TEXTURE) {
 320                 // the source is a regular texture object; we substitute
 321                 // the destination surface for the purposes of making a
 322                 // context current
 323                 rtt = false;
 324                 srcCtxData = oglDst;
 325             } else {
 326                 // the source is a pbuffer, backbuffer, or render-to-texture
 327                 // surface; we set rtt to true to differentiate this kind
 328                 // of surface from a regular texture object
 329                 rtt = true;
 330                 if (srctype == OGLSurfaceData.FBOBJECT) {
 331                     srcCtxData = oglDst;
 332                 } else {
 333                     srcCtxData = oglSrc;
 334                 }
 335             }
 336 
 337             OGLContext.validateContext(srcCtxData, oglDst,
 338                                        clip, comp, xform, null, null,
 339                                        ctxflags);
 340 
 341             if (biop != null) {
 342                 OGLBufImgOps.enableBufImgOp(rq, oglSrc, srcImg, biop);
 343             }
 344 
 345             int packedParams = createPackedParams(true, texture,
 346                                                   rtt, xform != null,
 347                                                   hint, 0 /*unused*/);
 348             enqueueBlit(rq, srcData, dstData,
 349                         packedParams,
 350                         sx1, sy1, sx2, sy2,
 351                         dx1, dy1, dx2, dy2);
 352 
 353             if (biop != null) {
 354                 OGLBufImgOps.disableBufImgOp(rq, biop);
 355             }
 356 
 357             if (rtt && oglDst.isOnScreen()) {
 358                 // we only have to flush immediately when copying from a
 359                 // (non-texture) surface to the screen; otherwise Swing apps
 360                 // might appear unresponsive until the auto-flush completes
 361                 rq.flushNow();
 362             }
 363         } finally {
 364             rq.unlock();
 365         }
 366     }
 367 }
 368 
 369 class OGLSurfaceToSurfaceBlit extends Blit {
 370 
 371     OGLSurfaceToSurfaceBlit() {
 372         super(OGLSurfaceData.OpenGLSurface,
 373               CompositeType.AnyAlpha,
 374               OGLSurfaceData.OpenGLSurface);
 375     }
 376 
 377     public void Blit(SurfaceData src, SurfaceData dst,
 378                      Composite comp, Region clip,
 379                      int sx, int sy, int dx, int dy, int w, int h)
 380     {
 381         OGLBlitLoops.IsoBlit(src, dst,
 382                              null, null,
 383                              comp, clip, null,
 384                              AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
 385                              sx, sy, sx+w, sy+h,
 386                              dx, dy, dx+w, dy+h,
 387                              false);
 388     }
 389 }
 390 
 391 class OGLSurfaceToSurfaceScale extends ScaledBlit {
 392 
 393     OGLSurfaceToSurfaceScale() {
 394         super(OGLSurfaceData.OpenGLSurface,
 395               CompositeType.AnyAlpha,
 396               OGLSurfaceData.OpenGLSurface);
 397     }
 398 
 399     public void Scale(SurfaceData src, SurfaceData dst,
 400                       Composite comp, Region clip,
 401                       int sx1, int sy1,
 402                       int sx2, int sy2,
 403                       double dx1, double dy1,
 404                       double dx2, double dy2)
 405     {
 406         OGLBlitLoops.IsoBlit(src, dst,
 407                              null, null,
 408                              comp, clip, null,
 409                              AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
 410                              sx1, sy1, sx2, sy2,
 411                              dx1, dy1, dx2, dy2,
 412                              false);
 413     }
 414 }
 415 
 416 class OGLSurfaceToSurfaceTransform extends TransformBlit {
 417 
 418     OGLSurfaceToSurfaceTransform() {
 419         super(OGLSurfaceData.OpenGLSurface,
 420               CompositeType.AnyAlpha,
 421               OGLSurfaceData.OpenGLSurface);
 422     }
 423 
 424     public void Transform(SurfaceData src, SurfaceData dst,
 425                           Composite comp, Region clip,
 426                           AffineTransform at, int hint,
 427                           int sx, int sy, int dx, int dy,
 428                           int w, int h)
 429     {
 430         OGLBlitLoops.IsoBlit(src, dst,
 431                              null, null,
 432                              comp, clip, at, hint,
 433                              sx, sy, sx+w, sy+h,
 434                              dx, dy, dx+w, dy+h,
 435                              false);
 436     }
 437 }
 438 
 439 class OGLRTTSurfaceToSurfaceBlit extends Blit {
 440 
 441     OGLRTTSurfaceToSurfaceBlit() {
 442         super(OGLSurfaceData.OpenGLSurfaceRTT,
 443               CompositeType.AnyAlpha,
 444               OGLSurfaceData.OpenGLSurface);
 445     }
 446 
 447     public void Blit(SurfaceData src, SurfaceData dst,
 448                      Composite comp, Region clip,
 449                      int sx, int sy, int dx, int dy, int w, int h)
 450     {
 451         OGLBlitLoops.IsoBlit(src, dst,
 452                              null, null,
 453                              comp, clip, null,
 454                              AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
 455                              sx, sy, sx+w, sy+h,
 456                              dx, dy, dx+w, dy+h,
 457                              true);
 458     }
 459 }
 460 
 461 class OGLRTTSurfaceToSurfaceScale extends ScaledBlit {
 462 
 463     OGLRTTSurfaceToSurfaceScale() {
 464         super(OGLSurfaceData.OpenGLSurfaceRTT,
 465               CompositeType.AnyAlpha,
 466               OGLSurfaceData.OpenGLSurface);
 467     }
 468 
 469     public void Scale(SurfaceData src, SurfaceData dst,
 470                       Composite comp, Region clip,
 471                       int sx1, int sy1,
 472                       int sx2, int sy2,
 473                       double dx1, double dy1,
 474                       double dx2, double dy2)
 475     {
 476         OGLBlitLoops.IsoBlit(src, dst,
 477                              null, null,
 478                              comp, clip, null,
 479                              AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
 480                              sx1, sy1, sx2, sy2,
 481                              dx1, dy1, dx2, dy2,
 482                              true);
 483     }
 484 }
 485 
 486 class OGLRTTSurfaceToSurfaceTransform extends TransformBlit {
 487 
 488     OGLRTTSurfaceToSurfaceTransform() {
 489         super(OGLSurfaceData.OpenGLSurfaceRTT,
 490               CompositeType.AnyAlpha,
 491               OGLSurfaceData.OpenGLSurface);
 492     }
 493 
 494     public void Transform(SurfaceData src, SurfaceData dst,
 495                           Composite comp, Region clip,
 496                           AffineTransform at, int hint,
 497                           int sx, int sy, int dx, int dy, int w, int h)
 498     {
 499         OGLBlitLoops.IsoBlit(src, dst,
 500                              null, null,
 501                              comp, clip, at, hint,
 502                              sx, sy, sx+w, sy+h,
 503                              dx, dy, dx+w, dy+h,
 504                              true);
 505     }
 506 }
 507 
 508 class OGLSurfaceToSwBlit extends Blit {
 509 
 510     private int typeval;
 511 
 512     // REMIND: destination will actually be opaque/premultiplied...
 513     OGLSurfaceToSwBlit(SurfaceType dstType, int typeval) {
 514         super(OGLSurfaceData.OpenGLSurface,
 515               CompositeType.SrcNoEa,
 516               dstType);
 517         this.typeval = typeval;
 518     }
 519 
 520     public void Blit(SurfaceData src, SurfaceData dst,
 521                      Composite comp, Region clip,
 522                      int sx, int sy, int dx, int dy,
 523                      int w, int h)
 524     {
 525         OGLRenderQueue rq = OGLRenderQueue.getInstance();
 526         rq.lock();
 527         try {
 528             // make sure the RenderQueue keeps a hard reference to the
 529             // destination (sysmem) SurfaceData to prevent it from being
 530             // disposed while the operation is processed on the QFT
 531             rq.addReference(dst);
 532 
 533             RenderBuffer buf = rq.getBuffer();
 534             OGLContext.validateContext((OGLSurfaceData)src);
 535 
 536             rq.ensureCapacityAndAlignment(48, 32);
 537             buf.putInt(SURFACE_TO_SW_BLIT);
 538             buf.putInt(sx).putInt(sy);
 539             buf.putInt(dx).putInt(dy);
 540             buf.putInt(w).putInt(h);
 541             buf.putInt(typeval);
 542             buf.putLong(src.getNativeOps());
 543             buf.putLong(dst.getNativeOps());
 544 
 545             // always flush immediately
 546             rq.flushNow();
 547         } finally {
 548             rq.unlock();
 549         }
 550     }
 551 }
 552 
 553 class OGLSwToSurfaceBlit extends Blit {
 554 
 555     private int typeval;
 556 
 557     OGLSwToSurfaceBlit(SurfaceType srcType, int typeval) {
 558         super(srcType,
 559               CompositeType.AnyAlpha,
 560               OGLSurfaceData.OpenGLSurface);
 561         this.typeval = typeval;
 562     }
 563 
 564     public void Blit(SurfaceData src, SurfaceData dst,
 565                      Composite comp, Region clip,
 566                      int sx, int sy, int dx, int dy, int w, int h)
 567     {
 568         OGLBlitLoops.Blit(src, dst,
 569                           comp, clip, null,
 570                           AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
 571                           sx, sy, sx+w, sy+h,
 572                           dx, dy, dx+w, dy+h,
 573                           typeval, false);
 574     }
 575 }
 576 
 577 class OGLSwToSurfaceScale extends ScaledBlit {
 578 
 579     private int typeval;
 580 
 581     OGLSwToSurfaceScale(SurfaceType srcType, int typeval) {
 582         super(srcType,
 583               CompositeType.AnyAlpha,
 584               OGLSurfaceData.OpenGLSurface);
 585         this.typeval = typeval;
 586     }
 587 
 588     public void Scale(SurfaceData src, SurfaceData dst,
 589                       Composite comp, Region clip,
 590                       int sx1, int sy1,
 591                       int sx2, int sy2,
 592                       double dx1, double dy1,
 593                       double dx2, double dy2)
 594     {
 595         OGLBlitLoops.Blit(src, dst,
 596                           comp, clip, null,
 597                           AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
 598                           sx1, sy1, sx2, sy2,
 599                           dx1, dy1, dx2, dy2,
 600                           typeval, false);
 601     }
 602 }
 603 
 604 class OGLSwToSurfaceTransform extends TransformBlit {
 605 
 606     private int typeval;
 607 
 608     OGLSwToSurfaceTransform(SurfaceType srcType, int typeval) {
 609         super(srcType,
 610               CompositeType.AnyAlpha,
 611               OGLSurfaceData.OpenGLSurface);
 612         this.typeval = typeval;
 613     }
 614 
 615     public void Transform(SurfaceData src, SurfaceData dst,
 616                           Composite comp, Region clip,
 617                           AffineTransform at, int hint,
 618                           int sx, int sy, int dx, int dy, int w, int h)
 619     {
 620         OGLBlitLoops.Blit(src, dst,
 621                           comp, clip, at, hint,
 622                           sx, sy, sx+w, sy+h,
 623                           dx, dy, dx+w, dy+h,
 624                           typeval, false);
 625     }
 626 }
 627 
 628 class OGLSwToTextureBlit extends Blit {
 629 
 630     private int typeval;
 631 
 632     OGLSwToTextureBlit(SurfaceType srcType, int typeval) {
 633         super(srcType,
 634               CompositeType.SrcNoEa,
 635               OGLSurfaceData.OpenGLTexture);
 636         this.typeval = typeval;
 637     }
 638 
 639     public void Blit(SurfaceData src, SurfaceData dst,
 640                      Composite comp, Region clip,
 641                      int sx, int sy, int dx, int dy, int w, int h)
 642     {
 643         OGLBlitLoops.Blit(src, dst,
 644                           comp, clip, null,
 645                           AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
 646                           sx, sy, sx+w, sy+h,
 647                           dx, dy, dx+w, dy+h,
 648                           typeval, true);
 649     }
 650 }
 651 
 652 class OGLTextureToSurfaceBlit extends Blit {
 653 
 654     OGLTextureToSurfaceBlit() {
 655         super(OGLSurfaceData.OpenGLTexture,
 656               CompositeType.AnyAlpha,
 657               OGLSurfaceData.OpenGLSurface);
 658     }
 659 
 660     public void Blit(SurfaceData src, SurfaceData dst,
 661                      Composite comp, Region clip,
 662                      int sx, int sy, int dx, int dy, int w, int h)
 663     {
 664         OGLBlitLoops.IsoBlit(src, dst,
 665                              null, null,
 666                              comp, clip, null,
 667                              AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
 668                              sx, sy, sx+w, sy+h,
 669                              dx, dy, dx+w, dy+h,
 670                              true);
 671     }
 672 }
 673 
 674 class OGLTextureToSurfaceScale extends ScaledBlit {
 675 
 676     OGLTextureToSurfaceScale() {
 677         super(OGLSurfaceData.OpenGLTexture,
 678               CompositeType.AnyAlpha,
 679               OGLSurfaceData.OpenGLSurface);
 680     }
 681 
 682     public void Scale(SurfaceData src, SurfaceData dst,
 683                       Composite comp, Region clip,
 684                       int sx1, int sy1,
 685                       int sx2, int sy2,
 686                       double dx1, double dy1,
 687                       double dx2, double dy2)
 688     {
 689         OGLBlitLoops.IsoBlit(src, dst,
 690                              null, null,
 691                              comp, clip, null,
 692                              AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
 693                              sx1, sy1, sx2, sy2,
 694                              dx1, dy1, dx2, dy2,
 695                              true);
 696     }
 697 }
 698 
 699 class OGLTextureToSurfaceTransform extends TransformBlit {
 700 
 701     OGLTextureToSurfaceTransform() {
 702         super(OGLSurfaceData.OpenGLTexture,
 703               CompositeType.AnyAlpha,
 704               OGLSurfaceData.OpenGLSurface);
 705     }
 706 
 707     public void Transform(SurfaceData src, SurfaceData dst,
 708                           Composite comp, Region clip,
 709                           AffineTransform at, int hint,
 710                           int sx, int sy, int dx, int dy,
 711                           int w, int h)
 712     {
 713         OGLBlitLoops.IsoBlit(src, dst,
 714                              null, null,
 715                              comp, clip, at, hint,
 716                              sx, sy, sx+w, sy+h,
 717                              dx, dy, dx+w, dy+h,
 718                              true);
 719     }
 720 }
 721 
 722 /**
 723  * This general Blit implementation converts any source surface to an
 724  * intermediate IntArgbPre surface, and then uses the more specific
 725  * IntArgbPre->OpenGLSurface/Texture loop to get the intermediate
 726  * (premultiplied) surface down to OpenGL.
 727  */
 728 class OGLGeneralBlit extends Blit {
 729 
 730     private Blit performop;
 731     private WeakReference<SurfaceData> srcTmp;
 732 
 733     OGLGeneralBlit(SurfaceType dstType,
 734                    CompositeType compType,
 735                    Blit performop)
 736     {
 737         super(SurfaceType.Any, compType, dstType);
 738         this.performop = performop;
 739     }
 740 
 741     public synchronized void Blit(SurfaceData src, SurfaceData dst,
 742                                   Composite comp, Region clip,
 743                                   int sx, int sy, int dx, int dy,
 744                                   int w, int h)
 745     {
 746         Blit convertsrc = Blit.getFromCache(src.getSurfaceType(),
 747                                             CompositeType.SrcNoEa,
 748                                             SurfaceType.IntArgbPre);
 749 
 750         SurfaceData cachedSrc = null;
 751         if (srcTmp != null) {
 752             // use cached intermediate surface, if available
 753             cachedSrc = srcTmp.get();
 754         }
 755 
 756         // convert source to IntArgbPre
 757         src = convertFrom(convertsrc, src, sx, sy, w, h,
 758                           cachedSrc, BufferedImage.TYPE_INT_ARGB_PRE);
 759 
 760         // copy IntArgbPre intermediate surface to OpenGL surface
 761         performop.Blit(src, dst, comp, clip,
 762                        0, 0, dx, dy, w, h);
 763 
 764         if (src != cachedSrc) {
 765             // cache the intermediate surface
 766             srcTmp = new WeakReference<>(src);
 767         }
 768     }
 769 }
 770 
 771 class OGLAnyCompositeBlit extends Blit {
 772     private WeakReference<SurfaceData> dstTmp;
 773 
 774     public OGLAnyCompositeBlit(SurfaceType dstType) {
 775         super(SurfaceType.Any, CompositeType.Any, dstType);
 776     }
 777     public synchronized void Blit(SurfaceData src, SurfaceData dst,
 778                                   Composite comp, Region clip,
 779                                   int sx, int sy, int dx, int dy,
 780                                   int w, int h)
 781     {
 782         Blit convertdst = Blit.getFromCache(dst.getSurfaceType(),
 783                                             CompositeType.SrcNoEa,
 784                                             SurfaceType.IntArgbPre);
 785 
 786         SurfaceData cachedDst = null;
 787 
 788         if (dstTmp != null) {
 789             // use cached intermediate surface, if available
 790             cachedDst = dstTmp.get();
 791         }
 792 
 793         // convert source to IntArgbPre
 794         SurfaceData dstBuffer = convertFrom(convertdst, dst, dx, dy, w, h,
 795                           cachedDst, BufferedImage.TYPE_INT_ARGB_PRE);
 796 
 797         Blit performop = Blit.getFromCache(src.getSurfaceType(),
 798                 CompositeType.Any, dstBuffer.getSurfaceType());
 799 
 800         performop.Blit(src, dstBuffer, comp, clip,
 801                        sx, sy, 0, 0, w, h);
 802 
 803         if (dstBuffer != cachedDst) {
 804             // cache the intermediate surface
 805             dstTmp = new WeakReference<>(dstBuffer);
 806         }
 807 
 808         // now blit the buffer back to the destination
 809         convertdst = Blit.getFromCache(dstBuffer.getSurfaceType(),
 810                                             CompositeType.SrcNoEa,
 811                                             dst.getSurfaceType());
 812         convertdst.Blit(dstBuffer, dst, AlphaComposite.Src,
 813                  clip, 0, 0, dx, dy, w, h);
 814     }
 815 }