Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/classes/sun/java2d/xr/MaskTileManager.java
32288 views
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
/*
179
* Optimization: When the tile only contains one rectangle, the
180
* composite-operation boundaries can be used as geometry
181
*/
182
if (rectCnt > 1) {
183
con.renderRectangles(maskPicture, XRUtils.PictOpSrc,
184
maskColor, tile.rects);
185
mask = maskPicture;
186
} else {
187
if (xrMgr.isTexturePaintActive()) {
188
mask = xrMgr.getExtraAlphaMask();
189
}
190
}
191
192
xrMgr.XRComposite(XRUtils.None, mask, dst.getPicture(),
193
x, y, tileDirtyArea.x, tileDirtyArea.y,
194
x, y, width, height);
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) +
278
rectTileList.getY(tileArrayIndex));
279
}
280
}
281
}
282
}
283
284
/**
285
* Limits the rect's coordinates to the mask coordinates. The result is used
286
* by growDirtyRegion.
287
*/
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
}
312
313