jdk/src/java.desktop/share/classes/sun/java2d/marlin/MarlinCache.java
changeset 39519 21bfc4452441
parent 36458 25786a73a5fc
child 40421 d5ee65e2b0fb
equal deleted inserted replaced
39518:cf5567d544b4 39519:21bfc4452441
    58         final byte[] _ALPHA_MAP = buildAlphaMap(MAX_AA_ALPHA);
    58         final byte[] _ALPHA_MAP = buildAlphaMap(MAX_AA_ALPHA);
    59 
    59 
    60         ALPHA_MAP_UNSAFE = new OffHeapArray(_ALPHA_MAP, _ALPHA_MAP.length); // 1K
    60         ALPHA_MAP_UNSAFE = new OffHeapArray(_ALPHA_MAP, _ALPHA_MAP.length); // 1K
    61         ALPHA_MAP =_ALPHA_MAP;
    61         ALPHA_MAP =_ALPHA_MAP;
    62 
    62 
    63         final Unsafe _unsafe = OffHeapArray.unsafe;
    63         final Unsafe _unsafe = OffHeapArray.UNSAFE;
    64         final long addr = ALPHA_MAP_UNSAFE.address;
    64         final long addr = ALPHA_MAP_UNSAFE.address;
    65 
    65 
    66         for (int i = 0; i < _ALPHA_MAP.length; i++) {
    66         for (int i = 0; i < _ALPHA_MAP.length; i++) {
    67             _unsafe.putByte(addr + i, _ALPHA_MAP[i]);
    67             _unsafe.putByte(addr + i, _ALPHA_MAP[i]);
    68         }
    68         }
   155                     // note: already checked (meanCrossingPerPixel <= 2)
   155                     // note: already checked (meanCrossingPerPixel <= 2)
   156                     // rewritten to avoid division:
   156                     // rewritten to avoid division:
   157                     || (width * heightSubPixel) >
   157                     || (width * heightSubPixel) >
   158                             ((edgeSumDeltaY - heightSubPixel) << BLOCK_SIZE_LG);
   158                             ((edgeSumDeltaY - heightSubPixel) << BLOCK_SIZE_LG);
   159 
   159 
   160                 if (doTrace && !useRLE) {
   160                 if (DO_TRACE && !useRLE) {
   161                     final float meanCrossings
   161                     final float meanCrossings
   162                         = ((float) edgeSumDeltaY) / heightSubPixel;
   162                         = ((float) edgeSumDeltaY) / heightSubPixel;
   163                     final float meanDist = width / (meanCrossings - 1);
   163                     final float meanDist = width / (meanCrossings - 1);
   164 
   164 
   165                     System.out.println("High complexity: "
   165                     System.out.println("High complexity: "
   178 
   178 
   179         // the ceiling of (maxy - miny + 1) / TILE_SIZE;
   179         // the ceiling of (maxy - miny + 1) / TILE_SIZE;
   180         final int nxTiles = (width + TILE_SIZE) >> TILE_SIZE_LG;
   180         final int nxTiles = (width + TILE_SIZE) >> TILE_SIZE_LG;
   181 
   181 
   182         if (nxTiles > INITIAL_ARRAY) {
   182         if (nxTiles > INITIAL_ARRAY) {
   183             if (doStats) {
   183             if (DO_STATS) {
   184                 RendererContext.stats.stat_array_marlincache_touchedTile
   184                 rdrCtx.stats.stat_array_marlincache_touchedTile
   185                     .add(nxTiles);
   185                     .add(nxTiles);
   186             }
   186             }
   187             touchedTile = rdrCtx.getIntArray(nxTiles);
   187             touchedTile = rdrCtx.getIntArray(nxTiles);
   188         }
   188         }
   189     }
   189     }
   204         // At last: resize back off-heap rowAA to initial size
   204         // At last: resize back off-heap rowAA to initial size
   205         if (rowAAChunk.length != INITIAL_CHUNK_ARRAY) {
   205         if (rowAAChunk.length != INITIAL_CHUNK_ARRAY) {
   206             // note: may throw OOME:
   206             // note: may throw OOME:
   207             rowAAChunk.resize(INITIAL_CHUNK_ARRAY);
   207             rowAAChunk.resize(INITIAL_CHUNK_ARRAY);
   208         }
   208         }
   209         if (doCleanDirty) {
   209         if (DO_CLEAN_DIRTY) {
   210             // Force zero-fill dirty arrays:
   210             // Force zero-fill dirty arrays:
   211             rowAAChunk.fill(BYTE_0);
   211             rowAAChunk.fill(BYTE_0);
   212         }
   212         }
   213     }
   213     }
   214 
   214 
   215     void resetTileLine(final int pminY) {
   215     void resetTileLine(final int pminY) {
   216         // update bboxY0 to process a complete tile line [0 - 32]
   216         // update bboxY0 to process a complete tile line [0 - 32]
   217         bboxY0 = pminY;
   217         bboxY0 = pminY;
   218 
   218 
   219         // reset current pos
   219         // reset current pos
   220         if (doStats) {
   220         if (DO_STATS) {
   221             RendererContext.stats.stat_cache_rowAAChunk.add(rowAAChunkPos);
   221             rdrCtx.stats.stat_cache_rowAAChunk.add(rowAAChunkPos);
   222         }
   222         }
   223         rowAAChunkPos = 0L;
   223         rowAAChunkPos = 0L;
   224 
   224 
   225         // Reset touchedTile:
   225         // Reset touchedTile:
   226         if (tileMin != Integer.MAX_VALUE) {
   226         if (tileMin != Integer.MAX_VALUE) {
   227             if (doStats) {
   227             if (DO_STATS) {
   228                 RendererContext.stats.stat_cache_tiles.add(tileMax - tileMin);
   228                 rdrCtx.stats.stat_cache_tiles.add(tileMax - tileMin);
   229             }
   229             }
   230             // clean only dirty touchedTile:
   230             // clean only dirty touchedTile:
   231             if (tileMax == 1) {
   231             if (tileMax == 1) {
   232                 touchedTile[0] = 0;
   232                 touchedTile[0] = 0;
   233             } else {
   233             } else {
   236             // reset tile used marks:
   236             // reset tile used marks:
   237             tileMin = Integer.MAX_VALUE;
   237             tileMin = Integer.MAX_VALUE;
   238             tileMax = Integer.MIN_VALUE;
   238             tileMax = Integer.MIN_VALUE;
   239         }
   239         }
   240 
   240 
   241         if (doCleanDirty) {
   241         if (DO_CLEAN_DIRTY) {
   242             // Force zero-fill dirty arrays:
   242             // Force zero-fill dirty arrays:
   243             rowAAChunk.fill(BYTE_0);
   243             rowAAChunk.fill(BYTE_0);
   244         }
   244         }
   245     }
   245     }
   246 
   246 
   265      * @param px1 last pixel exclusive x1
   265      * @param px1 last pixel exclusive x1
   266      */
   266      */
   267     void copyAARowNoRLE(final int[] alphaRow, final int y,
   267     void copyAARowNoRLE(final int[] alphaRow, final int y,
   268                    final int px0, final int px1)
   268                    final int px0, final int px1)
   269     {
   269     {
   270         if (doMonitors) {
   270         if (DO_MONITORS) {
   271             RendererContext.stats.mon_rdr_copyAARow.start();
   271             rdrCtx.stats.mon_rdr_copyAARow.start();
   272         }
   272         }
   273 
   273 
   274         // skip useless pixels above boundary
   274         // skip useless pixels above boundary
   275         final int px_bbox1 = FloatMath.min(px1, bboxX1);
   275         final int px_bbox1 = FloatMath.min(px1, bboxX1);
   276 
   276 
   277         if (doLogBounds) {
   277         if (DO_LOG_BOUNDS) {
   278             MarlinUtils.logInfo("row = [" + px0 + " ... " + px_bbox1
   278             MarlinUtils.logInfo("row = [" + px0 + " ... " + px_bbox1
   279                                 + " (" + px1 + ") [ for y=" + y);
   279                                 + " (" + px1 + ") [ for y=" + y);
   280         }
   280         }
   281 
   281 
   282         final int row = y - bboxY0;
   282         final int row = y - bboxY0;
   303         final OffHeapArray _rowAAChunk = rowAAChunk;
   303         final OffHeapArray _rowAAChunk = rowAAChunk;
   304         // ensure rowAAChunk capacity:
   304         // ensure rowAAChunk capacity:
   305         if (_rowAAChunk.length < needSize) {
   305         if (_rowAAChunk.length < needSize) {
   306             expandRowAAChunk(needSize);
   306             expandRowAAChunk(needSize);
   307         }
   307         }
   308         if (doStats) {
   308         if (DO_STATS) {
   309             RendererContext.stats.stat_cache_rowAA.add(px_bbox1 - px0);
   309             rdrCtx.stats.stat_cache_rowAA.add(px_bbox1 - px0);
   310         }
   310         }
   311 
   311 
   312         // rowAA contains only alpha values for range[x0; x1[
   312         // rowAA contains only alpha values for range[x0; x1[
   313         final int[] _touchedTile = touchedTile;
   313         final int[] _touchedTile = touchedTile;
   314         final int _TILE_SIZE_LG = TILE_SIZE_LG;
   314         final int _TILE_SIZE_LG = TILE_SIZE_LG;
   315 
   315 
   316         final int from = px0      - bboxX0; // first pixel inclusive
   316         final int from = px0      - bboxX0; // first pixel inclusive
   317         final int to   = px_bbox1 - bboxX0; //  last pixel exclusive
   317         final int to   = px_bbox1 - bboxX0; //  last pixel exclusive
   318 
   318 
   319         final Unsafe _unsafe = OffHeapArray.unsafe;
   319         final Unsafe _unsafe = OffHeapArray.UNSAFE;
   320         final long SIZE_BYTE = 1L;
   320         final long SIZE_BYTE = 1L;
   321         final long addr_alpha = ALPHA_MAP_UNSAFE.address;
   321         final long addr_alpha = ALPHA_MAP_UNSAFE.address;
   322         long addr_off = _rowAAChunk.address + pos;
   322         long addr_off = _rowAAChunk.address + pos;
   323 
   323 
   324         // compute alpha sum into rowAA:
   324         // compute alpha sum into rowAA:
   359         tx = ((to - 1) >> _TILE_SIZE_LG) + 1; // exclusive (+1 to be sure)
   359         tx = ((to - 1) >> _TILE_SIZE_LG) + 1; // exclusive (+1 to be sure)
   360         if (tx > tileMax) {
   360         if (tx > tileMax) {
   361             tileMax = tx;
   361             tileMax = tx;
   362         }
   362         }
   363 
   363 
   364         if (doLogBounds) {
   364         if (DO_LOG_BOUNDS) {
   365             MarlinUtils.logInfo("clear = [" + from + " ... " + to + "[");
   365             MarlinUtils.logInfo("clear = [" + from + " ... " + to + "[");
   366         }
   366         }
   367 
   367 
   368         // Clear alpha row for reuse:
   368         // Clear alpha row for reuse:
   369         IntArrayCache.fill(alphaRow, from, px1 - bboxX0, 0);
   369         IntArrayCache.fill(alphaRow, from, px1 - bboxX0, 0);
   370 
   370 
   371         if (doMonitors) {
   371         if (DO_MONITORS) {
   372             RendererContext.stats.mon_rdr_copyAARow.stop();
   372             rdrCtx.stats.mon_rdr_copyAARow.stop();
   373         }
   373         }
   374     }
   374     }
   375 
   375 
   376     void copyAARowRLE_WithBlockFlags(final int[] blkFlags, final int[] alphaRow,
   376     void copyAARowRLE_WithBlockFlags(final int[] blkFlags, final int[] alphaRow,
   377                       final int y, final int px0, final int px1)
   377                       final int y, final int px0, final int px1)
   378     {
   378     {
   379         if (doMonitors) {
   379         if (DO_MONITORS) {
   380             RendererContext.stats.mon_rdr_copyAARow.start();
   380             rdrCtx.stats.mon_rdr_copyAARow.start();
   381         }
   381         }
   382 
   382 
   383         // Copy rowAA data into the piscesCache if one is present
   383         // Copy rowAA data into the piscesCache if one is present
   384         final int _bboxX0 = bboxX0;
   384         final int _bboxX0 = bboxX0;
   385 
   385 
   389 
   389 
   390         // skip useless pixels above boundary
   390         // skip useless pixels above boundary
   391         final int px_bbox1 = FloatMath.min(px1, bboxX1);
   391         final int px_bbox1 = FloatMath.min(px1, bboxX1);
   392         final int to       = px_bbox1 - _bboxX0; //  last pixel exclusive
   392         final int to       = px_bbox1 - _bboxX0; //  last pixel exclusive
   393 
   393 
   394         if (doLogBounds) {
   394         if (DO_LOG_BOUNDS) {
   395             MarlinUtils.logInfo("row = [" + px0 + " ... " + px_bbox1
   395             MarlinUtils.logInfo("row = [" + px0 + " ... " + px_bbox1
   396                                 + " (" + px1 + ") [ for y=" + y);
   396                                 + " (" + px1 + ") [ for y=" + y);
   397         }
   397         }
   398 
   398 
   399         // get current position:
   399         // get current position:
   408         // ensure rowAAChunk capacity:
   408         // ensure rowAAChunk capacity:
   409         if (_rowAAChunk.length < needSize) {
   409         if (_rowAAChunk.length < needSize) {
   410             expandRowAAChunk(needSize);
   410             expandRowAAChunk(needSize);
   411         }
   411         }
   412 
   412 
   413         final Unsafe _unsafe = OffHeapArray.unsafe;
   413         final Unsafe _unsafe = OffHeapArray.UNSAFE;
   414         final long SIZE_INT = 4L;
   414         final long SIZE_INT = 4L;
   415         final long addr_alpha = ALPHA_MAP_UNSAFE.address;
   415         final long addr_alpha = ALPHA_MAP_UNSAFE.address;
   416         long addr_off = _rowAAChunk.address + initialPos;
   416         long addr_off = _rowAAChunk.address + initialPos;
   417 
   417 
   418         final int[] _touchedTile = touchedTile;
   418         final int[] _touchedTile = touchedTile;
   463                             // absX is the absolute x-coordinate:
   463                             // absX is the absolute x-coordinate:
   464                             // note: last pixel exclusive (>= 0)
   464                             // note: last pixel exclusive (>= 0)
   465                             // note: it should check X is smaller than 23bits (overflow)!
   465                             // note: it should check X is smaller than 23bits (overflow)!
   466 
   466 
   467                             // check address alignment to 4 bytes:
   467                             // check address alignment to 4 bytes:
   468                             if (doCheckUnsafe) {
   468                             if (DO_CHECK_UNSAFE) {
   469                                 if ((addr_off & 3) != 0) {
   469                                 if ((addr_off & 3) != 0) {
   470                                     MarlinUtils.logInfo("Misaligned Unsafe address: " + addr_off);
   470                                     MarlinUtils.logInfo("Misaligned Unsafe address: " + addr_off);
   471                                 }
   471                                 }
   472                             }
   472                             }
   473 
   473 
   488                                     touchTile(cx0, val, cx, runLen, _touchedTile);
   488                                     touchTile(cx0, val, cx, runLen, _touchedTile);
   489                                 }
   489                                 }
   490                             }
   490                             }
   491                             addr_off += SIZE_INT;
   491                             addr_off += SIZE_INT;
   492 
   492 
   493                             if (doStats) {
   493                             if (DO_STATS) {
   494                                 RendererContext.stats.hist_tile_generator_encoding_runLen
   494                                 rdrCtx.stats.hist_tile_generator_encoding_runLen
   495                                     .add(runLen);
   495                                     .add(runLen);
   496                             }
   496                             }
   497                             cx0 = cx;
   497                             cx0 = cx;
   498                         }
   498                         }
   499 
   499 
   511                                 val = MAX_AA_ALPHA;
   511                                 val = MAX_AA_ALPHA;
   512                             }
   512                             }
   513                         }
   513                         }
   514                     }
   514                     }
   515                 }
   515                 }
   516             } else if (doStats) {
   516             } else if (DO_STATS) {
   517                 skip++;
   517                 skip++;
   518             }
   518             }
   519         }
   519         }
   520 
   520 
   521         // Process remaining RLE run:
   521         // Process remaining RLE run:
   526         // absX is the absolute x-coordinate in bits 31 to 8 and val in bits 0..7
   526         // absX is the absolute x-coordinate in bits 31 to 8 and val in bits 0..7
   527         // note: last pixel exclusive (>= 0)
   527         // note: last pixel exclusive (>= 0)
   528         // note: it should check X is smaller than 23bits (overflow)!
   528         // note: it should check X is smaller than 23bits (overflow)!
   529 
   529 
   530         // check address alignment to 4 bytes:
   530         // check address alignment to 4 bytes:
   531         if (doCheckUnsafe) {
   531         if (DO_CHECK_UNSAFE) {
   532             if ((addr_off & 3) != 0) {
   532             if ((addr_off & 3) != 0) {
   533                 MarlinUtils.logInfo("Misaligned Unsafe address: " + addr_off);
   533                 MarlinUtils.logInfo("Misaligned Unsafe address: " + addr_off);
   534             }
   534             }
   535         }
   535         }
   536 
   536 
   551                 touchTile(cx0, val, to, runLen, _touchedTile);
   551                 touchTile(cx0, val, to, runLen, _touchedTile);
   552             }
   552             }
   553         }
   553         }
   554         addr_off += SIZE_INT;
   554         addr_off += SIZE_INT;
   555 
   555 
   556         if (doStats) {
   556         if (DO_STATS) {
   557             RendererContext.stats.hist_tile_generator_encoding_runLen
   557             rdrCtx.stats.hist_tile_generator_encoding_runLen
   558                 .add(runLen);
   558                 .add(runLen);
   559         }
   559         }
   560 
   560 
   561         long len = (addr_off - _rowAAChunk.address);
   561         long len = (addr_off - _rowAAChunk.address);
   562 
   562 
   564         rowAALen[row] = (len - initialPos);
   564         rowAALen[row] = (len - initialPos);
   565 
   565 
   566         // update current position:
   566         // update current position:
   567         rowAAChunkPos = len;
   567         rowAAChunkPos = len;
   568 
   568 
   569         if (doStats) {
   569         if (DO_STATS) {
   570             RendererContext.stats.stat_cache_rowAA.add(rowAALen[row]);
   570             rdrCtx.stats.stat_cache_rowAA.add(rowAALen[row]);
   571             RendererContext.stats.hist_tile_generator_encoding_ratio.add(
   571             rdrCtx.stats.hist_tile_generator_encoding_ratio.add(
   572                 (100 * skip) / (blkE - blkW)
   572                 (100 * skip) / (blkE - blkW)
   573             );
   573             );
   574         }
   574         }
   575 
   575 
   576         // update tile used marks:
   576         // update tile used marks:
   587         // Clear alpha row for reuse:
   587         // Clear alpha row for reuse:
   588         if (px1 > bboxX1) {
   588         if (px1 > bboxX1) {
   589             alphaRow[to    ] = 0;
   589             alphaRow[to    ] = 0;
   590             alphaRow[to + 1] = 0;
   590             alphaRow[to + 1] = 0;
   591         }
   591         }
   592         if (doChecks) {
   592         if (DO_CHECKS) {
   593             IntArrayCache.check(blkFlags, blkW, blkE, 0);
   593             IntArrayCache.check(blkFlags, blkW, blkE, 0);
   594             IntArrayCache.check(alphaRow, from, px1 - bboxX0, 0);
   594             IntArrayCache.check(alphaRow, from, px1 - bboxX0, 0);
   595         }
   595         }
   596 
   596 
   597         if (doMonitors) {
   597         if (DO_MONITORS) {
   598             RendererContext.stats.mon_rdr_copyAARow.stop();
   598             rdrCtx.stats.mon_rdr_copyAARow.stop();
   599         }
   599         }
   600     }
   600     }
   601 
   601 
   602     long startRLERow(final int row, final int x0, final int x1) {
   602     long startRLERow(final int row, final int x0, final int x1) {
   603         // rows are supposed to be added by increasing y.
   603         // rows are supposed to be added by increasing y.
   609         // update row index to current position:
   609         // update row index to current position:
   610         return (rowAAChunkIndex[row] = rowAAChunkPos);
   610         return (rowAAChunkIndex[row] = rowAAChunkPos);
   611     }
   611     }
   612 
   612 
   613     private void expandRowAAChunk(final long needSize) {
   613     private void expandRowAAChunk(final long needSize) {
   614         if (doStats) {
   614         if (DO_STATS) {
   615             RendererContext.stats.stat_array_marlincache_rowAAChunk
   615             rdrCtx.stats.stat_array_marlincache_rowAAChunk
   616                 .add(needSize);
   616                 .add(needSize);
   617         }
   617         }
   618 
   618 
   619         // note: throw IOOB if neededSize > 2Gb:
   619         // note: throw IOOB if neededSize > 2Gb:
   620         final long newSize = ArrayCache.getNewLargeSize(rowAAChunk.length, needSize);
   620         final long newSize = ArrayCache.getNewLargeSize(rowAAChunk.length, needSize);