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