• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 #include "compiler/VersionGLSL.h"
8 
9 static const int GLSL_VERSION_110 = 110;
10 static const int GLSL_VERSION_120 = 120;
11 
12 // We need to scan for two things:
13 // 1. "invariant" keyword: This can occur in both - vertex and fragment shaders
14 //    but only at the global scope.
15 // 2. "gl_PointCoord" built-in variable: This can only occur in fragment shader
16 //    but inside any scope.
17 // So we need to scan the entire fragment shader but only the global scope
18 // of vertex shader.
19 //
20 // TODO(alokp): The following two cases of invariant decalaration get lost
21 // during parsing - they do not get carried over to the intermediate tree.
22 // Handle these cases:
23 // 1. When a pragma is used to force all output variables to be invariant:
24 //    - #pragma STDGL invariant(all)
25 // 2. When a previously decalared or built-in variable is marked invariant:
26 //    - invariant gl_Position;
27 //    - varying vec3 color; invariant color;
28 //
TVersionGLSL(ShShaderType type)29 TVersionGLSL::TVersionGLSL(ShShaderType type)
30     : mShaderType(type),
31       mVersion(GLSL_VERSION_110)
32 {
33 }
34 
visitSymbol(TIntermSymbol * node)35 void TVersionGLSL::visitSymbol(TIntermSymbol* node)
36 {
37     ASSERT(mShaderType == SH_FRAGMENT_SHADER);
38 
39     if (node->getSymbol() == "gl_PointCoord")
40         updateVersion(GLSL_VERSION_120);
41 }
42 
visitConstantUnion(TIntermConstantUnion *)43 void TVersionGLSL::visitConstantUnion(TIntermConstantUnion*)
44 {
45     ASSERT(mShaderType == SH_FRAGMENT_SHADER);
46 }
47 
visitBinary(Visit,TIntermBinary *)48 bool TVersionGLSL::visitBinary(Visit, TIntermBinary*)
49 {
50     ASSERT(mShaderType == SH_FRAGMENT_SHADER);
51     return true;
52 }
53 
visitUnary(Visit,TIntermUnary *)54 bool TVersionGLSL::visitUnary(Visit, TIntermUnary*)
55 {
56     ASSERT(mShaderType == SH_FRAGMENT_SHADER);
57     return true;
58 }
59 
visitSelection(Visit,TIntermSelection *)60 bool TVersionGLSL::visitSelection(Visit, TIntermSelection*)
61 {
62     ASSERT(mShaderType == SH_FRAGMENT_SHADER);
63     return true;
64 }
65 
visitAggregate(Visit,TIntermAggregate * node)66 bool TVersionGLSL::visitAggregate(Visit, TIntermAggregate* node)
67 {
68     // We need to scan the entire fragment shader but only the global scope
69     // of vertex shader.
70     bool visitChildren = mShaderType == SH_FRAGMENT_SHADER ? true : false;
71 
72     switch (node->getOp()) {
73       case EOpSequence:
74         // We need to visit sequence children to get to global or inner scope.
75         visitChildren = true;
76         break;
77       case EOpDeclaration: {
78         const TIntermSequence& sequence = node->getSequence();
79         TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier();
80         if ((qualifier == EvqInvariantVaryingIn) ||
81             (qualifier == EvqInvariantVaryingOut)) {
82             updateVersion(GLSL_VERSION_120);
83         }
84         break;
85       }
86       default: break;
87     }
88 
89     return visitChildren;
90 }
91 
visitLoop(Visit,TIntermLoop *)92 bool TVersionGLSL::visitLoop(Visit, TIntermLoop*)
93 {
94     ASSERT(mShaderType == SH_FRAGMENT_SHADER);
95     return true;
96 }
97 
visitBranch(Visit,TIntermBranch *)98 bool TVersionGLSL::visitBranch(Visit, TIntermBranch*)
99 {
100     ASSERT(mShaderType == SH_FRAGMENT_SHADER);
101     return true;
102 }
103 
updateVersion(int version)104 void TVersionGLSL::updateVersion(int version)
105 {
106     mVersion = std::max(version, mVersion);
107 }
108 
109