1 /*
   2  * Copyright (c) 2008, 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.scenario.effect.compiler.backend.hw;
  27 
  28 import java.util.HashMap;
  29 import java.util.Map;
  30 import com.sun.scenario.effect.compiler.JSLParser;
  31 import com.sun.scenario.effect.compiler.model.Precision;
  32 import com.sun.scenario.effect.compiler.tree.FuncDef;
  33 import com.sun.scenario.effect.compiler.tree.ProgramUnit;
  34 
  35 /**
  36  */
  37 public class ES2Backend extends GLSLBackend {
  38 
  39     public ES2Backend(JSLParser parser, ProgramUnit program) {
  40         super(parser, program);
  41     }
  42 
  43     // GLSL v1.10 no longer has gl_TexCoord*; these are now passed in
  44     // from vertex shader as texCoord0/1
  45     private static final Map<String, String> varMap = new HashMap<String, String>();
  46     static {
  47         varMap.put("pos0",     "texCoord0");
  48         varMap.put("pos1",     "texCoord1");
  49         varMap.put("color",    "gl_FragColor");
  50         varMap.put("jsl_vertexColor", "perVertexColor");
  51     }
  52 
  53     private static final Map<String, String> funcMap = new HashMap<String, String>();
  54     static {
  55         funcMap.put("sample", "texture2D");
  56         funcMap.put("ddx", "dFdx");
  57         funcMap.put("ddy", "dFdy");
  58         funcMap.put("intcast", "int");
  59     }
  60 
  61     @Override
  62     protected String getVar(String v) {
  63         String s = varMap.get(v);
  64         return (s != null) ? s : v;
  65     }
  66 
  67     @Override
  68     protected String getFuncName(String f) {
  69         String s = funcMap.get(f);
  70         return (s != null) ? s : f;
  71     }
  72 
  73     @Override
  74     protected String getPrecision(Precision p) {
  75         return p.name();
  76     }
  77 
  78     @Override
  79     public void visitFuncDef(FuncDef d) {
  80         // this is a hack to help force the return value of certain Prism
  81         // shader functions to have lower precision
  82         String name = d.getFunction().getName();
  83         if ("mask".equals(name) || "paint".equals(name)) {
  84             output("lowp ");
  85         }
  86         super.visitFuncDef(d);
  87     }
  88 
  89     @Override
  90     protected String getHeader() {
  91         StringBuilder sb = new StringBuilder();
  92         // For the time being we are attempting to generate fragment programs
  93         // that will run on the desktop and on OpenGL ES 2.0 devices.
  94         // For OpenGL ES 2.0, fragment programs are required to specify the
  95         // precision for all variables.  Also for ES 2.0, the default GLSL
  96         // version is 1.00, so implicitly we are using "#version 100" for
  97         // that case.  We are not yet taking advantage of language features
  98         // above (desktop GLSL) version 1.10 so we can get away with not
  99         // including the #version directive here (it will implicitly be
 100         // "#version 110" for the desktop case).  It appears that the
 101         // desktop and ES versions of the GLSL spec may continue to be
 102         // developed independently (see section 10.23 in the GLSL ES spec),
 103         // so if we ever need to use a higher version for one case or the
 104         // other, it will get awkward since the #version string has to be
 105         // the first thing in the file (i.e., you can't put it inside the
 106         // "#ifdef GL_ES" section).
 107         // TODO: We are currently using highp across the board if it is
 108         // supported just to be safe, but there are likely many variables
 109         // that could live with mediump or lowp; should experiment with
 110         // using lower precision by default...
 111         sb.append("#ifdef GL_ES\n");
 112         sb.append("#extension GL_OES_standard_derivatives : enable\n");
 113         sb.append("#ifdef GL_FRAGMENT_PRECISION_HIGH\n");
 114         sb.append("precision highp float;\n");
 115         sb.append("precision highp int;\n");
 116         sb.append("#else\n");
 117         sb.append("precision mediump float;\n");
 118         sb.append("precision mediump int;\n");
 119         sb.append("#endif\n");
 120         sb.append("#else\n");
 121         sb.append("#define highp\n");
 122         sb.append("#define mediump\n");
 123         sb.append("#define lowp\n");
 124         sb.append("#endif\n");
 125 
 126         // output varying value declarations (passed from the vertex shader)
 127         if (maxTexCoordIndex >= 0) {
 128             sb.append("varying vec2 texCoord0;\n");
 129         }
 130         if (maxTexCoordIndex >= 1) {
 131             sb.append("varying vec2 texCoord1;\n");
 132         }
 133         if (isVertexColorReferenced) {
 134             sb.append("varying lowp vec4 perVertexColor;\n");
 135         }
 136 
 137         // output special pixcoord offset uniform variable declaration
 138         // at the top of the program, if needed
 139         if (isPixcoordReferenced) {
 140             sb.append("uniform vec4 jsl_pixCoordOffset;\n");
 141             sb.append("vec2 pixcoord = vec2(\n");
 142             sb.append("    gl_FragCoord.x-jsl_pixCoordOffset.x,\n");
 143             sb.append("    ((jsl_pixCoordOffset.z-gl_FragCoord.y)*jsl_pixCoordOffset.w)-jsl_pixCoordOffset.y);\n");
 144         }
 145 
 146         return sb.toString();
 147     }
 148 }