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 }