1 /*
   2  * Copyright (c) 2017, 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 package sun.java2d.xr;
  26 
  27 import java.awt.Point;
  28 import java.nio.ByteBuffer;
  29 
  30 /**
  31  * Buffer for uploading AA mask tile data.
  32  * Supports uploading multiple AA tiles within one buffer, by simply appending
  33  * the tiles in x-direction and starting a new line once the remaining width
  34  * is not sufficient anymore.
  35  *
  36  * @author Clemens Eisserer
  37  */
  38 public class AATileBuffer {
  39     private final static int SHM_THRESHOLD = 8192;
  40     private final static int SHM_THRESHOLD2 = 16384;
  41     
  42     final int bufferWidth;
  43     final int bufferHeight;
  44     final int bufferScan;
  45     final int yOffset;
  46     
  47     final AATileBufMan bufMan;
  48     final ByteBuffer buffer;
  49     final int bufferId; 
  50     final boolean shmCapable;
  51     
  52     int tileCount;
  53     int currY;
  54     int currX;
  55     int currentRowHeight;
  56     int maxRowWidth;
  57     
  58     public AATileBuffer(AATileBufMan bufMan, int bufferWidth, int bufferHeight, int bufferScan, int yOffset, int bufferId, ByteBuffer buffer, boolean shmCapable) {
  59         this.bufMan = bufMan;
  60         this.bufferWidth = bufferWidth;
  61         this.bufferHeight = bufferHeight;
  62         this.bufferScan = bufferScan;
  63         this.shmCapable = shmCapable;
  64         
  65         this.yOffset = yOffset;
  66         this.bufferId = bufferId;
  67         
  68         this.buffer = buffer;
  69     }
  70     
  71     public Point storeTile(int width, int height)  {
  72         int dstX;
  73         
  74         if(bufferHeight - currY - currentRowHeight < height) {
  75                 return null;
  76         }
  77         
  78         if(bufferHeight - currX > width) {
  79            dstX = currX;
  80            currX += width;
  81            currentRowHeight = Math.max(currentRowHeight, height);
  82            maxRowWidth = Math.max(maxRowWidth, currX);
  83         } else
  84         {
  85           dstX = 0;
  86           currX = width;
  87           currY += currentRowHeight;            
  88           currentRowHeight = height;
  89         }
  90         
  91         tileCount++;
  92         
  93         return new Point(dstX, currY);
  94     }
  95     
  96     public int getTileCount() {
  97         return tileCount;
  98     }
  99     
 100     public void reset() {
 101         currX = 0;
 102         currY = 0;
 103         currentRowHeight = 0;
 104         maxRowWidth = 0;
 105         tileCount = 0;
 106     }
 107     
 108     public Point getBufferBounds() {
 109         return new Point(maxRowWidth, currY + currentRowHeight);
 110     }
 111     
 112     public Point storeMaskTile(byte[] tileData, int width, int height, int maskOff,
 113             int tileScan, float ea) {
 114         
 115         Point pt = storeTile(width, height);
 116         if(pt == null) {
 117             return null;
 118         }
 119         
 120         /*
 121         if(ea < 0.99804687f) {
 122             for(int y=0; y < height; y++) {
 123                for(int x = 0; x < width; x++) {
 124                    tileData[]
 125                }
 126             }
 127         } */
 128         
 129         for(int y=0; y < height; y++) {
 130             int srcPos = tileScan * y  + maskOff;
 131             int dstPos = bufferScan * (pt.y + y) + pt.x;
 132             
 133             buffer.position(dstPos);
 134             buffer.put(tileData, srcPos, width);
 135         }
 136         
 137         return pt;
 138     }
 139     
 140     public ByteBuffer getByteBuffer() {
 141         return buffer;
 142     }
 143     
 144     public int getBufferScan() {
 145         return bufferScan;
 146     }
 147     
 148     public int getYOffset() {
 149         return yOffset;
 150     }
 151     
 152     public boolean isShmCapable() {
 153         return shmCapable;
 154     }
 155     
 156     public boolean isUploadWithShmProfitable() {
 157        int pixelsOccupied = maxRowWidth * (currY + currentRowHeight);
 158        
 159        // in case only one shm capable buffer is left, set the treshold higher
 160        // so we save the shm buffer for larger uploads later
 161        return ((bufMan.getIdleShmBufferCnt() > 1 && pixelsOccupied >= SHM_THRESHOLD)
 162                || pixelsOccupied >= SHM_THRESHOLD2) && shmCapable;
 163     }
 164     
 165     public int getBufferId() {
 166         return bufferId;
 167     }
 168 }