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 72 // MarlinFX specific: 73 // dirty bbox rectangle 74 public final Rectangle clip = new Rectangle(); 75 // dirty MaskMarlinAlphaConsumer 76 public MaskMarlinAlphaConsumer consumer = null; 77 78 // Array caches: 79 /* clean int[] cache (zero-filled) = 4 refs */ 80 private final IntArrayCache cleanIntCache = new IntArrayCache(true, 4); 81 /* dirty int[] cache = 4 refs */ 82 private final IntArrayCache dirtyIntCache = new IntArrayCache(false, 4); 83 /* dirty double[] cache = 3 refs */ 84 private final DoubleArrayCache dirtyDoubleCache = new DoubleArrayCache(false, 3); 85 /* dirty byte[] cache = 1 ref */ 86 private final ByteArrayCache dirtyByteCache = new ByteArrayCache(false, 1); 87 88 // RendererContext statistics 89 final RendererStats stats; 90 91 /** 92 * Constructor 93 * 94 * @param name context name (debugging) 95 */ 96 DRendererContext(final String name) { 97 if (LOG_CREATE_CONTEXT) { 98 MarlinUtils.logInfo("new RendererContext = " + name); 99 } 100 this.cleanerObj = new Object(); 101 102 // create first stats (needed by newOffHeapArray): 103 if (DO_STATS || DO_MONITORS) { 104 stats = RendererStats.createInstance(cleanerObj, name); 105 // push cache stats: 106 stats.cacheStats = new CacheStats[] { cleanIntCache.stats, 107 dirtyIntCache.stats, dirtyDoubleCache.stats, dirtyByteCache.stats 108 }; 109 } else { 110 stats = null; 111 } 112 113 // MarlinRenderingEngine.TransformingPathConsumer2D 114 transformerPC2D = new DTransformingPathConsumer2D(); 115 116 // Renderer shared memory: 117 rdrMem = new DRendererSharedMemory(this); 118 119 // Renderer: 120 renderer = new DRenderer(this); 121 122 stroker = new DStroker(this); 123 dasher = new DDasher(this); 124 } 125 126 /** 127 * Disposes this renderer context: 128 * clean up before reusing this context 129 */ 130 public void dispose() { 131 if (DO_STATS) { 132 if (stats.totalOffHeap > stats.totalOffHeapMax) { 133 stats.totalOffHeapMax = stats.totalOffHeap; 134 } 135 stats.totalOffHeap = 0L; 136 } 137 stroking = 0; 138 // if context is maked as DIRTY: 139 if (dirty) { 140 // may happen if an exception if thrown in the pipeline processing: 141 // force cleanup of all possible pipelined blocks (except Renderer): 142 143 // Dasher: 144 this.dasher.dispose(); 145 // Stroker: 146 this.stroker.dispose(); 147 148 // mark context as CLEAN: 149 dirty = false; 150 } 151 } 152 153 public DRendererNoAA getRendererNoAA() { 154 if (rendererNoAA == null) { 155 rendererNoAA = new DRendererNoAA(this); 156 } 157 return rendererNoAA; 158 } 159 160 OffHeapArray newOffHeapArray(final long initialSize) { 161 if (DO_STATS) { 162 stats.totalOffHeapInitial += initialSize; 163 } 164 return new OffHeapArray(cleanerObj, initialSize); 165 } 166 167 IntArrayCache.Reference newCleanIntArrayRef(final int initialSize) { 168 return cleanIntCache.createRef(initialSize); 169 } 170 171 IntArrayCache.Reference newDirtyIntArrayRef(final int initialSize) { 172 return dirtyIntCache.createRef(initialSize); 173 } 174 175 DoubleArrayCache.Reference newDirtyDoubleArrayRef(final int initialSize) { 176 return dirtyDoubleCache.createRef(initialSize); 177 } 178 179 ByteArrayCache.Reference newDirtyByteArrayRef(final int initialSize) { 180 return dirtyByteCache.createRef(initialSize); 181 } 182 183 static final class DRendererSharedMemory { 184 185 // edges [ints] stored in off-heap memory 186 final OffHeapArray edges; 187 188 // edgeBuckets ref (clean) 189 final IntArrayCache.Reference edgeBuckets_ref; 190 // edgeBucketCounts ref (clean) 191 final IntArrayCache.Reference edgeBucketCounts_ref; 192 193 // alphaLine ref (clean) 194 final IntArrayCache.Reference alphaLine_ref; 195 196 // crossings ref (dirty) 197 final IntArrayCache.Reference crossings_ref; 198 // edgePtrs ref (dirty) 199 final IntArrayCache.Reference edgePtrs_ref; 200 // merge sort initial arrays 201 // aux_crossings ref (dirty) 202 final IntArrayCache.Reference aux_crossings_ref; 203 // aux_edgePtrs ref (dirty) 204 final IntArrayCache.Reference aux_edgePtrs_ref; 205 206 // blkFlags ref (clean) 207 final IntArrayCache.Reference blkFlags_ref; 208 209 DRendererSharedMemory(final DRendererContext rdrCtx) { 210 edges = rdrCtx.newOffHeapArray(INITIAL_EDGES_CAPACITY); // 96K 211 212 edgeBuckets_ref = rdrCtx.newCleanIntArrayRef(INITIAL_BUCKET_ARRAY); // 64K 213 edgeBucketCounts_ref = rdrCtx.newCleanIntArrayRef(INITIAL_BUCKET_ARRAY); // 64K 214 215 // 2048 (pixelsize) pixel large 216 alphaLine_ref = rdrCtx.newCleanIntArrayRef(INITIAL_AA_ARRAY); // 8K 217 218 crossings_ref = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K 219 aux_crossings_ref = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K 220 edgePtrs_ref = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K 221 aux_edgePtrs_ref = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K 222 223 blkFlags_ref = rdrCtx.newCleanIntArrayRef(INITIAL_ARRAY); // 1K = 1 tile line 224 } 225 } 226 }