1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 //    names, trademarks, service marks, or product names of the Licensor
11 //    and its affiliates, except as required to comply with Section 4(c) of
12 //    the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 //     http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #include "pxr/imaging/garch/glApi.h"
25 
26 #include "pxr/imaging/hdSt/glConversions.h"
27 #include "pxr/base/tf/staticTokens.h"
28 #include "pxr/base/tf/stringUtils.h"
29 
30 #include <cctype>
31 
32 PXR_NAMESPACE_OPEN_SCOPE
33 
34 
35 GLenum
GetGlDepthFunc(HdCompareFunction func)36 HdStGLConversions::GetGlDepthFunc(HdCompareFunction func)
37 {
38     static GLenum HD_2_GL_DEPTH_FUNC[] =
39     {
40         GL_NEVER,    // HdCmpFuncNever
41         GL_LESS,     // HdCmpFuncLess
42         GL_EQUAL,    // HdCmpFuncEqual
43         GL_LEQUAL,   // HdCmpFuncLEqual
44         GL_GREATER,  // HdCmpFuncGreater
45         GL_NOTEQUAL, // HdCmpFuncNotEqual
46         GL_GEQUAL,   // HdCmpFuncGEqual
47         GL_ALWAYS,   // HdCmpFuncAlways
48     };
49     static_assert(
50         (sizeof(HD_2_GL_DEPTH_FUNC) / sizeof(HD_2_GL_DEPTH_FUNC[0])) ==
51                 HdCmpFuncLast, "Mismatch enum sizes in convert function");
52 
53     return HD_2_GL_DEPTH_FUNC[func];
54 }
55 
56 GLenum
GetGlStencilFunc(HdCompareFunction func)57 HdStGLConversions::GetGlStencilFunc(HdCompareFunction func)
58 {
59     static GLenum HD_2_GL_STENCIL_FUNC[] =
60     {
61         GL_NEVER,    // HdCmpFuncNever
62         GL_LESS,     // HdCmpFuncLess
63         GL_EQUAL,    // HdCmpFuncEqual
64         GL_LEQUAL,   // HdCmpFuncLEqual
65         GL_GREATER,  // HdCmpFuncGreater
66         GL_NOTEQUAL, // HdCmpFuncNotEqual
67         GL_GEQUAL,   // HdCmpFuncGEqual
68         GL_ALWAYS,   // HdCmpFuncAlways
69     };
70     static_assert(
71         (sizeof(HD_2_GL_STENCIL_FUNC) / sizeof(HD_2_GL_STENCIL_FUNC[0])) ==
72                 HdCmpFuncLast, "Mismatch enum sizes in convert function");
73 
74     return HD_2_GL_STENCIL_FUNC[func];
75 }
76 
77 GLenum
GetGlStencilOp(HdStencilOp op)78 HdStGLConversions::GetGlStencilOp(HdStencilOp op)
79 {
80     static GLenum HD_2_GL_STENCIL_OP[] =
81     {
82         GL_KEEP,      // HdStencilOpKeep
83         GL_ZERO,      // HdStencilOpZero
84         GL_REPLACE,   // HdStencilOpReplace
85         GL_INCR,      // HdStencilOpIncrement
86         GL_INCR_WRAP, // HdStencilOpIncrementWrap
87         GL_DECR,      // HdStencilOpDecrement
88         GL_DECR_WRAP, // HdStencilOpDecrementWrap
89         GL_INVERT,    // HdStencilOpInvert
90     };
91     static_assert(
92         (sizeof(HD_2_GL_STENCIL_OP) / sizeof(HD_2_GL_STENCIL_OP[0])) ==
93                 HdStencilOpLast, "Mismatch enum sizes in convert function");
94 
95     return HD_2_GL_STENCIL_OP[op];
96 }
97 
98 GLenum
GetGlBlendOp(HdBlendOp op)99 HdStGLConversions::GetGlBlendOp(HdBlendOp op)
100 {
101     static GLenum HD_2_GL_BLEND_OP[] =
102     {
103         GL_FUNC_ADD,              // HdBlendOpAdd
104         GL_FUNC_SUBTRACT,         // HdBlendOpSubtract
105         GL_FUNC_REVERSE_SUBTRACT, // HdBlendOpReverseSubtract
106         GL_MIN,                   // HdBlendOpMin
107         GL_MAX,                   // HdBlendOpMax
108     };
109     static_assert(
110         (sizeof(HD_2_GL_BLEND_OP) / sizeof(HD_2_GL_BLEND_OP[0])) ==
111                 HdBlendOpLast, "Mismatch enum sizes in convert function");
112 
113     return HD_2_GL_BLEND_OP[op];
114 }
115 
116 GLenum
GetGlBlendFactor(HdBlendFactor factor)117 HdStGLConversions::GetGlBlendFactor(HdBlendFactor factor)
118 {
119     static GLenum HD_2_GL_BLEND_FACTOR[] =
120     {
121         GL_ZERO,                        // HdBlendFactorZero,
122         GL_ONE,                         // HdBlendFactorOne,
123         GL_SRC_COLOR,                   // HdBlendFactorSrcColor,
124         GL_ONE_MINUS_SRC_COLOR,         // HdBlendFactorOneMinusSrcColor,
125         GL_DST_COLOR,                   // HdBlendFactorDstColor,
126         GL_ONE_MINUS_DST_COLOR,         // HdBlendFactorOneMinusDstColor,
127         GL_SRC_ALPHA,                   // HdBlendFactorSrcAlpha,
128         GL_ONE_MINUS_SRC_ALPHA,         // HdBlendFactorOneMinusSrcAlpha,
129         GL_DST_ALPHA,                   // HdBlendFactorDstAlpha,
130         GL_ONE_MINUS_DST_ALPHA,         // HdBlendFactorOneMinusDstAlpha,
131         GL_CONSTANT_COLOR,              // HdBlendFactorConstantColor,
132         GL_ONE_MINUS_CONSTANT_COLOR,    // HdBlendFactorOneMinusConstantColor,
133         GL_CONSTANT_ALPHA,              // HdBlendFactorConstantAlpha,
134         GL_ONE_MINUS_CONSTANT_ALPHA,    // HdBlendFactorOneMinusConstantAlpha,
135         GL_SRC_ALPHA_SATURATE,          // HdBlendFactorSrcAlphaSaturate,
136         GL_SRC1_COLOR,                  // HdBlendFactorSrc1Color,
137         GL_ONE_MINUS_SRC1_COLOR,        // HdBlendFactorOneMinusSrc1Color,
138         GL_SRC1_ALPHA,                  // HdBlendFactorSrc1Alpha,
139         GL_ONE_MINUS_SRC1_COLOR,        // HdBlendFactorOneMinusSrc1Alpha,
140     };
141     static_assert(
142         (sizeof(HD_2_GL_BLEND_FACTOR) / sizeof(HD_2_GL_BLEND_FACTOR[0])) ==
143                 HdBlendFactorLast, "Mismatch enum sizes in convert function");
144 
145     return HD_2_GL_BLEND_FACTOR[factor];
146 }
147 
148 int
GetGLAttribType(HdType type)149 HdStGLConversions::GetGLAttribType(HdType type)
150 {
151     switch (type) {
152     case HdTypeHalfFloatVec2:
153     case HdTypeHalfFloatVec4:
154         return GL_HALF_FLOAT;
155     case HdTypeInt32:
156     case HdTypeInt32Vec2:
157     case HdTypeInt32Vec3:
158     case HdTypeInt32Vec4:
159         return GL_INT;
160     case HdTypeUInt32:
161     case HdTypeUInt32Vec2:
162     case HdTypeUInt32Vec3:
163     case HdTypeUInt32Vec4:
164         return GL_UNSIGNED_INT;
165     case HdTypeFloat:
166     case HdTypeFloatVec2:
167     case HdTypeFloatVec3:
168     case HdTypeFloatVec4:
169     case HdTypeFloatMat3:
170     case HdTypeFloatMat4:
171         return GL_FLOAT;
172     case HdTypeDouble:
173     case HdTypeDoubleVec2:
174     case HdTypeDoubleVec3:
175     case HdTypeDoubleVec4:
176     case HdTypeDoubleMat3:
177     case HdTypeDoubleMat4:
178         return GL_DOUBLE;
179     case HdTypeInt32_2_10_10_10_REV:
180         return GL_INT_2_10_10_10_REV;
181     default:
182         break;
183     };
184     return -1;
185 }
186 
187 TF_DEFINE_PRIVATE_TOKENS(
188     _glTypeNames,
189     ((_bool, "bool"))
190 
191     ((_float, "float"))
192     (vec2)
193     (vec3)
194     (vec4)
195     (mat3)
196     (mat4)
197 
198     ((_double, "double"))
199     (dvec2)
200     (dvec3)
201     (dvec4)
202     (dmat3)
203     (dmat4)
204 
205     ((_int, "int"))
206     (ivec2)
207     (ivec3)
208     (ivec4)
209 
210     ((_uint, "uint"))
211     (uvec2)
212     (uvec3)
213     (uvec4)
214 
215     (packed_2_10_10_10)
216     (packed_half2)
217     (packed_half4)
218 );
219 
220 TfToken
GetGLSLTypename(HdType type)221 HdStGLConversions::GetGLSLTypename(HdType type)
222 {
223     switch (type) {
224     case HdTypeInvalid:
225     default:
226         return TfToken();
227 
228     // Packed types (require special handling in codegen)...
229     case HdTypeInt32_2_10_10_10_REV:
230         return _glTypeNames->packed_2_10_10_10;
231     // XXX: Note that we don't support half or half3, since we can't
232     // index-address them...
233     case HdTypeHalfFloatVec2:
234         return _glTypeNames->packed_half2;
235     case HdTypeHalfFloatVec4:
236         return _glTypeNames->packed_half4;
237 
238     case HdTypeBool:
239         return _glTypeNames->_bool;
240 
241     case HdTypeInt32:
242         return _glTypeNames->_int;
243     case HdTypeInt32Vec2:
244         return _glTypeNames->ivec2;
245     case HdTypeInt32Vec3:
246         return _glTypeNames->ivec3;
247     case HdTypeInt32Vec4:
248         return _glTypeNames->ivec4;
249 
250     case HdTypeUInt32:
251         return _glTypeNames->_uint;
252     case HdTypeUInt32Vec2:
253         return _glTypeNames->uvec2;
254     case HdTypeUInt32Vec3:
255         return _glTypeNames->uvec3;
256     case HdTypeUInt32Vec4:
257         return _glTypeNames->uvec4;
258 
259     case HdTypeFloat:
260         return _glTypeNames->_float;
261     case HdTypeFloatVec2:
262         return _glTypeNames->vec2;
263     case HdTypeFloatVec3:
264         return _glTypeNames->vec3;
265     case HdTypeFloatVec4:
266         return _glTypeNames->vec4;
267     case HdTypeFloatMat3:
268         return _glTypeNames->mat3;
269     case HdTypeFloatMat4:
270         return _glTypeNames->mat4;
271 
272     case HdTypeDouble:
273         return _glTypeNames->_double;
274     case HdTypeDoubleVec2:
275         return _glTypeNames->dvec2;
276     case HdTypeDoubleVec3:
277         return _glTypeNames->dvec3;
278     case HdTypeDoubleVec4:
279         return _glTypeNames->dvec4;
280     case HdTypeDoubleMat3:
281         return _glTypeNames->dmat3;
282     case HdTypeDoubleMat4:
283         return _glTypeNames->dmat4;
284     };
285 }
286 
287 // This isn't an exhaustive checker. It doesn't check for built-in/internal
288 // variable names in GLSL, reserved keywords and such.
289 static bool
_IsIdentiferGLSLCompatible(std::string const & in)290 _IsIdentiferGLSLCompatible(std::string const& in)
291 {
292     char const *p = in.c_str();
293 
294     // Leading non-alpha characters are not allowed.
295     if (*p && !isalpha(*p)) {
296         return false;
297     }
298     // Characters must be in [_a-zA-Z0-9]
299     while (*p) {
300         if (isalnum(*p)) {
301             p++;
302         } else {
303             // _ is allowed, but __ isn't
304             if (*p == '_' && *(p-1) != '_') {
305                 // checking the last character is safe here, because of the
306                 // earlier check for leading non-alpha characters.
307                 p++;
308             } else {
309                 return false;
310             }
311         }
312     }
313 
314     return true;
315 }
316 
317 TfToken
GetGLSLIdentifier(TfToken const & identifier)318 HdStGLConversions::GetGLSLIdentifier(TfToken const& identifier)
319 {
320     std::string const& in = identifier.GetString();
321     // Avoid allocating a string and constructing a token for the general case,
322     // wherein identifers conform to the naming rules.
323     if (_IsIdentiferGLSLCompatible(in)) {
324         return identifier;
325     }
326 
327     // Name-mangling rules:
328     // https://www.khronos.org/registry/OpenGL/specs/gl/GLSLangSpec.4.60.pdf
329     // We choose to specifically disallow:
330     // 1) Leading non-alpha characters: GLSL allows leading underscores, but we
331     //    choose to reserve them for internal use.
332     // 2) Consecutive underscores: To avoid unintended GLSL behaviors.
333     std::string result;
334     result.reserve(in.size());
335     char const *p = in.c_str();
336 
337     // Skip leading non-alpha characters.
338     while (*p && !isalpha(*p)) {
339         ++p;
340     }
341     for (; *p; ++p) {
342         bool isValidChar = isalnum(*p) || (*p == '_');
343         if (!isValidChar) {
344             // Replace characters not in [_a-zA-Z0-9] with _, unless the last
345             // character  added was also _.
346             // Calling back() is safe here because the first character is either
347             // alpha-numeric or null, as guaranteed by the while loop above.
348             if (result.back() != '_') {
349                 result.push_back('_');
350             }
351         } else if (*p == '_' && result.back() == '_') {
352             // no-op to skip consecutive _
353         } else {
354             result.push_back(*p);
355         }
356     }
357 
358     if (result.empty()) {
359         TF_CODING_ERROR("Invalid identifier '%s' could not be name-mangled",
360                         identifier.GetText());
361         return identifier;
362     }
363 
364     return TfToken(result);
365 }
366 
367 PXR_NAMESPACE_CLOSE_SCOPE
368 
369