xref: /aosp_15_r20/external/angle/src/common/PackedEnums.h (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 // Copyright 2017 The ANGLE Project Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 //
5 // PackedGLEnums_autogen.h:
6 //   Declares ANGLE-specific enums classes for GLEnum and functions operating
7 //   on them.
8 
9 #ifndef COMMON_PACKEDGLENUMS_H_
10 #define COMMON_PACKEDGLENUMS_H_
11 
12 #include "common/PackedEGLEnums_autogen.h"
13 #include "common/PackedGLEnums_autogen.h"
14 
15 #include <array>
16 #include <bitset>
17 #include <cstddef>
18 
19 #include <EGL/egl.h>
20 
21 #include "common/bitset_utils.h"
22 
23 namespace angle
24 {
25 
26 // Return the number of elements of a packed enum, including the InvalidEnum element.
27 template <typename E>
EnumSize()28 constexpr size_t EnumSize()
29 {
30     using UnderlyingType = typename std::underlying_type<E>::type;
31     return static_cast<UnderlyingType>(E::EnumCount);
32 }
33 
34 // Implementation of AllEnums which allows iterating over all the possible values for a packed enums
35 // like so:
36 //     for (auto value : AllEnums<MyPackedEnum>()) {
37 //         // Do something with the enum.
38 //     }
39 
40 template <typename E>
41 class EnumIterator final
42 {
43   private:
44     using UnderlyingType = typename std::underlying_type<E>::type;
45 
46   public:
EnumIterator(E value)47     EnumIterator(E value) : mValue(static_cast<UnderlyingType>(value)) {}
48     EnumIterator &operator++()
49     {
50         mValue++;
51         return *this;
52     }
53     bool operator==(const EnumIterator &other) const { return mValue == other.mValue; }
54     bool operator!=(const EnumIterator &other) const { return mValue != other.mValue; }
55     E operator*() const { return static_cast<E>(mValue); }
56 
57   private:
58     UnderlyingType mValue;
59 };
60 
61 template <typename E, size_t MaxSize = EnumSize<E>()>
62 struct AllEnums
63 {
beginAllEnums64     EnumIterator<E> begin() const { return {static_cast<E>(0)}; }
endAllEnums65     EnumIterator<E> end() const { return {static_cast<E>(MaxSize)}; }
66 };
67 
68 // PackedEnumMap<E, T> is like an std::array<T, E::EnumCount> but is indexed with enum values. It
69 // implements all of the std::array interface except with enum values instead of indices.
70 template <typename E, typename T, size_t MaxSize = EnumSize<E>()>
71 class PackedEnumMap
72 {
73     using UnderlyingType = typename std::underlying_type<E>::type;
74     using Storage        = std::array<T, MaxSize>;
75 
76   public:
77     using InitPair = std::pair<E, T>;
78 
79     constexpr PackedEnumMap() = default;
80 
PackedEnumMap(std::initializer_list<InitPair> init)81     constexpr PackedEnumMap(std::initializer_list<InitPair> init) : mPrivateData{}
82     {
83         // We use a for loop instead of range-for to work around a limitation in MSVC.
84         for (const InitPair *it = init.begin(); it != init.end(); ++it)
85         {
86             mPrivateData[static_cast<UnderlyingType>(it->first)] = it->second;
87         }
88     }
89 
90     // types:
91     using value_type      = T;
92     using pointer         = T *;
93     using const_pointer   = const T *;
94     using reference       = T &;
95     using const_reference = const T &;
96 
97     using size_type       = size_t;
98     using difference_type = ptrdiff_t;
99 
100     using iterator               = typename Storage::iterator;
101     using const_iterator         = typename Storage::const_iterator;
102     using reverse_iterator       = std::reverse_iterator<iterator>;
103     using const_reverse_iterator = std::reverse_iterator<const_iterator>;
104 
105     // No explicit construct/copy/destroy for aggregate type
fill(const T & u)106     void fill(const T &u) { mPrivateData.fill(u); }
swap(PackedEnumMap<E,T,MaxSize> & a)107     void swap(PackedEnumMap<E, T, MaxSize> &a) noexcept { mPrivateData.swap(a.mPrivateData); }
108 
109     // iterators:
begin()110     iterator begin() noexcept { return mPrivateData.begin(); }
begin()111     const_iterator begin() const noexcept { return mPrivateData.begin(); }
end()112     iterator end() noexcept { return mPrivateData.end(); }
end()113     const_iterator end() const noexcept { return mPrivateData.end(); }
114 
rbegin()115     reverse_iterator rbegin() noexcept { return mPrivateData.rbegin(); }
rbegin()116     const_reverse_iterator rbegin() const noexcept { return mPrivateData.rbegin(); }
rend()117     reverse_iterator rend() noexcept { return mPrivateData.rend(); }
rend()118     const_reverse_iterator rend() const noexcept { return mPrivateData.rend(); }
119 
120     // capacity:
size()121     constexpr size_type size() const noexcept { return mPrivateData.size(); }
max_size()122     constexpr size_type max_size() const noexcept { return mPrivateData.max_size(); }
empty()123     constexpr bool empty() const noexcept { return mPrivateData.empty(); }
124 
125     // element access:
126     reference operator[](E n)
127     {
128         ASSERT(static_cast<size_t>(n) < mPrivateData.size());
129         return mPrivateData[static_cast<UnderlyingType>(n)];
130     }
131 
132     constexpr const_reference operator[](E n) const
133     {
134         ASSERT(static_cast<size_t>(n) < mPrivateData.size());
135         return mPrivateData[static_cast<UnderlyingType>(n)];
136     }
137 
at(E n)138     const_reference at(E n) const { return mPrivateData.at(static_cast<UnderlyingType>(n)); }
at(E n)139     reference at(E n) { return mPrivateData.at(static_cast<UnderlyingType>(n)); }
140 
front()141     reference front() { return mPrivateData.front(); }
front()142     const_reference front() const { return mPrivateData.front(); }
back()143     reference back() { return mPrivateData.back(); }
back()144     const_reference back() const { return mPrivateData.back(); }
145 
data()146     T *data() noexcept { return mPrivateData.data(); }
data()147     const T *data() const noexcept { return mPrivateData.data(); }
148 
149     bool operator==(const PackedEnumMap &rhs) const { return mPrivateData == rhs.mPrivateData; }
150     bool operator!=(const PackedEnumMap &rhs) const { return mPrivateData != rhs.mPrivateData; }
151 
152     template <typename SubT = T>
153     typename std::enable_if<std::is_integral<SubT>::value>::type operator+=(
154         const PackedEnumMap<E, SubT, MaxSize> &rhs)
155     {
156         for (E e : AllEnums<E, MaxSize>())
157         {
158             at(e) += rhs[e];
159         }
160     }
161 
162   private:
163     Storage mPrivateData;
164 };
165 
166 // PackedEnumBitSetE> is like an std::bitset<E::EnumCount> but is indexed with enum values. It
167 // implements the std::bitset interface except with enum values instead of indices.
168 template <typename E, typename DataT = uint32_t>
169 using PackedEnumBitSet = BitSetT<EnumSize<E>(), DataT, E>;
170 
171 }  // namespace angle
172 
173 #define ANGLE_DEFINE_ID_TYPE(Type)          \
174     class Type;                             \
175     struct Type##ID                         \
176     {                                       \
177         GLuint value;                       \
178     };                                      \
179     template <>                             \
180     struct ResourceTypeToID<Type>           \
181     {                                       \
182         using IDType = Type##ID;            \
183     };                                      \
184     template <>                             \
185     struct IsResourceIDType<Type##ID>       \
186     {                                       \
187         static constexpr bool value = true; \
188     };
189 
190 namespace gl
191 {
192 
193 TextureType TextureTargetToType(TextureTarget target);
194 TextureTarget NonCubeTextureTypeToTarget(TextureType type);
195 
196 TextureTarget CubeFaceIndexToTextureTarget(size_t face);
197 size_t CubeMapTextureTargetToFaceIndex(TextureTarget target);
198 bool IsCubeMapFaceTarget(TextureTarget target);
199 
200 constexpr TextureTarget kCubeMapTextureTargetMin = TextureTarget::CubeMapPositiveX;
201 constexpr TextureTarget kCubeMapTextureTargetMax = TextureTarget::CubeMapNegativeZ;
202 constexpr TextureTarget kAfterCubeMapTextureTargetMax =
203     static_cast<TextureTarget>(static_cast<uint8_t>(kCubeMapTextureTargetMax) + 1);
204 struct AllCubeFaceTextureTargets
205 {
beginAllCubeFaceTextureTargets206     angle::EnumIterator<TextureTarget> begin() const { return kCubeMapTextureTargetMin; }
endAllCubeFaceTextureTargets207     angle::EnumIterator<TextureTarget> end() const { return kAfterCubeMapTextureTargetMax; }
208 };
209 
210 constexpr std::array<ShaderType, 2> kAllGLES2ShaderTypes = {ShaderType::Vertex,
211                                                             ShaderType::Fragment};
212 
213 constexpr ShaderType kShaderTypeMin = ShaderType::Vertex;
214 constexpr ShaderType kShaderTypeMax = ShaderType::Compute;
215 constexpr ShaderType kAfterShaderTypeMax =
216     static_cast<ShaderType>(static_cast<uint8_t>(kShaderTypeMax) + 1);
217 struct AllShaderTypes
218 {
beginAllShaderTypes219     angle::EnumIterator<ShaderType> begin() const { return kShaderTypeMin; }
endAllShaderTypes220     angle::EnumIterator<ShaderType> end() const { return kAfterShaderTypeMax; }
221 };
222 
223 constexpr size_t kGraphicsShaderCount = static_cast<size_t>(ShaderType::EnumCount) - 1u;
224 // Arrange the shader types in the order of rendering pipeline
225 constexpr std::array<ShaderType, kGraphicsShaderCount> kAllGraphicsShaderTypes = {
226     ShaderType::Vertex, ShaderType::TessControl, ShaderType::TessEvaluation, ShaderType::Geometry,
227     ShaderType::Fragment};
228 
229 using ShaderBitSet = angle::PackedEnumBitSet<ShaderType, uint8_t>;
230 static_assert(sizeof(ShaderBitSet) == sizeof(uint8_t), "Unexpected size");
231 
232 template <typename T>
233 using ShaderMap = angle::PackedEnumMap<ShaderType, T>;
234 
235 const char *ShaderTypeToString(ShaderType shaderType);
236 
237 TextureType SamplerTypeToTextureType(GLenum samplerType);
238 TextureType ImageTypeToTextureType(GLenum imageType);
239 
240 bool IsMultisampled(gl::TextureType type);
241 bool IsArrayTextureType(gl::TextureType type);
242 bool IsLayeredTextureType(gl::TextureType type);
243 
244 bool IsStaticBufferUsage(BufferUsage useage);
245 
246 enum class PrimitiveMode : uint8_t
247 {
248     Points                 = 0x0,
249     Lines                  = 0x1,
250     LineLoop               = 0x2,
251     LineStrip              = 0x3,
252     Triangles              = 0x4,
253     TriangleStrip          = 0x5,
254     TriangleFan            = 0x6,
255     Unused1                = 0x7,
256     Unused2                = 0x8,
257     Unused3                = 0x9,
258     LinesAdjacency         = 0xA,
259     LineStripAdjacency     = 0xB,
260     TrianglesAdjacency     = 0xC,
261     TriangleStripAdjacency = 0xD,
262     Patches                = 0xE,
263 
264     InvalidEnum = 0xF,
265     EnumCount   = 0xF,
266 };
267 
268 template <>
269 constexpr PrimitiveMode FromGLenum<PrimitiveMode>(GLenum from)
270 {
271     if (from >= static_cast<GLenum>(PrimitiveMode::EnumCount))
272     {
273         return PrimitiveMode::InvalidEnum;
274     }
275 
276     return static_cast<PrimitiveMode>(from);
277 }
278 
ToGLenum(PrimitiveMode from)279 constexpr GLenum ToGLenum(PrimitiveMode from)
280 {
281     return static_cast<GLenum>(from);
282 }
283 
284 static_assert(ToGLenum(PrimitiveMode::Points) == GL_POINTS, "PrimitiveMode violation");
285 static_assert(ToGLenum(PrimitiveMode::Lines) == GL_LINES, "PrimitiveMode violation");
286 static_assert(ToGLenum(PrimitiveMode::LineLoop) == GL_LINE_LOOP, "PrimitiveMode violation");
287 static_assert(ToGLenum(PrimitiveMode::LineStrip) == GL_LINE_STRIP, "PrimitiveMode violation");
288 static_assert(ToGLenum(PrimitiveMode::Triangles) == GL_TRIANGLES, "PrimitiveMode violation");
289 static_assert(ToGLenum(PrimitiveMode::TriangleStrip) == GL_TRIANGLE_STRIP,
290               "PrimitiveMode violation");
291 static_assert(ToGLenum(PrimitiveMode::TriangleFan) == GL_TRIANGLE_FAN, "PrimitiveMode violation");
292 static_assert(ToGLenum(PrimitiveMode::LinesAdjacency) == GL_LINES_ADJACENCY,
293               "PrimitiveMode violation");
294 static_assert(ToGLenum(PrimitiveMode::LineStripAdjacency) == GL_LINE_STRIP_ADJACENCY,
295               "PrimitiveMode violation");
296 static_assert(ToGLenum(PrimitiveMode::TrianglesAdjacency) == GL_TRIANGLES_ADJACENCY,
297               "PrimitiveMode violation");
298 static_assert(ToGLenum(PrimitiveMode::TriangleStripAdjacency) == GL_TRIANGLE_STRIP_ADJACENCY,
299               "PrimitiveMode violation");
300 
301 std::ostream &operator<<(std::ostream &os, PrimitiveMode value);
302 
303 enum class DrawElementsType : size_t
304 {
305     UnsignedByte  = 0,
306     UnsignedShort = 1,
307     UnsignedInt   = 2,
308     InvalidEnum   = 3,
309     EnumCount     = 3,
310 };
311 
312 template <>
313 constexpr DrawElementsType FromGLenum<DrawElementsType>(GLenum from)
314 {
315 
316     GLenum scaled = (from - GL_UNSIGNED_BYTE);
317     // This code sequence generates a ROR instruction on x86/arm. We want to check if the lowest bit
318     // of scaled is set and if (scaled >> 1) is greater than a non-pot value. If we rotate the
319     // lowest bit to the hightest bit both conditions can be checked with a single test.
320     static_assert(sizeof(GLenum) == 4, "Update (scaled << 31) to sizeof(GLenum) * 8 - 1");
321     GLenum packed = (scaled >> 1) | (scaled << 31);
322 
323     // operator ? with a simple assignment usually translates to a cmov instruction and thus avoids
324     // a branch.
325     packed = (packed >= static_cast<GLenum>(DrawElementsType::EnumCount))
326                  ? static_cast<GLenum>(DrawElementsType::InvalidEnum)
327                  : packed;
328 
329     return static_cast<DrawElementsType>(packed);
330 }
331 
ToGLenum(DrawElementsType from)332 constexpr GLenum ToGLenum(DrawElementsType from)
333 {
334     return ((static_cast<GLenum>(from) << 1) + GL_UNSIGNED_BYTE);
335 }
336 
337 #define ANGLE_VALIDATE_PACKED_ENUM(type, packed, glenum)                 \
338     static_assert(ToGLenum(type::packed) == glenum, #type " violation"); \
339     static_assert(FromGLenum<type>(glenum) == type::packed, #type " violation")
340 
341 ANGLE_VALIDATE_PACKED_ENUM(DrawElementsType, UnsignedByte, GL_UNSIGNED_BYTE);
342 ANGLE_VALIDATE_PACKED_ENUM(DrawElementsType, UnsignedShort, GL_UNSIGNED_SHORT);
343 ANGLE_VALIDATE_PACKED_ENUM(DrawElementsType, UnsignedInt, GL_UNSIGNED_INT);
344 
345 std::ostream &operator<<(std::ostream &os, DrawElementsType value);
346 
347 enum class BlendEquationType
348 {
349     Add             = 0,  // GLenum == 0x8006
350     Min             = 1,  // GLenum == 0x8007
351     Max             = 2,  // GLenum == 0x8008
352     Unused          = 3,
353     Subtract        = 4,  // GLenum == 0x800A
354     ReverseSubtract = 5,  // GLenum == 0x800B
355 
356     Multiply   = 6,   // GLenum == 0x9294
357     Screen     = 7,   // GLenum == 0x9295
358     Overlay    = 8,   // GLenum == 0x9296
359     Darken     = 9,   // GLenum == 0x9297
360     Lighten    = 10,  // GLenum == 0x9298
361     Colordodge = 11,  // GLenum == 0x9299
362     Colorburn  = 12,  // GLenum == 0x929A
363     Hardlight  = 13,  // GLenum == 0x929B
364     Softlight  = 14,  // GLenum == 0x929C
365     Unused2    = 15,
366     Difference = 16,  // GLenum == 0x929E
367     Unused3    = 17,
368     Exclusion  = 18,  // GLenum == 0x92A0
369 
370     HslHue        = 19,  // GLenum == 0x92AD
371     HslSaturation = 20,  // GLenum == 0x92AE
372     HslColor      = 21,  // GLenum == 0x92AF
373     HslLuminosity = 22,  // GLenum == 0x92B0
374 
375     InvalidEnum = 23,
376     EnumCount   = InvalidEnum
377 };
378 
379 using BlendEquationBitSet = angle::PackedEnumBitSet<gl::BlendEquationType>;
380 
381 template <>
382 constexpr BlendEquationType FromGLenum<BlendEquationType>(GLenum from)
383 {
384     if (from <= GL_FUNC_REVERSE_SUBTRACT)
385     {
386         const GLenum scaled = (from - GL_FUNC_ADD);
387         return (scaled == static_cast<GLenum>(BlendEquationType::Unused))
388                    ? BlendEquationType::InvalidEnum
389                    : static_cast<BlendEquationType>(scaled);
390     }
391     if (from <= GL_EXCLUSION_KHR)
392     {
393         const GLenum scaled =
394             (from - GL_MULTIPLY_KHR + static_cast<uint32_t>(BlendEquationType::Multiply));
395         return (scaled == static_cast<GLenum>(BlendEquationType::Unused2) ||
396                 scaled == static_cast<GLenum>(BlendEquationType::Unused3))
397                    ? BlendEquationType::InvalidEnum
398                    : static_cast<BlendEquationType>(scaled);
399     }
400     if (from <= GL_HSL_LUMINOSITY_KHR)
401     {
402         return static_cast<BlendEquationType>(from - GL_HSL_HUE_KHR +
403                                               static_cast<uint32_t>(BlendEquationType::HslHue));
404     }
405     return BlendEquationType::InvalidEnum;
406 }
407 
ToGLenum(BlendEquationType from)408 constexpr GLenum ToGLenum(BlendEquationType from)
409 {
410     if (from <= BlendEquationType::ReverseSubtract)
411     {
412         return static_cast<GLenum>(from) + GL_FUNC_ADD;
413     }
414     if (from <= BlendEquationType::Exclusion)
415     {
416         return static_cast<GLenum>(from) - static_cast<GLenum>(BlendEquationType::Multiply) +
417                GL_MULTIPLY_KHR;
418     }
419     return static_cast<GLenum>(from) - static_cast<GLenum>(BlendEquationType::HslHue) +
420            GL_HSL_HUE_KHR;
421 }
422 
423 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Add, GL_FUNC_ADD);
424 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Min, GL_MIN);
425 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Max, GL_MAX);
426 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Subtract, GL_FUNC_SUBTRACT);
427 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, ReverseSubtract, GL_FUNC_REVERSE_SUBTRACT);
428 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Multiply, GL_MULTIPLY_KHR);
429 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Screen, GL_SCREEN_KHR);
430 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Overlay, GL_OVERLAY_KHR);
431 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Darken, GL_DARKEN_KHR);
432 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Lighten, GL_LIGHTEN_KHR);
433 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Colordodge, GL_COLORDODGE_KHR);
434 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Colorburn, GL_COLORBURN_KHR);
435 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Hardlight, GL_HARDLIGHT_KHR);
436 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Softlight, GL_SOFTLIGHT_KHR);
437 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Difference, GL_DIFFERENCE_KHR);
438 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Exclusion, GL_EXCLUSION_KHR);
439 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, HslHue, GL_HSL_HUE_KHR);
440 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, HslSaturation, GL_HSL_SATURATION_KHR);
441 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, HslColor, GL_HSL_COLOR_KHR);
442 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, HslLuminosity, GL_HSL_LUMINOSITY_KHR);
443 
444 std::ostream &operator<<(std::ostream &os, BlendEquationType value);
445 
446 enum class BlendFactorType
447 {
448     Zero = 0,  // GLenum == 0
449     One  = 1,  // GLenum == 1
450 
451     MinSrcDstType    = 2,
452     SrcColor         = 2,   // GLenum == 0x0300
453     OneMinusSrcColor = 3,   // GLenum == 0x0301
454     SrcAlpha         = 4,   // GLenum == 0x0302
455     OneMinusSrcAlpha = 5,   // GLenum == 0x0303
456     DstAlpha         = 6,   // GLenum == 0x0304
457     OneMinusDstAlpha = 7,   // GLenum == 0x0305
458     DstColor         = 8,   // GLenum == 0x0306
459     OneMinusDstColor = 9,   // GLenum == 0x0307
460     SrcAlphaSaturate = 10,  // GLenum == 0x0308
461     MaxSrcDstType    = 10,
462 
463     MinConstantType       = 11,
464     ConstantColor         = 11,  // GLenum == 0x8001
465     OneMinusConstantColor = 12,  // GLenum == 0x8002
466     ConstantAlpha         = 13,  // GLenum == 0x8003
467     OneMinusConstantAlpha = 14,  // GLenum == 0x8004
468     MaxConstantType       = 14,
469 
470     // GL_EXT_blend_func_extended
471 
472     Src1Alpha = 15,  // GLenum == 0x8589
473 
474     Src1Color         = 16,  // GLenum == 0x88F9
475     OneMinusSrc1Color = 17,  // GLenum == 0x88FA
476     OneMinusSrc1Alpha = 18,  // GLenum == 0x88FB
477 
478     InvalidEnum = 19,
479     EnumCount   = 19
480 };
481 
482 template <>
483 constexpr BlendFactorType FromGLenum<BlendFactorType>(GLenum from)
484 {
485     if (from <= 1)
486         return static_cast<BlendFactorType>(from);
487     if (from >= GL_SRC_COLOR && from <= GL_SRC_ALPHA_SATURATE)
488         return static_cast<BlendFactorType>(from - GL_SRC_COLOR + 2);
489     if (from >= GL_CONSTANT_COLOR && from <= GL_ONE_MINUS_CONSTANT_ALPHA)
490         return static_cast<BlendFactorType>(from - GL_CONSTANT_COLOR + 11);
491     if (from == GL_SRC1_ALPHA_EXT)
492         return BlendFactorType::Src1Alpha;
493     if (from >= GL_SRC1_COLOR_EXT && from <= GL_ONE_MINUS_SRC1_ALPHA_EXT)
494         return static_cast<BlendFactorType>(from - GL_SRC1_COLOR_EXT + 16);
495     return BlendFactorType::InvalidEnum;
496 }
497 
ToGLenum(BlendFactorType from)498 constexpr GLenum ToGLenum(BlendFactorType from)
499 {
500     const GLenum value = static_cast<GLenum>(from);
501     if (value <= 1)
502         return value;
503     if (from >= BlendFactorType::MinSrcDstType && from <= BlendFactorType::MaxSrcDstType)
504         return value - 2 + GL_SRC_COLOR;
505     if (from >= BlendFactorType::MinConstantType && from <= BlendFactorType::MaxConstantType)
506         return value - 11 + GL_CONSTANT_COLOR;
507     if (from == BlendFactorType::Src1Alpha)
508         return GL_SRC1_ALPHA_EXT;
509     return value - 16 + GL_SRC1_COLOR_EXT;
510 }
511 
512 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, Zero, GL_ZERO);
513 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, One, GL_ONE);
514 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, SrcColor, GL_SRC_COLOR);
515 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusSrcColor, GL_ONE_MINUS_SRC_COLOR);
516 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, SrcAlpha, GL_SRC_ALPHA);
517 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusSrcAlpha, GL_ONE_MINUS_SRC_ALPHA);
518 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, DstAlpha, GL_DST_ALPHA);
519 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusDstAlpha, GL_ONE_MINUS_DST_ALPHA);
520 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, DstColor, GL_DST_COLOR);
521 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusDstColor, GL_ONE_MINUS_DST_COLOR);
522 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, SrcAlphaSaturate, GL_SRC_ALPHA_SATURATE);
523 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, ConstantColor, GL_CONSTANT_COLOR);
524 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusConstantColor, GL_ONE_MINUS_CONSTANT_COLOR);
525 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, ConstantAlpha, GL_CONSTANT_ALPHA);
526 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusConstantAlpha, GL_ONE_MINUS_CONSTANT_ALPHA);
527 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, Src1Alpha, GL_SRC1_ALPHA_EXT);
528 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, Src1Color, GL_SRC1_COLOR_EXT);
529 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusSrc1Color, GL_ONE_MINUS_SRC1_COLOR_EXT);
530 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusSrc1Alpha, GL_ONE_MINUS_SRC1_ALPHA_EXT);
531 
532 std::ostream &operator<<(std::ostream &os, BlendFactorType value);
533 
534 enum class VertexAttribType
535 {
536     Byte               = 0,   // GLenum == 0x1400
537     UnsignedByte       = 1,   // GLenum == 0x1401
538     Short              = 2,   // GLenum == 0x1402
539     UnsignedShort      = 3,   // GLenum == 0x1403
540     Int                = 4,   // GLenum == 0x1404
541     UnsignedInt        = 5,   // GLenum == 0x1405
542     Float              = 6,   // GLenum == 0x1406
543     Unused1            = 7,   // GLenum == 0x1407
544     Unused2            = 8,   // GLenum == 0x1408
545     Unused3            = 9,   // GLenum == 0x1409
546     Unused4            = 10,  // GLenum == 0x140A
547     HalfFloat          = 11,  // GLenum == 0x140B
548     Fixed              = 12,  // GLenum == 0x140C
549     MaxBasicType       = 12,
550     UnsignedInt2101010 = 13,  // GLenum == 0x8368
551     HalfFloatOES       = 14,  // GLenum == 0x8D61
552     Int2101010         = 15,  // GLenum == 0x8D9F
553     UnsignedInt1010102 = 16,  // GLenum == 0x8DF6
554     Int1010102         = 17,  // GLenum == 0x8DF7
555     InvalidEnum        = 18,
556     EnumCount          = 18,
557 };
558 
559 template <>
560 constexpr VertexAttribType FromGLenum<VertexAttribType>(GLenum from)
561 {
562     GLenum packed = from - GL_BYTE;
563     if (packed <= static_cast<GLenum>(VertexAttribType::MaxBasicType))
564         return static_cast<VertexAttribType>(packed);
565     if (from == GL_UNSIGNED_INT_2_10_10_10_REV)
566         return VertexAttribType::UnsignedInt2101010;
567     if (from == GL_HALF_FLOAT_OES)
568         return VertexAttribType::HalfFloatOES;
569     if (from == GL_INT_2_10_10_10_REV)
570         return VertexAttribType::Int2101010;
571     if (from == GL_UNSIGNED_INT_10_10_10_2_OES)
572         return VertexAttribType::UnsignedInt1010102;
573     if (from == GL_INT_10_10_10_2_OES)
574         return VertexAttribType::Int1010102;
575     return VertexAttribType::InvalidEnum;
576 }
577 
ToGLenum(VertexAttribType from)578 constexpr GLenum ToGLenum(VertexAttribType from)
579 {
580     // This could be optimized using a constexpr table.
581     if (from == VertexAttribType::Int2101010)
582         return GL_INT_2_10_10_10_REV;
583     if (from == VertexAttribType::HalfFloatOES)
584         return GL_HALF_FLOAT_OES;
585     if (from == VertexAttribType::UnsignedInt2101010)
586         return GL_UNSIGNED_INT_2_10_10_10_REV;
587     if (from == VertexAttribType::UnsignedInt1010102)
588         return GL_UNSIGNED_INT_10_10_10_2_OES;
589     if (from == VertexAttribType::Int1010102)
590         return GL_INT_10_10_10_2_OES;
591     return static_cast<GLenum>(from) + GL_BYTE;
592 }
593 
594 ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Byte, GL_BYTE);
595 ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, UnsignedByte, GL_UNSIGNED_BYTE);
596 ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Short, GL_SHORT);
597 ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, UnsignedShort, GL_UNSIGNED_SHORT);
598 ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Int, GL_INT);
599 ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, UnsignedInt, GL_UNSIGNED_INT);
600 ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Float, GL_FLOAT);
601 ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, HalfFloat, GL_HALF_FLOAT);
602 ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Fixed, GL_FIXED);
603 ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Int2101010, GL_INT_2_10_10_10_REV);
604 ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, HalfFloatOES, GL_HALF_FLOAT_OES);
605 ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, UnsignedInt2101010, GL_UNSIGNED_INT_2_10_10_10_REV);
606 ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Int1010102, GL_INT_10_10_10_2_OES);
607 ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, UnsignedInt1010102, GL_UNSIGNED_INT_10_10_10_2_OES);
608 
609 std::ostream &operator<<(std::ostream &os, VertexAttribType value);
610 
611 enum class TessEvaluationType
612 {
613     Triangles             = 0,
614     Quads                 = 1,
615     Isolines              = 2,
616     EqualSpacing          = 3,
617     FractionalEvenSpacing = 4,
618     FractionalOddSpacing  = 5,
619     Cw                    = 6,
620     Ccw                   = 7,
621     PointMode             = 8,
622     InvalidEnum           = 9,
623     EnumCount             = 9
624 };
625 
626 template <>
627 constexpr TessEvaluationType FromGLenum<TessEvaluationType>(GLenum from)
628 {
629     if (from == GL_TRIANGLES)
630         return TessEvaluationType::Triangles;
631     if (from == GL_QUADS)
632         return TessEvaluationType::Quads;
633     if (from == GL_ISOLINES)
634         return TessEvaluationType::Isolines;
635     if (from == GL_EQUAL)
636         return TessEvaluationType::EqualSpacing;
637     if (from == GL_FRACTIONAL_EVEN)
638         return TessEvaluationType::FractionalEvenSpacing;
639     if (from == GL_FRACTIONAL_ODD)
640         return TessEvaluationType::FractionalOddSpacing;
641     if (from == GL_CW)
642         return TessEvaluationType::Cw;
643     if (from == GL_CCW)
644         return TessEvaluationType::Ccw;
645     if (from == GL_TESS_GEN_POINT_MODE)
646         return TessEvaluationType::PointMode;
647     return TessEvaluationType::InvalidEnum;
648 }
649 
ToGLenum(TessEvaluationType from)650 constexpr GLenum ToGLenum(TessEvaluationType from)
651 {
652     switch (from)
653     {
654         case TessEvaluationType::Triangles:
655             return GL_TRIANGLES;
656         case TessEvaluationType::Quads:
657             return GL_QUADS;
658         case TessEvaluationType::Isolines:
659             return GL_ISOLINES;
660         case TessEvaluationType::EqualSpacing:
661             return GL_EQUAL;
662         case TessEvaluationType::FractionalEvenSpacing:
663             return GL_FRACTIONAL_EVEN;
664         case TessEvaluationType::FractionalOddSpacing:
665             return GL_FRACTIONAL_ODD;
666         case TessEvaluationType::Cw:
667             return GL_CW;
668         case TessEvaluationType::Ccw:
669             return GL_CCW;
670         case TessEvaluationType::PointMode:
671             return GL_TESS_GEN_POINT_MODE;
672         default:
673             return GL_INVALID_ENUM;
674     }
675 }
676 
677 ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, Triangles, GL_TRIANGLES);
678 ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, Quads, GL_QUADS);
679 ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, Isolines, GL_ISOLINES);
680 ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, EqualSpacing, GL_EQUAL);
681 ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, FractionalEvenSpacing, GL_FRACTIONAL_EVEN);
682 ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, FractionalOddSpacing, GL_FRACTIONAL_ODD);
683 ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, Cw, GL_CW);
684 ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, Ccw, GL_CCW);
685 ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, PointMode, GL_TESS_GEN_POINT_MODE);
686 
687 std::ostream &operator<<(std::ostream &os, TessEvaluationType value);
688 
689 // Typesafe object handles.
690 
691 template <typename T>
692 struct ResourceTypeToID;
693 
694 template <typename T>
695 struct IsResourceIDType;
696 
697 #define ANGLE_GL_ID_TYPES_OP(X) \
698     X(Buffer)                   \
699     X(Context)                  \
700     X(FenceNV)                  \
701     X(Framebuffer)              \
702     X(MemoryObject)             \
703     X(Path)                     \
704     X(ProgramPipeline)          \
705     X(Query)                    \
706     X(Renderbuffer)             \
707     X(Sampler)                  \
708     X(Semaphore)                \
709     X(Sync)                     \
710     X(Texture)                  \
711     X(TransformFeedback)        \
712     X(VertexArray)
713 
714 ANGLE_GL_ID_TYPES_OP(ANGLE_DEFINE_ID_TYPE)
715 
716 #undef ANGLE_GL_ID_TYPES_OP
717 
718 // Shaders and programs are a bit special as they share IDs.
719 struct ShaderProgramID
720 {
721     GLuint value;
722 };
723 
724 template <>
725 struct IsResourceIDType<ShaderProgramID>
726 {
727     constexpr static bool value = true;
728 };
729 
730 class Shader;
731 template <>
732 struct ResourceTypeToID<Shader>
733 {
734     using IDType = ShaderProgramID;
735 };
736 
737 class Program;
738 template <>
739 struct ResourceTypeToID<Program>
740 {
741     using IDType = ShaderProgramID;
742 };
743 
744 template <typename T>
745 struct ResourceTypeToID
746 {
747     using IDType = void;
748 };
749 
750 template <typename T>
751 struct IsResourceIDType
752 {
753     static constexpr bool value = false;
754 };
755 
756 template <typename T>
757 bool ValueEquals(T lhs, T rhs)
758 {
759     return lhs.value == rhs.value;
760 }
761 
762 // Util funcs for resourceIDs
763 template <typename T>
764 typename std::enable_if<IsResourceIDType<T>::value, bool>::type operator==(const T &lhs,
765                                                                            const T &rhs)
766 {
767     return lhs.value == rhs.value;
768 }
769 
770 template <typename T>
771 typename std::enable_if<IsResourceIDType<T>::value, bool>::type operator!=(const T &lhs,
772                                                                            const T &rhs)
773 {
774     return lhs.value != rhs.value;
775 }
776 
777 template <typename T>
778 typename std::enable_if<IsResourceIDType<T>::value, bool>::type operator<(const T &lhs,
779                                                                           const T &rhs)
780 {
781     return lhs.value < rhs.value;
782 }
783 
784 // Used to unbox typed values.
785 template <typename ResourceIDType>
786 GLuint GetIDValue(ResourceIDType id);
787 
788 template <typename ResourceIDType>
789 inline GLuint GetIDValue(ResourceIDType id)
790 {
791     return id.value;
792 }
793 
794 struct UniformLocation
795 {
796     int value;
797 };
798 
799 bool operator<(const UniformLocation &lhs, const UniformLocation &rhs);
800 
801 struct UniformBlockIndex
802 {
803     uint32_t value;
804 };
805 
806 bool IsEmulatedCompressedFormat(GLenum format);
807 }  // namespace gl
808 
809 namespace egl
810 {
811 MessageType ErrorCodeToMessageType(EGLint errorCode);
812 
813 struct Config;
814 class Device;
815 class Display;
816 class Image;
817 class Surface;
818 class Stream;
819 class Sync;
820 
821 #define ANGLE_EGL_ID_TYPES_OP(X) \
822     X(Image)                     \
823     X(Surface)                   \
824     X(Sync)
825 
826 template <typename T>
827 struct ResourceTypeToID;
828 
829 template <typename T>
830 struct IsResourceIDType;
831 
832 ANGLE_EGL_ID_TYPES_OP(ANGLE_DEFINE_ID_TYPE)
833 
834 #undef ANGLE_EGL_ID_TYPES_OP
835 
836 template <>
837 struct IsResourceIDType<gl::ContextID>
838 {
839     static constexpr bool value = true;
840 };
841 
842 template <typename T>
843 struct IsResourceIDType
844 {
845     static constexpr bool value = false;
846 };
847 
848 // Util funcs for resourceIDs
849 template <typename T>
850 typename std::enable_if<IsResourceIDType<T>::value && !std::is_same<T, gl::ContextID>::value,
851                         bool>::type
852 operator==(const T &lhs, const T &rhs)
853 {
854     return lhs.value == rhs.value;
855 }
856 
857 template <typename T>
858 typename std::enable_if<IsResourceIDType<T>::value && !std::is_same<T, gl::ContextID>::value,
859                         bool>::type
860 operator<(const T &lhs, const T &rhs)
861 {
862     return lhs.value < rhs.value;
863 }
864 }  // namespace egl
865 
866 #undef ANGLE_DEFINE_ID_TYPE
867 
868 namespace egl_gl
869 {
870 gl::TextureTarget EGLCubeMapTargetToCubeMapTarget(EGLenum eglTarget);
871 gl::TextureTarget EGLImageTargetToTextureTarget(EGLenum eglTarget);
872 gl::TextureType EGLTextureTargetToTextureType(EGLenum eglTarget);
873 }  // namespace egl_gl
874 
875 namespace gl
876 {
877 // First case: handling packed enums.
878 template <typename EnumT, typename FromT>
879 typename std::enable_if<std::is_enum<EnumT>::value, EnumT>::type PackParam(FromT from)
880 {
881     return FromGLenum<EnumT>(from);
882 }
883 
884 // Second case: handling non-pointer resource ids.
885 template <typename EnumT, typename FromT>
886 typename std::enable_if<!std::is_pointer<FromT>::value && !std::is_enum<EnumT>::value, EnumT>::type
887 PackParam(FromT from)
888 {
889     return {from};
890 }
891 
892 template <typename EnumT>
893 using IsEGLImage = std::is_same<EnumT, egl::ImageID>;
894 
895 template <typename EnumT>
896 using IsGLSync = std::is_same<EnumT, gl::SyncID>;
897 
898 template <typename EnumT>
899 using IsEGLSync = std::is_same<EnumT, egl::SyncID>;
900 
901 // Third case: handling EGLImage, GLSync and EGLSync pointer resource ids.
902 template <typename EnumT, typename FromT>
903 typename std::enable_if<IsEGLImage<EnumT>::value || IsGLSync<EnumT>::value ||
904                             IsEGLSync<EnumT>::value,
905                         EnumT>::type
906 PackParam(FromT from)
907 {
908     return {static_cast<GLuint>(reinterpret_cast<uintptr_t>(from))};
909 }
910 
911 // Fourth case: handling non-EGLImage non-GLsync resource ids.
912 template <typename EnumT, typename FromT>
913 typename std::enable_if<std::is_pointer<FromT>::value && !std::is_enum<EnumT>::value &&
914                             !IsEGLImage<EnumT>::value && !IsGLSync<EnumT>::value,
915                         EnumT>::type
916 PackParam(FromT from)
917 {
918     static_assert(sizeof(typename std::remove_pointer<EnumT>::type) ==
919                       sizeof(typename std::remove_pointer<FromT>::type),
920                   "Types have different sizes");
921     static_assert(
922         std::is_same<
923             decltype(std::remove_pointer<EnumT>::type::value),
924             typename std::remove_const<typename std::remove_pointer<FromT>::type>::type>::value,
925         "Data types are different");
926     return reinterpret_cast<EnumT>(from);
927 }
928 }  // namespace gl
929 
930 #endif  // COMMON_PACKEDGLENUMS_H_
931