1 /*
   2  * Copyright (c) 1999, 2018, 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.loops;
  27 
  28 import java.awt.Composite;
  29 import java.awt.CompositeContext;
  30 import java.awt.RenderingHints;
  31 import java.awt.image.ColorModel;
  32 import java.awt.image.Raster;
  33 import java.awt.image.WritableRaster;
  34 import java.lang.ref.WeakReference;
  35 import sun.java2d.loops.GraphicsPrimitive;
  36 import sun.java2d.SurfaceData;
  37 import sun.java2d.pipe.Region;
  38 import sun.java2d.pipe.SpanIterator;
  39 
  40 /**
  41  * Blit
  42  * 1) copies rectangle of pixels from one surface to another
  43  * 2) performs compositing of colors based upon a Composite
  44  *    parameter
  45  *
  46  * precise behavior is undefined if the source surface
  47  * and the destination surface are the same surface
  48  * with overlapping regions of pixels
  49  */
  50 
  51 public class Blit extends GraphicsPrimitive
  52 {
  53     public static final String methodSignature = "Blit(...)".toString();
  54 
  55     public static final int primTypeID = makePrimTypeID();
  56 
  57     private static RenderCache blitcache = new RenderCache(20);
  58 
  59     public static Blit locate(SurfaceType srctype,
  60                               CompositeType comptype,
  61                               SurfaceType dsttype)
  62     {
  63         return (Blit)
  64             GraphicsPrimitiveMgr.locate(primTypeID,
  65                                         srctype, comptype, dsttype);
  66     }
  67 
  68     public static Blit getFromCache(SurfaceType src,
  69                                     CompositeType comp,
  70                                     SurfaceType dst)
  71     {
  72         Object o = blitcache.get(src, comp, dst);
  73         if (o != null) {
  74             return (Blit) o;
  75         }
  76 
  77         Blit blit = locate(src, comp, dst);
  78         if (blit == null) {
  79             System.out.println("blit loop not found for:");
  80             System.out.println("src:  "+src);
  81             System.out.println("comp: "+comp);
  82             System.out.println("dst:  "+dst);
  83         } else {
  84             blitcache.put(src, comp, dst, blit);
  85         }
  86         return blit;
  87     }
  88 
  89     protected Blit(SurfaceType srctype,
  90                    CompositeType comptype,
  91                    SurfaceType dsttype)
  92     {
  93         super(methodSignature, primTypeID, srctype, comptype, dsttype);
  94     }
  95 
  96     public Blit(long pNativePrim,
  97                 SurfaceType srctype,
  98                 CompositeType comptype,
  99                 SurfaceType dsttype)
 100     {
 101         super(pNativePrim, methodSignature, primTypeID, srctype, comptype, dsttype);
 102     }
 103 
 104     /**
 105      * All Blit implementors must have this invoker method
 106      */
 107     public native void Blit(SurfaceData src, SurfaceData dst,
 108                             Composite comp, Region clip,
 109                             int srcx, int srcy,
 110                             int dstx, int dsty,
 111                             int width, int height);
 112 
 113     static {
 114         GraphicsPrimitiveMgr.registerGeneral(new Blit(null, null, null));
 115     }
 116 
 117     public GraphicsPrimitive makePrimitive(SurfaceType srctype,
 118                                            CompositeType comptype,
 119                                            SurfaceType dsttype)
 120     {
 121         /*
 122         System.out.println("Constructing general blit for:");
 123         System.out.println("src:  "+srctype);
 124         System.out.println("comp: "+comptype);
 125         System.out.println("dst:  "+dsttype);
 126         */
 127 
 128         if (comptype.isDerivedFrom(CompositeType.Xor)) {
 129             GeneralXorBlit gxb = new GeneralXorBlit(srctype,
 130                                                     comptype,
 131                                                     dsttype);
 132             setupGeneralBinaryOp(gxb);
 133             return gxb;
 134         } else if (comptype.isDerivedFrom(CompositeType.AnyAlpha)) {
 135             return new GeneralMaskBlit(srctype, comptype, dsttype);
 136         } else {
 137             return AnyBlit.instance;
 138         }
 139     }
 140 
 141     private static class AnyBlit extends Blit {
 142         public static AnyBlit instance = new AnyBlit();
 143 
 144         public AnyBlit() {
 145             super(SurfaceType.Any, CompositeType.Any, SurfaceType.Any);
 146         }
 147 
 148         public void Blit(SurfaceData srcData,
 149                          SurfaceData dstData,
 150                          Composite comp,
 151                          Region clip,
 152                          int srcx, int srcy,
 153                          int dstx, int dsty,
 154                          int width, int height)
 155         {
 156             ColorModel srcCM = srcData.getColorModel();
 157             ColorModel dstCM = dstData.getColorModel();
 158             // REMIND: Should get RenderingHints from sg2d
 159             CompositeContext ctx = comp.createContext(srcCM, dstCM,
 160                                                       new RenderingHints(null));
 161             Raster srcRas = srcData.getRaster(srcx, srcy, width, height);
 162             WritableRaster dstRas =
 163                 (WritableRaster) dstData.getRaster(dstx, dsty, width, height);
 164 
 165             if (clip == null) {
 166                 clip = Region.getInstanceXYWH(dstx, dsty, width, height);
 167             }
 168             int[] span = {dstx, dsty, dstx+width, dsty+height};
 169             SpanIterator si = clip.getSpanIterator(span);
 170             srcx -= dstx;
 171             srcy -= dsty;
 172             while (si.nextSpan(span)) {
 173                 int w = span[2] - span[0];
 174                 int h = span[3] - span[1];
 175                 Raster tmpSrcRas = srcRas.createChild(srcx + span[0], srcy + span[1],
 176                                                       w, h, 0, 0, null);
 177                 WritableRaster tmpDstRas = dstRas.createWritableChild(span[0], span[1],
 178                                                                       w, h, 0, 0, null);
 179                 ctx.compose(tmpSrcRas, tmpDstRas, tmpDstRas);
 180             }
 181             ctx.dispose();
 182         }
 183     }
 184 
 185     private static class GeneralMaskBlit extends Blit {
 186         MaskBlit performop;
 187 
 188         public GeneralMaskBlit(SurfaceType srctype,
 189                                CompositeType comptype,
 190                                SurfaceType dsttype)
 191         {
 192             super(srctype, comptype, dsttype);
 193             performop = MaskBlit.locate(srctype, comptype, dsttype);
 194         }
 195 
 196         public void Blit(SurfaceData srcData,
 197                          SurfaceData dstData,
 198                          Composite comp,
 199                          Region clip,
 200                          int srcx, int srcy,
 201                          int dstx, int dsty,
 202                          int width, int height)
 203         {
 204             performop.MaskBlit(srcData, dstData, comp, clip,
 205                                srcx, srcy, dstx, dsty,
 206                                width, height,
 207                                null, 0, 0);
 208         }
 209     }
 210 
 211     private static class GeneralXorBlit
 212         extends Blit
 213         implements GeneralBinaryOp
 214     {
 215         Blit convertsrc;
 216         Blit convertdst;
 217         Blit performop;
 218         Blit convertresult;
 219 
 220         WeakReference<SurfaceData> srcTmp;
 221         WeakReference<SurfaceData> dstTmp;
 222 
 223         public GeneralXorBlit(SurfaceType srctype,
 224                               CompositeType comptype,
 225                               SurfaceType dsttype)
 226         {
 227             super(srctype, comptype, dsttype);
 228         }
 229 
 230         public void setPrimitives(Blit srcconverter,
 231                                   Blit dstconverter,
 232                                   GraphicsPrimitive genericop,
 233                                   Blit resconverter)
 234         {
 235             this.convertsrc = srcconverter;
 236             this.convertdst = dstconverter;
 237             this.performop = (Blit) genericop;
 238             this.convertresult = resconverter;
 239         }
 240 
 241         public synchronized void Blit(SurfaceData srcData,
 242                                       SurfaceData dstData,
 243                                       Composite comp,
 244                                       Region clip,
 245                                       int srcx, int srcy,
 246                                       int dstx, int dsty,
 247                                       int width, int height)
 248         {
 249             SurfaceData src, dst;
 250             Region opclip;
 251             int sx, sy, dx, dy;
 252 
 253             if (convertsrc == null) {
 254                 src = srcData;
 255                 sx = srcx;
 256                 sy = srcy;
 257             } else {
 258                 SurfaceData cachedSrc = null;
 259                 if (srcTmp != null) {
 260                     cachedSrc = srcTmp.get();
 261                 }
 262                 src = convertFrom(convertsrc, srcData, srcx, srcy,
 263                                   width, height, cachedSrc);
 264                 sx = 0;
 265                 sy = 0;
 266                 if (src != cachedSrc) {
 267                     srcTmp = new WeakReference<>(src);
 268                 }
 269             }
 270 
 271             if (convertdst == null) {
 272                 dst = dstData;
 273                 dx = dstx;
 274                 dy = dsty;
 275                 opclip = clip;
 276             } else {
 277                 // assert: convertresult != null
 278                 SurfaceData cachedDst = null;
 279                 if (dstTmp != null) {
 280                     cachedDst = dstTmp.get();
 281                 }
 282                 dst = convertFrom(convertdst, dstData, dstx, dsty,
 283                                   width, height, cachedDst);
 284                 dx = 0;
 285                 dy = 0;
 286                 opclip = null;
 287                 if (dst != cachedDst) {
 288                     dstTmp = new WeakReference<>(dst);
 289                 }
 290             }
 291 
 292             performop.Blit(src, dst, comp, opclip,
 293                            sx, sy, dx, dy,
 294                            width, height);
 295 
 296             if (convertresult != null) {
 297                 // assert: convertdst != null
 298                 convertTo(convertresult, dst, dstData, clip,
 299                           dstx, dsty, width, height);
 300             }
 301         }
 302     }
 303 
 304     public GraphicsPrimitive traceWrap() {
 305         return new TraceBlit(this);
 306     }
 307 
 308     private static class TraceBlit extends Blit {
 309         Blit target;
 310 
 311         public TraceBlit(Blit target) {
 312             super(target.getSourceType(),
 313                   target.getCompositeType(),
 314                   target.getDestType());
 315             this.target = target;
 316         }
 317 
 318         public GraphicsPrimitive traceWrap() {
 319             return this;
 320         }
 321 
 322         public void Blit(SurfaceData src, SurfaceData dst,
 323                          Composite comp, Region clip,
 324                          int srcx, int srcy, int dstx, int dsty,
 325                          int width, int height)
 326         {
 327             if ((traceflags & TRACEPTIME) == 0) {
 328                 tracePrimitive(target);
 329             }
 330             long time = System.nanoTime();
 331             target.Blit(src, dst, comp, clip,
 332                         srcx, srcy, dstx, dsty, width, height);
 333             tracePrimitiveTime(target, System.nanoTime() - time);
 334         }
 335     }
 336 }