< prev index next >

src/java.desktop/unix/classes/sun/java2d/xr/RectTileManager.java

Print this page
rev 48925 : Xrender: Rename MaskTil(eManager) to RectTile(Manager) to avoid confusion later
rev 48927 : Xrender: make aa tile mask handling a responsibility of the backend implementation
rev 48932 : XRender: Update+introduce copyright statements + comments + unused import removal
   1 /*
   2  * Copyright (c) 2010, 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.xr;
  27 
  28 import java.awt.*;
  29 import java.util.*;
  30 
  31 /**
  32  * We render non-antialiased geometry (consisting of rectangles) into a mask,
  33  * which is later used in a composition step.
  34  * To avoid mask-allocations of large size, MaskTileManager splits
  35  * geometry larger than MASK_SIZE into several tiles,
  36  * and stores the geometry in instances of MaskTile.
  37  *
  38  * @author Clemens Eisserer
  39  */
  40 
  41 public class MaskTileManager {
  42 
  43     public static final int MASK_SIZE = 256;
  44 
  45     MaskTile mainTile = new MaskTile();
  46 
  47     ArrayList<MaskTile> tileList;
  48     int allocatedTiles = 0;
  49     int xTiles, yTiles;
  50 
  51     XRCompositeManager xrMgr;
  52     XRBackend con;
  53 
  54     int maskPixmap;
  55     int maskPicture;
  56     long maskGC;
  57 
  58     public MaskTileManager(XRCompositeManager xrMgr, int parentXid) {
  59         tileList = new ArrayList<MaskTile>();
  60         this.xrMgr = xrMgr;
  61         this.con = xrMgr.getBackend();
  62 
  63         maskPixmap = con.createPixmap(parentXid, 8, MASK_SIZE, MASK_SIZE);
  64         maskPicture = con.createPicture(maskPixmap, XRUtils.PictStandardA8);
  65         con.renderRectangle(maskPicture, XRUtils.PictOpClear,
  66                             new XRColor(Color.black),
  67                             0, 0, MASK_SIZE, MASK_SIZE);
  68         maskGC = con.createGC(maskPixmap);
  69         con.setGCExposures(maskGC, false);
  70     }
  71 
  72     /**
  73      * Transfers the geometry stored (rectangles, lines) to one or more masks,
  74      * and renders the result to the destination surface.
  75      */
  76     public void fillMask(XRSurfaceData dst) {
  77 
  78         boolean maskRequired = xrMgr.maskRequired();
  79         boolean maskEvaluated = XRUtils.isMaskEvaluated(xrMgr.compRule);
  80 
  81         if (maskRequired && maskEvaluated) {
  82             mainTile.calculateDirtyAreas();
  83             DirtyRegion dirtyArea = mainTile.getDirtyArea().cloneRegion();
  84             mainTile.translate(-dirtyArea.x, -dirtyArea.y);
  85 
  86             XRColor maskColor = xrMgr.getMaskColor();
  87 
  88             // We don't need tiling if all geometry fits in a single tile
  89             if (dirtyArea.getWidth() <= MASK_SIZE &&
  90                 dirtyArea.getHeight() <= MASK_SIZE)
  91             {
  92                 compositeSingleTile(dst, mainTile, dirtyArea,
  93                                      maskRequired, 0, 0, maskColor);
  94             } else {
  95                 allocTiles(dirtyArea);
  96                 tileRects();
  97 
  98                 for (int i = 0; i < yTiles; i++) {
  99                     for (int m = 0; m < xTiles; m++) {
 100                         MaskTile tile = tileList.get(i * xTiles + m);
 101 
 102                         int tileStartX = m * MASK_SIZE;
 103                         int tileStartY = i * MASK_SIZE;
 104                         compositeSingleTile(dst, tile, dirtyArea, maskRequired,
 105                                             tileStartX, tileStartY, maskColor);
 106                     }
 107                 }
 108             }
 109         } else {
 110             /*
 111              * If a mask would be required to store geometry (maskRequired)
 112              * composition has to be done rectangle-by-rectagle.
 113              */
 114             if(xrMgr.isSolidPaintActive()) {
 115                 xrMgr.XRRenderRectangles(dst, mainTile.getRects());
 116             } else {
 117                 xrMgr.XRCompositeRectangles(dst, mainTile.getRects());
 118             }
 119         }
 120 
 121         mainTile.reset();
 122     }
 123 
 124     /**
 125      * Uploads aa geometry generated for maskblit/fill into the mask pixmap.
 126      */
 127     public int uploadMask(int w, int h, int maskscan, int maskoff, byte[] mask) {
 128         int maskPic = XRUtils.None;
 129 
 130         if (mask != null) {
 131             float maskAlpha =
 132                  xrMgr.isTexturePaintActive() ? xrMgr.getExtraAlpha() : 1.0f;
 133             con.putMaskImage(maskPixmap, maskGC, mask, 0, 0, 0, 0,
 134                              w, h, maskoff, maskscan, maskAlpha);
 135             maskPic = maskPicture;
 136         } else if (xrMgr.isTexturePaintActive()) {
 137             maskPic = xrMgr.getExtraAlphaMask();
 138          }
 139 
 140         return maskPic;
 141     }
 142 
 143     /**
 144      * Clears the area of the mask-pixmap used for uploading aa coverage values.
 145      */
 146     public void clearUploadMask(int mask, int w, int h) {
 147         if (mask == maskPicture) {
 148             con.renderRectangle(maskPicture, XRUtils.PictOpClear,
 149                                 XRColor.NO_ALPHA, 0, 0, w, h);
 150         }
 151     }
 152 
 153 
 154     /**
 155      * Renders the rectangles provided to the mask, and does a composition
 156      * operation with the properties set inXRCompositeManager.
 157      */
 158     protected void compositeSingleTile(XRSurfaceData dst, MaskTile tile,
 159                                        DirtyRegion dirtyArea,
 160                                        boolean maskRequired,
 161                                        int tileStartX, int tileStartY,
 162                                        XRColor maskColor) {
 163         if (tile.rects.getSize() > 0) {
 164             DirtyRegion tileDirtyArea = tile.getDirtyArea();
 165 
 166             int x = tileDirtyArea.x + tileStartX + dirtyArea.x;
 167             int y = tileDirtyArea.y + tileStartY + dirtyArea.y;
 168             int width = tileDirtyArea.x2 - tileDirtyArea.x;
 169             int height = tileDirtyArea.y2 - tileDirtyArea.y;
 170             width = Math.min(width, MASK_SIZE);
 171             height = Math.min(height, MASK_SIZE);
 172 
 173             int rectCnt = tile.rects.getSize();
 174 
 175             if (maskRequired) {
 176                 int mask = XRUtils.None;
 177 
 178                 /*


 195 
 196                 /* Clear dirty rectangle of the rect-mask */
 197                 if (rectCnt > 1) {
 198                     con.renderRectangle(maskPicture, XRUtils.PictOpClear,
 199                                         XRColor.NO_ALPHA,
 200                                         tileDirtyArea.x, tileDirtyArea.y,
 201                                         width, height);
 202                 }
 203 
 204                 tile.reset();
 205             } else if (rectCnt > 0) {
 206                 tile.rects.translateRects(tileStartX + dirtyArea.x,
 207                                           tileStartY + dirtyArea.y);
 208                 xrMgr.XRRenderRectangles(dst, tile.rects);
 209             }
 210         }
 211     }
 212 
 213 
 214     /**
 215      * Allocates enough MaskTile instances, to cover the whole
 216      * mask area, or resets existing ones.
 217      */
 218     protected void allocTiles(DirtyRegion maskArea) {
 219         xTiles = (maskArea.getWidth() / MASK_SIZE) + 1;
 220         yTiles = (maskArea.getHeight() / MASK_SIZE) + 1;
 221         int tileCnt = xTiles * yTiles;
 222 
 223         if (tileCnt > allocatedTiles) {
 224             for (int i = 0; i < tileCnt; i++) {
 225                 if (i < allocatedTiles) {
 226                     tileList.get(i).reset();
 227                 } else {
 228                     tileList.add(new MaskTile());
 229                 }
 230             }
 231 
 232             allocatedTiles = tileCnt;
 233         }
 234     }
 235 
 236     /**
 237      * Tiles the stored rectangles, if they are larger than the MASK_SIZE
 238      */
 239     protected void tileRects() {
 240         GrowableRectArray rects = mainTile.rects;
 241 
 242         for (int i = 0; i < rects.getSize(); i++) {
 243             int tileXStartIndex = rects.getX(i) / MASK_SIZE;
 244             int tileYStartIndex = rects.getY(i) / MASK_SIZE;
 245             int tileXLength =
 246                 ((rects.getX(i) + rects.getWidth(i)) / MASK_SIZE + 1) -
 247                  tileXStartIndex;
 248             int tileYLength =
 249                  ((rects.getY(i) + rects.getHeight(i)) / MASK_SIZE + 1) -
 250                  tileYStartIndex;
 251 
 252             for (int n = 0; n < tileYLength; n++) {
 253                 for (int m = 0; m < tileXLength; m++) {
 254 
 255                     int tileIndex =
 256                          xTiles * (tileYStartIndex + n) + tileXStartIndex + m;
 257                     MaskTile tile = tileList.get(tileIndex);
 258 
 259                     GrowableRectArray rectTileList = tile.getRects();
 260                     int tileArrayIndex = rectTileList.getNextIndex();
 261 
 262                     int tileStartPosX = (tileXStartIndex + m) * MASK_SIZE;
 263                     int tileStartPosY = (tileYStartIndex + n) * MASK_SIZE;
 264 
 265                     rectTileList.setX(tileArrayIndex, rects.getX(i) - tileStartPosX);
 266                     rectTileList.setY(tileArrayIndex, rects.getY(i) - tileStartPosY);
 267                     rectTileList.setWidth(tileArrayIndex, rects.getWidth(i));
 268                     rectTileList.setHeight(tileArrayIndex, rects.getHeight(i));
 269 
 270                     limitRectCoords(rectTileList, tileArrayIndex);
 271 
 272                     tile.getDirtyArea().growDirtyRegion
 273                        (rectTileList.getX(tileArrayIndex),
 274                         rectTileList.getY(tileArrayIndex),
 275                         rectTileList.getWidth(tileArrayIndex) +
 276                              rectTileList.getX(tileArrayIndex),
 277                         rectTileList.getHeight(tileArrayIndex) +


 288     private void limitRectCoords(GrowableRectArray rects, int index) {
 289         if ((rects.getX(index) + rects.getWidth(index)) > MASK_SIZE) {
 290             rects.setWidth(index, MASK_SIZE - rects.getX(index));
 291         }
 292         if ((rects.getY(index) + rects.getHeight(index)) > MASK_SIZE) {
 293             rects.setHeight(index, MASK_SIZE - rects.getY(index));
 294         }
 295         if (rects.getX(index) < 0) {
 296             rects.setWidth(index, rects.getWidth(index) + rects.getX(index));
 297             rects.setX(index, 0);
 298         }
 299         if (rects.getY(index) < 0) {
 300             rects.setHeight(index, rects.getHeight(index) + rects.getY(index));
 301             rects.setY(index, 0);
 302         }
 303     }
 304 
 305     /**
 306      * @return MainTile to which rectangles are added before composition.
 307      */
 308     public MaskTile getMainTile() {
 309         return mainTile;
 310      }
 311 }
   1 /*
   2  * Copyright (c) 2010, 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.xr;
  27 
  28 import java.awt.*;
  29 import java.util.*;
  30 
  31 /**
  32  * We render non-antialiased geometry (consisting of rectangles) into a mask,
  33  * which is later used in a composition step.
  34  * To avoid mask-allocations of large size, RectTileManager splits
  35  * geometry larger than MASK_SIZE into several tiles,
  36  * and stores the geometry in instances of RectTile.
  37  *
  38  * @author Clemens Eisserer
  39  */
  40 
  41 public class RectTileManager {
  42 
  43     public static final int MASK_SIZE = 256;
  44 
  45     RectTile mainTile = new RectTile();
  46 
  47     ArrayList<RectTile> tileList;
  48     int allocatedTiles = 0;
  49     int xTiles, yTiles;
  50 
  51     XRCompositeManager xrMgr;
  52     XRBackend con;
  53 
  54     int maskPixmap;
  55     int maskPicture;
  56     long maskGC;
  57 
  58     public RectTileManager(XRCompositeManager xrMgr, int parentXid) {
  59         tileList = new ArrayList<RectTile>();
  60         this.xrMgr = xrMgr;
  61         this.con = xrMgr.getBackend();
  62 
  63         maskPixmap = con.createPixmap(parentXid, 8, MASK_SIZE, MASK_SIZE);
  64         maskPicture = con.createPicture(maskPixmap, XRUtils.PictStandardA8);
  65         con.renderRectangle(maskPicture, XRUtils.PictOpClear,
  66                             new XRColor(Color.black),
  67                             0, 0, MASK_SIZE, MASK_SIZE);
  68         maskGC = con.createGC(maskPixmap);
  69         con.setGCExposures(maskGC, false);
  70     }
  71 
  72     /**
  73      * Transfers the geometry stored (rectangles, lines) to one or more masks,
  74      * and renders the result to the destination surface.
  75      */
  76     public void fillMask(XRSurfaceData dst) {
  77 
  78         boolean maskRequired = xrMgr.maskRequired();
  79         boolean maskEvaluated = XRUtils.isMaskEvaluated(xrMgr.compRule);
  80 
  81         if (maskRequired && maskEvaluated) {
  82             mainTile.calculateDirtyAreas();
  83             DirtyRegion dirtyArea = mainTile.getDirtyArea().cloneRegion();
  84             mainTile.translate(-dirtyArea.x, -dirtyArea.y);
  85 
  86             XRColor maskColor = xrMgr.getMaskColor();
  87 
  88             // We don't need tiling if all geometry fits in a single tile
  89             if (dirtyArea.getWidth() <= MASK_SIZE &&
  90                 dirtyArea.getHeight() <= MASK_SIZE)
  91             {
  92                 compositeSingleTile(dst, mainTile, dirtyArea,
  93                                      maskRequired, 0, 0, maskColor);
  94             } else {
  95                 allocTiles(dirtyArea);
  96                 tileRects();
  97 
  98                 for (int i = 0; i < yTiles; i++) {
  99                     for (int m = 0; m < xTiles; m++) {
 100                         RectTile tile = tileList.get(i * xTiles + m);
 101 
 102                         int tileStartX = m * MASK_SIZE;
 103                         int tileStartY = i * MASK_SIZE;
 104                         compositeSingleTile(dst, tile, dirtyArea, maskRequired,
 105                                             tileStartX, tileStartY, maskColor);
 106                     }
 107                 }
 108             }
 109         } else {
 110             /*
 111              * If a mask would be required to store geometry (maskRequired)
 112              * composition has to be done rectangle-by-rectagle.
 113              */
 114             if(xrMgr.isSolidPaintActive()) {
 115                 xrMgr.XRRenderRectangles(dst, mainTile.getRects());
 116             } else {
 117                 xrMgr.XRCompositeRectangles(dst, mainTile.getRects());
 118             }
 119         }
 120 
 121         mainTile.reset();
 122     }
 123 
 124     /**






























 125      * Renders the rectangles provided to the mask, and does a composition
 126      * operation with the properties set inXRCompositeManager.
 127      */
 128     protected void compositeSingleTile(XRSurfaceData dst, RectTile tile,
 129                                        DirtyRegion dirtyArea,
 130                                        boolean maskRequired,
 131                                        int tileStartX, int tileStartY,
 132                                        XRColor maskColor) {
 133         if (tile.rects.getSize() > 0) {
 134             DirtyRegion tileDirtyArea = tile.getDirtyArea();
 135 
 136             int x = tileDirtyArea.x + tileStartX + dirtyArea.x;
 137             int y = tileDirtyArea.y + tileStartY + dirtyArea.y;
 138             int width = tileDirtyArea.x2 - tileDirtyArea.x;
 139             int height = tileDirtyArea.y2 - tileDirtyArea.y;
 140             width = Math.min(width, MASK_SIZE);
 141             height = Math.min(height, MASK_SIZE);
 142 
 143             int rectCnt = tile.rects.getSize();
 144 
 145             if (maskRequired) {
 146                 int mask = XRUtils.None;
 147 
 148                 /*


 165 
 166                 /* Clear dirty rectangle of the rect-mask */
 167                 if (rectCnt > 1) {
 168                     con.renderRectangle(maskPicture, XRUtils.PictOpClear,
 169                                         XRColor.NO_ALPHA,
 170                                         tileDirtyArea.x, tileDirtyArea.y,
 171                                         width, height);
 172                 }
 173 
 174                 tile.reset();
 175             } else if (rectCnt > 0) {
 176                 tile.rects.translateRects(tileStartX + dirtyArea.x,
 177                                           tileStartY + dirtyArea.y);
 178                 xrMgr.XRRenderRectangles(dst, tile.rects);
 179             }
 180         }
 181     }
 182 
 183 
 184     /**
 185      * Allocates enough RectTile instances, to cover the whole
 186      * mask area, or resets existing ones.
 187      */
 188     protected void allocTiles(DirtyRegion maskArea) {
 189         xTiles = (maskArea.getWidth() / MASK_SIZE) + 1;
 190         yTiles = (maskArea.getHeight() / MASK_SIZE) + 1;
 191         int tileCnt = xTiles * yTiles;
 192 
 193         if (tileCnt > allocatedTiles) {
 194             for (int i = 0; i < tileCnt; i++) {
 195                 if (i < allocatedTiles) {
 196                     tileList.get(i).reset();
 197                 } else {
 198                     tileList.add(new RectTile());
 199                 }
 200             }
 201 
 202             allocatedTiles = tileCnt;
 203         }
 204     }
 205 
 206     /**
 207      * Tiles the stored rectangles, if they are larger than the MASK_SIZE
 208      */
 209     protected void tileRects() {
 210         GrowableRectArray rects = mainTile.rects;
 211 
 212         for (int i = 0; i < rects.getSize(); i++) {
 213             int tileXStartIndex = rects.getX(i) / MASK_SIZE;
 214             int tileYStartIndex = rects.getY(i) / MASK_SIZE;
 215             int tileXLength =
 216                 ((rects.getX(i) + rects.getWidth(i)) / MASK_SIZE + 1) -
 217                  tileXStartIndex;
 218             int tileYLength =
 219                  ((rects.getY(i) + rects.getHeight(i)) / MASK_SIZE + 1) -
 220                  tileYStartIndex;
 221 
 222             for (int n = 0; n < tileYLength; n++) {
 223                 for (int m = 0; m < tileXLength; m++) {
 224 
 225                     int tileIndex =
 226                          xTiles * (tileYStartIndex + n) + tileXStartIndex + m;
 227                     RectTile tile = tileList.get(tileIndex);
 228 
 229                     GrowableRectArray rectTileList = tile.getRects();
 230                     int tileArrayIndex = rectTileList.getNextIndex();
 231 
 232                     int tileStartPosX = (tileXStartIndex + m) * MASK_SIZE;
 233                     int tileStartPosY = (tileYStartIndex + n) * MASK_SIZE;
 234 
 235                     rectTileList.setX(tileArrayIndex, rects.getX(i) - tileStartPosX);
 236                     rectTileList.setY(tileArrayIndex, rects.getY(i) - tileStartPosY);
 237                     rectTileList.setWidth(tileArrayIndex, rects.getWidth(i));
 238                     rectTileList.setHeight(tileArrayIndex, rects.getHeight(i));
 239 
 240                     limitRectCoords(rectTileList, tileArrayIndex);
 241 
 242                     tile.getDirtyArea().growDirtyRegion
 243                        (rectTileList.getX(tileArrayIndex),
 244                         rectTileList.getY(tileArrayIndex),
 245                         rectTileList.getWidth(tileArrayIndex) +
 246                              rectTileList.getX(tileArrayIndex),
 247                         rectTileList.getHeight(tileArrayIndex) +


 258     private void limitRectCoords(GrowableRectArray rects, int index) {
 259         if ((rects.getX(index) + rects.getWidth(index)) > MASK_SIZE) {
 260             rects.setWidth(index, MASK_SIZE - rects.getX(index));
 261         }
 262         if ((rects.getY(index) + rects.getHeight(index)) > MASK_SIZE) {
 263             rects.setHeight(index, MASK_SIZE - rects.getY(index));
 264         }
 265         if (rects.getX(index) < 0) {
 266             rects.setWidth(index, rects.getWidth(index) + rects.getX(index));
 267             rects.setX(index, 0);
 268         }
 269         if (rects.getY(index) < 0) {
 270             rects.setHeight(index, rects.getHeight(index) + rects.getY(index));
 271             rects.setY(index, 0);
 272         }
 273     }
 274 
 275     /**
 276      * @return MainTile to which rectangles are added before composition.
 277      */
 278     public RectTile getMainTile() {
 279         return mainTile;
 280      }
 281 }
< prev index next >