1 /*
   2  * Copyright (c) 2007, 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.marlin;
  27 
  28 import java.security.AccessController;
  29 import static com.sun.marlin.MarlinUtils.logInfo;
  30 import com.sun.ReentrantContextProvider;
  31 import com.sun.ReentrantContextProviderCLQ;
  32 import com.sun.ReentrantContextProviderTL;
  33 import com.sun.javafx.geom.PathIterator;
  34 import com.sun.prism.BasicStroke;
  35 import java.security.PrivilegedAction;
  36 
  37 /**
  38  * Marlin RendererEngine implementation (derived from Pisces)
  39  */
  40 public class MarlinRenderingEngine implements MarlinConst
  41 {
  42     /**
  43      * Private constructor to prevent instantiation.
  44      */
  45     private MarlinRenderingEngine() {
  46     }
  47 
  48     static {
  49         if (PathIterator.WIND_NON_ZERO != MarlinRenderer.WIND_NON_ZERO ||
  50             PathIterator.WIND_EVEN_ODD != MarlinRenderer.WIND_EVEN_ODD ||
  51             BasicStroke.JOIN_MITER != Stroker.JOIN_MITER ||
  52             BasicStroke.JOIN_ROUND != Stroker.JOIN_ROUND ||
  53             BasicStroke.JOIN_BEVEL != Stroker.JOIN_BEVEL ||
  54             BasicStroke.CAP_BUTT != Stroker.CAP_BUTT ||
  55             BasicStroke.CAP_ROUND != Stroker.CAP_ROUND ||
  56             BasicStroke.CAP_SQUARE != Stroker.CAP_SQUARE)
  57         {
  58             throw new InternalError("mismatched renderer constants");
  59         }
  60 
  61         logSettings(Renderer.class.getName());
  62     }
  63 
  64     // --- RendererContext handling ---
  65     // use ThreadLocal or ConcurrentLinkedQueue to get one RendererContext
  66     private static final boolean USE_THREAD_LOCAL;
  67 
  68     // reference type stored in either TL or CLQ
  69     static final int REF_TYPE;
  70 
  71     // Per-thread RendererContext
  72     private static final ReentrantContextProvider<RendererContext> RDR_CTX_PROVIDER;
  73 
  74     // Static initializer to use TL or CLQ mode
  75     static {
  76         USE_THREAD_LOCAL = MarlinProperties.isUseThreadLocal();
  77 
  78         // Soft reference by default:
  79         final String refType = AccessController.doPrivileged(
  80             (PrivilegedAction<String>) () -> {
  81                 String value = System.getProperty("prism.marlin.useRef");
  82                 return (value == null) ? "soft" : value;
  83             });
  84         switch (refType) {
  85             default:
  86             case "soft":
  87                 REF_TYPE = ReentrantContextProvider.REF_SOFT;
  88                 break;
  89             case "weak":
  90                 REF_TYPE = ReentrantContextProvider.REF_WEAK;
  91                 break;
  92             case "hard":
  93                 REF_TYPE = ReentrantContextProvider.REF_HARD;
  94                 break;
  95         }
  96 
  97         if (USE_THREAD_LOCAL) {
  98             RDR_CTX_PROVIDER = new ReentrantContextProviderTL<RendererContext>(REF_TYPE)
  99                 {
 100                     @Override
 101                     protected RendererContext newContext() {
 102                         return RendererContext.createContext();
 103                     }
 104                 };
 105         } else {
 106             RDR_CTX_PROVIDER = new ReentrantContextProviderCLQ<RendererContext>(REF_TYPE)
 107                 {
 108                     @Override
 109                     protected RendererContext newContext() {
 110                         return RendererContext.createContext();
 111                     }
 112                 };
 113         }
 114     }
 115 
 116     private static boolean SETTINGS_LOGGED = !ENABLE_LOGS;
 117 
 118     public static void logSettings(final String reClass) {
 119         // log information at startup
 120         if (SETTINGS_LOGGED) {
 121             return;
 122         }
 123         SETTINGS_LOGGED = true;
 124 
 125         String refType;
 126         switch (REF_TYPE) {
 127             default:
 128             case ReentrantContextProvider.REF_HARD:
 129                 refType = "hard";
 130                 break;
 131             case ReentrantContextProvider.REF_SOFT:
 132                 refType = "soft";
 133                 break;
 134             case ReentrantContextProvider.REF_WEAK:
 135                 refType = "weak";
 136                 break;
 137         }
 138 
 139         logInfo("=========================================================="
 140                 + "=====================");
 141 
 142         logInfo("Marlin software rasterizer    = ENABLED");
 143         logInfo("Version                       = ["
 144                 + Version.getVersion() + "]");
 145         logInfo("prism.marlin                  = "
 146                 + reClass);
 147         logInfo("prism.marlin.useThreadLocal   = "
 148                 + USE_THREAD_LOCAL);
 149         logInfo("prism.marlin.useRef           = "
 150                 + refType);
 151 
 152         logInfo("prism.marlin.edges            = "
 153                 + MarlinConst.INITIAL_EDGES_COUNT);
 154         logInfo("prism.marlin.pixelsize        = "
 155                 + MarlinConst.INITIAL_PIXEL_DIM);
 156 
 157         logInfo("prism.marlin.subPixel_log2_X  = "
 158                 + MarlinConst.SUBPIXEL_LG_POSITIONS_X);
 159         logInfo("prism.marlin.subPixel_log2_Y  = "
 160                 + MarlinConst.SUBPIXEL_LG_POSITIONS_Y);
 161 
 162         logInfo("prism.marlin.blockSize_log2   = "
 163                 + MarlinConst.BLOCK_SIZE_LG);
 164 
 165         // RLE / blockFlags settings
 166 
 167         logInfo("prism.marlin.forceRLE         = "
 168                 + MarlinProperties.isForceRLE());
 169         logInfo("prism.marlin.forceNoRLE       = "
 170                 + MarlinProperties.isForceNoRLE());
 171         logInfo("prism.marlin.useTileFlags     = "
 172                 + MarlinProperties.isUseTileFlags());
 173         logInfo("prism.marlin.useTileFlags.useHeuristics = "
 174                 + MarlinProperties.isUseTileFlagsWithHeuristics());
 175         logInfo("prism.marlin.rleMinWidth      = "
 176                 + MarlinConst.RLE_MIN_WIDTH);
 177 
 178         // optimisation parameters
 179         logInfo("prism.marlin.useSimplifier    = "
 180                 + MarlinConst.USE_SIMPLIFIER);
 181 
 182         // debugging parameters
 183         logInfo("prism.marlin.doStats          = "
 184                 + MarlinConst.DO_STATS);
 185         logInfo("prism.marlin.doMonitors       = "
 186                 + MarlinConst.DO_MONITORS);
 187         logInfo("prism.marlin.doChecks         = "
 188                 + MarlinConst.DO_CHECKS);
 189 
 190         // logging parameters
 191         logInfo("prism.marlin.log              = "
 192                 + MarlinConst.ENABLE_LOGS);
 193         logInfo("prism.marlin.useLogger        = "
 194                 + MarlinConst.USE_LOGGER);
 195         logInfo("prism.marlin.logCreateContext = "
 196                 + MarlinConst.LOG_CREATE_CONTEXT);
 197         logInfo("prism.marlin.logUnsafeMalloc  = "
 198                 + MarlinConst.LOG_UNSAFE_MALLOC);
 199 
 200         // quality settings
 201         logInfo("Renderer settings:");
 202         logInfo("CUB_COUNT_LG = " + Renderer.CUB_COUNT_LG);
 203         logInfo("CUB_DEC_BND  = " + Renderer.CUB_DEC_BND);
 204         logInfo("CUB_INC_BND  = " + Renderer.CUB_INC_BND);
 205         logInfo("QUAD_DEC_BND = " + Renderer.QUAD_DEC_BND);
 206 
 207         logInfo("INITIAL_EDGES_CAPACITY        = "
 208                 + MarlinConst.INITIAL_EDGES_CAPACITY);
 209         logInfo("INITIAL_CROSSING_COUNT        = "
 210                 + Renderer.INITIAL_CROSSING_COUNT);
 211 
 212         logInfo("=========================================================="
 213                 + "=====================");
 214     }
 215 
 216     /**
 217      * Get the RendererContext instance dedicated to the current thread
 218      * @return RendererContext instance
 219      */
 220     @SuppressWarnings({"unchecked"})
 221     public static RendererContext getRendererContext() {
 222         final RendererContext rdrCtx = RDR_CTX_PROVIDER.acquire();
 223         if (DO_MONITORS) {
 224             rdrCtx.stats.mon_pre_getAATileGenerator.start();
 225         }
 226         return rdrCtx;
 227     }
 228 
 229     /**
 230      * Reset and return the given RendererContext instance for reuse
 231      * @param rdrCtx RendererContext instance
 232      */
 233     public static void returnRendererContext(final RendererContext rdrCtx) {
 234         rdrCtx.dispose();
 235 
 236         if (DO_MONITORS) {
 237             rdrCtx.stats.mon_pre_getAATileGenerator.stop();
 238         }
 239         RDR_CTX_PROVIDER.release(rdrCtx);
 240     }
 241 }