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