1 /* 2 * Copyright (c) 2015, 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 23 * questions. 24 */ 25 26 package com.sun.marlin; 27 28 import java.util.concurrent.atomic.AtomicInteger; 29 import com.sun.util.reentrant.ReentrantContext; 30 import com.sun.javafx.geom.Rectangle; 31 import com.sun.marlin.ArrayCacheConst.CacheStats; 32 33 /** 34 * This class is a renderer context dedicated to a single thread 35 */ 36 public final class DRendererContext extends ReentrantContext implements MarlinConst { 37 38 // RendererContext creation counter 39 private static final AtomicInteger CTX_COUNT = new AtomicInteger(1); 40 41 /** 42 * Create a new renderer context 43 * 44 * @return new RendererContext instance 45 */ 46 public static DRendererContext createContext() { 47 return new DRendererContext("ctx" 48 + Integer.toString(CTX_COUNT.getAndIncrement())); 49 } 50 51 // Smallest object used as Cleaner's parent reference 52 private final Object cleanerObj; 53 // dirty flag indicating an exception occured during pipeline in pathTo() 54 public boolean dirty = false; 55 // shared data 56 public final float[] float6 = new float[6]; 57 // shared curve (dirty) (Renderer / Stroker) 58 final DCurve curve = new DCurve(); 59 // MarlinRenderingEngine.TransformingPathConsumer2D 60 public final DTransformingPathConsumer2D transformerPC2D; 61 // shared memory between renderer instances: 62 final DRendererSharedMemory rdrMem; 63 public final DRenderer renderer; 64 private DRendererNoAA rendererNoAA = null; 65 public final DStroker stroker; 66 // Simplifies out collinear lines 67 public final DCollinearSimplifier simplifier = new DCollinearSimplifier(); 68 public final DDasher dasher; 69 // flag indicating the shape is stroked (1) or filled (0) 70 int stroking = 0; 71 // flag indicating to clip the shape 72 public boolean doClip = false; 73 // flag indicating if the path is closed or not (in advance) to handle properly caps 74 boolean closedPath = false; 75 // clip rectangle (ymin, ymax, xmin, xmax): 76 public final double[] clipRect = new double[4]; 77 78 // MarlinFX specific: 79 // dirty bbox rectangle 80 public final Rectangle clip = new Rectangle(); 81 // dirty MaskMarlinAlphaConsumer 82 public MaskMarlinAlphaConsumer consumer = null; 83 84 // Array caches: 85 /* clean int[] cache (zero-filled) = 4 refs */ 86 private final IntArrayCache cleanIntCache = new IntArrayCache(true, 4); 87 /* dirty int[] cache = 4 refs */ 88 private final IntArrayCache dirtyIntCache = new IntArrayCache(false, 4); 89 /* dirty double[] cache = 3 refs */ 90 private final DoubleArrayCache dirtyDoubleCache = new DoubleArrayCache(false, 3); 91 /* dirty byte[] cache = 1 ref */ 92 private final ByteArrayCache dirtyByteCache = new ByteArrayCache(false, 1); 93 94 // RendererContext statistics 95 final RendererStats stats; 96 97 /** 98 * Constructor 99 * 100 * @param name context name (debugging) 101 */ 102 DRendererContext(final String name) { 103 if (LOG_CREATE_CONTEXT) { 104 MarlinUtils.logInfo("new RendererContext = " + name); 105 } 106 this.cleanerObj = new Object(); 107 108 // create first stats (needed by newOffHeapArray): 109 if (DO_STATS || DO_MONITORS) { 110 stats = RendererStats.createInstance(cleanerObj, name); 111 // push cache stats: 112 stats.cacheStats = new CacheStats[] { cleanIntCache.stats, 113 dirtyIntCache.stats, dirtyDoubleCache.stats, dirtyByteCache.stats 114 }; 115 } else { 116 stats = null; 117 } 118 119 // MarlinRenderingEngine.TransformingPathConsumer2D 120 transformerPC2D = new DTransformingPathConsumer2D(this); 121 122 // Renderer shared memory: 123 rdrMem = new DRendererSharedMemory(this); 124 125 // Renderer: 126 renderer = new DRenderer(this); 127 128 stroker = new DStroker(this); 129 dasher = new DDasher(this); 130 } 131 132 /** 133 * Disposes this renderer context: 134 * clean up before reusing this context 135 */ 136 public void dispose() { 137 if (DO_STATS) { 138 if (stats.totalOffHeap > stats.totalOffHeapMax) { 139 stats.totalOffHeapMax = stats.totalOffHeap; 140 } 141 stats.totalOffHeap = 0L; 142 } 143 stroking = 0; 144 doClip = false; 145 closedPath = false; 146 147 // if context is maked as DIRTY: 148 if (dirty) { 149 // may happen if an exception if thrown in the pipeline processing: 150 // force cleanup of all possible pipelined blocks (except Renderer): 151 152 // Dasher: 153 this.dasher.dispose(); 154 // Stroker: 155 this.stroker.dispose(); 156 157 // mark context as CLEAN: 158 dirty = false; 159 } 160 } 161 162 public DRendererNoAA getRendererNoAA() { 163 if (rendererNoAA == null) { 164 rendererNoAA = new DRendererNoAA(this); 165 } 166 return rendererNoAA; 167 } 168 169 OffHeapArray newOffHeapArray(final long initialSize) { 170 if (DO_STATS) { 171 stats.totalOffHeapInitial += initialSize; 172 } 173 return new OffHeapArray(cleanerObj, initialSize); 174 } 175 176 IntArrayCache.Reference newCleanIntArrayRef(final int initialSize) { 177 return cleanIntCache.createRef(initialSize); 178 } 179 180 IntArrayCache.Reference newDirtyIntArrayRef(final int initialSize) { 181 return dirtyIntCache.createRef(initialSize); 182 } 183 184 DoubleArrayCache.Reference newDirtyDoubleArrayRef(final int initialSize) { 185 return dirtyDoubleCache.createRef(initialSize); 186 } 187 188 ByteArrayCache.Reference newDirtyByteArrayRef(final int initialSize) { 189 return dirtyByteCache.createRef(initialSize); 190 } 191 192 static final class DRendererSharedMemory { 193 194 // edges [ints] stored in off-heap memory 195 final OffHeapArray edges; 196 197 // edgeBuckets ref (clean) 198 final IntArrayCache.Reference edgeBuckets_ref; 199 // edgeBucketCounts ref (clean) 200 final IntArrayCache.Reference edgeBucketCounts_ref; 201 202 // alphaLine ref (clean) 203 final IntArrayCache.Reference alphaLine_ref; 204 205 // crossings ref (dirty) 206 final IntArrayCache.Reference crossings_ref; 207 // edgePtrs ref (dirty) 208 final IntArrayCache.Reference edgePtrs_ref; 209 // merge sort initial arrays 210 // aux_crossings ref (dirty) 211 final IntArrayCache.Reference aux_crossings_ref; 212 // aux_edgePtrs ref (dirty) 213 final IntArrayCache.Reference aux_edgePtrs_ref; 214 215 // blkFlags ref (clean) 216 final IntArrayCache.Reference blkFlags_ref; 217 218 DRendererSharedMemory(final DRendererContext rdrCtx) { 219 edges = rdrCtx.newOffHeapArray(INITIAL_EDGES_CAPACITY); // 96K 220 221 edgeBuckets_ref = rdrCtx.newCleanIntArrayRef(INITIAL_BUCKET_ARRAY); // 64K 222 edgeBucketCounts_ref = rdrCtx.newCleanIntArrayRef(INITIAL_BUCKET_ARRAY); // 64K 223 224 // 2048 (pixelsize) pixel large 225 alphaLine_ref = rdrCtx.newCleanIntArrayRef(INITIAL_AA_ARRAY); // 8K 226 227 crossings_ref = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K 228 aux_crossings_ref = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K 229 edgePtrs_ref = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K 230 aux_edgePtrs_ref = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K 231 232 blkFlags_ref = rdrCtx.newCleanIntArrayRef(INITIAL_ARRAY); // 1K = 1 tile line 233 } 234 } 235 }