Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/classes/sun/java2d/xr/MaskTileManager.java
32288 views
/*1* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.java2d.xr;2627import java.awt.*;28import java.util.*;2930/**31* We render non-antialiased geometry (consisting of rectangles) into a mask,32* which is later used in a composition step.33* To avoid mask-allocations of large size, MaskTileManager splits34* geometry larger than MASK_SIZE into several tiles,35* and stores the geometry in instances of MaskTile.36*37* @author Clemens Eisserer38*/3940public class MaskTileManager {4142public static final int MASK_SIZE = 256;4344MaskTile mainTile = new MaskTile();4546ArrayList<MaskTile> tileList;47int allocatedTiles = 0;48int xTiles, yTiles;4950XRCompositeManager xrMgr;51XRBackend con;5253int maskPixmap;54int maskPicture;55long maskGC;5657public MaskTileManager(XRCompositeManager xrMgr, int parentXid) {58tileList = new ArrayList<MaskTile>();59this.xrMgr = xrMgr;60this.con = xrMgr.getBackend();6162maskPixmap = con.createPixmap(parentXid, 8, MASK_SIZE, MASK_SIZE);63maskPicture = con.createPicture(maskPixmap, XRUtils.PictStandardA8);64con.renderRectangle(maskPicture, XRUtils.PictOpClear,65new XRColor(Color.black),660, 0, MASK_SIZE, MASK_SIZE);67maskGC = con.createGC(maskPixmap);68con.setGCExposures(maskGC, false);69}7071/**72* Transfers the geometry stored (rectangles, lines) to one or more masks,73* and renders the result to the destination surface.74*/75public void fillMask(XRSurfaceData dst) {7677boolean maskRequired = xrMgr.maskRequired();78boolean maskEvaluated = XRUtils.isMaskEvaluated(xrMgr.compRule);7980if (maskRequired && maskEvaluated) {81mainTile.calculateDirtyAreas();82DirtyRegion dirtyArea = mainTile.getDirtyArea().cloneRegion();83mainTile.translate(-dirtyArea.x, -dirtyArea.y);8485XRColor maskColor = xrMgr.getMaskColor();8687// We don't need tiling if all geometry fits in a single tile88if (dirtyArea.getWidth() <= MASK_SIZE &&89dirtyArea.getHeight() <= MASK_SIZE)90{91compositeSingleTile(dst, mainTile, dirtyArea,92maskRequired, 0, 0, maskColor);93} else {94allocTiles(dirtyArea);95tileRects();9697for (int i = 0; i < yTiles; i++) {98for (int m = 0; m < xTiles; m++) {99MaskTile tile = tileList.get(i * xTiles + m);100101int tileStartX = m * MASK_SIZE;102int tileStartY = i * MASK_SIZE;103compositeSingleTile(dst, tile, dirtyArea, maskRequired,104tileStartX, tileStartY, maskColor);105}106}107}108} else {109/*110* If a mask would be required to store geometry (maskRequired)111* composition has to be done rectangle-by-rectagle.112*/113if(xrMgr.isSolidPaintActive()) {114xrMgr.XRRenderRectangles(dst, mainTile.getRects());115} else {116xrMgr.XRCompositeRectangles(dst, mainTile.getRects());117}118}119120mainTile.reset();121}122123/**124* Uploads aa geometry generated for maskblit/fill into the mask pixmap.125*/126public int uploadMask(int w, int h, int maskscan, int maskoff, byte[] mask) {127int maskPic = XRUtils.None;128129if (mask != null) {130float maskAlpha =131xrMgr.isTexturePaintActive() ? xrMgr.getExtraAlpha() : 1.0f;132con.putMaskImage(maskPixmap, maskGC, mask, 0, 0, 0, 0,133w, h, maskoff, maskscan, maskAlpha);134maskPic = maskPicture;135} else if (xrMgr.isTexturePaintActive()) {136maskPic = xrMgr.getExtraAlphaMask();137}138139return maskPic;140}141142/**143* Clears the area of the mask-pixmap used for uploading aa coverage values.144*/145public void clearUploadMask(int mask, int w, int h) {146if (mask == maskPicture) {147con.renderRectangle(maskPicture, XRUtils.PictOpClear,148XRColor.NO_ALPHA, 0, 0, w, h);149}150}151152153/**154* Renders the rectangles provided to the mask, and does a composition155* operation with the properties set inXRCompositeManager.156*/157protected void compositeSingleTile(XRSurfaceData dst, MaskTile tile,158DirtyRegion dirtyArea,159boolean maskRequired,160int tileStartX, int tileStartY,161XRColor maskColor) {162if (tile.rects.getSize() > 0) {163DirtyRegion tileDirtyArea = tile.getDirtyArea();164165int x = tileDirtyArea.x + tileStartX + dirtyArea.x;166int y = tileDirtyArea.y + tileStartY + dirtyArea.y;167int width = tileDirtyArea.x2 - tileDirtyArea.x;168int height = tileDirtyArea.y2 - tileDirtyArea.y;169width = Math.min(width, MASK_SIZE);170height = Math.min(height, MASK_SIZE);171172int rectCnt = tile.rects.getSize();173174if (maskRequired) {175int mask = XRUtils.None;176177/*178* Optimization: When the tile only contains one rectangle, the179* composite-operation boundaries can be used as geometry180*/181if (rectCnt > 1) {182con.renderRectangles(maskPicture, XRUtils.PictOpSrc,183maskColor, tile.rects);184mask = maskPicture;185} else {186if (xrMgr.isTexturePaintActive()) {187mask = xrMgr.getExtraAlphaMask();188}189}190191xrMgr.XRComposite(XRUtils.None, mask, dst.getPicture(),192x, y, tileDirtyArea.x, tileDirtyArea.y,193x, y, width, height);194195/* Clear dirty rectangle of the rect-mask */196if (rectCnt > 1) {197con.renderRectangle(maskPicture, XRUtils.PictOpClear,198XRColor.NO_ALPHA,199tileDirtyArea.x, tileDirtyArea.y,200width, height);201}202203tile.reset();204} else if (rectCnt > 0) {205tile.rects.translateRects(tileStartX + dirtyArea.x,206tileStartY + dirtyArea.y);207xrMgr.XRRenderRectangles(dst, tile.rects);208}209}210}211212213/**214* Allocates enough MaskTile instances, to cover the whole215* mask area, or resets existing ones.216*/217protected void allocTiles(DirtyRegion maskArea) {218xTiles = (maskArea.getWidth() / MASK_SIZE) + 1;219yTiles = (maskArea.getHeight() / MASK_SIZE) + 1;220int tileCnt = xTiles * yTiles;221222if (tileCnt > allocatedTiles) {223for (int i = 0; i < tileCnt; i++) {224if (i < allocatedTiles) {225tileList.get(i).reset();226} else {227tileList.add(new MaskTile());228}229}230231allocatedTiles = tileCnt;232}233}234235/**236* Tiles the stored rectangles, if they are larger than the MASK_SIZE237*/238protected void tileRects() {239GrowableRectArray rects = mainTile.rects;240241for (int i = 0; i < rects.getSize(); i++) {242int tileXStartIndex = rects.getX(i) / MASK_SIZE;243int tileYStartIndex = rects.getY(i) / MASK_SIZE;244int tileXLength =245((rects.getX(i) + rects.getWidth(i)) / MASK_SIZE + 1) -246tileXStartIndex;247int tileYLength =248((rects.getY(i) + rects.getHeight(i)) / MASK_SIZE + 1) -249tileYStartIndex;250251for (int n = 0; n < tileYLength; n++) {252for (int m = 0; m < tileXLength; m++) {253254int tileIndex =255xTiles * (tileYStartIndex + n) + tileXStartIndex + m;256MaskTile tile = tileList.get(tileIndex);257258GrowableRectArray rectTileList = tile.getRects();259int tileArrayIndex = rectTileList.getNextIndex();260261int tileStartPosX = (tileXStartIndex + m) * MASK_SIZE;262int tileStartPosY = (tileYStartIndex + n) * MASK_SIZE;263264rectTileList.setX(tileArrayIndex, rects.getX(i) - tileStartPosX);265rectTileList.setY(tileArrayIndex, rects.getY(i) - tileStartPosY);266rectTileList.setWidth(tileArrayIndex, rects.getWidth(i));267rectTileList.setHeight(tileArrayIndex, rects.getHeight(i));268269limitRectCoords(rectTileList, tileArrayIndex);270271tile.getDirtyArea().growDirtyRegion272(rectTileList.getX(tileArrayIndex),273rectTileList.getY(tileArrayIndex),274rectTileList.getWidth(tileArrayIndex) +275rectTileList.getX(tileArrayIndex),276rectTileList.getHeight(tileArrayIndex) +277rectTileList.getY(tileArrayIndex));278}279}280}281}282283/**284* Limits the rect's coordinates to the mask coordinates. The result is used285* by growDirtyRegion.286*/287private void limitRectCoords(GrowableRectArray rects, int index) {288if ((rects.getX(index) + rects.getWidth(index)) > MASK_SIZE) {289rects.setWidth(index, MASK_SIZE - rects.getX(index));290}291if ((rects.getY(index) + rects.getHeight(index)) > MASK_SIZE) {292rects.setHeight(index, MASK_SIZE - rects.getY(index));293}294if (rects.getX(index) < 0) {295rects.setWidth(index, rects.getWidth(index) + rects.getX(index));296rects.setX(index, 0);297}298if (rects.getY(index) < 0) {299rects.setHeight(index, rects.getHeight(index) + rects.getY(index));300rects.setY(index, 0);301}302}303304/**305* @return MainTile to which rectangles are added before composition.306*/307public MaskTile getMainTile() {308return mainTile;309}310}311312313