/* * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.sun.marlin; import java.security.AccessController; import static com.sun.marlin.MarlinUtils.logInfo; import com.sun.util.reentrant.ReentrantContextProvider; import com.sun.util.reentrant.ReentrantContextProviderCLQ; import com.sun.util.reentrant.ReentrantContextProviderTL; import com.sun.javafx.geom.PathIterator; import com.sun.prism.BasicStroke; import java.security.PrivilegedAction; /** * Marlin RendererEngine implementation (derived from Pisces) */ public class DMarlinRenderingEngine implements MarlinConst { /** * Private constructor to prevent instantiation. */ private DMarlinRenderingEngine() { } static { if (PathIterator.WIND_NON_ZERO != DMarlinRenderer.WIND_NON_ZERO || PathIterator.WIND_EVEN_ODD != DMarlinRenderer.WIND_EVEN_ODD || BasicStroke.JOIN_MITER != Stroker.JOIN_MITER || BasicStroke.JOIN_ROUND != Stroker.JOIN_ROUND || BasicStroke.JOIN_BEVEL != Stroker.JOIN_BEVEL || BasicStroke.CAP_BUTT != Stroker.CAP_BUTT || BasicStroke.CAP_ROUND != Stroker.CAP_ROUND || BasicStroke.CAP_SQUARE != Stroker.CAP_SQUARE) { throw new InternalError("mismatched renderer constants"); } } // --- DRendererContext handling --- // use ThreadLocal or ConcurrentLinkedQueue to get one DRendererContext private static final boolean USE_THREAD_LOCAL; // reference type stored in either TL or CLQ static final int REF_TYPE; // Per-thread DRendererContext private static final ReentrantContextProvider RDR_CTX_PROVIDER; // Static initializer to use TL or CLQ mode static { USE_THREAD_LOCAL = MarlinProperties.isUseThreadLocal(); // Soft reference by default: final String refType = AccessController.doPrivileged( (PrivilegedAction) () -> { String value = System.getProperty("prism.marlin.useRef"); return (value == null) ? "soft" : value; }); switch (refType) { default: case "soft": REF_TYPE = ReentrantContextProvider.REF_SOFT; break; case "weak": REF_TYPE = ReentrantContextProvider.REF_WEAK; break; case "hard": REF_TYPE = ReentrantContextProvider.REF_HARD; break; } if (USE_THREAD_LOCAL) { RDR_CTX_PROVIDER = new ReentrantContextProviderTL(REF_TYPE) { @Override protected DRendererContext newContext() { return DRendererContext.createContext(); } }; } else { RDR_CTX_PROVIDER = new ReentrantContextProviderCLQ(REF_TYPE) { @Override protected DRendererContext newContext() { return DRendererContext.createContext(); } }; } logSettings(DRenderer.class.getName()); } private static boolean SETTINGS_LOGGED = !ENABLE_LOGS; public static void logSettings(final String reClass) { // log information at startup if (SETTINGS_LOGGED) { return; } SETTINGS_LOGGED = true; String refType; switch (REF_TYPE) { default: case ReentrantContextProvider.REF_HARD: refType = "hard"; break; case ReentrantContextProvider.REF_SOFT: refType = "soft"; break; case ReentrantContextProvider.REF_WEAK: refType = "weak"; break; } logInfo("==========================================================" + "====================="); logInfo("Marlin software rasterizer = ENABLED"); logInfo("Version = [" + Version.getVersion() + "]"); logInfo("prism.marlin = " + reClass); logInfo("prism.marlin.useThreadLocal = " + USE_THREAD_LOCAL); logInfo("prism.marlin.useRef = " + refType); logInfo("prism.marlin.edges = " + MarlinConst.INITIAL_EDGES_COUNT); logInfo("prism.marlin.pixelsize = " + MarlinConst.INITIAL_PIXEL_DIM); logInfo("prism.marlin.subPixel_log2_X = " + MarlinConst.SUBPIXEL_LG_POSITIONS_X); logInfo("prism.marlin.subPixel_log2_Y = " + MarlinConst.SUBPIXEL_LG_POSITIONS_Y); logInfo("prism.marlin.blockSize_log2 = " + MarlinConst.BLOCK_SIZE_LG); // RLE / blockFlags settings logInfo("prism.marlin.forceRLE = " + MarlinProperties.isForceRLE()); logInfo("prism.marlin.forceNoRLE = " + MarlinProperties.isForceNoRLE()); logInfo("prism.marlin.useTileFlags = " + MarlinProperties.isUseTileFlags()); logInfo("prism.marlin.useTileFlags.useHeuristics = " + MarlinProperties.isUseTileFlagsWithHeuristics()); logInfo("prism.marlin.rleMinWidth = " + MarlinConst.RLE_MIN_WIDTH); // optimisation parameters logInfo("prism.marlin.useSimplifier = " + MarlinConst.USE_SIMPLIFIER); // debugging parameters logInfo("prism.marlin.doStats = " + MarlinConst.DO_STATS); logInfo("prism.marlin.doMonitors = " + MarlinConst.DO_MONITORS); logInfo("prism.marlin.doChecks = " + MarlinConst.DO_CHECKS); // logging parameters logInfo("prism.marlin.log = " + MarlinConst.ENABLE_LOGS); logInfo("prism.marlin.useLogger = " + MarlinConst.USE_LOGGER); logInfo("prism.marlin.logCreateContext = " + MarlinConst.LOG_CREATE_CONTEXT); logInfo("prism.marlin.logUnsafeMalloc = " + MarlinConst.LOG_UNSAFE_MALLOC); // quality settings logInfo("Renderer settings:"); logInfo("CUB_COUNT_LG = " + Renderer.CUB_COUNT_LG); logInfo("CUB_DEC_BND = " + Renderer.CUB_DEC_BND); logInfo("CUB_INC_BND = " + Renderer.CUB_INC_BND); logInfo("QUAD_DEC_BND = " + Renderer.QUAD_DEC_BND); logInfo("USE_SUBDIVIDE_QUAD = " + RendererNoAA.USE_SUBDIVIDE_QUAD); logInfo("QUAD_ERR_SUBPIX = " + RendererNoAA.QUAD_ERR_SUBPIX); logInfo("INITIAL_EDGES_CAPACITY = " + MarlinConst.INITIAL_EDGES_CAPACITY); logInfo("INITIAL_CROSSING_COUNT = " + Renderer.INITIAL_CROSSING_COUNT); logInfo("==========================================================" + "====================="); } /** * Get the DRendererContext instance dedicated to the current thread * @return DRendererContext instance */ @SuppressWarnings({"unchecked"}) public static DRendererContext getRendererContext() { final DRendererContext rdrCtx = RDR_CTX_PROVIDER.acquire(); if (DO_MONITORS) { rdrCtx.stats.mon_pre_getAATileGenerator.start(); } return rdrCtx; } /** * Reset and return the given DRendererContext instance for reuse * @param rdrCtx DRendererContext instance */ public static void returnRendererContext(final DRendererContext rdrCtx) { rdrCtx.dispose(); if (DO_MONITORS) { rdrCtx.stats.mon_pre_getAATileGenerator.stop(); } RDR_CTX_PROVIDER.release(rdrCtx); } }