author | lbourges |
Wed, 17 May 2017 22:05:11 +0200 | |
changeset 47126 | 188ef162f019 |
parent 40421 | d5ee65e2b0fb |
permissions | -rw-r--r-- |
34417 | 1 |
/* |
47126 | 2 |
* Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. |
34417 | 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.marlin; |
|
27 |
||
28 |
import jdk.internal.misc.Unsafe; |
|
29 |
||
30 |
/** |
|
31 |
* An object used to cache pre-rendered complex paths. |
|
32 |
* |
|
33 |
* @see Renderer |
|
34 |
*/ |
|
35 |
public final class MarlinCache implements MarlinConst { |
|
36 |
||
37 |
static final boolean FORCE_RLE = MarlinProperties.isForceRLE(); |
|
38 |
static final boolean FORCE_NO_RLE = MarlinProperties.isForceNoRLE(); |
|
39 |
// minimum width to try using RLE encoding: |
|
40 |
static final int RLE_MIN_WIDTH |
|
41 |
= Math.max(BLOCK_SIZE, MarlinProperties.getRLEMinWidth()); |
|
42 |
// maximum width for RLE encoding: |
|
43 |
// values are stored as int [x|alpha] where alpha is 8 bits |
|
44 |
static final int RLE_MAX_WIDTH = 1 << (24 - 1); |
|
45 |
||
46 |
// 2048 (pixelSize) alpha values (width) x 32 rows (tile) = 64K bytes |
|
47 |
// x1 instead of 4 bytes (RLE) ie 1/4 capacity or average good RLE compression |
|
47126 | 48 |
static final long INITIAL_CHUNK_ARRAY = TILE_H * INITIAL_PIXEL_DIM; // 64K |
34417 | 49 |
|
50 |
// The alpha map used by this object (taken out of our map cache) to convert |
|
51 |
// pixel coverage counts gotten from MarlinCache (which are in the range |
|
52 |
// [0, maxalpha]) into alpha values, which are in [0,256). |
|
53 |
static final byte[] ALPHA_MAP; |
|
54 |
||
55 |
static final OffHeapArray ALPHA_MAP_UNSAFE; |
|
56 |
||
57 |
static { |
|
58 |
final byte[] _ALPHA_MAP = buildAlphaMap(MAX_AA_ALPHA); |
|
59 |
||
60 |
ALPHA_MAP_UNSAFE = new OffHeapArray(_ALPHA_MAP, _ALPHA_MAP.length); // 1K |
|
61 |
ALPHA_MAP =_ALPHA_MAP; |
|
62 |
||
39519
21bfc4452441
8159093: Fix coding conventions in Marlin renderer
lbourges
parents:
36458
diff
changeset
|
63 |
final Unsafe _unsafe = OffHeapArray.UNSAFE; |
34417 | 64 |
final long addr = ALPHA_MAP_UNSAFE.address; |
65 |
||
66 |
for (int i = 0; i < _ALPHA_MAP.length; i++) { |
|
67 |
_unsafe.putByte(addr + i, _ALPHA_MAP[i]); |
|
68 |
} |
|
69 |
} |
|
70 |
||
71 |
int bboxX0, bboxY0, bboxX1, bboxY1; |
|
72 |
||
73 |
// 1D dirty arrays |
|
74 |
// row index in rowAAChunk[] |
|
47126 | 75 |
final long[] rowAAChunkIndex = new long[TILE_H]; |
34417 | 76 |
// first pixel (inclusive) for each row |
47126 | 77 |
final int[] rowAAx0 = new int[TILE_H]; |
34417 | 78 |
// last pixel (exclusive) for each row |
47126 | 79 |
final int[] rowAAx1 = new int[TILE_H]; |
34417 | 80 |
// encoding mode (0=raw, 1=RLE encoding) for each row |
47126 | 81 |
final int[] rowAAEnc = new int[TILE_H]; |
34417 | 82 |
// coded length (RLE encoding) for each row |
47126 | 83 |
final long[] rowAALen = new long[TILE_H]; |
34417 | 84 |
// last position in RLE decoding for each row (getAlpha): |
47126 | 85 |
final long[] rowAAPos = new long[TILE_H]; |
34417 | 86 |
|
87 |
// dirty off-heap array containing pixel coverages for (32) rows (packed) |
|
88 |
// if encoding=raw, it contains alpha coverage values (val) as integer |
|
89 |
// if encoding=RLE, it contains tuples (val, last x-coordinate exclusive) |
|
90 |
// use rowAAx0/rowAAx1 to get row indices within this chunk |
|
91 |
final OffHeapArray rowAAChunk; |
|
92 |
||
93 |
// current position in rowAAChunk array |
|
94 |
long rowAAChunkPos; |
|
95 |
||
96 |
// touchedTile[i] is the sum of all the alphas in the tile with |
|
97 |
// x=j*TILE_SIZE+bboxX0. |
|
98 |
int[] touchedTile; |
|
99 |
||
47126 | 100 |
// per-thread renderer stats |
101 |
final RendererStats rdrStats; |
|
34417 | 102 |
|
40421
d5ee65e2b0fb
8159638: Improve array caches and renderer stats in Marlin renderer
lbourges
parents:
39519
diff
changeset
|
103 |
// touchedTile ref (clean) |
d5ee65e2b0fb
8159638: Improve array caches and renderer stats in Marlin renderer
lbourges
parents:
39519
diff
changeset
|
104 |
private final IntArrayCache.Reference touchedTile_ref; |
34417 | 105 |
|
106 |
int tileMin, tileMax; |
|
107 |
||
108 |
boolean useRLE = false; |
|
109 |
||
47126 | 110 |
MarlinCache(final IRendererContext rdrCtx) { |
111 |
this.rdrStats = rdrCtx.stats(); |
|
34417 | 112 |
|
40421
d5ee65e2b0fb
8159638: Improve array caches and renderer stats in Marlin renderer
lbourges
parents:
39519
diff
changeset
|
113 |
rowAAChunk = rdrCtx.newOffHeapArray(INITIAL_CHUNK_ARRAY); // 64K |
34417 | 114 |
|
40421
d5ee65e2b0fb
8159638: Improve array caches and renderer stats in Marlin renderer
lbourges
parents:
39519
diff
changeset
|
115 |
touchedTile_ref = rdrCtx.newCleanIntArrayRef(INITIAL_ARRAY); // 1K = 1 tile line |
d5ee65e2b0fb
8159638: Improve array caches and renderer stats in Marlin renderer
lbourges
parents:
39519
diff
changeset
|
116 |
touchedTile = touchedTile_ref.initial; |
34417 | 117 |
|
118 |
// tile used marks: |
|
119 |
tileMin = Integer.MAX_VALUE; |
|
120 |
tileMax = Integer.MIN_VALUE; |
|
121 |
} |
|
122 |
||
47126 | 123 |
void init(int minx, int miny, int maxx, int maxy) |
34417 | 124 |
{ |
125 |
// assert maxy >= miny && maxx >= minx; |
|
126 |
bboxX0 = minx; |
|
127 |
bboxY0 = miny; |
|
128 |
bboxX1 = maxx; |
|
129 |
bboxY1 = maxy; |
|
130 |
||
131 |
final int width = (maxx - minx); |
|
132 |
||
133 |
if (FORCE_NO_RLE) { |
|
134 |
useRLE = false; |
|
135 |
} else if (FORCE_RLE) { |
|
136 |
useRLE = true; |
|
137 |
} else { |
|
138 |
// heuristics: use both bbox area and complexity |
|
139 |
// ie number of primitives: |
|
140 |
||
141 |
// fast check min and max width (maxx < 23bits): |
|
142 |
if (width <= RLE_MIN_WIDTH || width >= RLE_MAX_WIDTH) { |
|
143 |
useRLE = false; |
|
144 |
} else { |
|
47126 | 145 |
useRLE = true; |
34417 | 146 |
} |
147 |
} |
|
148 |
||
149 |
// the ceiling of (maxy - miny + 1) / TILE_SIZE; |
|
47126 | 150 |
final int nxTiles = (width + TILE_W) >> TILE_W_LG; |
34417 | 151 |
|
152 |
if (nxTiles > INITIAL_ARRAY) { |
|
39519
21bfc4452441
8159093: Fix coding conventions in Marlin renderer
lbourges
parents:
36458
diff
changeset
|
153 |
if (DO_STATS) { |
47126 | 154 |
rdrStats.stat_array_marlincache_touchedTile.add(nxTiles); |
34417 | 155 |
} |
40421
d5ee65e2b0fb
8159638: Improve array caches and renderer stats in Marlin renderer
lbourges
parents:
39519
diff
changeset
|
156 |
touchedTile = touchedTile_ref.getArray(nxTiles); |
34417 | 157 |
} |
158 |
} |
|
159 |
||
160 |
/** |
|
161 |
* Disposes this cache: |
|
162 |
* clean up before reusing this instance |
|
163 |
*/ |
|
164 |
void dispose() { |
|
165 |
// Reset touchedTile if needed: |
|
166 |
resetTileLine(0); |
|
167 |
||
40421
d5ee65e2b0fb
8159638: Improve array caches and renderer stats in Marlin renderer
lbourges
parents:
39519
diff
changeset
|
168 |
if (DO_STATS) { |
47126 | 169 |
rdrStats.totalOffHeap += rowAAChunk.length; |
40421
d5ee65e2b0fb
8159638: Improve array caches and renderer stats in Marlin renderer
lbourges
parents:
39519
diff
changeset
|
170 |
} |
d5ee65e2b0fb
8159638: Improve array caches and renderer stats in Marlin renderer
lbourges
parents:
39519
diff
changeset
|
171 |
|
34417 | 172 |
// Return arrays: |
40421
d5ee65e2b0fb
8159638: Improve array caches and renderer stats in Marlin renderer
lbourges
parents:
39519
diff
changeset
|
173 |
touchedTile = touchedTile_ref.putArray(touchedTile, 0, 0); // already zero filled |
d5ee65e2b0fb
8159638: Improve array caches and renderer stats in Marlin renderer
lbourges
parents:
39519
diff
changeset
|
174 |
|
34417 | 175 |
// At last: resize back off-heap rowAA to initial size |
176 |
if (rowAAChunk.length != INITIAL_CHUNK_ARRAY) { |
|
177 |
// note: may throw OOME: |
|
178 |
rowAAChunk.resize(INITIAL_CHUNK_ARRAY); |
|
179 |
} |
|
39519
21bfc4452441
8159093: Fix coding conventions in Marlin renderer
lbourges
parents:
36458
diff
changeset
|
180 |
if (DO_CLEAN_DIRTY) { |
34417 | 181 |
// Force zero-fill dirty arrays: |
182 |
rowAAChunk.fill(BYTE_0); |
|
183 |
} |
|
184 |
} |
|
185 |
||
186 |
void resetTileLine(final int pminY) { |
|
187 |
// update bboxY0 to process a complete tile line [0 - 32] |
|
188 |
bboxY0 = pminY; |
|
189 |
||
190 |
// reset current pos |
|
39519
21bfc4452441
8159093: Fix coding conventions in Marlin renderer
lbourges
parents:
36458
diff
changeset
|
191 |
if (DO_STATS) { |
47126 | 192 |
rdrStats.stat_cache_rowAAChunk.add(rowAAChunkPos); |
34417 | 193 |
} |
194 |
rowAAChunkPos = 0L; |
|
195 |
||
196 |
// Reset touchedTile: |
|
197 |
if (tileMin != Integer.MAX_VALUE) { |
|
39519
21bfc4452441
8159093: Fix coding conventions in Marlin renderer
lbourges
parents:
36458
diff
changeset
|
198 |
if (DO_STATS) { |
47126 | 199 |
rdrStats.stat_cache_tiles.add(tileMax - tileMin); |
34417 | 200 |
} |
201 |
// clean only dirty touchedTile: |
|
202 |
if (tileMax == 1) { |
|
203 |
touchedTile[0] = 0; |
|
204 |
} else { |
|
205 |
IntArrayCache.fill(touchedTile, tileMin, tileMax, 0); |
|
206 |
} |
|
207 |
// reset tile used marks: |
|
208 |
tileMin = Integer.MAX_VALUE; |
|
209 |
tileMax = Integer.MIN_VALUE; |
|
210 |
} |
|
211 |
||
39519
21bfc4452441
8159093: Fix coding conventions in Marlin renderer
lbourges
parents:
36458
diff
changeset
|
212 |
if (DO_CLEAN_DIRTY) { |
34417 | 213 |
// Force zero-fill dirty arrays: |
214 |
rowAAChunk.fill(BYTE_0); |
|
215 |
} |
|
216 |
} |
|
217 |
||
218 |
void clearAARow(final int y) { |
|
219 |
// process tile line [0 - 32] |
|
220 |
final int row = y - bboxY0; |
|
221 |
||
222 |
// update pixel range: |
|
223 |
rowAAx0[row] = 0; // first pixel inclusive |
|
224 |
rowAAx1[row] = 0; // last pixel exclusive |
|
225 |
rowAAEnc[row] = 0; // raw encoding |
|
226 |
||
227 |
// note: leave rowAAChunkIndex[row] undefined |
|
228 |
// and rowAALen[row] & rowAAPos[row] (RLE) |
|
229 |
} |
|
230 |
||
231 |
/** |
|
232 |
* Copy the given alpha data into the rowAA cache |
|
233 |
* @param alphaRow alpha data to copy from |
|
234 |
* @param y y pixel coordinate |
|
235 |
* @param px0 first pixel inclusive x0 |
|
236 |
* @param px1 last pixel exclusive x1 |
|
237 |
*/ |
|
238 |
void copyAARowNoRLE(final int[] alphaRow, final int y, |
|
239 |
final int px0, final int px1) |
|
240 |
{ |
|
241 |
// skip useless pixels above boundary |
|
242 |
final int px_bbox1 = FloatMath.min(px1, bboxX1); |
|
243 |
||
39519
21bfc4452441
8159093: Fix coding conventions in Marlin renderer
lbourges
parents:
36458
diff
changeset
|
244 |
if (DO_LOG_BOUNDS) { |
34417 | 245 |
MarlinUtils.logInfo("row = [" + px0 + " ... " + px_bbox1 |
246 |
+ " (" + px1 + ") [ for y=" + y); |
|
247 |
} |
|
248 |
||
249 |
final int row = y - bboxY0; |
|
250 |
||
251 |
// update pixel range: |
|
252 |
rowAAx0[row] = px0; // first pixel inclusive |
|
253 |
rowAAx1[row] = px_bbox1; // last pixel exclusive |
|
254 |
rowAAEnc[row] = 0; // raw encoding |
|
255 |
||
256 |
// get current position (bytes): |
|
257 |
final long pos = rowAAChunkPos; |
|
258 |
// update row index to current position: |
|
259 |
rowAAChunkIndex[row] = pos; |
|
260 |
||
34689
4b5bf9f960c8
8145055: Marlin renderer causes unaligned write accesses
lbourges
parents:
34417
diff
changeset
|
261 |
// determine need array size: |
4b5bf9f960c8
8145055: Marlin renderer causes unaligned write accesses
lbourges
parents:
34417
diff
changeset
|
262 |
// for RLE encoding, position must be aligned to 4 bytes (int): |
4b5bf9f960c8
8145055: Marlin renderer causes unaligned write accesses
lbourges
parents:
34417
diff
changeset
|
263 |
// align - 1 = 3 so add +3 and round-off by mask ~3 = -4 |
4b5bf9f960c8
8145055: Marlin renderer causes unaligned write accesses
lbourges
parents:
34417
diff
changeset
|
264 |
final long needSize = pos + ((px_bbox1 - px0 + 3) & -4); |
34417 | 265 |
|
266 |
// update next position (bytes): |
|
267 |
rowAAChunkPos = needSize; |
|
268 |
||
269 |
// update row data: |
|
270 |
final OffHeapArray _rowAAChunk = rowAAChunk; |
|
271 |
// ensure rowAAChunk capacity: |
|
272 |
if (_rowAAChunk.length < needSize) { |
|
273 |
expandRowAAChunk(needSize); |
|
274 |
} |
|
39519
21bfc4452441
8159093: Fix coding conventions in Marlin renderer
lbourges
parents:
36458
diff
changeset
|
275 |
if (DO_STATS) { |
47126 | 276 |
rdrStats.stat_cache_rowAA.add(px_bbox1 - px0); |
34417 | 277 |
} |
278 |
||
279 |
// rowAA contains only alpha values for range[x0; x1[ |
|
280 |
final int[] _touchedTile = touchedTile; |
|
47126 | 281 |
final int _TILE_SIZE_LG = TILE_W_LG; |
34417 | 282 |
|
283 |
final int from = px0 - bboxX0; // first pixel inclusive |
|
284 |
final int to = px_bbox1 - bboxX0; // last pixel exclusive |
|
285 |
||
39519
21bfc4452441
8159093: Fix coding conventions in Marlin renderer
lbourges
parents:
36458
diff
changeset
|
286 |
final Unsafe _unsafe = OffHeapArray.UNSAFE; |
34417 | 287 |
final long SIZE_BYTE = 1L; |
288 |
final long addr_alpha = ALPHA_MAP_UNSAFE.address; |
|
289 |
long addr_off = _rowAAChunk.address + pos; |
|
290 |
||
291 |
// compute alpha sum into rowAA: |
|
292 |
for (int x = from, val = 0; x < to; x++) { |
|
293 |
// alphaRow is in [0; MAX_COVERAGE] |
|
294 |
val += alphaRow[x]; // [from; to[ |
|
295 |
||
296 |
// ensure values are in [0; MAX_AA_ALPHA] range |
|
297 |
if (DO_AA_RANGE_CHECK) { |
|
298 |
if (val < 0) { |
|
299 |
System.out.println("Invalid coverage = " + val); |
|
300 |
val = 0; |
|
301 |
} |
|
302 |
if (val > MAX_AA_ALPHA) { |
|
303 |
System.out.println("Invalid coverage = " + val); |
|
304 |
val = MAX_AA_ALPHA; |
|
305 |
} |
|
306 |
} |
|
307 |
||
308 |
// store alpha sum (as byte): |
|
309 |
if (val == 0) { |
|
47126 | 310 |
_unsafe.putByte(addr_off, (byte)0); // [0-255] |
34417 | 311 |
} else { |
47126 | 312 |
_unsafe.putByte(addr_off, _unsafe.getByte(addr_alpha + val)); // [0-255] |
34417 | 313 |
|
314 |
// update touchedTile |
|
315 |
_touchedTile[x >> _TILE_SIZE_LG] += val; |
|
316 |
} |
|
317 |
addr_off += SIZE_BYTE; |
|
318 |
} |
|
319 |
||
320 |
// update tile used marks: |
|
321 |
int tx = from >> _TILE_SIZE_LG; // inclusive |
|
322 |
if (tx < tileMin) { |
|
323 |
tileMin = tx; |
|
324 |
} |
|
325 |
||
326 |
tx = ((to - 1) >> _TILE_SIZE_LG) + 1; // exclusive (+1 to be sure) |
|
327 |
if (tx > tileMax) { |
|
328 |
tileMax = tx; |
|
329 |
} |
|
330 |
||
39519
21bfc4452441
8159093: Fix coding conventions in Marlin renderer
lbourges
parents:
36458
diff
changeset
|
331 |
if (DO_LOG_BOUNDS) { |
34417 | 332 |
MarlinUtils.logInfo("clear = [" + from + " ... " + to + "["); |
333 |
} |
|
334 |
||
335 |
// Clear alpha row for reuse: |
|
47126 | 336 |
IntArrayCache.fill(alphaRow, from, px1 + 1 - bboxX0, 0); |
34417 | 337 |
} |
338 |
||
339 |
void copyAARowRLE_WithBlockFlags(final int[] blkFlags, final int[] alphaRow, |
|
340 |
final int y, final int px0, final int px1) |
|
341 |
{ |
|
342 |
// Copy rowAA data into the piscesCache if one is present |
|
343 |
final int _bboxX0 = bboxX0; |
|
344 |
||
345 |
// process tile line [0 - 32] |
|
47126 | 346 |
final int row = y - bboxY0; |
34417 | 347 |
final int from = px0 - _bboxX0; // first pixel inclusive |
348 |
||
349 |
// skip useless pixels above boundary |
|
350 |
final int px_bbox1 = FloatMath.min(px1, bboxX1); |
|
351 |
final int to = px_bbox1 - _bboxX0; // last pixel exclusive |
|
352 |
||
39519
21bfc4452441
8159093: Fix coding conventions in Marlin renderer
lbourges
parents:
36458
diff
changeset
|
353 |
if (DO_LOG_BOUNDS) { |
34417 | 354 |
MarlinUtils.logInfo("row = [" + px0 + " ... " + px_bbox1 |
355 |
+ " (" + px1 + ") [ for y=" + y); |
|
356 |
} |
|
357 |
||
358 |
// get current position: |
|
359 |
final long initialPos = startRLERow(row, px0, px_bbox1); |
|
360 |
||
361 |
// determine need array size: |
|
362 |
// pessimistic: max needed size = deltaX x 4 (1 int) |
|
34689
4b5bf9f960c8
8145055: Marlin renderer causes unaligned write accesses
lbourges
parents:
34417
diff
changeset
|
363 |
final long needSize = initialPos + ((to - from) << 2); |
34417 | 364 |
|
365 |
// update row data: |
|
366 |
OffHeapArray _rowAAChunk = rowAAChunk; |
|
367 |
// ensure rowAAChunk capacity: |
|
368 |
if (_rowAAChunk.length < needSize) { |
|
369 |
expandRowAAChunk(needSize); |
|
370 |
} |
|
371 |
||
39519
21bfc4452441
8159093: Fix coding conventions in Marlin renderer
lbourges
parents:
36458
diff
changeset
|
372 |
final Unsafe _unsafe = OffHeapArray.UNSAFE; |
34417 | 373 |
final long SIZE_INT = 4L; |
374 |
final long addr_alpha = ALPHA_MAP_UNSAFE.address; |
|
375 |
long addr_off = _rowAAChunk.address + initialPos; |
|
376 |
||
377 |
final int[] _touchedTile = touchedTile; |
|
47126 | 378 |
final int _TILE_SIZE_LG = TILE_W_LG; |
34417 | 379 |
final int _BLK_SIZE_LG = BLOCK_SIZE_LG; |
380 |
||
381 |
// traverse flagged blocks: |
|
382 |
final int blkW = (from >> _BLK_SIZE_LG); |
|
383 |
final int blkE = (to >> _BLK_SIZE_LG) + 1; |
|
47126 | 384 |
// ensure last block flag = 0 to process final block: |
385 |
blkFlags[blkE] = 0; |
|
34417 | 386 |
|
387 |
// Perform run-length encoding and store results in the piscesCache |
|
388 |
int val = 0; |
|
389 |
int cx0 = from; |
|
390 |
int runLen; |
|
391 |
||
392 |
final int _MAX_VALUE = Integer.MAX_VALUE; |
|
393 |
int last_t0 = _MAX_VALUE; |
|
394 |
||
395 |
int skip = 0; |
|
396 |
||
397 |
for (int t = blkW, blk_x0, blk_x1, cx, delta; t <= blkE; t++) { |
|
398 |
if (blkFlags[t] != 0) { |
|
399 |
blkFlags[t] = 0; |
|
400 |
||
401 |
if (last_t0 == _MAX_VALUE) { |
|
402 |
last_t0 = t; |
|
403 |
} |
|
404 |
continue; |
|
405 |
} |
|
406 |
if (last_t0 != _MAX_VALUE) { |
|
407 |
// emit blocks: |
|
408 |
blk_x0 = FloatMath.max(last_t0 << _BLK_SIZE_LG, from); |
|
409 |
last_t0 = _MAX_VALUE; |
|
410 |
||
411 |
// (last block pixel+1) inclusive => +1 |
|
412 |
blk_x1 = FloatMath.min((t << _BLK_SIZE_LG) + 1, to); |
|
413 |
||
414 |
for (cx = blk_x0; cx < blk_x1; cx++) { |
|
415 |
if ((delta = alphaRow[cx]) != 0) { |
|
416 |
alphaRow[cx] = 0; |
|
417 |
||
418 |
// not first rle entry: |
|
419 |
if (cx != cx0) { |
|
420 |
runLen = cx - cx0; |
|
421 |
||
422 |
// store alpha coverage (ensure within bounds): |
|
423 |
// as [absX|val] where: |
|
424 |
// absX is the absolute x-coordinate: |
|
425 |
// note: last pixel exclusive (>= 0) |
|
426 |
// note: it should check X is smaller than 23bits (overflow)! |
|
427 |
||
34689
4b5bf9f960c8
8145055: Marlin renderer causes unaligned write accesses
lbourges
parents:
34417
diff
changeset
|
428 |
// check address alignment to 4 bytes: |
39519
21bfc4452441
8159093: Fix coding conventions in Marlin renderer
lbourges
parents:
36458
diff
changeset
|
429 |
if (DO_CHECK_UNSAFE) { |
34689
4b5bf9f960c8
8145055: Marlin renderer causes unaligned write accesses
lbourges
parents:
34417
diff
changeset
|
430 |
if ((addr_off & 3) != 0) { |
4b5bf9f960c8
8145055: Marlin renderer causes unaligned write accesses
lbourges
parents:
34417
diff
changeset
|
431 |
MarlinUtils.logInfo("Misaligned Unsafe address: " + addr_off); |
4b5bf9f960c8
8145055: Marlin renderer causes unaligned write accesses
lbourges
parents:
34417
diff
changeset
|
432 |
} |
4b5bf9f960c8
8145055: Marlin renderer causes unaligned write accesses
lbourges
parents:
34417
diff
changeset
|
433 |
} |
4b5bf9f960c8
8145055: Marlin renderer causes unaligned write accesses
lbourges
parents:
34417
diff
changeset
|
434 |
|
34417 | 435 |
// special case to encode entries into a single int: |
436 |
if (val == 0) { |
|
437 |
_unsafe.putInt(addr_off, |
|
438 |
((_bboxX0 + cx) << 8) |
|
439 |
); |
|
440 |
} else { |
|
441 |
_unsafe.putInt(addr_off, |
|
442 |
((_bboxX0 + cx) << 8) |
|
47126 | 443 |
| (((int) _unsafe.getByte(addr_alpha + val)) & 0xFF) // [0-255] |
34417 | 444 |
); |
445 |
||
446 |
if (runLen == 1) { |
|
447 |
_touchedTile[cx0 >> _TILE_SIZE_LG] += val; |
|
448 |
} else { |
|
449 |
touchTile(cx0, val, cx, runLen, _touchedTile); |
|
450 |
} |
|
451 |
} |
|
452 |
addr_off += SIZE_INT; |
|
453 |
||
39519
21bfc4452441
8159093: Fix coding conventions in Marlin renderer
lbourges
parents:
36458
diff
changeset
|
454 |
if (DO_STATS) { |
47126 | 455 |
rdrStats.hist_tile_generator_encoding_runLen |
34417 | 456 |
.add(runLen); |
457 |
} |
|
458 |
cx0 = cx; |
|
459 |
} |
|
460 |
||
461 |
// alpha value = running sum of coverage delta: |
|
462 |
val += delta; |
|
463 |
||
464 |
// ensure values are in [0; MAX_AA_ALPHA] range |
|
465 |
if (DO_AA_RANGE_CHECK) { |
|
466 |
if (val < 0) { |
|
467 |
System.out.println("Invalid coverage = " + val); |
|
468 |
val = 0; |
|
469 |
} |
|
470 |
if (val > MAX_AA_ALPHA) { |
|
471 |
System.out.println("Invalid coverage = " + val); |
|
472 |
val = MAX_AA_ALPHA; |
|
473 |
} |
|
474 |
} |
|
475 |
} |
|
476 |
} |
|
39519
21bfc4452441
8159093: Fix coding conventions in Marlin renderer
lbourges
parents:
36458
diff
changeset
|
477 |
} else if (DO_STATS) { |
34417 | 478 |
skip++; |
479 |
} |
|
480 |
} |
|
481 |
||
482 |
// Process remaining RLE run: |
|
483 |
runLen = to - cx0; |
|
484 |
||
485 |
// store alpha coverage (ensure within bounds): |
|
486 |
// as (int)[absX|val] where: |
|
487 |
// absX is the absolute x-coordinate in bits 31 to 8 and val in bits 0..7 |
|
488 |
// note: last pixel exclusive (>= 0) |
|
489 |
// note: it should check X is smaller than 23bits (overflow)! |
|
490 |
||
34689
4b5bf9f960c8
8145055: Marlin renderer causes unaligned write accesses
lbourges
parents:
34417
diff
changeset
|
491 |
// check address alignment to 4 bytes: |
39519
21bfc4452441
8159093: Fix coding conventions in Marlin renderer
lbourges
parents:
36458
diff
changeset
|
492 |
if (DO_CHECK_UNSAFE) { |
34689
4b5bf9f960c8
8145055: Marlin renderer causes unaligned write accesses
lbourges
parents:
34417
diff
changeset
|
493 |
if ((addr_off & 3) != 0) { |
4b5bf9f960c8
8145055: Marlin renderer causes unaligned write accesses
lbourges
parents:
34417
diff
changeset
|
494 |
MarlinUtils.logInfo("Misaligned Unsafe address: " + addr_off); |
4b5bf9f960c8
8145055: Marlin renderer causes unaligned write accesses
lbourges
parents:
34417
diff
changeset
|
495 |
} |
4b5bf9f960c8
8145055: Marlin renderer causes unaligned write accesses
lbourges
parents:
34417
diff
changeset
|
496 |
} |
4b5bf9f960c8
8145055: Marlin renderer causes unaligned write accesses
lbourges
parents:
34417
diff
changeset
|
497 |
|
34417 | 498 |
// special case to encode entries into a single int: |
499 |
if (val == 0) { |
|
500 |
_unsafe.putInt(addr_off, |
|
501 |
((_bboxX0 + to) << 8) |
|
502 |
); |
|
503 |
} else { |
|
504 |
_unsafe.putInt(addr_off, |
|
505 |
((_bboxX0 + to) << 8) |
|
47126 | 506 |
| (((int) _unsafe.getByte(addr_alpha + val)) & 0xFF) // [0-255] |
34417 | 507 |
); |
508 |
||
509 |
if (runLen == 1) { |
|
510 |
_touchedTile[cx0 >> _TILE_SIZE_LG] += val; |
|
511 |
} else { |
|
512 |
touchTile(cx0, val, to, runLen, _touchedTile); |
|
513 |
} |
|
514 |
} |
|
515 |
addr_off += SIZE_INT; |
|
516 |
||
39519
21bfc4452441
8159093: Fix coding conventions in Marlin renderer
lbourges
parents:
36458
diff
changeset
|
517 |
if (DO_STATS) { |
47126 | 518 |
rdrStats.hist_tile_generator_encoding_runLen.add(runLen); |
34417 | 519 |
} |
520 |
||
521 |
long len = (addr_off - _rowAAChunk.address); |
|
522 |
||
523 |
// update coded length as bytes: |
|
524 |
rowAALen[row] = (len - initialPos); |
|
525 |
||
526 |
// update current position: |
|
527 |
rowAAChunkPos = len; |
|
528 |
||
39519
21bfc4452441
8159093: Fix coding conventions in Marlin renderer
lbourges
parents:
36458
diff
changeset
|
529 |
if (DO_STATS) { |
47126 | 530 |
rdrStats.stat_cache_rowAA.add(rowAALen[row]); |
531 |
rdrStats.hist_tile_generator_encoding_ratio.add( |
|
34417 | 532 |
(100 * skip) / (blkE - blkW) |
533 |
); |
|
534 |
} |
|
535 |
||
536 |
// update tile used marks: |
|
537 |
int tx = from >> _TILE_SIZE_LG; // inclusive |
|
538 |
if (tx < tileMin) { |
|
539 |
tileMin = tx; |
|
540 |
} |
|
541 |
||
542 |
tx = ((to - 1) >> _TILE_SIZE_LG) + 1; // exclusive (+1 to be sure) |
|
543 |
if (tx > tileMax) { |
|
544 |
tileMax = tx; |
|
545 |
} |
|
546 |
||
547 |
// Clear alpha row for reuse: |
|
47126 | 548 |
alphaRow[to] = 0; |
39519
21bfc4452441
8159093: Fix coding conventions in Marlin renderer
lbourges
parents:
36458
diff
changeset
|
549 |
if (DO_CHECKS) { |
36458
25786a73a5fc
8148886: SEGV in sun.java2d.marlin.Renderer._endRendering
lbourges
parents:
35688
diff
changeset
|
550 |
IntArrayCache.check(blkFlags, blkW, blkE, 0); |
47126 | 551 |
IntArrayCache.check(alphaRow, from, px1 + 1 - bboxX0, 0); |
34417 | 552 |
} |
553 |
} |
|
554 |
||
555 |
long startRLERow(final int row, final int x0, final int x1) { |
|
556 |
// rows are supposed to be added by increasing y. |
|
557 |
rowAAx0[row] = x0; // first pixel inclusive |
|
558 |
rowAAx1[row] = x1; // last pixel exclusive |
|
559 |
rowAAEnc[row] = 1; // RLE encoding |
|
560 |
rowAAPos[row] = 0L; // position = 0 |
|
561 |
||
562 |
// update row index to current position: |
|
563 |
return (rowAAChunkIndex[row] = rowAAChunkPos); |
|
564 |
} |
|
565 |
||
566 |
private void expandRowAAChunk(final long needSize) { |
|
39519
21bfc4452441
8159093: Fix coding conventions in Marlin renderer
lbourges
parents:
36458
diff
changeset
|
567 |
if (DO_STATS) { |
47126 | 568 |
rdrStats.stat_array_marlincache_rowAAChunk.add(needSize); |
34417 | 569 |
} |
570 |
||
571 |
// note: throw IOOB if neededSize > 2Gb: |
|
40421
d5ee65e2b0fb
8159638: Improve array caches and renderer stats in Marlin renderer
lbourges
parents:
39519
diff
changeset
|
572 |
final long newSize = ArrayCacheConst.getNewLargeSize(rowAAChunk.length, |
d5ee65e2b0fb
8159638: Improve array caches and renderer stats in Marlin renderer
lbourges
parents:
39519
diff
changeset
|
573 |
needSize); |
34417 | 574 |
|
575 |
rowAAChunk.resize(newSize); |
|
576 |
} |
|
577 |
||
578 |
private void touchTile(final int x0, final int val, final int x1, |
|
579 |
final int runLen, |
|
580 |
final int[] _touchedTile) |
|
581 |
{ |
|
582 |
// the x and y of the current row, minus bboxX0, bboxY0 |
|
583 |
// process tile line [0 - 32] |
|
47126 | 584 |
final int _TILE_SIZE_LG = TILE_W_LG; |
34417 | 585 |
|
586 |
// update touchedTile |
|
587 |
int tx = (x0 >> _TILE_SIZE_LG); |
|
588 |
||
589 |
// handle trivial case: same tile (x0, x0+runLen) |
|
590 |
if (tx == (x1 >> _TILE_SIZE_LG)) { |
|
591 |
// same tile: |
|
592 |
_touchedTile[tx] += val * runLen; |
|
593 |
return; |
|
594 |
} |
|
595 |
||
596 |
final int tx1 = (x1 - 1) >> _TILE_SIZE_LG; |
|
597 |
||
598 |
if (tx <= tx1) { |
|
599 |
final int nextTileXCoord = (tx + 1) << _TILE_SIZE_LG; |
|
600 |
_touchedTile[tx++] += val * (nextTileXCoord - x0); |
|
601 |
} |
|
602 |
if (tx < tx1) { |
|
603 |
// don't go all the way to tx1 - we need to handle the last |
|
604 |
// tile as a special case (just like we did with the first |
|
605 |
final int tileVal = (val << _TILE_SIZE_LG); |
|
606 |
for (; tx < tx1; tx++) { |
|
607 |
_touchedTile[tx] += tileVal; |
|
608 |
} |
|
609 |
} |
|
610 |
// they will be equal unless x0 >> TILE_SIZE_LG == tx1 |
|
611 |
if (tx == tx1) { |
|
612 |
final int txXCoord = tx << _TILE_SIZE_LG; |
|
613 |
final int nextTileXCoord = (tx + 1) << _TILE_SIZE_LG; |
|
614 |
||
615 |
final int lastXCoord = (nextTileXCoord <= x1) ? nextTileXCoord : x1; |
|
616 |
_touchedTile[tx] += val * (lastXCoord - txXCoord); |
|
617 |
} |
|
618 |
} |
|
619 |
||
620 |
int alphaSumInTile(final int x) { |
|
47126 | 621 |
return touchedTile[(x - bboxX0) >> TILE_W_LG]; |
34417 | 622 |
} |
623 |
||
624 |
@Override |
|
625 |
public String toString() { |
|
626 |
return "bbox = [" |
|
627 |
+ bboxX0 + ", " + bboxY0 + " => " |
|
628 |
+ bboxX1 + ", " + bboxY1 + "]\n"; |
|
629 |
} |
|
630 |
||
631 |
private static byte[] buildAlphaMap(final int maxalpha) { |
|
632 |
// double size ! |
|
633 |
final byte[] alMap = new byte[maxalpha << 1]; |
|
634 |
final int halfmaxalpha = maxalpha >> 2; |
|
635 |
for (int i = 0; i <= maxalpha; i++) { |
|
636 |
alMap[i] = (byte) ((i * 255 + halfmaxalpha) / maxalpha); |
|
637 |
// System.out.println("alphaMap[" + i + "] = " |
|
638 |
// + Byte.toUnsignedInt(alMap[i])); |
|
639 |
} |
|
640 |
return alMap; |
|
641 |
} |
|
642 |
} |