1 /* 2 * Copyright (c) 2007, 2016, 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.security.AccessController; 29 import static com.sun.marlin.MarlinUtils.logInfo; 30 import com.sun.util.reentrant.ReentrantContextProvider; 31 import com.sun.util.reentrant.ReentrantContextProviderCLQ; 32 import com.sun.util.reentrant.ReentrantContextProviderTL; 33 import com.sun.javafx.geom.PathIterator; 34 import com.sun.prism.BasicStroke; 35 import java.security.PrivilegedAction; 36 37 /** 38 * Marlin RendererEngine implementation (derived from Pisces) 39 */ 40 public class DMarlinRenderingEngine implements MarlinConst 41 { 42 /** 43 * Private constructor to prevent instantiation. 44 */ 45 private DMarlinRenderingEngine() { 46 } 47 48 static { 49 if (PathIterator.WIND_NON_ZERO != DMarlinRenderer.WIND_NON_ZERO || 50 PathIterator.WIND_EVEN_ODD != DMarlinRenderer.WIND_EVEN_ODD || 51 BasicStroke.JOIN_MITER != Stroker.JOIN_MITER || 52 BasicStroke.JOIN_ROUND != Stroker.JOIN_ROUND || 53 BasicStroke.JOIN_BEVEL != Stroker.JOIN_BEVEL || 54 BasicStroke.CAP_BUTT != Stroker.CAP_BUTT || 55 BasicStroke.CAP_ROUND != Stroker.CAP_ROUND || 56 BasicStroke.CAP_SQUARE != Stroker.CAP_SQUARE) 57 { 58 throw new InternalError("mismatched renderer constants"); 59 } 60 } 61 62 // --- DRendererContext handling --- 63 // use ThreadLocal or ConcurrentLinkedQueue to get one DRendererContext 64 private static final boolean USE_THREAD_LOCAL; 65 66 // reference type stored in either TL or CLQ 67 static final int REF_TYPE; 68 69 // Per-thread DRendererContext 70 private static final ReentrantContextProvider<DRendererContext> RDR_CTX_PROVIDER; 71 72 // Static initializer to use TL or CLQ mode 73 static { 74 USE_THREAD_LOCAL = MarlinProperties.isUseThreadLocal(); 75 76 // Soft reference by default: 77 final String refType = AccessController.doPrivileged( 78 (PrivilegedAction<String>) () -> { 79 String value = System.getProperty("prism.marlin.useRef"); 80 return (value == null) ? "soft" : value; 81 }); 82 switch (refType) { 83 default: 84 case "soft": 85 REF_TYPE = ReentrantContextProvider.REF_SOFT; 86 break; 87 case "weak": 88 REF_TYPE = ReentrantContextProvider.REF_WEAK; 89 break; 90 case "hard": 91 REF_TYPE = ReentrantContextProvider.REF_HARD; 92 break; 93 } 94 95 if (USE_THREAD_LOCAL) { 96 RDR_CTX_PROVIDER = new ReentrantContextProviderTL<DRendererContext>(REF_TYPE) 97 { 98 @Override 99 protected DRendererContext newContext() { 100 return DRendererContext.createContext(); 101 } 102 }; 103 } else { 104 RDR_CTX_PROVIDER = new ReentrantContextProviderCLQ<DRendererContext>(REF_TYPE) 105 { 106 @Override 107 protected DRendererContext newContext() { 108 return DRendererContext.createContext(); 109 } 110 }; 111 } 112 113 logSettings(DRenderer.class.getName()); 114 } 115 116 private static boolean SETTINGS_LOGGED = !ENABLE_LOGS; 117 118 public static void logSettings(final String reClass) { 119 // log information at startup 120 if (SETTINGS_LOGGED) { 121 return; 122 } 123 SETTINGS_LOGGED = true; 124 125 String refType; 126 switch (REF_TYPE) { 127 default: 128 case ReentrantContextProvider.REF_HARD: 129 refType = "hard"; 130 break; 131 case ReentrantContextProvider.REF_SOFT: 132 refType = "soft"; 133 break; 134 case ReentrantContextProvider.REF_WEAK: 135 refType = "weak"; 136 break; 137 } 138 139 logInfo("==========================================================" 140 + "====================="); 141 142 logInfo("Marlin software rasterizer = ENABLED"); 143 logInfo("Version = [" 144 + Version.getVersion() + "]"); 145 logInfo("prism.marlin = " 146 + reClass); 147 logInfo("prism.marlin.useThreadLocal = " 148 + USE_THREAD_LOCAL); 149 logInfo("prism.marlin.useRef = " 150 + refType); 151 152 logInfo("prism.marlin.edges = " 153 + MarlinConst.INITIAL_EDGES_COUNT); 154 logInfo("prism.marlin.pixelsize = " 155 + MarlinConst.INITIAL_PIXEL_DIM); 156 157 logInfo("prism.marlin.subPixel_log2_X = " 158 + MarlinConst.SUBPIXEL_LG_POSITIONS_X); 159 logInfo("prism.marlin.subPixel_log2_Y = " 160 + MarlinConst.SUBPIXEL_LG_POSITIONS_Y); 161 162 logInfo("prism.marlin.blockSize_log2 = " 163 + MarlinConst.BLOCK_SIZE_LG); 164 165 // RLE / blockFlags settings 166 167 logInfo("prism.marlin.forceRLE = " 168 + MarlinProperties.isForceRLE()); 169 logInfo("prism.marlin.forceNoRLE = " 170 + MarlinProperties.isForceNoRLE()); 171 logInfo("prism.marlin.useTileFlags = " 172 + MarlinProperties.isUseTileFlags()); 173 logInfo("prism.marlin.useTileFlags.useHeuristics = " 174 + MarlinProperties.isUseTileFlagsWithHeuristics()); 175 logInfo("prism.marlin.rleMinWidth = " 176 + MarlinConst.RLE_MIN_WIDTH); 177 178 // optimisation parameters 179 logInfo("prism.marlin.useSimplifier = " 180 + MarlinConst.USE_SIMPLIFIER); 181 182 // debugging parameters 183 logInfo("prism.marlin.doStats = " 184 + MarlinConst.DO_STATS); 185 logInfo("prism.marlin.doMonitors = " 186 + MarlinConst.DO_MONITORS); 187 logInfo("prism.marlin.doChecks = " 188 + MarlinConst.DO_CHECKS); 189 190 // logging parameters 191 logInfo("prism.marlin.log = " 192 + MarlinConst.ENABLE_LOGS); 193 logInfo("prism.marlin.useLogger = " 194 + MarlinConst.USE_LOGGER); 195 logInfo("prism.marlin.logCreateContext = " 196 + MarlinConst.LOG_CREATE_CONTEXT); 197 logInfo("prism.marlin.logUnsafeMalloc = " 198 + MarlinConst.LOG_UNSAFE_MALLOC); 199 200 // quality settings 201 logInfo("Renderer settings:"); 202 logInfo("CUB_COUNT_LG = " + Renderer.CUB_COUNT_LG); 203 logInfo("CUB_DEC_BND = " + Renderer.CUB_DEC_BND); 204 logInfo("CUB_INC_BND = " + Renderer.CUB_INC_BND); 205 logInfo("QUAD_DEC_BND = " + Renderer.QUAD_DEC_BND); 206 207 logInfo("USE_SUBDIVIDE_QUAD = " + RendererNoAA.USE_SUBDIVIDE_QUAD); 208 logInfo("QUAD_ERR_SUBPIX = " + RendererNoAA.QUAD_ERR_SUBPIX); 209 210 logInfo("INITIAL_EDGES_CAPACITY = " 211 + MarlinConst.INITIAL_EDGES_CAPACITY); 212 logInfo("INITIAL_CROSSING_COUNT = " 213 + Renderer.INITIAL_CROSSING_COUNT); 214 215 logInfo("==========================================================" 216 + "====================="); 217 } 218 219 /** 220 * Get the DRendererContext instance dedicated to the current thread 221 * @return DRendererContext instance 222 */ 223 @SuppressWarnings({"unchecked"}) 224 public static DRendererContext getRendererContext() { 225 final DRendererContext rdrCtx = RDR_CTX_PROVIDER.acquire(); 226 if (DO_MONITORS) { 227 rdrCtx.stats.mon_pre_getAATileGenerator.start(); 228 } 229 return rdrCtx; 230 } 231 232 /** 233 * Reset and return the given DRendererContext instance for reuse 234 * @param rdrCtx DRendererContext instance 235 */ 236 public static void returnRendererContext(final DRendererContext rdrCtx) { 237 rdrCtx.dispose(); 238 239 if (DO_MONITORS) { 240 rdrCtx.stats.mon_pre_getAATileGenerator.stop(); 241 } 242 RDR_CTX_PROVIDER.release(rdrCtx); 243 } 244 }