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