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