< prev index next >

src/java.desktop/share/classes/sun/java2d/marlin/MarlinCache.java

Print this page

        

*** 1,7 **** /* ! * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this --- 1,7 ---- /* ! * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this
*** 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;
*** 340,352 **** } } // store alpha sum (as byte): if (val == 0) { ! _unsafe.putByte(addr_off, (byte)0); // [0..255] } else { ! _unsafe.putByte(addr_off, _unsafe.getByte(addr_alpha + val)); // [0..255] // update touchedTile _touchedTile[x >> _TILE_SIZE_LG] += val; } addr_off += SIZE_BYTE; --- 305,317 ---- } } // store alpha sum (as byte): if (val == 0) { ! _unsafe.putByte(addr_off, (byte)0); // [0-255] } else { ! _unsafe.putByte(addr_off, _unsafe.getByte(addr_alpha + val)); // [0-255] // update touchedTile _touchedTile[x >> _TILE_SIZE_LG] += val; } addr_off += SIZE_BYTE;
*** 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;
*** 479,489 **** ((_bboxX0 + cx) << 8) ); } else { _unsafe.putInt(addr_off, ((_bboxX0 + cx) << 8) ! | (((int) _unsafe.getByte(addr_alpha + val)) & 0xFF) // [0..255] ); if (runLen == 1) { _touchedTile[cx0 >> _TILE_SIZE_LG] += val; } else { --- 438,448 ---- ((_bboxX0 + cx) << 8) ); } else { _unsafe.putInt(addr_off, ((_bboxX0 + cx) << 8) ! | (((int) _unsafe.getByte(addr_alpha + val)) & 0xFF) // [0-255] ); if (runLen == 1) { _touchedTile[cx0 >> _TILE_SIZE_LG] += val; } else {
*** 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; }
*** 542,552 **** ((_bboxX0 + to) << 8) ); } else { _unsafe.putInt(addr_off, ((_bboxX0 + to) << 8) ! | (((int) _unsafe.getByte(addr_alpha + val)) & 0xFF) // [0..255] ); if (runLen == 1) { _touchedTile[cx0 >> _TILE_SIZE_LG] += val; } else { --- 501,511 ---- ((_bboxX0 + to) << 8) ); } else { _unsafe.putInt(addr_off, ((_bboxX0 + to) << 8) ! | (((int) _unsafe.getByte(addr_alpha + val)) & 0xFF) // [0-255] ); if (runLen == 1) { _touchedTile[cx0 >> _TILE_SIZE_LG] += val; } else {
*** 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 >