< prev index next >
src/java.desktop/share/classes/sun/java2d/marlin/MarlinCache.java
Print this page
*** 43,53 ****
// values are stored as int [x|alpha] where alpha is 8 bits
static final int RLE_MAX_WIDTH = 1 << (24 - 1);
// 2048 (pixelSize) alpha values (width) x 32 rows (tile) = 64K bytes
// x1 instead of 4 bytes (RLE) ie 1/4 capacity or average good RLE compression
! static final long INITIAL_CHUNK_ARRAY = TILE_SIZE * INITIAL_PIXEL_DIM; // 64K
// The alpha map used by this object (taken out of our map cache) to convert
// pixel coverage counts gotten from MarlinCache (which are in the range
// [0, maxalpha]) into alpha values, which are in [0,256).
static final byte[] ALPHA_MAP;
--- 43,53 ----
// values are stored as int [x|alpha] where alpha is 8 bits
static final int RLE_MAX_WIDTH = 1 << (24 - 1);
// 2048 (pixelSize) alpha values (width) x 32 rows (tile) = 64K bytes
// x1 instead of 4 bytes (RLE) ie 1/4 capacity or average good RLE compression
! static final long INITIAL_CHUNK_ARRAY = TILE_H * INITIAL_PIXEL_DIM; // 64K
// The alpha map used by this object (taken out of our map cache) to convert
// pixel coverage counts gotten from MarlinCache (which are in the range
// [0, maxalpha]) into alpha values, which are in [0,256).
static final byte[] ALPHA_MAP;
*** 70,90 ****
int bboxX0, bboxY0, bboxX1, bboxY1;
// 1D dirty arrays
// row index in rowAAChunk[]
! final long[] rowAAChunkIndex = new long[TILE_SIZE];
// first pixel (inclusive) for each row
! final int[] rowAAx0 = new int[TILE_SIZE];
// last pixel (exclusive) for each row
! final int[] rowAAx1 = new int[TILE_SIZE];
// encoding mode (0=raw, 1=RLE encoding) for each row
! final int[] rowAAEnc = new int[TILE_SIZE];
// coded length (RLE encoding) for each row
! final long[] rowAALen = new long[TILE_SIZE];
// last position in RLE decoding for each row (getAlpha):
! final long[] rowAAPos = new long[TILE_SIZE];
// dirty off-heap array containing pixel coverages for (32) rows (packed)
// if encoding=raw, it contains alpha coverage values (val) as integer
// if encoding=RLE, it contains tuples (val, last x-coordinate exclusive)
// use rowAAx0/rowAAx1 to get row indices within this chunk
--- 70,90 ----
int bboxX0, bboxY0, bboxX1, bboxY1;
// 1D dirty arrays
// row index in rowAAChunk[]
! final long[] rowAAChunkIndex = new long[TILE_H];
// first pixel (inclusive) for each row
! final int[] rowAAx0 = new int[TILE_H];
// last pixel (exclusive) for each row
! final int[] rowAAx1 = new int[TILE_H];
// encoding mode (0=raw, 1=RLE encoding) for each row
! final int[] rowAAEnc = new int[TILE_H];
// coded length (RLE encoding) for each row
! final long[] rowAALen = new long[TILE_H];
// last position in RLE decoding for each row (getAlpha):
! final long[] rowAAPos = new long[TILE_H];
// dirty off-heap array containing pixel coverages for (32) rows (packed)
// if encoding=raw, it contains alpha coverage values (val) as integer
// if encoding=RLE, it contains tuples (val, last x-coordinate exclusive)
// use rowAAx0/rowAAx1 to get row indices within this chunk
*** 95,116 ****
// touchedTile[i] is the sum of all the alphas in the tile with
// x=j*TILE_SIZE+bboxX0.
int[] touchedTile;
! // per-thread renderer context
! final RendererContext rdrCtx;
// touchedTile ref (clean)
private final IntArrayCache.Reference touchedTile_ref;
int tileMin, tileMax;
boolean useRLE = false;
! MarlinCache(final RendererContext rdrCtx) {
! this.rdrCtx = rdrCtx;
rowAAChunk = rdrCtx.newOffHeapArray(INITIAL_CHUNK_ARRAY); // 64K
touchedTile_ref = rdrCtx.newCleanIntArrayRef(INITIAL_ARRAY); // 1K = 1 tile line
touchedTile = touchedTile_ref.initial;
--- 95,116 ----
// touchedTile[i] is the sum of all the alphas in the tile with
// x=j*TILE_SIZE+bboxX0.
int[] touchedTile;
! // per-thread renderer stats
! final RendererStats rdrStats;
// touchedTile ref (clean)
private final IntArrayCache.Reference touchedTile_ref;
int tileMin, tileMax;
boolean useRLE = false;
! MarlinCache(final IRendererContext rdrCtx) {
! this.rdrStats = rdrCtx.stats();
rowAAChunk = rdrCtx.newOffHeapArray(INITIAL_CHUNK_ARRAY); // 64K
touchedTile_ref = rdrCtx.newCleanIntArrayRef(INITIAL_ARRAY); // 1K = 1 tile line
touchedTile = touchedTile_ref.initial;
*** 118,128 ****
// tile used marks:
tileMin = Integer.MAX_VALUE;
tileMax = Integer.MIN_VALUE;
}
! void init(int minx, int miny, int maxx, int maxy, int edgeSumDeltaY)
{
// assert maxy >= miny && maxx >= minx;
bboxX0 = minx;
bboxY0 = miny;
bboxX1 = maxx;
--- 118,128 ----
// tile used marks:
tileMin = Integer.MAX_VALUE;
tileMax = Integer.MIN_VALUE;
}
! void init(int minx, int miny, int maxx, int maxy)
{
// assert maxy >= miny && maxx >= minx;
bboxX0 = minx;
bboxY0 = miny;
bboxX1 = maxx;
*** 140,190 ****
// fast check min and max width (maxx < 23bits):
if (width <= RLE_MIN_WIDTH || width >= RLE_MAX_WIDTH) {
useRLE = false;
} else {
! // perimeter approach: how fit the total length into given height:
!
! // if stroking: meanCrossings /= 2 => divide edgeSumDeltaY by 2
! final int heightSubPixel
! = (((maxy - miny) << SUBPIXEL_LG_POSITIONS_Y) << rdrCtx.stroking);
!
! // check meanDist > block size:
! // check width / (meanCrossings - 1) >= RLE_THRESHOLD
!
! // fast case: (meanCrossingPerPixel <= 2) means 1 span only
! useRLE = (edgeSumDeltaY <= (heightSubPixel << 1))
! // note: already checked (meanCrossingPerPixel <= 2)
! // rewritten to avoid division:
! || (width * heightSubPixel) >
! ((edgeSumDeltaY - heightSubPixel) << BLOCK_SIZE_LG);
!
! if (DO_TRACE && !useRLE) {
! final float meanCrossings
! = ((float) edgeSumDeltaY) / heightSubPixel;
! final float meanDist = width / (meanCrossings - 1);
!
! System.out.println("High complexity: "
! + " for bbox[width = " + width
! + " height = " + (maxy - miny)
! + "] edgeSumDeltaY = " + edgeSumDeltaY
! + " heightSubPixel = " + heightSubPixel
! + " meanCrossings = "+ meanCrossings
! + " meanDist = " + meanDist
! + " width = " + (width * heightSubPixel)
! + " <= criteria: " + ((edgeSumDeltaY - heightSubPixel) << BLOCK_SIZE_LG)
! );
! }
}
}
// the ceiling of (maxy - miny + 1) / TILE_SIZE;
! final int nxTiles = (width + TILE_SIZE) >> TILE_SIZE_LG;
if (nxTiles > INITIAL_ARRAY) {
if (DO_STATS) {
! rdrCtx.stats.stat_array_marlincache_touchedTile.add(nxTiles);
}
touchedTile = touchedTile_ref.getArray(nxTiles);
}
}
--- 140,159 ----
// fast check min and max width (maxx < 23bits):
if (width <= RLE_MIN_WIDTH || width >= RLE_MAX_WIDTH) {
useRLE = false;
} else {
! useRLE = true;
}
}
// the ceiling of (maxy - miny + 1) / TILE_SIZE;
! final int nxTiles = (width + TILE_W) >> TILE_W_LG;
if (nxTiles > INITIAL_ARRAY) {
if (DO_STATS) {
! rdrStats.stat_array_marlincache_touchedTile.add(nxTiles);
}
touchedTile = touchedTile_ref.getArray(nxTiles);
}
}
*** 195,205 ****
void dispose() {
// Reset touchedTile if needed:
resetTileLine(0);
if (DO_STATS) {
! rdrCtx.stats.totalOffHeap += rowAAChunk.length;
}
// Return arrays:
touchedTile = touchedTile_ref.putArray(touchedTile, 0, 0); // already zero filled
--- 164,174 ----
void dispose() {
// Reset touchedTile if needed:
resetTileLine(0);
if (DO_STATS) {
! rdrStats.totalOffHeap += rowAAChunk.length;
}
// Return arrays:
touchedTile = touchedTile_ref.putArray(touchedTile, 0, 0); // already zero filled
*** 218,235 ****
// update bboxY0 to process a complete tile line [0 - 32]
bboxY0 = pminY;
// reset current pos
if (DO_STATS) {
! rdrCtx.stats.stat_cache_rowAAChunk.add(rowAAChunkPos);
}
rowAAChunkPos = 0L;
// Reset touchedTile:
if (tileMin != Integer.MAX_VALUE) {
if (DO_STATS) {
! rdrCtx.stats.stat_cache_tiles.add(tileMax - tileMin);
}
// clean only dirty touchedTile:
if (tileMax == 1) {
touchedTile[0] = 0;
} else {
--- 187,204 ----
// update bboxY0 to process a complete tile line [0 - 32]
bboxY0 = pminY;
// reset current pos
if (DO_STATS) {
! rdrStats.stat_cache_rowAAChunk.add(rowAAChunkPos);
}
rowAAChunkPos = 0L;
// Reset touchedTile:
if (tileMin != Integer.MAX_VALUE) {
if (DO_STATS) {
! rdrStats.stat_cache_tiles.add(tileMax - tileMin);
}
// clean only dirty touchedTile:
if (tileMax == 1) {
touchedTile[0] = 0;
} else {
*** 267,280 ****
* @param px1 last pixel exclusive x1
*/
void copyAARowNoRLE(final int[] alphaRow, final int y,
final int px0, final int px1)
{
- if (DO_MONITORS) {
- rdrCtx.stats.mon_rdr_copyAARow.start();
- }
-
// skip useless pixels above boundary
final int px_bbox1 = FloatMath.min(px1, bboxX1);
if (DO_LOG_BOUNDS) {
MarlinUtils.logInfo("row = [" + px0 + " ... " + px_bbox1
--- 236,245 ----
*** 306,321 ****
// ensure rowAAChunk capacity:
if (_rowAAChunk.length < needSize) {
expandRowAAChunk(needSize);
}
if (DO_STATS) {
! rdrCtx.stats.stat_cache_rowAA.add(px_bbox1 - px0);
}
// rowAA contains only alpha values for range[x0; x1[
final int[] _touchedTile = touchedTile;
! final int _TILE_SIZE_LG = TILE_SIZE_LG;
final int from = px0 - bboxX0; // first pixel inclusive
final int to = px_bbox1 - bboxX0; // last pixel exclusive
final Unsafe _unsafe = OffHeapArray.UNSAFE;
--- 271,286 ----
// ensure rowAAChunk capacity:
if (_rowAAChunk.length < needSize) {
expandRowAAChunk(needSize);
}
if (DO_STATS) {
! rdrStats.stat_cache_rowAA.add(px_bbox1 - px0);
}
// rowAA contains only alpha values for range[x0; x1[
final int[] _touchedTile = touchedTile;
! final int _TILE_SIZE_LG = TILE_W_LG;
final int from = px0 - bboxX0; // first pixel inclusive
final int to = px_bbox1 - bboxX0; // last pixel exclusive
final Unsafe _unsafe = OffHeapArray.UNSAFE;
*** 366,394 ****
if (DO_LOG_BOUNDS) {
MarlinUtils.logInfo("clear = [" + from + " ... " + to + "[");
}
// Clear alpha row for reuse:
! IntArrayCache.fill(alphaRow, from, px1 - bboxX0, 0);
!
! if (DO_MONITORS) {
! rdrCtx.stats.mon_rdr_copyAARow.stop();
! }
}
void copyAARowRLE_WithBlockFlags(final int[] blkFlags, final int[] alphaRow,
final int y, final int px0, final int px1)
{
- if (DO_MONITORS) {
- rdrCtx.stats.mon_rdr_copyAARow.start();
- }
-
// Copy rowAA data into the piscesCache if one is present
final int _bboxX0 = bboxX0;
// process tile line [0 - 32]
! final int row = y - bboxY0;
final int from = px0 - _bboxX0; // first pixel inclusive
// skip useless pixels above boundary
final int px_bbox1 = FloatMath.min(px1, bboxX1);
final int to = px_bbox1 - _bboxX0; // last pixel exclusive
--- 331,351 ----
if (DO_LOG_BOUNDS) {
MarlinUtils.logInfo("clear = [" + from + " ... " + to + "[");
}
// Clear alpha row for reuse:
! IntArrayCache.fill(alphaRow, from, px1 + 1 - bboxX0, 0);
}
void copyAARowRLE_WithBlockFlags(final int[] blkFlags, final int[] alphaRow,
final int y, final int px0, final int px1)
{
// Copy rowAA data into the piscesCache if one is present
final int _bboxX0 = bboxX0;
// process tile line [0 - 32]
! final int row = y - bboxY0;
final int from = px0 - _bboxX0; // first pixel inclusive
// skip useless pixels above boundary
final int px_bbox1 = FloatMath.min(px1, bboxX1);
final int to = px_bbox1 - _bboxX0; // last pixel exclusive
*** 416,431 ****
final long SIZE_INT = 4L;
final long addr_alpha = ALPHA_MAP_UNSAFE.address;
long addr_off = _rowAAChunk.address + initialPos;
final int[] _touchedTile = touchedTile;
! final int _TILE_SIZE_LG = TILE_SIZE_LG;
final int _BLK_SIZE_LG = BLOCK_SIZE_LG;
// traverse flagged blocks:
final int blkW = (from >> _BLK_SIZE_LG);
final int blkE = (to >> _BLK_SIZE_LG) + 1;
// Perform run-length encoding and store results in the piscesCache
int val = 0;
int cx0 = from;
int runLen;
--- 373,390 ----
final long SIZE_INT = 4L;
final long addr_alpha = ALPHA_MAP_UNSAFE.address;
long addr_off = _rowAAChunk.address + initialPos;
final int[] _touchedTile = touchedTile;
! final int _TILE_SIZE_LG = TILE_W_LG;
final int _BLK_SIZE_LG = BLOCK_SIZE_LG;
// traverse flagged blocks:
final int blkW = (from >> _BLK_SIZE_LG);
final int blkE = (to >> _BLK_SIZE_LG) + 1;
+ // ensure last block flag = 0 to process final block:
+ blkFlags[blkE] = 0;
// Perform run-length encoding and store results in the piscesCache
int val = 0;
int cx0 = from;
int runLen;
*** 491,501 ****
}
}
addr_off += SIZE_INT;
if (DO_STATS) {
! rdrCtx.stats.hist_tile_generator_encoding_runLen
.add(runLen);
}
cx0 = cx;
}
--- 450,460 ----
}
}
addr_off += SIZE_INT;
if (DO_STATS) {
! rdrStats.hist_tile_generator_encoding_runLen
.add(runLen);
}
cx0 = cx;
}
*** 554,564 ****
}
}
addr_off += SIZE_INT;
if (DO_STATS) {
! rdrCtx.stats.hist_tile_generator_encoding_runLen.add(runLen);
}
long len = (addr_off - _rowAAChunk.address);
// update coded length as bytes:
--- 513,523 ----
}
}
addr_off += SIZE_INT;
if (DO_STATS) {
! rdrStats.hist_tile_generator_encoding_runLen.add(runLen);
}
long len = (addr_off - _rowAAChunk.address);
// update coded length as bytes:
*** 566,577 ****
// update current position:
rowAAChunkPos = len;
if (DO_STATS) {
! rdrCtx.stats.stat_cache_rowAA.add(rowAALen[row]);
! rdrCtx.stats.hist_tile_generator_encoding_ratio.add(
(100 * skip) / (blkE - blkW)
);
}
// update tile used marks:
--- 525,536 ----
// update current position:
rowAAChunkPos = len;
if (DO_STATS) {
! rdrStats.stat_cache_rowAA.add(rowAALen[row]);
! rdrStats.hist_tile_generator_encoding_ratio.add(
(100 * skip) / (blkE - blkW)
);
}
// update tile used marks:
*** 584,604 ****
if (tx > tileMax) {
tileMax = tx;
}
// Clear alpha row for reuse:
! if (px1 > bboxX1) {
! alphaRow[to ] = 0;
! alphaRow[to + 1] = 0;
! }
if (DO_CHECKS) {
IntArrayCache.check(blkFlags, blkW, blkE, 0);
! IntArrayCache.check(alphaRow, from, px1 - bboxX0, 0);
! }
!
! if (DO_MONITORS) {
! rdrCtx.stats.mon_rdr_copyAARow.stop();
}
}
long startRLERow(final int row, final int x0, final int x1) {
// rows are supposed to be added by increasing y.
--- 543,556 ----
if (tx > tileMax) {
tileMax = tx;
}
// Clear alpha row for reuse:
! alphaRow[to] = 0;
if (DO_CHECKS) {
IntArrayCache.check(blkFlags, blkW, blkE, 0);
! IntArrayCache.check(alphaRow, from, px1 + 1 - bboxX0, 0);
}
}
long startRLERow(final int row, final int x0, final int x1) {
// rows are supposed to be added by increasing y.
*** 611,621 ****
return (rowAAChunkIndex[row] = rowAAChunkPos);
}
private void expandRowAAChunk(final long needSize) {
if (DO_STATS) {
! rdrCtx.stats.stat_array_marlincache_rowAAChunk.add(needSize);
}
// note: throw IOOB if neededSize > 2Gb:
final long newSize = ArrayCacheConst.getNewLargeSize(rowAAChunk.length,
needSize);
--- 563,573 ----
return (rowAAChunkIndex[row] = rowAAChunkPos);
}
private void expandRowAAChunk(final long needSize) {
if (DO_STATS) {
! rdrStats.stat_array_marlincache_rowAAChunk.add(needSize);
}
// note: throw IOOB if neededSize > 2Gb:
final long newSize = ArrayCacheConst.getNewLargeSize(rowAAChunk.length,
needSize);
*** 627,637 ****
final int runLen,
final int[] _touchedTile)
{
// the x and y of the current row, minus bboxX0, bboxY0
// process tile line [0 - 32]
! final int _TILE_SIZE_LG = TILE_SIZE_LG;
// update touchedTile
int tx = (x0 >> _TILE_SIZE_LG);
// handle trivial case: same tile (x0, x0+runLen)
--- 579,589 ----
final int runLen,
final int[] _touchedTile)
{
// the x and y of the current row, minus bboxX0, bboxY0
// process tile line [0 - 32]
! final int _TILE_SIZE_LG = TILE_W_LG;
// update touchedTile
int tx = (x0 >> _TILE_SIZE_LG);
// handle trivial case: same tile (x0, x0+runLen)
*** 664,674 ****
_touchedTile[tx] += val * (lastXCoord - txXCoord);
}
}
int alphaSumInTile(final int x) {
! return touchedTile[(x - bboxX0) >> TILE_SIZE_LG];
}
@Override
public String toString() {
return "bbox = ["
--- 616,626 ----
_touchedTile[tx] += val * (lastXCoord - txXCoord);
}
}
int alphaSumInTile(final int x) {
! return touchedTile[(x - bboxX0) >> TILE_W_LG];
}
@Override
public String toString() {
return "bbox = ["
< prev index next >