1 /* 2 * Copyright (c) 2010, 2015, 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.prism.impl; 27 28 import java.security.AccessController; 29 import java.security.PrivilegedAction; 30 import java.util.Arrays; 31 import java.util.Collections; 32 import java.util.List; 33 import java.util.Properties; 34 import java.util.StringTokenizer; 35 import com.sun.javafx.PlatformUtil; 36 import com.sun.javafx.util.Utils; 37 38 /** 39 * Contains the runtime arguments used by Prism. 40 */ 41 public final class PrismSettings { 42 43 public static final boolean verbose; 44 public static final boolean debug; 45 public static final boolean trace; 46 public static final boolean printAllocs; 47 public static final boolean isVsyncEnabled; 48 public static final boolean dirtyOptsEnabled; 49 public static final boolean occlusionCullingEnabled; 50 public static final boolean scrollCacheOpt; 51 public static final boolean threadCheck; 52 public static final boolean cacheSimpleShapes; 53 public static final boolean cacheComplexShapes; 54 public static final boolean useNewImageLoader; 55 public static final List<String> tryOrder; 56 public static final int prismStatFrequency; 57 public static final boolean doNativePisces; 58 public static final String refType; 59 public static final boolean forceRepaint; 60 public static final boolean noFallback; 61 public static final boolean showDirtyRegions; 62 public static final boolean showOverdraw; 63 public static final boolean printRenderGraph; 64 public static final int minRTTSize; 65 public static final int dirtyRegionCount; 66 public static final boolean disableBadDriverWarning; 67 public static final boolean forceGPU; 68 public static final int maxTextureSize; 69 public static final int primTextureSize; 70 public static final boolean disableRegionCaching; 71 public static final boolean forcePow2; 72 public static final boolean noClampToZero; 73 public static final boolean disableD3D9Ex; 74 public static final boolean allowHiDPIScaling; 75 public static final long maxVram; 76 public static final long targetVram; 77 public static final boolean poolStats; 78 public static final boolean poolDebug; 79 public static final boolean disableEffects; 80 public static final int glyphCacheWidth; 81 public static final int glyphCacheHeight; 82 public static final String perfLog; 83 public static final boolean perfLogExitFlush; 84 public static final boolean perfLogFirstPaintFlush; 85 public static final boolean perfLogFirstPaintExit; 86 public static final boolean superShader; 87 public static final boolean skipMeshNormalComputation; 88 public static final boolean forceUploadingPainter; 89 public static final boolean forceAlphaTestShader; 90 public static final boolean forceNonAntialiasedShape; 91 92 93 private PrismSettings() { 94 } 95 96 private static void printBooleanOption(boolean opt, String trueStr) { 97 if (opt) { 98 System.out.println(trueStr); 99 } else { 100 System.out.print("Not "); 101 System.out.print(Character.toLowerCase(trueStr.charAt(0))); 102 System.out.println(trueStr.substring(1)); 103 } 104 } 105 106 static { 107 final Properties systemProperties = 108 (Properties) AccessController.doPrivileged( 109 (PrivilegedAction) () -> System.getProperties()); 110 111 /* Vsync */ 112 isVsyncEnabled = getBoolean(systemProperties, "prism.vsync", true) 113 && !getBoolean(systemProperties, 114 "javafx.animation.fullspeed", 115 false); 116 117 /* Dirty region optimizations */ 118 dirtyOptsEnabled = getBoolean(systemProperties, "prism.dirtyopts", 119 true); 120 occlusionCullingEnabled = 121 dirtyOptsEnabled && getBoolean(systemProperties, 122 "prism.occlusion.culling", 123 true); 124 125 // The maximum number of dirty regions to use. The absolute max that we can 126 // support at present is 15. 127 dirtyRegionCount = Utils.clamp(0, getInt(systemProperties, "prism.dirtyregioncount", 6, null), 15); 128 129 // Scrolling cache optimization 130 scrollCacheOpt = getBoolean(systemProperties, "prism.scrollcacheopt", true); 131 132 /* Dirty region optimizations */ 133 threadCheck = getBoolean(systemProperties, "prism.threadcheck", false); 134 135 /* Draws overlay rectangles showing where the dirty regions were */ 136 showDirtyRegions = getBoolean(systemProperties, "prism.showdirty", false); 137 138 /* 139 * Draws overlay rectangles showing not only the dirty regions, but how many times 140 * each area within that dirty region was drawn (covered by bounds of a drawn object). 141 */ 142 showOverdraw = getBoolean(systemProperties, "prism.showoverdraw", false); 143 144 /* Prints out the render graph, annotated with dirty opts information */ 145 printRenderGraph = getBoolean(systemProperties, "prism.printrendergraph", false); 146 147 /* Force scene repaint on every frame */ 148 forceRepaint = getBoolean(systemProperties, "prism.forcerepaint", false); 149 150 /* disable fallback to another toolkit if prism couldn't be init-ed */ 151 noFallback = getBoolean(systemProperties, "prism.noFallback", false); 152 153 /* Shape caching optimizations */ 154 String cache = systemProperties.getProperty("prism.cacheshapes", 155 "complex"); 156 if ("all".equals(cache) || "true".equals(cache)) { 157 cacheSimpleShapes = true; 158 cacheComplexShapes = true; 159 } else if ("complex".equals(cache)) { 160 cacheSimpleShapes = false; 161 cacheComplexShapes = true; 162 } else { 163 cacheSimpleShapes = false; 164 cacheComplexShapes = false; 165 } 166 167 /* New javafx-iio image loader */ 168 useNewImageLoader = getBoolean(systemProperties, "prism.newiio", true); 169 170 /* Verbose output*/ 171 verbose = getBoolean(systemProperties, "prism.verbose", false); 172 173 /* Prism statistics print frequency, <=0 means "do not print" */ 174 prismStatFrequency = 175 getInt(systemProperties, "prism.printStats", 176 0, 1, "Try -Dprism.printStats=<true or number>"); 177 178 /* Debug output*/ 179 debug = getBoolean(systemProperties, "prism.debug", false); 180 181 /* Trace output*/ 182 trace = getBoolean(systemProperties, "prism.trace", false); 183 184 /* Print texture allocation data */ 185 printAllocs = getBoolean(systemProperties, "prism.printallocs", false); 186 187 /* Disable bad driver check warning */ 188 disableBadDriverWarning = getBoolean(systemProperties, 189 "prism.disableBadDriverWarning", 190 false); 191 192 /* Force GPU, if GPU is PS 3 capable, disable GPU qualification check. */ 193 forceGPU = getBoolean(systemProperties, "prism.forceGPU", false); 194 195 /* Skip mesh normal computation */ 196 skipMeshNormalComputation = getBoolean(systemProperties, 197 "prism.experimental.skipMeshNormalComputation", false); 198 199 String order = systemProperties.getProperty("prism.order"); 200 String[] tryOrderArr; 201 if (order != null) { 202 tryOrderArr = split(order, ","); 203 } else { 204 if (PlatformUtil.isWindows()) { 205 tryOrderArr = new String[] { "d3d", "sw" }; 206 } else if (PlatformUtil.isMac()) { 207 tryOrderArr = new String[] { "es2", "sw" }; 208 } else if (PlatformUtil.isIOS()) { 209 tryOrderArr = new String[] { "es2" }; 210 } else if (PlatformUtil.isAndroid()) { 211 tryOrderArr = new String[] { "es2" }; 212 } else if (PlatformUtil.isLinux()) { 213 tryOrderArr = new String[] { "es2", "sw" }; 214 } else { 215 tryOrderArr = new String[] { "sw" }; 216 } 217 } 218 219 tryOrder = Collections.unmodifiableList(Arrays.asList(tryOrderArr)); 220 221 String npprop = systemProperties.getProperty("prism.nativepisces"); 222 if (npprop == null) { 223 doNativePisces = PlatformUtil.isEmbedded() || !PlatformUtil.isLinux(); 224 } else { 225 doNativePisces = Boolean.parseBoolean(npprop); 226 } 227 228 String primtex = systemProperties.getProperty("prism.primtextures"); 229 if (primtex == null) { 230 primTextureSize = PlatformUtil.isEmbedded() ? -1 : 0; 231 } else if (primtex.equals("true")) { 232 primTextureSize = -1; 233 } else if (primtex.equals("false")) { 234 primTextureSize = 0; 235 } else { 236 primTextureSize = 237 parseInt(primtex, 0, 238 "Try -Dprism.primtextures=[true|false|<number>]"); 239 } 240 241 /* Setting for reference type used by Disposer */ 242 refType = systemProperties.getProperty("prism.reftype"); 243 244 forcePow2 = getBoolean(systemProperties, "prism.forcepowerof2", false); 245 noClampToZero = getBoolean(systemProperties, "prism.noclamptozero", false); 246 247 allowHiDPIScaling = getBoolean(systemProperties, "prism.allowhidpi", true); 248 249 maxVram = getLong(systemProperties, "prism.maxvram", 512 * 1024 * 1024, 250 "Try -Dprism.maxvram=<long>[kKmMgG]"); 251 targetVram = getLong(systemProperties, "prism.targetvram", maxVram / 8, maxVram, 252 "Try -Dprism.targetvram=<long>[kKmMgG]|<double(0,100)>%"); 253 poolStats = getBoolean(systemProperties, "prism.poolstats", false); 254 poolDebug = getBoolean(systemProperties, "prism.pooldebug", false); 255 256 if (verbose) { 257 System.out.print("Prism pipeline init order: "); 258 for (String s : tryOrder) { 259 System.out.print(s+" "); 260 } 261 System.out.println(""); 262 String piscestype = (doNativePisces ? "native" : "java"); 263 System.out.println("Using " + piscestype + "-based Pisces rasterizer"); 264 printBooleanOption(dirtyOptsEnabled, "Using dirty region optimizations"); 265 if (primTextureSize == 0) { 266 System.out.println("Not using texture mask for primitives"); 267 } else if (primTextureSize < 0) { 268 System.out.println("Using system sized mask for primitives"); 269 } else { 270 System.out.println("Using "+primTextureSize+" sized mask for primitives"); 271 } 272 printBooleanOption(forcePow2, "Forcing power of 2 sizes for textures"); 273 printBooleanOption(!noClampToZero, "Using hardware CLAMP_TO_ZERO mode"); 274 printBooleanOption(allowHiDPIScaling, "Opting in for HiDPI pixel scaling"); 275 } 276 277 /* 278 * Setting for maximum texture size. Default is 4096. 279 * This will clamp the limit reported by the card to the specified 280 * value. A value of <= 0 will disable this clamping, causing the 281 * limit reported by the card to be used without modification. 282 * 283 * See RT-21998. This is a workaround for the fact that we don't 284 * yet handle the case where a texture allocation fails during 285 * rendering of a very large tiled image. 286 */ 287 int size = getInt(systemProperties, "prism.maxTextureSize", 288 4096, "Try -Dprism.maxTextureSize=<number>"); 289 290 if (size <= 0) { 291 size = Integer.MAX_VALUE; 292 } 293 maxTextureSize = size; 294 295 /* 296 * Check minimum RTT size 297 * This is needed for some embedded platforms to avoid rendering artifacts 298 * when rendering into small RTT. 299 */ 300 minRTTSize = getInt(systemProperties, "prism.minrttsize", 301 PlatformUtil.isEmbedded() ? 16 : 0, "Try -Dprism.minrttsize=<number>"); 302 303 disableRegionCaching = getBoolean(systemProperties, 304 "prism.disableRegionCaching", 305 false); 306 307 disableD3D9Ex = getBoolean(systemProperties, "prism.disableD3D9Ex", false); 308 309 disableEffects = getBoolean(systemProperties, "prism.disableEffects", false); 310 311 glyphCacheWidth = getInt(systemProperties, "prism.glyphCacheWidth", 1024, 312 "Try -Dprism.glyphCacheWidth=<number>"); 313 glyphCacheHeight = getInt(systemProperties, "prism.glyphCacheHeight", 1024, 314 "Try -Dprism.glyphCacheHeight=<number>"); 315 316 /* 317 * Performance Logger flags 318 * Enable the performance logger, print on exit, print on first paint etc. 319 */ 320 perfLog = systemProperties.getProperty("sun.perflog"); 321 perfLogExitFlush = getBoolean(systemProperties, "sun.perflog.fx.exitflush", false, true); 322 perfLogFirstPaintFlush = getBoolean(systemProperties, "sun.perflog.fx.firstpaintflush", false, true); 323 perfLogFirstPaintExit = getBoolean(systemProperties, "sun.perflog.fx.firstpaintexit", false, true); 324 325 superShader = getBoolean(systemProperties, "prism.supershader", true); 326 327 // Force uploading painter (e.g., to avoid Linux live-resize jittering) 328 forceUploadingPainter = getBoolean(systemProperties, "prism.forceUploadingPainter", false); 329 330 // Force the use of fragment shader that does alpha testing (i.e. discard if alpha == 0.0) 331 forceAlphaTestShader = getBoolean(systemProperties, "prism.forceAlphaTestShader", false); 332 333 // Force non anti-aliasing (not smooth) shape rendering 334 forceNonAntialiasedShape = getBoolean(systemProperties, "prism.forceNonAntialiasedShape", false); 335 336 } 337 338 private static int parseInt(String s, int dflt, int trueDflt, 339 String errMsg) { 340 return "true".equalsIgnoreCase(s) 341 ? trueDflt 342 : parseInt(s, dflt, errMsg); 343 } 344 345 private static int parseInt(String s, int dflt, String errMsg) { 346 if (s != null) { 347 try { 348 return Integer.parseInt(s); 349 } catch (Exception e) { 350 if (errMsg != null) { 351 System.err.println(errMsg); 352 } 353 } 354 } 355 356 return dflt; 357 } 358 359 private static long parseLong(String s, long dflt, long rel, String errMsg) { 360 if (s != null && s.length() > 0) { 361 long mult = 1; 362 if (s.endsWith("%")) { 363 if (rel > 0) { 364 try { 365 s = s.substring(0, s.length() - 1); 366 double percent = Double.parseDouble(s); 367 if (percent >= 0 && percent <= 100) { 368 return Math.round(rel * percent / 100.0); 369 } 370 } catch (Exception e) { 371 } 372 } 373 374 if (errMsg != null) { 375 System.err.println(errMsg); 376 } 377 return dflt; 378 } 379 if (s.endsWith("k") || s.endsWith("K")) { 380 mult = 1024L; 381 } else if (s.endsWith("m") || s.endsWith("M")) { 382 mult = 1024L * 1024L; 383 } else if (s.endsWith("g") || s.endsWith("G")) { 384 mult = 1024L * 1024L * 1024L; 385 } 386 if (mult > 1) { 387 s = s.substring(0, s.length() - 1); 388 } 389 try { 390 return Long.parseLong(s) * mult; 391 } catch (Exception e) { 392 if (errMsg != null) { 393 System.err.println(errMsg); 394 } 395 } 396 } 397 398 return dflt; 399 } 400 401 /* A simple version of String.split(), since that isn't available on CDC */ 402 private static String[] split(String str, String delim) { 403 StringTokenizer st = new StringTokenizer(str, delim); 404 String[] ret = new String[st.countTokens()]; 405 int i = 0; 406 while (st.hasMoreTokens()) { 407 ret[i++] = st.nextToken(); 408 } 409 return ret; 410 } 411 412 private static boolean getBoolean(Properties properties, 413 String key, 414 boolean dflt) { 415 final String strval = properties.getProperty(key); 416 return (strval != null) ? Boolean.parseBoolean(strval) : dflt; 417 } 418 419 private static boolean getBoolean(Properties properties, 420 String key, 421 boolean dflt, 422 boolean dfltIfDefined) { 423 final String strval = properties.getProperty(key); 424 if (strval != null && strval.length() == 0) return dfltIfDefined; 425 return (strval != null) ? Boolean.parseBoolean(strval) : dflt; 426 } 427 428 private static int getInt(Properties properties, 429 String key, 430 int dflt, 431 int trueDflt, 432 String errMsg) { 433 return parseInt(properties.getProperty(key), 434 dflt, 435 trueDflt, 436 errMsg); 437 } 438 439 private static int getInt(Properties properties, 440 String key, 441 int dflt, 442 String errMsg) { 443 return parseInt(properties.getProperty(key), 444 dflt, 445 errMsg); 446 } 447 448 private static long getLong(Properties properties, 449 String key, 450 long dflt, 451 String errMsg) 452 { 453 return parseLong(properties.getProperty(key), 454 dflt, 0, 455 errMsg); 456 } 457 458 private static long getLong(Properties properties, 459 String key, 460 long dflt, long rel, 461 String errMsg) 462 { 463 return parseLong(properties.getProperty(key), 464 dflt, rel, 465 errMsg); 466 } 467 }