1 /* 2 * Copyright (c) 2007, 2018, 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 final class MarlinRenderingEngine implements MarlinConst 41 { 42 /** 43 * Private constructor to prevent instantiation. 44 */ 45 private MarlinRenderingEngine() { 46 } 47 48 static { 49 if (PathIterator.WIND_NON_ZERO != WIND_NON_ZERO || 50 PathIterator.WIND_EVEN_ODD != WIND_EVEN_ODD || 51 BasicStroke.JOIN_MITER != JOIN_MITER || 52 BasicStroke.JOIN_ROUND != JOIN_ROUND || 53 BasicStroke.JOIN_BEVEL != JOIN_BEVEL || 54 BasicStroke.CAP_BUTT != CAP_BUTT || 55 BasicStroke.CAP_ROUND != CAP_ROUND || 56 BasicStroke.CAP_SQUARE != CAP_SQUARE) 57 { 58 throw new InternalError("mismatched renderer constants"); 59 } 60 } 61 62 // --- RendererContext handling --- 63 // use ThreadLocal or ConcurrentLinkedQueue to get one RendererContext 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 RendererContext 70 private static final ReentrantContextProvider<RendererContext> 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<RendererContext>(REF_TYPE) 97 { 98 @Override 99 protected RendererContext newContext() { 100 return RendererContext.createContext(); 101 } 102 }; 103 } else { 104 RDR_CTX_PROVIDER = new ReentrantContextProviderCLQ<RendererContext>(REF_TYPE) 105 { 106 @Override 107 protected RendererContext newContext() { 108 return RendererContext.createContext(); 109 } 110 }; 111 } 112 113 logSettings(Renderer.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.pixelWidth = " 155 + MarlinConst.INITIAL_PIXEL_WIDTH); 156 logInfo("prism.marlin.pixelHeight = " 157 + MarlinConst.INITIAL_PIXEL_HEIGHT); 158 159 logInfo("prism.marlin.profile = " 160 + (MarlinProperties.isProfileQuality() ? 161 "quality" : "speed")); 162 163 logInfo("prism.marlin.subPixel_log2_X = " 164 + MarlinConst.SUBPIXEL_LG_POSITIONS_X); 165 logInfo("prism.marlin.subPixel_log2_Y = " 166 + MarlinConst.SUBPIXEL_LG_POSITIONS_Y); 167 168 logInfo("prism.marlin.blockSize_log2 = " 169 + MarlinConst.BLOCK_SIZE_LG); 170 171 // RLE / blockFlags settings 172 173 logInfo("prism.marlin.forceRLE = " 174 + MarlinProperties.isForceRLE()); 175 logInfo("prism.marlin.forceNoRLE = " 176 + MarlinProperties.isForceNoRLE()); 177 logInfo("prism.marlin.useTileFlags = " 178 + MarlinProperties.isUseTileFlags()); 179 logInfo("prism.marlin.useTileFlags.useHeuristics = " 180 + MarlinProperties.isUseTileFlagsWithHeuristics()); 181 logInfo("prism.marlin.rleMinWidth = " 182 + MarlinConst.RLE_MIN_WIDTH); 183 184 // optimisation parameters 185 logInfo("prism.marlin.useSimplifier = " 186 + MarlinConst.USE_SIMPLIFIER); 187 logInfo("prism.marlin.usePathSimplifier= " 188 + MarlinConst.USE_PATH_SIMPLIFIER); 189 logInfo("prism.marlin.pathSimplifier.pixTol = " 190 + MarlinProperties.getPathSimplifierPixelTolerance()); 191 192 logInfo("prism.marlin.clip = " 193 + MarlinProperties.isDoClip()); 194 logInfo("prism.marlin.clip.runtime.enable = " 195 + MarlinProperties.isDoClipRuntimeFlag()); 196 197 logInfo("prism.marlin.clip.subdivider = " 198 + MarlinProperties.isDoClipSubdivider()); 199 logInfo("prism.marlin.clip.subdivider.minLength = " 200 + MarlinProperties.getSubdividerMinLength()); 201 202 // debugging parameters 203 logInfo("prism.marlin.doStats = " 204 + MarlinConst.DO_STATS); 205 logInfo("prism.marlin.doMonitors = " 206 + MarlinConst.DO_MONITORS); 207 logInfo("prism.marlin.doChecks = " 208 + MarlinConst.DO_CHECKS); 209 210 // logging parameters 211 logInfo("prism.marlin.log = " 212 + MarlinConst.ENABLE_LOGS); 213 logInfo("prism.marlin.useLogger = " 214 + MarlinConst.USE_LOGGER); 215 logInfo("prism.marlin.logCreateContext = " 216 + MarlinConst.LOG_CREATE_CONTEXT); 217 logInfo("prism.marlin.logUnsafeMalloc = " 218 + MarlinConst.LOG_UNSAFE_MALLOC); 219 220 // quality settings 221 logInfo("prism.marlin.curve_len_err = " 222 + MarlinProperties.getCurveLengthError()); 223 logInfo("prism.marlin.cubic_dec_d2 = " 224 + MarlinProperties.getCubicDecD2()); 225 logInfo("prism.marlin.cubic_inc_d1 = " 226 + MarlinProperties.getCubicIncD1()); 227 logInfo("prism.marlin.quad_dec_d2 = " 228 + MarlinProperties.getQuadDecD2()); 229 230 logInfo("Renderer settings:"); 231 logInfo("CUB_DEC_BND = " + Renderer.CUB_DEC_BND); 232 logInfo("CUB_INC_BND = " + Renderer.CUB_INC_BND); 233 logInfo("QUAD_DEC_BND = " + Renderer.QUAD_DEC_BND); 234 235 logInfo("INITIAL_EDGES_CAPACITY = " 236 + MarlinConst.INITIAL_EDGES_CAPACITY); 237 logInfo("INITIAL_CROSSING_COUNT = " 238 + MarlinConst.INITIAL_CROSSING_COUNT); 239 240 logInfo("==========================================================" 241 + "====================="); 242 } 243 244 /** 245 * Get the RendererContext instance dedicated to the current thread 246 * @return RendererContext instance 247 */ 248 @SuppressWarnings({"unchecked"}) 249 public static RendererContext getRendererContext() { 250 final RendererContext rdrCtx = RDR_CTX_PROVIDER.acquire(); 251 if (DO_MONITORS) { 252 rdrCtx.stats.mon_pre_getAATileGenerator.start(); 253 } 254 return rdrCtx; 255 } 256 257 /** 258 * Reset and return the given RendererContext instance for reuse 259 * @param rdrCtx RendererContext instance 260 */ 261 public static void returnRendererContext(final RendererContext rdrCtx) { 262 rdrCtx.dispose(); 263 264 if (DO_MONITORS) { 265 rdrCtx.stats.mon_pre_getAATileGenerator.stop(); 266 } 267 RDR_CTX_PROVIDER.release(rdrCtx); 268 } 269 }