1 /*
2 * Copyright (c) 2007, 2017, 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
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
48 static final long INITIAL_CHUNK_ARRAY = TILE_H * INITIAL_PIXEL_DIM; // 64K
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
63 final Unsafe _unsafe = OffHeapArray.UNSAFE;
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 }
275 // rowAA contains only alpha values for range[x0; x1[
276 final int[] _touchedTile = touchedTile;
277 final int _TILE_SIZE_LG = TILE_W_LG;
278
279 final int from = px0 - bboxX0; // first pixel inclusive
280 final int to = px_bbox1 - bboxX0; // last pixel exclusive
281
282 final Unsafe _unsafe = OffHeapArray.UNSAFE;
283 final long SIZE_BYTE = 1L;
284 final long addr_alpha = ALPHA_MAP_UNSAFE.address;
285 long addr_off = _rowAAChunk.address + pos;
286
287 // compute alpha sum into rowAA:
288 for (int x = from, val = 0; x < to; x++) {
289 // alphaRow is in [0; MAX_COVERAGE]
290 val += alphaRow[x]; // [from; to[
291
292 // ensure values are in [0; MAX_AA_ALPHA] range
293 if (DO_AA_RANGE_CHECK) {
294 if (val < 0) {
295 System.out.println("Invalid coverage = " + val);
296 val = 0;
297 }
298 if (val > MAX_AA_ALPHA) {
299 System.out.println("Invalid coverage = " + val);
300 val = MAX_AA_ALPHA;
301 }
302 }
303
304 // store alpha sum (as byte):
305 if (val == 0) {
306 _unsafe.putByte(addr_off, (byte)0); // [0-255]
307 } else {
308 _unsafe.putByte(addr_off, _unsafe.getByte(addr_alpha + val)); // [0-255]
309
310 // update touchedTile
311 _touchedTile[x >> _TILE_SIZE_LG] += val;
312 }
313 addr_off += SIZE_BYTE;
314 }
315
316 // update tile used marks:
317 int tx = from >> _TILE_SIZE_LG; // inclusive
318 if (tx < tileMin) {
319 tileMin = tx;
443 _touchedTile[cx0 >> _TILE_SIZE_LG] += val;
444 } else {
445 touchTile(cx0, val, cx, runLen, _touchedTile);
446 }
447 }
448 addr_off += SIZE_INT;
449
450 if (DO_STATS) {
451 rdrStats.hist_tile_generator_encoding_runLen
452 .add(runLen);
453 }
454 cx0 = cx;
455 }
456
457 // alpha value = running sum of coverage delta:
458 val += delta;
459
460 // ensure values are in [0; MAX_AA_ALPHA] range
461 if (DO_AA_RANGE_CHECK) {
462 if (val < 0) {
463 System.out.println("Invalid coverage = " + val);
464 val = 0;
465 }
466 if (val > MAX_AA_ALPHA) {
467 System.out.println("Invalid coverage = " + val);
468 val = MAX_AA_ALPHA;
469 }
470 }
471 }
472 }
473 } else if (DO_STATS) {
474 skip++;
475 }
476 }
477
478 // Process remaining RLE run:
479 runLen = to - cx0;
480
481 // store alpha coverage (ensure within bounds):
482 // as (int)[absX|val] where:
483 // absX is the absolute x-coordinate in bits 31 to 8 and val in bits 0..7
484 // note: last pixel exclusive (>= 0)
485 // note: it should check X is smaller than 23bits (overflow)!
486
487 // check address alignment to 4 bytes:
613 }
614 }
615
616 int alphaSumInTile(final int x) {
617 return touchedTile[(x - bboxX0) >> TILE_W_LG];
618 }
619
620 @Override
621 public String toString() {
622 return "bbox = ["
623 + bboxX0 + ", " + bboxY0 + " => "
624 + bboxX1 + ", " + bboxY1 + "]\n";
625 }
626
627 private static byte[] buildAlphaMap(final int maxalpha) {
628 // double size !
629 final byte[] alMap = new byte[maxalpha << 1];
630 final int halfmaxalpha = maxalpha >> 2;
631 for (int i = 0; i <= maxalpha; i++) {
632 alMap[i] = (byte) ((i * 255 + halfmaxalpha) / maxalpha);
633 // System.out.println("alphaMap[" + i + "] = "
634 // + Byte.toUnsignedInt(alMap[i]));
635 }
636 return alMap;
637 }
638 }
|
1 /*
2 * Copyright (c) 2007, 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
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 // 4096 (pixels) alpha values (width) x 64 rows / 4 (tile) = 64K bytes
47 // x1 instead of 4 bytes (RLE) ie 1/4 capacity or average good RLE compression
48 static final long INITIAL_CHUNK_ARRAY = TILE_H * INITIAL_PIXEL_WIDTH >> 2; // 64K
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
63 final Unsafe _unsafe = OffHeapArray.UNSAFE;
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 }
275 // rowAA contains only alpha values for range[x0; x1[
276 final int[] _touchedTile = touchedTile;
277 final int _TILE_SIZE_LG = TILE_W_LG;
278
279 final int from = px0 - bboxX0; // first pixel inclusive
280 final int to = px_bbox1 - bboxX0; // last pixel exclusive
281
282 final Unsafe _unsafe = OffHeapArray.UNSAFE;
283 final long SIZE_BYTE = 1L;
284 final long addr_alpha = ALPHA_MAP_UNSAFE.address;
285 long addr_off = _rowAAChunk.address + pos;
286
287 // compute alpha sum into rowAA:
288 for (int x = from, val = 0; x < to; x++) {
289 // alphaRow is in [0; MAX_COVERAGE]
290 val += alphaRow[x]; // [from; to[
291
292 // ensure values are in [0; MAX_AA_ALPHA] range
293 if (DO_AA_RANGE_CHECK) {
294 if (val < 0) {
295 MarlinUtils.logInfo("Invalid coverage = " + val);
296 val = 0;
297 }
298 if (val > MAX_AA_ALPHA) {
299 MarlinUtils.logInfo("Invalid coverage = " + val);
300 val = MAX_AA_ALPHA;
301 }
302 }
303
304 // store alpha sum (as byte):
305 if (val == 0) {
306 _unsafe.putByte(addr_off, (byte)0); // [0-255]
307 } else {
308 _unsafe.putByte(addr_off, _unsafe.getByte(addr_alpha + val)); // [0-255]
309
310 // update touchedTile
311 _touchedTile[x >> _TILE_SIZE_LG] += val;
312 }
313 addr_off += SIZE_BYTE;
314 }
315
316 // update tile used marks:
317 int tx = from >> _TILE_SIZE_LG; // inclusive
318 if (tx < tileMin) {
319 tileMin = tx;
443 _touchedTile[cx0 >> _TILE_SIZE_LG] += val;
444 } else {
445 touchTile(cx0, val, cx, runLen, _touchedTile);
446 }
447 }
448 addr_off += SIZE_INT;
449
450 if (DO_STATS) {
451 rdrStats.hist_tile_generator_encoding_runLen
452 .add(runLen);
453 }
454 cx0 = cx;
455 }
456
457 // alpha value = running sum of coverage delta:
458 val += delta;
459
460 // ensure values are in [0; MAX_AA_ALPHA] range
461 if (DO_AA_RANGE_CHECK) {
462 if (val < 0) {
463 MarlinUtils.logInfo("Invalid coverage = " + val);
464 val = 0;
465 }
466 if (val > MAX_AA_ALPHA) {
467 MarlinUtils.logInfo("Invalid coverage = " + val);
468 val = MAX_AA_ALPHA;
469 }
470 }
471 }
472 }
473 } else if (DO_STATS) {
474 skip++;
475 }
476 }
477
478 // Process remaining RLE run:
479 runLen = to - cx0;
480
481 // store alpha coverage (ensure within bounds):
482 // as (int)[absX|val] where:
483 // absX is the absolute x-coordinate in bits 31 to 8 and val in bits 0..7
484 // note: last pixel exclusive (>= 0)
485 // note: it should check X is smaller than 23bits (overflow)!
486
487 // check address alignment to 4 bytes:
613 }
614 }
615
616 int alphaSumInTile(final int x) {
617 return touchedTile[(x - bboxX0) >> TILE_W_LG];
618 }
619
620 @Override
621 public String toString() {
622 return "bbox = ["
623 + bboxX0 + ", " + bboxY0 + " => "
624 + bboxX1 + ", " + bboxY1 + "]\n";
625 }
626
627 private static byte[] buildAlphaMap(final int maxalpha) {
628 // double size !
629 final byte[] alMap = new byte[maxalpha << 1];
630 final int halfmaxalpha = maxalpha >> 2;
631 for (int i = 0; i <= maxalpha; i++) {
632 alMap[i] = (byte) ((i * 255 + halfmaxalpha) / maxalpha);
633 }
634 return alMap;
635 }
636 }
|