/*
 * Copyright (c) 2009, 2014, 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.scenario.effect.impl;

import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import com.sun.javafx.PlatformUtil;
import com.sun.scenario.effect.FilterContext;

A factory that produces a Renderer instance appropriate for the desktop and tv stacks (either Swing or Prism based). This class dynamically locates a Renderer using the java.lang.reflect package, which is not available on CLDC. The CLDC-based mobile stack may substitute their own version of this class that does not rely on reflection.
/** * A factory that produces a {@code Renderer} instance appropriate for * the desktop and tv stacks (either Swing or Prism based). This class * dynamically locates a {@code Renderer} using the java.lang.reflect package, * which is not available on CLDC. The CLDC-based mobile stack may * substitute their own version of this class that does not rely on reflection. */
class RendererFactory { private static String rootPkg = Renderer.rootPkg; private static boolean tryRSL = true; private static boolean trySIMD = false; // by default we only enable jogl hw acceleration on MacOS private static boolean tryJOGL = PlatformUtil.isMac(); private static boolean tryPrism = true; static { try { if ("false".equals(System.getProperty("decora.rsl"))) { tryRSL = false; } if ("false".equals(System.getProperty("decora.simd"))) { trySIMD = false; } String tryJOGLProp = System.getProperty("decora.jogl"); if (tryJOGLProp != null) { tryJOGL = Boolean.parseBoolean(tryJOGLProp); } if ("false".equals(System.getProperty("decora.prism"))) { tryPrism = false; } } catch (SecurityException ignore) { } } private static boolean isRSLFriendly(Class klass) { // can't use reflection here to check for sun.* class when running // in sandbox; however, we are allowed to walk up the tree and // check names of interfaces loaded by the system if (klass.getName().equals("sun.java2d.pipe.hw.AccelGraphicsConfig")) { return true; } boolean rsl = false; for (Class iface : klass.getInterfaces()) { if (isRSLFriendly(iface)) { rsl = true; break; } } return rsl; } private static boolean isRSLAvailable(FilterContext fctx) { return isRSLFriendly(fctx.getReferent().getClass()); } private static Renderer createRSLRenderer(FilterContext fctx) { try { Class klass = Class.forName(rootPkg + ".impl.j2d.rsl.RSLRenderer"); Method m = klass.getMethod("createRenderer", new Class[] { FilterContext.class }); return (Renderer)m.invoke(null, new Object[] { fctx }); } catch (Throwable e) {} return null; } private static Renderer createJOGLRenderer(FilterContext fctx) { if (tryJOGL) { try { Class klass = Class.forName(rootPkg + ".impl.j2d.jogl.JOGLRenderer"); Method m = klass.getMethod("createRenderer", new Class[] { FilterContext.class }); return (Renderer)m.invoke(null, new Object[] { fctx }); } catch (Throwable e) {} // don't disable jogl if failed, it may be available for other config } return null; } private static Renderer createPrismRenderer(FilterContext fctx) { if (tryPrism) { try { Class klass = Class.forName(rootPkg + ".impl.prism.PrRenderer"); Method m = klass.getMethod("createRenderer", new Class[] { FilterContext.class }); return (Renderer)m.invoke(null, new Object[] { fctx }); } catch (Throwable e) { e.printStackTrace(); } // don't disable prism if failed, it may be available for other config } return null; } private static Renderer getSSERenderer() { if (trySIMD) { try { Class klass = Class.forName(rootPkg + ".impl.j2d.J2DSWRenderer"); Method m = klass.getMethod("getSSEInstance", (Class[])null); Renderer sseRenderer = (Renderer)m.invoke(null, (Object[])null); if (sseRenderer != null) { return sseRenderer; } } catch (Throwable e) {e.printStackTrace();} // don't bother trying to find SSE renderer again trySIMD = false; } return null; } private static Renderer getJavaRenderer() { try { Class klass = Class.forName(rootPkg + ".impl.prism.sw.PSWRenderer"); Class screenClass = Class.forName("com.sun.glass.ui.Screen"); Method m = klass.getMethod("createJSWInstance", new Class[] { screenClass }); Renderer jswRenderer = (Renderer)m.invoke(null, new Object[] { null } ); if (jswRenderer != null) { return jswRenderer; } } catch (Throwable e) {e.printStackTrace();} return null; } private static Renderer getJavaRenderer(FilterContext fctx) { try { Class klass = Class.forName(rootPkg + ".impl.prism.sw.PSWRenderer"); Method m = klass.getMethod("createJSWInstance", new Class[] { FilterContext.class }); Renderer jswRenderer = (Renderer)m.invoke(null, new Object[] { fctx } ); if (jswRenderer != null) { return jswRenderer; } } catch (Throwable e) {} return null; } static Renderer getSoftwareRenderer() { Renderer r = getSSERenderer(); if (r == null) { r = getJavaRenderer(); } return r; } static Renderer createRenderer(final FilterContext fctx) { return AccessController.doPrivileged((PrivilegedAction<Renderer>) () -> { Renderer r = null; // Class.getSimpleName is not available on CDC String klassName = fctx.getClass().getName(); String simpleName = klassName.substring(klassName.lastIndexOf(".") + 1); if (simpleName.equals("PrFilterContext") && tryPrism) { r = createPrismRenderer(fctx); } // check to see whether one of the hardware accelerated // Java 2D pipelines is in use and exposes the necessary // "resource sharing layer" APIs (only in Sun's JDK 6u10 and above) if (r == null && tryRSL && isRSLAvailable(fctx)) { // try locating an RSLRenderer (need to use reflection in case // certain RSL backend classes are not available; // this step will trigger lazy downloading of impl jars // via JNLP, if not already available) r = createRSLRenderer(fctx); } if (r == null && tryJOGL) { // next try the JOGL renderer r = createJOGLRenderer(fctx); } if (r == null && trySIMD) { // next try the SSE renderer r = getSSERenderer(); } if (r == null) { // otherwise, fall back on the Java/CPU renderer r = getJavaRenderer(fctx); } return r; }); } }