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