1 /* 2 * Copyright (c) 2010, 2013, 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.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 threadCheck; 51 public static final boolean cacheSimpleShapes; 52 public static final boolean cacheComplexShapes; 53 public static final boolean useNewImageLoader; 54 public static final List<String> tryOrder; 55 public static final int prismStatFrequency; 56 public static final boolean doPiscesText; 57 public static final boolean doOpenPiscesText; 58 public static final boolean doNativePisces; 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 boolean shutdownHook; 66 public static final int minTextureSize; 67 public static final int minRTTSize; 68 public static final int dirtyRegionCount; 69 public static final boolean disableBadDriverWarning; 70 public static final boolean forceGPU; 71 public static final int maxTextureSize; 72 public static final int primTextureSize; 73 public static final boolean disableRegionCaching; 74 public static final boolean forcePow2; 75 public static final boolean noClampToZero; 76 public static final boolean disableD3D9Ex; 77 public static final boolean allowHiDPIScaling; 78 public static final long maxVram; 79 public static final long targetVram; 80 public static final boolean poolStats; 81 public static final boolean poolDebug; 82 public static final boolean disableEffects; 83 public static final int glyphCacheWidth; 84 public static final int glyphCacheHeight; 85 public static final String perfLog; 86 public static final boolean perfLogExitFlush; 87 public static final boolean perfLogFirstPaintFlush; 88 public static final boolean perfLogFirstPaintExit; 89 public static final boolean superShader; 90 91 private PrismSettings() { 92 } 93 94 private static void printBooleanOption(boolean opt, String trueStr) { 95 if (opt) { 96 System.out.println(trueStr); 97 } else { 98 System.out.print("Not "); 99 System.out.print(Character.toLowerCase(trueStr.charAt(0))); 100 System.out.println(trueStr.substring(1)); 101 } 102 } 103 104 static { 105 final Properties systemProperties = 106 (Properties) AccessController.doPrivileged( 107 new PrivilegedAction() { 108 @Override 109 public Object run() { 110 return System.getProperties(); 111 } 112 }); 113 114 /* Vsync */ 115 isVsyncEnabled = getBoolean(systemProperties, "prism.vsync", true) 116 && !getBoolean(systemProperties, 117 "javafx.animation.fullspeed", 118 false); 119 120 /* Dirty region optimizations */ 121 dirtyOptsEnabled = getBoolean(systemProperties, "prism.dirtyopts", 122 true); 123 occlusionCullingEnabled = 124 dirtyOptsEnabled && getBoolean(systemProperties, 125 "prism.occlusion.culling", 126 true); 127 128 // The maximum number of dirty regions to use. The absolute max that we can 129 // support at present is 15. 130 dirtyRegionCount = Utils.clamp(0, getInt(systemProperties, "prism.dirtyregioncount", 6, null), 15); 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 String order = systemProperties.getProperty("prism.order"); 196 String[] tryOrderArr; 197 if (order != null) { 198 tryOrderArr = split(order, ","); 199 } else { 200 if (PlatformUtil.isWindows()) { 201 tryOrderArr = new String[] { "d3d", "sw" }; 202 } else if (PlatformUtil.isMac()) { 203 tryOrderArr = new String[] { "es2", "sw" }; 204 } else if (PlatformUtil.isIOS()) { 205 tryOrderArr = new String[] { "es2" }; 206 } else if (PlatformUtil.isAndroid()) { 207 tryOrderArr = new String[] { "es2" }; 208 } else if (PlatformUtil.isLinux()) { 209 tryOrderArr = new String[] { "es2", "sw" }; 210 } else { 211 tryOrderArr = new String[] { "sw" }; 212 } 213 } 214 215 tryOrder = Collections.unmodifiableList(Arrays.asList(tryOrderArr)); 216 217 String npprop = systemProperties.getProperty("prism.nativepisces"); 218 if (npprop == null) { 219 doNativePisces = PlatformUtil.isEmbedded() || !PlatformUtil.isLinux(); 220 } else { 221 doNativePisces = Boolean.parseBoolean(npprop); 222 } 223 224 /* Setting for text. 225 */ 226 String text = systemProperties.getProperty("prism.text", ""); 227 doPiscesText = "pisces".equals(text); 228 doOpenPiscesText = "openpisces".equals(text); 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 /* shutdown the pipeline on System.exit, ^c - needed with X11, so linux default is true */ 247 shutdownHook = getBoolean(systemProperties, "prism.shutdownHook", 248 PlatformUtil.isUnix()); 249 250 forcePow2 = getBoolean(systemProperties, "prism.forcepowerof2", false); 251 noClampToZero = getBoolean(systemProperties, "prism.noclamptozero", false); 252 253 allowHiDPIScaling = getBoolean(systemProperties, "prism.allowhidpi", true); 254 255 maxVram = getLong(systemProperties, "prism.maxvram", 256 * 1024 * 1024, null); 256 targetVram = getLong(systemProperties, "prism.targetvram", maxVram * 3 / 4, null); 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 (PrismSettings.doPiscesText || PrismSettings.doOpenPiscesText) { 267 System.out.println("Using " + text + " for text rasterization"); 268 } else { 269 System.out.println("Using platform text rasterizer"); 270 } 271 String piscestype = (doNativePisces ? "native" : "java"); 272 System.out.println("Using " + piscestype + "-based Pisces rasterizer"); 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 texture size 306 * This is a workaround for the bugs seen on device creating small textures (see TVP-256) 307 * This value should not be set normally. 308 */ 309 minTextureSize = getInt(systemProperties, "prism.mintexturesize", 0, 310 "Try -Dprism.mintexturesize=<number>"); 311 312 /* 313 * Check minimum RTT size 314 * This is needed for some embedded platforms to avoid rendering artifacts 315 * when rendering into small RTT. 316 */ 317 minRTTSize = getInt(systemProperties, "prism.minrttsize", 318 PlatformUtil.isEmbedded() ? 16 : 0, "Try -Dprism.minrttsize=<number>"); 319 320 disableRegionCaching = getBoolean(systemProperties, 321 "prism.disableRegionCaching", 322 false); 323 324 disableD3D9Ex = getBoolean(systemProperties, "prism.disableD3D9Ex", true); 325 326 disableEffects = getBoolean(systemProperties, "prism.disableEffects", false); 327 328 glyphCacheWidth = getInt(systemProperties, "prism.glyphCacheWidth", 1024, 329 "Try -Dprism.glyphCacheWidth=<number>"); 330 glyphCacheHeight = getInt(systemProperties, "prism.glyphCacheHeight", 1024, 331 "Try -Dprism.glyphCacheHeight=<number>"); 332 333 /* 334 * Performance Logger flags 335 * Enable the performance logger, print on exit, print on first paint etc. 336 */ 337 perfLog = systemProperties.getProperty("sun.perflog"); 338 perfLogExitFlush = getBoolean(systemProperties, "sun.perflog.fx.exitflush", false, true); 339 perfLogFirstPaintFlush = getBoolean(systemProperties, "sun.perflog.fx.firstpaintflush", false, true); 340 perfLogFirstPaintExit = getBoolean(systemProperties, "sun.perflog.fx.firstpaintexit", false, true); 341 342 superShader = getBoolean(systemProperties, "prism.supershader", true); 343 } 344 345 private static int parseInt(String s, int dflt, int trueDflt, 346 String errMsg) { 347 return "true".equalsIgnoreCase(s) 348 ? trueDflt 349 : parseInt(s, dflt, errMsg); 350 } 351 352 private static int parseInt(String s, int dflt, String errMsg) { 353 if (s != null) { 354 try { 355 return Integer.parseInt(s); 356 } catch (Exception e) { 357 if (errMsg != null) { 358 System.err.println(errMsg); 359 } 360 } 361 } 362 363 return dflt; 364 } 365 366 private static long parseLong(String s, long dflt, String errMsg) { 367 if (s != null && s.length() > 0) { 368 long mult = 1; 369 if (s.endsWith("k") || s.endsWith("K")) { 370 mult = 1024L; 371 } else if (s.endsWith("m") || s.endsWith("M")) { 372 mult = 1024L * 1024L; 373 } else if (s.endsWith("g") || s.endsWith("G")) { 374 mult = 1024L * 1024L * 1024L; 375 } 376 if (mult > 1) { 377 s = s.substring(0, s.length() - 1); 378 } 379 try { 380 return Long.parseLong(s) * mult; 381 } catch (Exception e) { 382 if (errMsg != null) { 383 System.err.println(errMsg); 384 } 385 } 386 } 387 388 return dflt; 389 } 390 391 /* A simple version of String.split(), since that isn't available on CDC */ 392 private static String[] split(String str, String delim) { 393 StringTokenizer st = new StringTokenizer(str, delim); 394 String[] ret = new String[st.countTokens()]; 395 int i = 0; 396 while (st.hasMoreTokens()) { 397 ret[i++] = st.nextToken(); 398 } 399 return ret; 400 } 401 402 private static boolean getBoolean(Properties properties, 403 String key, 404 boolean dflt) { 405 final String strval = properties.getProperty(key); 406 return (strval != null) ? Boolean.parseBoolean(strval) : dflt; 407 } 408 409 private static boolean getBoolean(Properties properties, 410 String key, 411 boolean dflt, 412 boolean dfltIfDefined) { 413 final String strval = properties.getProperty(key); 414 if (strval != null && strval.length() == 0) return dfltIfDefined; 415 return (strval != null) ? Boolean.parseBoolean(strval) : dflt; 416 } 417 418 private static int getInt(Properties properties, 419 String key, 420 int dflt, 421 int trueDflt, 422 String errMsg) { 423 return parseInt(properties.getProperty(key), 424 dflt, 425 trueDflt, 426 errMsg); 427 } 428 429 private static int getInt(Properties properties, 430 String key, 431 int dflt, 432 String errMsg) { 433 return parseInt(properties.getProperty(key), 434 dflt, 435 errMsg); 436 } 437 438 private static long getLong(Properties properties, 439 String key, 440 long dflt, 441 String errMsg) 442 { 443 return parseLong(properties.getProperty(key), 444 dflt, 445 errMsg); 446 } 447 }