1 //
2 // Copyright 2019 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/hgi/enums.h"
27 #include "pxr/imaging/hgiGL/conversions.h"
28 
29 #include "pxr/base/tf/iterator.h"
30 #include "pxr/base/tf/staticTokens.h"
31 #include "pxr/base/tf/stringUtils.h"
32 
33 PXR_NAMESPACE_OPEN_SCOPE
34 
35 struct _FormatDesc {
36     GLenum format;
37     GLenum type;
38     GLenum internalFormat;
39 };
40 
41 static const _FormatDesc FORMAT_DESC[] =
42 {
43     // format,  type,             internal format
44     {GL_RED,  GL_UNSIGNED_BYTE, GL_R8          }, // UNorm8
45     {GL_RG,   GL_UNSIGNED_BYTE, GL_RG8         }, // UNorm8Vec2
46     // {GL_RGB,  GL_UNSIGNED_BYTE, GL_RGB8       }, // Unsupported by HgiFormat
47     {GL_RGBA, GL_UNSIGNED_BYTE, GL_RGBA8       }, // UNorm8Vec4
48 
49     {GL_RED,  GL_BYTE,          GL_R8_SNORM    }, // SNorm8
50     {GL_RG,   GL_BYTE,          GL_RG8_SNORM   }, // SNorm8Vec2
51     // {GL_RGB,  GL_BYTE,         GL_RGB8_SNORM  }, // Unsupported by HgiFormat
52     {GL_RGBA, GL_BYTE,          GL_RGBA8_SNORM }, // SNorm8Vec4
53 
54     {GL_RED,  GL_HALF_FLOAT,    GL_R16F        }, // Float16
55     {GL_RG,   GL_HALF_FLOAT,    GL_RG16F       }, // Float16Vec2
56     {GL_RGB,  GL_HALF_FLOAT,    GL_RGB16F      }, // Float16Vec3
57     {GL_RGBA, GL_HALF_FLOAT,    GL_RGBA16F     }, // Float16Vec4
58 
59     {GL_RED,  GL_FLOAT,         GL_R32F        }, // Float32
60     {GL_RG,   GL_FLOAT,         GL_RG32F       }, // Float32Vec2
61     {GL_RGB,  GL_FLOAT,         GL_RGB32F      }, // Float32Vec3
62     {GL_RGBA, GL_FLOAT,         GL_RGBA32F     }, // Float32Vec4
63 
64     {GL_RED_INTEGER,  GL_SHORT, GL_R16I        }, // Int16
65     {GL_RG_INTEGER,   GL_SHORT, GL_RG16I       }, // Int16Vec2
66     {GL_RGB_INTEGER,  GL_SHORT, GL_RGB16I      }, // Int16Vec3
67     {GL_RGBA_INTEGER, GL_SHORT, GL_RGBA16I     }, // Int16Vec4
68 
69     {GL_RED_INTEGER,  GL_UNSIGNED_SHORT,GL_R16UI        }, // UInt16
70     {GL_RG_INTEGER,   GL_UNSIGNED_SHORT,GL_RG16UI       }, // UInt16Vec2
71     {GL_RGB_INTEGER,  GL_UNSIGNED_SHORT,GL_RGB16UI      }, // UInt16Vec3
72     {GL_RGBA_INTEGER, GL_UNSIGNED_SHORT,GL_RGBA16UI     }, // UInt16Vec4
73 
74     {GL_RED_INTEGER,  GL_INT,   GL_R32I        }, // Int32
75     {GL_RG_INTEGER,   GL_INT,   GL_RG32I       }, // Int32Vec2
76     {GL_RGB_INTEGER,  GL_INT,   GL_RGB32I      }, // Int32Vec3
77     {GL_RGBA_INTEGER, GL_INT,   GL_RGBA32I     }, // Int32Vec4
78 
79     // {GL_RGB,  GL_UNSIGNED_BYTE, GL_SRGB8      }, // Unsupported by HgiFormat
80     {GL_RGBA, GL_UNSIGNED_BYTE, GL_SRGB8_ALPHA8}, // UNorm8Vec4sRGB,
81 
82     {GL_RGB,  GL_FLOAT,
83               GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT  }, // BC6FloatVec3
84     {GL_RGB,  GL_FLOAT,
85               GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT}, // BC6UFloatVec3
86     {GL_RGBA, GL_UNSIGNED_BYTE,
87               GL_COMPRESSED_RGBA_BPTC_UNORM }, // BC7UNorm8Vec4
88     {GL_RGBA, GL_UNSIGNED_BYTE,
89               GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM }, // BC7UNorm8Vec4srgb
90     {GL_RGBA, GL_UNSIGNED_BYTE,
91               GL_COMPRESSED_RGBA_S3TC_DXT1_EXT }, // BC1UNorm8Vec4
92     {GL_RGBA, GL_UNSIGNED_BYTE,
93               GL_COMPRESSED_RGBA_S3TC_DXT5_EXT }, // BC3UNorm8Vec4
94 
95     {GL_DEPTH_STENCIL, GL_FLOAT, GL_DEPTH32F_STENCIL8}, // Float32UInt8
96 
97 };
98 
99 // A few random format validations to make sure out GL table stays aligned
100 // with the HgiFormat table.
_CompileTimeValidateHgiFormatTable()101 constexpr bool _CompileTimeValidateHgiFormatTable() {
102     return (TfArraySize(FORMAT_DESC) == HgiFormatCount &&
103             HgiFormatUNorm8 == 0 &&
104             HgiFormatFloat16Vec4 == 9 &&
105             HgiFormatFloat32Vec4 == 13 &&
106             HgiFormatUInt16Vec4 == 21 &&
107             HgiFormatUNorm8Vec4srgb == 26 &&
108             HgiFormatBC3UNorm8Vec4 == 32) ? true : false;
109 }
110 
111 static_assert(_CompileTimeValidateHgiFormatTable(),
112               "_FormatDesc array out of sync with HgiFormat enum");
113 
114 static const uint32_t
115 _ShaderStageTable[][2] =
116 {
117     {HgiShaderStageVertex,              GL_VERTEX_SHADER},
118     {HgiShaderStageFragment,            GL_FRAGMENT_SHADER},
119     {HgiShaderStageCompute,             GL_COMPUTE_SHADER},
120     {HgiShaderStageTessellationControl, GL_TESS_CONTROL_SHADER},
121     {HgiShaderStageTessellationEval,    GL_TESS_EVALUATION_SHADER},
122     {HgiShaderStageGeometry,            GL_GEOMETRY_SHADER}
123 };
124 
125 static const uint32_t
126 _CullModeTable[HgiCullModeCount][2] =
127 {
128     {HgiCullModeNone,         GL_NONE},
129     {HgiCullModeFront,        GL_FRONT},
130     {HgiCullModeBack,         GL_BACK},
131     {HgiCullModeFrontAndBack, GL_FRONT_AND_BACK}
132 };
133 
134 static const uint32_t
135 _PolygonModeTable[HgiCullModeCount][2] =
136 {
137     {HgiPolygonModeFill,  GL_FILL},
138     {HgiPolygonModeLine,  GL_LINE},
139     {HgiPolygonModePoint, GL_POINT},
140 };
141 
142 static uint32_t
143 _blendEquationTable[HgiBlendOpCount][2] =
144 {
145     {HgiBlendOpAdd,             GL_FUNC_ADD},
146     {HgiBlendOpSubtract,        GL_FUNC_SUBTRACT},
147     {HgiBlendOpReverseSubtract, GL_FUNC_REVERSE_SUBTRACT},
148     {HgiBlendOpMin,             GL_MIN},
149     {HgiBlendOpMax,             GL_MAX},
150 };
151 
152 static uint32_t _blendFactorTable[HgiBlendFactorCount][2] =
153 {
154     {HgiBlendFactorZero,                  GL_ZERO},
155     {HgiBlendFactorOne,                   GL_ONE},
156     {HgiBlendFactorSrcColor,              GL_SRC_COLOR},
157     {HgiBlendFactorOneMinusSrcColor,      GL_ONE_MINUS_SRC_COLOR},
158     {HgiBlendFactorDstColor,              GL_DST_COLOR},
159     {HgiBlendFactorOneMinusDstColor,      GL_ONE_MINUS_DST_COLOR},
160     {HgiBlendFactorSrcAlpha,              GL_SRC_ALPHA},
161     {HgiBlendFactorOneMinusSrcAlpha,      GL_ONE_MINUS_SRC_ALPHA},
162     {HgiBlendFactorDstAlpha,              GL_DST_ALPHA},
163     {HgiBlendFactorOneMinusDstAlpha,      GL_ONE_MINUS_DST_ALPHA},
164     {HgiBlendFactorConstantColor,         GL_CONSTANT_COLOR},
165     {HgiBlendFactorOneMinusConstantColor, GL_ONE_MINUS_CONSTANT_COLOR},
166     {HgiBlendFactorConstantAlpha,         GL_CONSTANT_ALPHA},
167     {HgiBlendFactorOneMinusConstantAlpha, GL_ONE_MINUS_CONSTANT_ALPHA},
168     {HgiBlendFactorSrcAlphaSaturate,      GL_SRC_ALPHA_SATURATE},
169     {HgiBlendFactorSrc1Color,             GL_SRC1_COLOR},
170     {HgiBlendFactorOneMinusSrc1Color,     GL_ONE_MINUS_SRC1_COLOR},
171     {HgiBlendFactorSrc1Alpha,             GL_SRC1_ALPHA},
172     {HgiBlendFactorOneMinusSrc1Alpha,     GL_ONE_MINUS_SRC1_COLOR},
173 };
174 
175 static uint32_t
176 _compareFunctionTable[HgiCompareFunctionCount][2] =
177 {
178     {HgiCompareFunctionNever,    GL_NEVER},
179     {HgiCompareFunctionLess,     GL_LESS},
180     {HgiCompareFunctionEqual,    GL_EQUAL},
181     {HgiCompareFunctionLEqual,   GL_LEQUAL},
182     {HgiCompareFunctionGreater,  GL_GREATER},
183     {HgiCompareFunctionNotEqual, GL_NOTEQUAL},
184     {HgiCompareFunctionGEqual,   GL_GEQUAL},
185     {HgiCompareFunctionAlways,   GL_ALWAYS},
186 };
187 
188 static uint32_t
189 _textureTypeTable[HgiTextureTypeCount][2] =
190 {
191     {HgiTextureType1D,      GL_TEXTURE_1D},
192     {HgiTextureType2D,      GL_TEXTURE_2D},
193     {HgiTextureType3D,      GL_TEXTURE_3D},
194     {HgiTextureType1DArray, GL_TEXTURE_1D_ARRAY},
195     {HgiTextureType2DArray, GL_TEXTURE_2D_ARRAY}
196 };
197 
198 static uint32_t
199 _samplerAddressModeTable[HgiSamplerAddressModeCount][2] =
200 {
201     {HgiSamplerAddressModeClampToEdge,        GL_CLAMP_TO_EDGE},
202     {HgiSamplerAddressModeMirrorClampToEdge,  GL_MIRROR_CLAMP_TO_EDGE},
203     {HgiSamplerAddressModeRepeat,             GL_REPEAT},
204     {HgiSamplerAddressModeMirrorRepeat,       GL_MIRRORED_REPEAT},
205     {HgiSamplerAddressModeClampToBorderColor, GL_CLAMP_TO_BORDER}
206 };
207 
208 static const uint32_t
209 _componentSwizzleTable[HgiComponentSwizzleCount][2] =
210 {
211     {HgiComponentSwizzleZero, GL_ZERO},
212     {HgiComponentSwizzleOne,  GL_ONE},
213     {HgiComponentSwizzleR,    GL_RED},
214     {HgiComponentSwizzleG,    GL_GREEN},
215     {HgiComponentSwizzleB,    GL_BLUE},
216     {HgiComponentSwizzleA,    GL_ALPHA}
217 };
218 
219 static const uint32_t
220 _primitiveTypeTable[HgiPrimitiveTypeCount][2] =
221 {
222     {HgiPrimitiveTypePointList,    GL_POINTS},
223     {HgiPrimitiveTypeLineList,     GL_LINES},
224     {HgiPrimitiveTypeLineStrip,    GL_LINES_ADJACENCY},
225     {HgiPrimitiveTypeTriangleList, GL_TRIANGLES},
226     {HgiPrimitiveTypePatchList,    GL_PATCHES}
227 };
228 
229 void
GetFormat(HgiFormat inFormat,GLenum * outFormat,GLenum * outType,GLenum * outInternalFormat)230 HgiGLConversions::GetFormat(
231         HgiFormat inFormat,
232         GLenum *outFormat,
233         GLenum *outType,
234         GLenum *outInternalFormat)
235 {
236     if ((inFormat < 0) || (inFormat >= HgiFormatCount))
237     {
238         TF_CODING_ERROR("Unexpected  %d", inFormat);
239         if (outFormat) {
240             *outFormat = GL_RGBA;
241         }
242         if (outType) {
243             *outType = GL_BYTE;
244         }
245         if (outInternalFormat) {
246             *outInternalFormat = GL_RGBA8;
247         }
248         return;
249     }
250 
251     const _FormatDesc &desc = FORMAT_DESC[inFormat];
252     if (outFormat) {
253         *outFormat = desc.format;
254     }
255     if (outType) {
256         *outType = desc.type;
257     }
258     if (outInternalFormat) {
259         *outInternalFormat = desc.internalFormat;
260     }
261 }
262 
263 GLenum
GetFormatType(HgiFormat inFormat)264 HgiGLConversions::GetFormatType(HgiFormat inFormat)
265 {
266     const _FormatDesc &desc = FORMAT_DESC[inFormat];
267     return desc.type;
268 }
269 
270 std::vector<GLenum>
GetShaderStages(HgiShaderStage ss)271 HgiGLConversions::GetShaderStages(HgiShaderStage ss)
272 {
273     std::vector<GLenum> stages;
274     for (const auto& f : _ShaderStageTable) {
275         if (ss & f[0]) stages.push_back(f[1]);
276     }
277 
278     if (stages.empty()) {
279         TF_CODING_ERROR("Missing shader stage table entry");
280     }
281     return stages;
282 }
283 
284 GLenum
GetCullMode(HgiCullMode cm)285 HgiGLConversions::GetCullMode(HgiCullMode cm)
286 {
287     return _CullModeTable[cm][1];
288 }
289 
290 GLenum
GetPolygonMode(HgiPolygonMode pm)291 HgiGLConversions::GetPolygonMode(HgiPolygonMode pm)
292 {
293     return _PolygonModeTable[pm][1];
294 }
295 
296 GLenum
GetBlendFactor(HgiBlendFactor bf)297 HgiGLConversions::GetBlendFactor(HgiBlendFactor bf)
298 {
299     return _blendFactorTable[bf][1];
300 }
301 
302 GLenum
GetBlendEquation(HgiBlendOp bo)303 HgiGLConversions::GetBlendEquation(HgiBlendOp bo)
304 {
305     return _blendEquationTable[bo][1];
306 }
307 
308 GLenum
GetDepthCompareFunction(HgiCompareFunction cf)309 HgiGLConversions::GetDepthCompareFunction(HgiCompareFunction cf)
310 {
311     return _compareFunctionTable[cf][1];
312 }
313 
314 GLenum
GetTextureType(HgiTextureType tt)315 HgiGLConversions::GetTextureType(HgiTextureType tt)
316 {
317     return _textureTypeTable[tt][1];
318 }
319 
320 GLenum
GetSamplerAddressMode(HgiSamplerAddressMode am)321 HgiGLConversions::GetSamplerAddressMode(HgiSamplerAddressMode am)
322 {
323     return _samplerAddressModeTable[am][1];
324 }
325 
326 GLenum
GetMagFilter(HgiSamplerFilter sf)327 HgiGLConversions::GetMagFilter(HgiSamplerFilter sf)
328 {
329     switch(sf) {
330         case HgiSamplerFilterNearest: return GL_NEAREST;
331         case HgiSamplerFilterLinear: return GL_LINEAR;
332         default: break;
333     }
334 
335     TF_CODING_ERROR("Unsupported sampler options");
336     return GL_NONE;
337 }
338 
339 GLenum
GetMinFilter(HgiSamplerFilter minFilter,HgiMipFilter mipFilter)340 HgiGLConversions::GetMinFilter(
341     HgiSamplerFilter minFilter,
342     HgiMipFilter mipFilter)
343 {
344     switch(mipFilter) {
345     // No mip-filter supplied (no mipmapping), return min-filter
346     case HgiMipFilterNotMipmapped :
347         switch(minFilter) {
348             case HgiSamplerFilterNearest: return GL_NEAREST;
349             case HgiSamplerFilterLinear: return GL_LINEAR;
350             default: TF_CODING_ERROR("Unsupported type"); break;
351         }
352 
353     // Mip filter is nearest, combine min and mip filter into one enum
354     case HgiMipFilterNearest:
355         switch(minFilter) {
356             case HgiSamplerFilterNearest: return GL_NEAREST_MIPMAP_NEAREST;
357             case HgiSamplerFilterLinear: return GL_LINEAR_MIPMAP_NEAREST;
358             default: TF_CODING_ERROR("Unsupported typr"); break;
359         }
360 
361     // Mip filter is linear, combine min and mip filter into one enum
362     case HgiMipFilterLinear:
363         switch(minFilter) {
364             case HgiSamplerFilterNearest: return GL_NEAREST_MIPMAP_LINEAR;
365             case HgiSamplerFilterLinear: return GL_LINEAR_MIPMAP_LINEAR;
366             default: TF_CODING_ERROR("Unsupported typr"); break;
367         }
368 
369     default: break;
370     }
371 
372     TF_CODING_ERROR("Unsupported sampler options");
373     return GL_NONE;
374 }
375 
376 GLenum
GetComponentSwizzle(HgiComponentSwizzle componentSwizzle)377 HgiGLConversions::GetComponentSwizzle(HgiComponentSwizzle componentSwizzle)
378 {
379     return _componentSwizzleTable[componentSwizzle][1];
380 }
381 
382 GLenum
GetPrimitiveType(HgiPrimitiveType pt)383 HgiGLConversions::GetPrimitiveType(HgiPrimitiveType pt)
384 {
385     return _primitiveTypeTable[pt][1];
386 }
387 
388 PXR_NAMESPACE_CLOSE_SCOPE
389