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 }
|