Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #ifndef GrGLSL_DEFINED | 8 #ifndef GrGLSL_DEFINED |
| 9 #define GrGLSL_DEFINED | 9 #define GrGLSL_DEFINED |
| 10 | 10 |
| 11 #include "gl/GrGLInterface.h" | 11 #include "gl/GrGLInterface.h" |
| 12 #include "GrColor.h" | 12 #include "GrColor.h" |
| 13 #include "GrTypesPriv.h" | 13 #include "GrTypesPriv.h" |
| 14 #include "SkString.h" | |
| 14 | 15 |
| 15 class GrGLContextInfo; | 16 class GrGLContextInfo; |
| 16 class GrGLShaderVar; | 17 class GrGLShaderVar; |
| 17 class SkString; | |
| 18 | 18 |
| 19 // Limited set of GLSL versions we build shaders for. Caller should round | 19 // Limited set of GLSL versions we build shaders for. Caller should round |
| 20 // down the GLSL version to one of these enums. | 20 // down the GLSL version to one of these enums. |
| 21 enum GrGLSLGeneration { | 21 enum GrGLSLGeneration { |
| 22 /** | 22 /** |
| 23 * Desktop GLSL 1.10 and ES2 shading language (based on desktop GLSL 1.20) | 23 * Desktop GLSL 1.10 and ES2 shading language (based on desktop GLSL 1.20) |
| 24 */ | 24 */ |
| 25 k110_GrGLSLGeneration, | 25 k110_GrGLSLGeneration, |
| 26 /** | 26 /** |
| 27 * Desktop GLSL 1.30 | 27 * Desktop GLSL 1.30 |
| 28 */ | 28 */ |
| 29 k130_GrGLSLGeneration, | 29 k130_GrGLSLGeneration, |
| 30 /** | 30 /** |
| 31 * Desktop GLSL 1.40 | 31 * Desktop GLSL 1.40 |
| 32 */ | 32 */ |
| 33 k140_GrGLSLGeneration, | 33 k140_GrGLSLGeneration, |
| 34 /** | 34 /** |
| 35 * Desktop GLSL 1.50 | 35 * Desktop GLSL 1.50 |
| 36 */ | 36 */ |
| 37 k150_GrGLSLGeneration, | 37 k150_GrGLSLGeneration, |
| 38 }; | 38 }; |
| 39 | 39 |
| 40 enum GrSLConstantVec { | |
| 41 kZeros_GrSLConstantVec, | |
| 42 kOnes_GrSLConstantVec, | |
| 43 kNone_GrSLConstantVec, | |
| 44 }; | |
| 45 | |
| 46 namespace { | |
| 47 static inline int GrSLTypeToVecLength(GrSLType type) { | |
| 48 static const int kVecLengths[] = { | |
| 49 0, // kVoid_GrSLType | |
| 50 1, // kFloat_GrSLType | |
| 51 2, // kVec2f_GrSLType | |
| 52 3, // kVec3f_GrSLType | |
| 53 4, // kVec4f_GrSLType | |
| 54 1, // kMat33f_GrSLType | |
| 55 1, // kMat44f_GrSLType | |
| 56 1, // kSampler2D_GrSLType | |
| 57 }; | |
| 58 GR_STATIC_ASSERT(kGrSLTypeCount == GR_ARRAY_COUNT(kVecLengths)); | |
| 59 return kVecLengths[type]; | |
| 60 } | |
| 61 | |
| 62 static inline const char* GrGLSLOnesVecf(int count) { | |
| 63 static const char* kONESVEC[] = {"ERROR", "1.0", "vec2(1,1)", | |
| 64 "vec3(1,1,1)", "vec4(1,1,1,1)"}; | |
| 65 SkASSERT(count >= 1 && count < (int)GR_ARRAY_COUNT(kONESVEC)); | |
| 66 return kONESVEC[count]; | |
| 67 } | |
| 68 | |
| 69 static inline const char* GrGLSLZerosVecf(int count) { | |
| 70 static const char* kZEROSVEC[] = {"ERROR", "0.0", "vec2(0,0)", | |
| 71 "vec3(0,0,0)", "vec4(0,0,0,0)"}; | |
| 72 SkASSERT(count >= 1 && count < (int)GR_ARRAY_COUNT(kZEROSVEC)); | |
| 73 return kZEROSVEC[count]; | |
| 74 } | |
| 75 } | |
| 76 | |
| 77 /** | 40 /** |
| 78 * Gets the most recent GLSL Generation compatible with the OpenGL context. | 41 * Gets the most recent GLSL Generation compatible with the OpenGL context. |
| 79 */ | 42 */ |
| 80 GrGLSLGeneration GrGetGLSLGeneration(GrGLBinding binding, | 43 GrGLSLGeneration GrGetGLSLGeneration(GrGLBinding binding, |
| 81 const GrGLInterface* gl); | 44 const GrGLInterface* gl); |
| 82 | 45 |
| 83 /** | 46 /** |
| 84 * Returns a string to include at the beginning of a shader to declare the GLSL | 47 * Returns a string to include at the beginning of a shader to declare the GLSL |
| 85 * version. | 48 * version. |
| 86 */ | 49 */ |
| 87 const char* GrGetGLSLVersionDecl(const GrGLContextInfo&); | 50 const char* GrGetGLSLVersionDecl(const GrGLContextInfo&); |
| 88 | 51 |
| 89 /** | 52 /** |
| 90 * Converts a GrSLType to a string containing the name of the equivalent GLSL ty pe. | 53 * Converts a GrSLType to a string containing the name of the equivalent GLSL ty pe. |
| 91 */ | 54 */ |
| 92 static const char* GrGLSLTypeString(GrSLType t) { | 55 static inline const char* GrGLSLTypeString(GrSLType t) { |
| 93 switch (t) { | 56 switch (t) { |
| 94 case kVoid_GrSLType: | 57 case kVoid_GrSLType: |
| 95 return "void"; | 58 return "void"; |
| 96 case kFloat_GrSLType: | 59 case kFloat_GrSLType: |
| 97 return "float"; | 60 return "float"; |
| 98 case kVec2f_GrSLType: | 61 case kVec2f_GrSLType: |
| 99 return "vec2"; | 62 return "vec2"; |
| 100 case kVec3f_GrSLType: | 63 case kVec3f_GrSLType: |
| 101 return "vec3"; | 64 return "vec3"; |
| 102 case kVec4f_GrSLType: | 65 case kVec4f_GrSLType: |
| 103 return "vec4"; | 66 return "vec4"; |
| 104 case kMat33f_GrSLType: | 67 case kMat33f_GrSLType: |
| 105 return "mat3"; | 68 return "mat3"; |
| 106 case kMat44f_GrSLType: | 69 case kMat44f_GrSLType: |
| 107 return "mat4"; | 70 return "mat4"; |
| 108 case kSampler2D_GrSLType: | 71 case kSampler2D_GrSLType: |
| 109 return "sampler2D"; | 72 return "sampler2D"; |
| 110 default: | 73 default: |
| 111 GrCrash("Unknown shader var type."); | 74 GrCrash("Unknown shader var type."); |
| 112 return ""; // suppress warning | 75 return ""; // suppress warning |
| 113 } | 76 } |
| 114 } | 77 } |
| 115 | 78 |
| 116 /** Return the type enum for a vector of floats of length n (1..4), | 79 /** A class representing a GLSL expression. |
| 117 e.g. 1 -> "float", 2 -> "vec2", ... */ | 80 * The instance can be a variable name, expression or vecN(0) or vecN(1). Does s imple constant |
| 118 static inline const char* GrGLSLFloatVectorTypeString(int n) { | 81 * folding with help of 1 and 0. |
| 119 return GrGLSLTypeString(GrSLFloatVectorType(n)); | 82 * Complex expressions can be constructed with operators *, +, - |
| 120 } | 83 */ |
| 121 | 84 template <int N> |
| 122 /** Return the GLSL swizzle operator for a homogenous component of a vector | 85 class GrGLSLExpr { |
| 123 with the given number of coordinates, e.g. 2 -> ".y", 3 -> ".z" */ | 86 public: |
| 124 const char* GrGLSLVectorHomogCoord(int count); | 87 /** Constructs an invalid expression. |
| 125 const char* GrGLSLVectorHomogCoord(GrSLType type); | 88 * Useful only as a return value from functions that never actually return |
| 126 | 89 * this and instances that will be assigned to later. */ |
| 127 /** Return the GLSL swizzle operator for a nonhomogenous components of a vector | 90 GrGLSLExpr() |
| 128 with the given number of coordinates, e.g. 2 -> ".x", 3 -> ".xy" */ | 91 : fType(kFullExpr_ExprType) { |
| 129 const char* GrGLSLVectorNonhomogCoords(int count); | 92 SK_COMPILE_ASSERT(N > 0 && N <= 4, dimensions_not_in_range); |
| 130 const char* GrGLSLVectorNonhomogCoords(GrSLType type); | 93 // The only constructor that is allowed to build an empty expression. |
| 94 SkASSERT(!this->isValid()); | |
| 95 } | |
| 96 | |
| 97 /** Constructs an expression with all components as value v */ | |
| 98 explicit GrGLSLExpr(int v) { | |
| 99 SK_COMPILE_ASSERT(N > 0 && N <= 4, dimensions_not_in_range); | |
| 100 if (v == 0) { | |
| 101 fType = kZeros_ExprType; | |
| 102 } else if (v == 1) { | |
| 103 fType = kOnes_ExprType; | |
| 104 } else { | |
| 105 fType = kFullExpr_ExprType; | |
| 106 fExpr.appendf(this->CastIntStr(), v); | |
| 107 } | |
| 108 } | |
| 109 | |
| 110 /** Constructs an expression from a string. | |
| 111 * Argument expr is a simple expression or a parenthesized expression. */ | |
| 112 // TODO: make explicit once effects input Exprs. | |
| 113 GrGLSLExpr(const char expr[]) { | |
| 114 SK_COMPILE_ASSERT(N > 0 && N <= 4, dimensions_not_in_range); | |
| 115 if (NULL == expr) { // TODO: remove this once effects input Exprs. | |
| 116 fType = kOnes_ExprType; | |
| 117 } else { | |
| 118 fType = kFullExpr_ExprType; | |
| 119 fExpr = expr; | |
| 120 } | |
| 121 SkASSERT(this->isValid()); | |
| 122 } | |
| 123 | |
| 124 /** Constructs an expression from a string. | |
| 125 * Argument expr is a simple expression or a parenthesized expression. */ | |
| 126 // TODO: make explicit once effects input Exprs. | |
| 127 GrGLSLExpr(const SkString& expr) { | |
| 128 SK_COMPILE_ASSERT(N > 0 && N <= 4, dimensions_not_in_range); | |
| 129 if (expr.isEmpty()) { // TODO: remove this once effects input Exprs. | |
| 130 fType = kOnes_ExprType; | |
| 131 } else { | |
| 132 fType = kFullExpr_ExprType; | |
| 133 fExpr = expr; | |
| 134 } | |
| 135 SkASSERT(this->isValid()); | |
| 136 } | |
| 137 | |
| 138 bool isOnes() const { return kOnes_ExprType == fType; } | |
| 139 bool isZeros() const { return kZeros_ExprType == fType; } | |
| 140 | |
| 141 const char* c_str() const { | |
| 142 if (kZeros_ExprType == fType) { | |
| 143 return this->ZerosStr(); | |
|
bsalomon
2013/10/09 19:53:31
Ok, so maybe I asked you to do this-> here before,
| |
| 144 } else if (kOnes_ExprType == fType) { | |
| 145 return this->OnesStr(); | |
|
bsalomon
2013/10/09 19:53:31
and here
| |
| 146 } | |
| 147 SkASSERT(!fExpr.isEmpty()); // Empty expressions should not be used. | |
| 148 return fExpr.c_str(); | |
| 149 } | |
| 150 | |
| 151 private: | |
| 152 GrGLSLExpr(const char format[], const char in0[]) | |
| 153 : fType(kFullExpr_ExprType) { | |
| 154 fExpr.appendf(format, in0); | |
| 155 } | |
| 156 | |
| 157 GrGLSLExpr(const char format[], const char in0[], const char in1[]) | |
| 158 : fType(kFullExpr_ExprType) { | |
| 159 fExpr.appendf(format, in0, in1); | |
| 160 } | |
| 161 | |
| 162 GrGLSLExpr(const char format[], const char in0[], char in1) | |
| 163 : fType(kFullExpr_ExprType) { | |
| 164 fExpr.appendf(format, in0, in1); | |
| 165 } | |
| 166 | |
| 167 bool isValid() const { | |
| 168 return kFullExpr_ExprType != fType || !fExpr.isEmpty(); | |
| 169 } | |
| 170 | |
| 171 static const char* ZerosStr(); | |
| 172 static const char* OnesStr(); | |
| 173 static const char* ExtractAlphaStr(); | |
| 174 static const char* CastStr(); | |
| 175 static const char* CastIntStr(); | |
| 176 | |
| 177 /** Casts the expression expr into smaller or bigger expression. | |
| 178 * Casting is done with GLSL rules: | |
| 179 * M==3, N==4 vec3(a, b, c) -> vec4(a, b, c, 0) | |
| 180 * N==4, M==3 vec4(a, b, c, d) -> vec3(a, b, c) | |
| 181 */ | |
| 182 template <int M> | |
| 183 static GrGLSLExpr<N> VectorCast(const GrGLSLExpr<M>& expr); | |
| 184 | |
| 185 /** GLSL multiplication: component-wise or multiply each component by a scal ar. | |
| 186 * M == N --> vecN(in0.x * in1.x, ...) | |
| 187 * M == 1 --> vecN(in0.x * in1, ...) | |
| 188 * otherwise --> compile-time error | |
| 189 */ | |
| 190 template <int M> | |
| 191 static GrGLSLExpr<N> Mul(const GrGLSLExpr<N>& in0, const GrGLSLExpr<M>& in1) ; | |
| 192 | |
| 193 /** GLSL addition: component-wise or add a scalar to each compoment. | |
| 194 * M == N --> vecN(in0.x + in1.x, ...) | |
| 195 * M == 1 --> vecN(in0.x + in1, ...) | |
| 196 * otherwise --> compile-time error | |
| 197 */ | |
| 198 template <int M> | |
| 199 static GrGLSLExpr<N> Add(const GrGLSLExpr<N>& in0, const GrGLSLExpr<M>& in1) ; | |
| 200 | |
| 201 /** GLSL subtraction: component-wise or subtract compoments by a scalar. | |
| 202 * M == N --> vecN(in0.x - in1.x, ...) | |
| 203 * M == 1 --> vecN(in0.x - in1, ...) | |
| 204 * otherwise --> compile-time error | |
| 205 */ | |
| 206 template <int M> | |
| 207 static GrGLSLExpr<N> Sub(const GrGLSLExpr<N>& in0, const GrGLSLExpr<M>& in1) ; | |
| 208 | |
| 209 enum ExprType { | |
| 210 kZeros_ExprType, | |
| 211 kOnes_ExprType, | |
| 212 kFullExpr_ExprType, | |
| 213 }; | |
| 214 ExprType fType; | |
| 215 SkString fExpr; | |
| 216 | |
| 217 template <int> friend class GrGLSLExpr; | |
| 218 | |
| 219 /** Multiplies two expressions component-wise. */ | |
| 220 template <int M> friend GrGLSLExpr<M> operator*(const GrGLSLExpr<M>&, const GrGLSLExpr<M>&); | |
| 221 /** Adds two expressions component-wise. */ | |
| 222 template <int M> friend GrGLSLExpr<M> operator+(const GrGLSLExpr<M>&, const GrGLSLExpr<M>&); | |
| 223 /** Subtracts two expressions component-wise. */ | |
| 224 template <int M> friend GrGLSLExpr<M> operator-(const GrGLSLExpr<M>&, const GrGLSLExpr<M>&); | |
| 225 /** Multiplies every component of an expression with a scalar expression. */ | |
| 226 friend GrGLSLExpr<4> operator*(const GrGLSLExpr<4>&, const GrGLSLExpr<1>&); | |
| 227 /** Adds a scalar expression to every component of an expression. */ | |
| 228 friend GrGLSLExpr<4> operator+(const GrGLSLExpr<4>&, const GrGLSLExpr<1>&); | |
| 229 /** Subtracts a scalar expression from every component of an expression. */ | |
| 230 friend GrGLSLExpr<4> operator-(const GrGLSLExpr<4>&, const GrGLSLExpr<1>&); | |
| 231 | |
| 232 friend GrGLSLExpr<1> GrGLSLExprExtractAlpha(const GrGLSLExpr<4>& expr); | |
| 233 friend GrGLSLExpr<4> GrGLSLExprCast4(const GrGLSLExpr<1>& expr); | |
| 234 }; | |
| 235 | |
| 236 | |
| 237 template <int N> | |
| 238 inline GrGLSLExpr<N> operator*(const GrGLSLExpr<N>& in0, const GrGLSLExpr<N>&in1 ) { | |
| 239 return GrGLSLExpr<N>::Mul(in0, in1); | |
| 240 } | |
| 241 | |
| 242 template <int N> | |
| 243 inline GrGLSLExpr<N> operator+(const GrGLSLExpr<N>& in0, const GrGLSLExpr<N>&in1 ) { | |
| 244 return GrGLSLExpr<N>::Add(in0, in1); | |
| 245 } | |
| 246 | |
| 247 template <int N> | |
| 248 inline GrGLSLExpr<N> operator-(const GrGLSLExpr<N>& in0, const GrGLSLExpr<N>&in1 ) { | |
| 249 return GrGLSLExpr<N>::Sub(in0, in1); | |
| 250 } | |
| 251 | |
| 252 inline GrGLSLExpr<4> operator*(const GrGLSLExpr<4>& in0, const GrGLSLExpr<1>& in 1) { | |
| 253 return GrGLSLExpr<4>::Mul(in0, in1); | |
| 254 } | |
| 255 | |
| 256 inline GrGLSLExpr<4> operator+(const GrGLSLExpr<4>& in0, const GrGLSLExpr<1>& in 1) { | |
| 257 return GrGLSLExpr<4>::Add(in0, in1); | |
| 258 } | |
| 259 | |
| 260 inline GrGLSLExpr<4> operator-(const GrGLSLExpr<4>& in0, const GrGLSLExpr<1>& in 1) { | |
| 261 return GrGLSLExpr<4>::Sub(in0, in1); | |
| 262 } | |
| 263 | |
| 264 /** Casts an vec1 expression to vec4 expresison, eg. vec1(v) -> vec4(v,v,v,v). */ | |
| 265 GrGLSLExpr<4> GrGLSLExprCast4(const GrGLSLExpr<1>& expr); | |
| 266 | |
| 267 /** Extracts alpha component from an expression of vec<4>. */ | |
| 268 GrGLSLExpr<1> GrGLSLExprExtractAlpha(const GrGLSLExpr<4>& expr); | |
| 131 | 269 |
| 132 /** | 270 /** |
| 133 * Produces a string that is the result of modulating two inputs. The inputs mu st be vecN or | 271 * Does an inplace mul, *=, of vec4VarName by mulFactor. |
| 134 * float. The result is always a vecN. The inputs may be expressions, not just identifier names. | 272 * A semicolon and newline are added after the assignment. |
| 135 * Either can be NULL or "" in which case the default params control whether a vector of ones or | |
| 136 * zeros. It is an error to pass kNone for default<i> if in<i> is NULL or "". N ote that when the | |
| 137 * function determines that the result is a zeros or ones vec then any expressi on represented by | |
| 138 * or in1 will not be emitted (side effects won't occur). The return value indi cates whether a | |
| 139 * known zeros or ones vector resulted. The output can be suppressed when known vector is produced | |
| 140 * by passing true for omitIfConstVec. | |
| 141 */ | |
| 142 template <int N> | |
| 143 GrSLConstantVec GrGLSLModulatef(SkString* outAppend, | |
| 144 const char* in0, | |
| 145 const char* in1, | |
| 146 GrSLConstantVec default0 = kOnes_GrSLConstantVec , | |
| 147 GrSLConstantVec default1 = kOnes_GrSLConstantVec , | |
| 148 bool omitIfConstVec = false); | |
| 149 | |
| 150 /** | |
| 151 * Produces a string that is the result of adding two inputs. The inputs must be vecN or | |
| 152 * float. The result is always a vecN. The inputs may be expressions, not just i dentifier names. | |
| 153 * Either can be NULL or "" in which case the default params control whether a v ector of ones or | |
| 154 * zeros. It is an error to pass kNone for default<i> if in<i> is NULL or "". No te that when the | |
| 155 * function determines that the result is a zeros or ones vec then any expressio n represented by | |
| 156 * or in1 will not be emitted (side effects won't occur). The return value indic ates whether a | |
| 157 * known zeros or ones vector resulted. The output can be suppressed when known vector is produced | |
| 158 * by passing true for omitIfConstVec. | |
| 159 */ | 273 */ |
| 160 template <int N> | 274 void GrGLSLMulVarBy4f(SkString* outAppend, unsigned tabCnt, |
| 161 GrSLConstantVec GrGLSLAddf(SkString* outAppend, | 275 const char* vec4VarName, const GrGLSLExpr<4>& mulFactor); |
| 162 const char* in0, | |
| 163 const char* in1, | |
| 164 GrSLConstantVec default0 = kZeros_GrSLConstantVec, | |
| 165 GrSLConstantVec default1 = kZeros_GrSLConstantVec, | |
| 166 bool omitIfConstVec = false); | |
| 167 | |
| 168 /** | |
| 169 * Produces a string that is the result of subtracting two inputs. The inputs mu st be vecN or | |
| 170 * float. The result is always a vecN. The inputs may be expressions, not just i dentifier names. | |
| 171 * Either can be NULL or "" in which case the default params control whether a v ector of ones or | |
| 172 * zeros. It is an error to pass kNone for default<i> if in<i> is NULL or "". No te that when the | |
| 173 * function determines that the result is a zeros or ones vec then any expressio n represented by | |
| 174 * or in1 will not be emitted (side effects won't occur). The return value indic ates whether a | |
| 175 * known zeros or ones vector resulted. The output can be suppressed when known vector is produced | |
| 176 * by passing true for omitIfConstVec. | |
| 177 */ | |
| 178 template <int N> | |
| 179 GrSLConstantVec GrGLSLSubtractf(SkString* outAppend, | |
| 180 const char* in0, | |
| 181 const char* in1, | |
| 182 GrSLConstantVec default0 = kZeros_GrSLConstantVe c, | |
| 183 GrSLConstantVec default1 = kZeros_GrSLConstantVe c, | |
| 184 bool omitIfConstVec = false); | |
| 185 | |
| 186 /** | |
| 187 * Does an inplace mul, *=, of vec4VarName by mulFactor. If mulFactorDefault is not kNone then | |
| 188 * mulFactor may be either "" or NULL. In this case either nothing will be appen ded (kOnes) or an | |
| 189 * assignment of vec(0,0,0,0) will be appended (kZeros). The assignment is prepe nded by tabCnt tabs. | |
| 190 * A semicolon and newline are added after the assignment. (TODO: Remove tabCnt when we auto-insert | |
| 191 * tabs to GrGLEffect-generated lines.) If a zeros vec is assigned then the retu rn value is | |
| 192 * kZeros, otherwise kNone. | |
| 193 */ | |
| 194 GrSLConstantVec GrGLSLMulVarBy4f(SkString* outAppend, | |
| 195 int tabCnt, | |
| 196 const char* vec4VarName, | |
| 197 const char* mulFactor, | |
| 198 GrSLConstantVec mulFactorDefault = kOnes_GrSLCo nstantVec); | |
| 199 | |
| 200 /** | |
| 201 * Given an expression that evaluates to a GLSL vec4, extract a component. If ex pr is NULL or "" | |
| 202 * the value of defaultExpr is used. It is an error to pass an empty expr and ha ve set defaultExpr | |
| 203 * to kNone. The return value indicates whether the value is known to be 0 or 1. If omitIfConst is | |
| 204 * set then nothing is appended when the return is not kNone. | |
| 205 */ | |
| 206 GrSLConstantVec GrGLSLGetComponent4f(SkString* outAppend, | |
| 207 const char* expr, | |
| 208 GrColorComponentFlags component, | |
| 209 GrSLConstantVec defaultExpr = kNone_GrSLCon stantVec, | |
| 210 bool omitIfConst = false); | |
| 211 | 276 |
| 212 #include "GrGLSL_impl.h" | 277 #include "GrGLSL_impl.h" |
| 213 | 278 |
| 214 #endif | 279 #endif |
| OLD | NEW |