• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
243 bool IsStaticBufferUsage(BufferUsage useage);
244 
245 enum class PrimitiveMode : uint8_t
246 {
247     Points                 = 0x0,
248     Lines                  = 0x1,
249     LineLoop               = 0x2,
250     LineStrip              = 0x3,
251     Triangles              = 0x4,
252     TriangleStrip          = 0x5,
253     TriangleFan            = 0x6,
254     Unused1                = 0x7,
255     Unused2                = 0x8,
256     Unused3                = 0x9,
257     LinesAdjacency         = 0xA,
258     LineStripAdjacency     = 0xB,
259     TrianglesAdjacency     = 0xC,
260     TriangleStripAdjacency = 0xD,
261     Patches                = 0xE,
262 
263     InvalidEnum = 0xF,
264     EnumCount   = 0xF,
265 };
266 
267 template <>
268 constexpr PrimitiveMode FromGLenum<PrimitiveMode>(GLenum from)
269 {
270     if (from >= static_cast<GLenum>(PrimitiveMode::EnumCount))
271     {
272         return PrimitiveMode::InvalidEnum;
273     }
274 
275     return static_cast<PrimitiveMode>(from);
276 }
277 
ToGLenum(PrimitiveMode from)278 constexpr GLenum ToGLenum(PrimitiveMode from)
279 {
280     return static_cast<GLenum>(from);
281 }
282 
283 static_assert(ToGLenum(PrimitiveMode::Points) == GL_POINTS, "PrimitiveMode violation");
284 static_assert(ToGLenum(PrimitiveMode::Lines) == GL_LINES, "PrimitiveMode violation");
285 static_assert(ToGLenum(PrimitiveMode::LineLoop) == GL_LINE_LOOP, "PrimitiveMode violation");
286 static_assert(ToGLenum(PrimitiveMode::LineStrip) == GL_LINE_STRIP, "PrimitiveMode violation");
287 static_assert(ToGLenum(PrimitiveMode::Triangles) == GL_TRIANGLES, "PrimitiveMode violation");
288 static_assert(ToGLenum(PrimitiveMode::TriangleStrip) == GL_TRIANGLE_STRIP,
289               "PrimitiveMode violation");
290 static_assert(ToGLenum(PrimitiveMode::TriangleFan) == GL_TRIANGLE_FAN, "PrimitiveMode violation");
291 static_assert(ToGLenum(PrimitiveMode::LinesAdjacency) == GL_LINES_ADJACENCY,
292               "PrimitiveMode violation");
293 static_assert(ToGLenum(PrimitiveMode::LineStripAdjacency) == GL_LINE_STRIP_ADJACENCY,
294               "PrimitiveMode violation");
295 static_assert(ToGLenum(PrimitiveMode::TrianglesAdjacency) == GL_TRIANGLES_ADJACENCY,
296               "PrimitiveMode violation");
297 static_assert(ToGLenum(PrimitiveMode::TriangleStripAdjacency) == GL_TRIANGLE_STRIP_ADJACENCY,
298               "PrimitiveMode violation");
299 
300 std::ostream &operator<<(std::ostream &os, PrimitiveMode value);
301 
302 enum class DrawElementsType : size_t
303 {
304     UnsignedByte  = 0,
305     UnsignedShort = 1,
306     UnsignedInt   = 2,
307     InvalidEnum   = 3,
308     EnumCount     = 3,
309 };
310 
311 template <>
312 constexpr DrawElementsType FromGLenum<DrawElementsType>(GLenum from)
313 {
314 
315     GLenum scaled = (from - GL_UNSIGNED_BYTE);
316     // This code sequence generates a ROR instruction on x86/arm. We want to check if the lowest bit
317     // of scaled is set and if (scaled >> 1) is greater than a non-pot value. If we rotate the
318     // lowest bit to the hightest bit both conditions can be checked with a single test.
319     static_assert(sizeof(GLenum) == 4, "Update (scaled << 31) to sizeof(GLenum) * 8 - 1");
320     GLenum packed = (scaled >> 1) | (scaled << 31);
321 
322     // operator ? with a simple assignment usually translates to a cmov instruction and thus avoids
323     // a branch.
324     packed = (packed >= static_cast<GLenum>(DrawElementsType::EnumCount))
325                  ? static_cast<GLenum>(DrawElementsType::InvalidEnum)
326                  : packed;
327 
328     return static_cast<DrawElementsType>(packed);
329 }
330 
ToGLenum(DrawElementsType from)331 constexpr GLenum ToGLenum(DrawElementsType from)
332 {
333     return ((static_cast<GLenum>(from) << 1) + GL_UNSIGNED_BYTE);
334 }
335 
336 #define ANGLE_VALIDATE_PACKED_ENUM(type, packed, glenum)                 \
337     static_assert(ToGLenum(type::packed) == glenum, #type " violation"); \
338     static_assert(FromGLenum<type>(glenum) == type::packed, #type " violation")
339 
340 ANGLE_VALIDATE_PACKED_ENUM(DrawElementsType, UnsignedByte, GL_UNSIGNED_BYTE);
341 ANGLE_VALIDATE_PACKED_ENUM(DrawElementsType, UnsignedShort, GL_UNSIGNED_SHORT);
342 ANGLE_VALIDATE_PACKED_ENUM(DrawElementsType, UnsignedInt, GL_UNSIGNED_INT);
343 
344 std::ostream &operator<<(std::ostream &os, DrawElementsType value);
345 
346 enum class BlendEquationType
347 {
348     Add             = 0,  // GLenum == 0x8006
349     Min             = 1,  // GLenum == 0x8007
350     Max             = 2,  // GLenum == 0x8008
351     Unused          = 3,
352     Subtract        = 4,  // GLenum == 0x800A
353     ReverseSubtract = 5,  // GLenum == 0x800B
354 
355     Multiply   = 6,   // GLenum == 0x9294
356     Screen     = 7,   // GLenum == 0x9295
357     Overlay    = 8,   // GLenum == 0x9296
358     Darken     = 9,   // GLenum == 0x9297
359     Lighten    = 10,  // GLenum == 0x9298
360     Colordodge = 11,  // GLenum == 0x9299
361     Colorburn  = 12,  // GLenum == 0x929A
362     Hardlight  = 13,  // GLenum == 0x929B
363     Softlight  = 14,  // GLenum == 0x929C
364     Unused2    = 15,
365     Difference = 16,  // GLenum == 0x929E
366     Unused3    = 17,
367     Exclusion  = 18,  // GLenum == 0x92A0
368 
369     HslHue        = 19,  // GLenum == 0x92AD
370     HslSaturation = 20,  // GLenum == 0x92AE
371     HslColor      = 21,  // GLenum == 0x92AF
372     HslLuminosity = 22,  // GLenum == 0x92B0
373 
374     InvalidEnum = 23,
375     EnumCount   = InvalidEnum
376 };
377 
378 using BlendEquationBitSet = angle::PackedEnumBitSet<gl::BlendEquationType>;
379 
380 template <>
381 constexpr BlendEquationType FromGLenum<BlendEquationType>(GLenum from)
382 {
383     if (from <= GL_FUNC_REVERSE_SUBTRACT)
384     {
385         const GLenum scaled = (from - GL_FUNC_ADD);
386         return (scaled == static_cast<GLenum>(BlendEquationType::Unused))
387                    ? BlendEquationType::InvalidEnum
388                    : static_cast<BlendEquationType>(scaled);
389     }
390     if (from <= GL_EXCLUSION_KHR)
391     {
392         const GLenum scaled =
393             (from - GL_MULTIPLY_KHR + static_cast<uint32_t>(BlendEquationType::Multiply));
394         return (scaled == static_cast<GLenum>(BlendEquationType::Unused2) ||
395                 scaled == static_cast<GLenum>(BlendEquationType::Unused3))
396                    ? BlendEquationType::InvalidEnum
397                    : static_cast<BlendEquationType>(scaled);
398     }
399     if (from <= GL_HSL_LUMINOSITY_KHR)
400     {
401         return static_cast<BlendEquationType>(from - GL_HSL_HUE_KHR +
402                                               static_cast<uint32_t>(BlendEquationType::HslHue));
403     }
404     return BlendEquationType::InvalidEnum;
405 }
406 
ToGLenum(BlendEquationType from)407 constexpr GLenum ToGLenum(BlendEquationType from)
408 {
409     if (from <= BlendEquationType::ReverseSubtract)
410     {
411         return static_cast<GLenum>(from) + GL_FUNC_ADD;
412     }
413     if (from <= BlendEquationType::Exclusion)
414     {
415         return static_cast<GLenum>(from) - static_cast<GLenum>(BlendEquationType::Multiply) +
416                GL_MULTIPLY_KHR;
417     }
418     return static_cast<GLenum>(from) - static_cast<GLenum>(BlendEquationType::HslHue) +
419            GL_HSL_HUE_KHR;
420 }
421 
422 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Add, GL_FUNC_ADD);
423 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Min, GL_MIN);
424 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Max, GL_MAX);
425 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Subtract, GL_FUNC_SUBTRACT);
426 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, ReverseSubtract, GL_FUNC_REVERSE_SUBTRACT);
427 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Multiply, GL_MULTIPLY_KHR);
428 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Screen, GL_SCREEN_KHR);
429 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Overlay, GL_OVERLAY_KHR);
430 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Darken, GL_DARKEN_KHR);
431 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Lighten, GL_LIGHTEN_KHR);
432 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Colordodge, GL_COLORDODGE_KHR);
433 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Colorburn, GL_COLORBURN_KHR);
434 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Hardlight, GL_HARDLIGHT_KHR);
435 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Softlight, GL_SOFTLIGHT_KHR);
436 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Difference, GL_DIFFERENCE_KHR);
437 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Exclusion, GL_EXCLUSION_KHR);
438 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, HslHue, GL_HSL_HUE_KHR);
439 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, HslSaturation, GL_HSL_SATURATION_KHR);
440 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, HslColor, GL_HSL_COLOR_KHR);
441 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, HslLuminosity, GL_HSL_LUMINOSITY_KHR);
442 
443 std::ostream &operator<<(std::ostream &os, BlendEquationType value);
444 
445 enum class BlendFactorType
446 {
447     Zero = 0,  // GLenum == 0
448     One  = 1,  // GLenum == 1
449 
450     MinSrcDstType    = 2,
451     SrcColor         = 2,   // GLenum == 0x0300
452     OneMinusSrcColor = 3,   // GLenum == 0x0301
453     SrcAlpha         = 4,   // GLenum == 0x0302
454     OneMinusSrcAlpha = 5,   // GLenum == 0x0303
455     DstAlpha         = 6,   // GLenum == 0x0304
456     OneMinusDstAlpha = 7,   // GLenum == 0x0305
457     DstColor         = 8,   // GLenum == 0x0306
458     OneMinusDstColor = 9,   // GLenum == 0x0307
459     SrcAlphaSaturate = 10,  // GLenum == 0x0308
460     MaxSrcDstType    = 10,
461 
462     MinConstantType       = 11,
463     ConstantColor         = 11,  // GLenum == 0x8001
464     OneMinusConstantColor = 12,  // GLenum == 0x8002
465     ConstantAlpha         = 13,  // GLenum == 0x8003
466     OneMinusConstantAlpha = 14,  // GLenum == 0x8004
467     MaxConstantType       = 14,
468 
469     // GL_EXT_blend_func_extended
470 
471     Src1Alpha = 15,  // GLenum == 0x8589
472 
473     Src1Color         = 16,  // GLenum == 0x88F9
474     OneMinusSrc1Color = 17,  // GLenum == 0x88FA
475     OneMinusSrc1Alpha = 18,  // GLenum == 0x88FB
476 
477     InvalidEnum = 19,
478     EnumCount   = 19
479 };
480 
481 template <>
482 constexpr BlendFactorType FromGLenum<BlendFactorType>(GLenum from)
483 {
484     if (from <= 1)
485         return static_cast<BlendFactorType>(from);
486     if (from >= GL_SRC_COLOR && from <= GL_SRC_ALPHA_SATURATE)
487         return static_cast<BlendFactorType>(from - GL_SRC_COLOR + 2);
488     if (from >= GL_CONSTANT_COLOR && from <= GL_ONE_MINUS_CONSTANT_ALPHA)
489         return static_cast<BlendFactorType>(from - GL_CONSTANT_COLOR + 11);
490     if (from == GL_SRC1_ALPHA_EXT)
491         return BlendFactorType::Src1Alpha;
492     if (from >= GL_SRC1_COLOR_EXT && from <= GL_ONE_MINUS_SRC1_ALPHA_EXT)
493         return static_cast<BlendFactorType>(from - GL_SRC1_COLOR_EXT + 16);
494     return BlendFactorType::InvalidEnum;
495 }
496 
ToGLenum(BlendFactorType from)497 constexpr GLenum ToGLenum(BlendFactorType from)
498 {
499     const GLenum value = static_cast<GLenum>(from);
500     if (value <= 1)
501         return value;
502     if (from >= BlendFactorType::MinSrcDstType && from <= BlendFactorType::MaxSrcDstType)
503         return value - 2 + GL_SRC_COLOR;
504     if (from >= BlendFactorType::MinConstantType && from <= BlendFactorType::MaxConstantType)
505         return value - 11 + GL_CONSTANT_COLOR;
506     if (from == BlendFactorType::Src1Alpha)
507         return GL_SRC1_ALPHA_EXT;
508     return value - 16 + GL_SRC1_COLOR_EXT;
509 }
510 
511 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, Zero, GL_ZERO);
512 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, One, GL_ONE);
513 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, SrcColor, GL_SRC_COLOR);
514 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusSrcColor, GL_ONE_MINUS_SRC_COLOR);
515 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, SrcAlpha, GL_SRC_ALPHA);
516 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusSrcAlpha, GL_ONE_MINUS_SRC_ALPHA);
517 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, DstAlpha, GL_DST_ALPHA);
518 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusDstAlpha, GL_ONE_MINUS_DST_ALPHA);
519 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, DstColor, GL_DST_COLOR);
520 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusDstColor, GL_ONE_MINUS_DST_COLOR);
521 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, SrcAlphaSaturate, GL_SRC_ALPHA_SATURATE);
522 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, ConstantColor, GL_CONSTANT_COLOR);
523 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusConstantColor, GL_ONE_MINUS_CONSTANT_COLOR);
524 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, ConstantAlpha, GL_CONSTANT_ALPHA);
525 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusConstantAlpha, GL_ONE_MINUS_CONSTANT_ALPHA);
526 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, Src1Alpha, GL_SRC1_ALPHA_EXT);
527 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, Src1Color, GL_SRC1_COLOR_EXT);
528 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusSrc1Color, GL_ONE_MINUS_SRC1_COLOR_EXT);
529 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusSrc1Alpha, GL_ONE_MINUS_SRC1_ALPHA_EXT);
530 
531 std::ostream &operator<<(std::ostream &os, BlendFactorType value);
532 
533 enum class VertexAttribType
534 {
535     Byte               = 0,   // GLenum == 0x1400
536     UnsignedByte       = 1,   // GLenum == 0x1401
537     Short              = 2,   // GLenum == 0x1402
538     UnsignedShort      = 3,   // GLenum == 0x1403
539     Int                = 4,   // GLenum == 0x1404
540     UnsignedInt        = 5,   // GLenum == 0x1405
541     Float              = 6,   // GLenum == 0x1406
542     Unused1            = 7,   // GLenum == 0x1407
543     Unused2            = 8,   // GLenum == 0x1408
544     Unused3            = 9,   // GLenum == 0x1409
545     Unused4            = 10,  // GLenum == 0x140A
546     HalfFloat          = 11,  // GLenum == 0x140B
547     Fixed              = 12,  // GLenum == 0x140C
548     MaxBasicType       = 12,
549     UnsignedInt2101010 = 13,  // GLenum == 0x8368
550     HalfFloatOES       = 14,  // GLenum == 0x8D61
551     Int2101010         = 15,  // GLenum == 0x8D9F
552     UnsignedInt1010102 = 16,  // GLenum == 0x8DF6
553     Int1010102         = 17,  // GLenum == 0x8DF7
554     InvalidEnum        = 18,
555     EnumCount          = 18,
556 };
557 
558 template <>
559 constexpr VertexAttribType FromGLenum<VertexAttribType>(GLenum from)
560 {
561     GLenum packed = from - GL_BYTE;
562     if (packed <= static_cast<GLenum>(VertexAttribType::MaxBasicType))
563         return static_cast<VertexAttribType>(packed);
564     if (from == GL_UNSIGNED_INT_2_10_10_10_REV)
565         return VertexAttribType::UnsignedInt2101010;
566     if (from == GL_HALF_FLOAT_OES)
567         return VertexAttribType::HalfFloatOES;
568     if (from == GL_INT_2_10_10_10_REV)
569         return VertexAttribType::Int2101010;
570     if (from == GL_UNSIGNED_INT_10_10_10_2_OES)
571         return VertexAttribType::UnsignedInt1010102;
572     if (from == GL_INT_10_10_10_2_OES)
573         return VertexAttribType::Int1010102;
574     return VertexAttribType::InvalidEnum;
575 }
576 
ToGLenum(VertexAttribType from)577 constexpr GLenum ToGLenum(VertexAttribType from)
578 {
579     // This could be optimized using a constexpr table.
580     if (from == VertexAttribType::Int2101010)
581         return GL_INT_2_10_10_10_REV;
582     if (from == VertexAttribType::HalfFloatOES)
583         return GL_HALF_FLOAT_OES;
584     if (from == VertexAttribType::UnsignedInt2101010)
585         return GL_UNSIGNED_INT_2_10_10_10_REV;
586     if (from == VertexAttribType::UnsignedInt1010102)
587         return GL_UNSIGNED_INT_10_10_10_2_OES;
588     if (from == VertexAttribType::Int1010102)
589         return GL_INT_10_10_10_2_OES;
590     return static_cast<GLenum>(from) + GL_BYTE;
591 }
592 
593 ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Byte, GL_BYTE);
594 ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, UnsignedByte, GL_UNSIGNED_BYTE);
595 ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Short, GL_SHORT);
596 ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, UnsignedShort, GL_UNSIGNED_SHORT);
597 ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Int, GL_INT);
598 ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, UnsignedInt, GL_UNSIGNED_INT);
599 ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Float, GL_FLOAT);
600 ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, HalfFloat, GL_HALF_FLOAT);
601 ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Fixed, GL_FIXED);
602 ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Int2101010, GL_INT_2_10_10_10_REV);
603 ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, HalfFloatOES, GL_HALF_FLOAT_OES);
604 ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, UnsignedInt2101010, GL_UNSIGNED_INT_2_10_10_10_REV);
605 ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Int1010102, GL_INT_10_10_10_2_OES);
606 ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, UnsignedInt1010102, GL_UNSIGNED_INT_10_10_10_2_OES);
607 
608 std::ostream &operator<<(std::ostream &os, VertexAttribType value);
609 
610 enum class TessEvaluationType
611 {
612     Triangles             = 0,
613     Quads                 = 1,
614     Isolines              = 2,
615     EqualSpacing          = 3,
616     FractionalEvenSpacing = 4,
617     FractionalOddSpacing  = 5,
618     Cw                    = 6,
619     Ccw                   = 7,
620     PointMode             = 8,
621     InvalidEnum           = 9,
622     EnumCount             = 9
623 };
624 
625 template <>
626 constexpr TessEvaluationType FromGLenum<TessEvaluationType>(GLenum from)
627 {
628     if (from == GL_TRIANGLES)
629         return TessEvaluationType::Triangles;
630     if (from == GL_QUADS)
631         return TessEvaluationType::Quads;
632     if (from == GL_ISOLINES)
633         return TessEvaluationType::Isolines;
634     if (from == GL_EQUAL)
635         return TessEvaluationType::EqualSpacing;
636     if (from == GL_FRACTIONAL_EVEN)
637         return TessEvaluationType::FractionalEvenSpacing;
638     if (from == GL_FRACTIONAL_ODD)
639         return TessEvaluationType::FractionalOddSpacing;
640     if (from == GL_CW)
641         return TessEvaluationType::Cw;
642     if (from == GL_CCW)
643         return TessEvaluationType::Ccw;
644     if (from == GL_TESS_GEN_POINT_MODE)
645         return TessEvaluationType::PointMode;
646     return TessEvaluationType::InvalidEnum;
647 }
648 
ToGLenum(TessEvaluationType from)649 constexpr GLenum ToGLenum(TessEvaluationType from)
650 {
651     switch (from)
652     {
653         case TessEvaluationType::Triangles:
654             return GL_TRIANGLES;
655         case TessEvaluationType::Quads:
656             return GL_QUADS;
657         case TessEvaluationType::Isolines:
658             return GL_ISOLINES;
659         case TessEvaluationType::EqualSpacing:
660             return GL_EQUAL;
661         case TessEvaluationType::FractionalEvenSpacing:
662             return GL_FRACTIONAL_EVEN;
663         case TessEvaluationType::FractionalOddSpacing:
664             return GL_FRACTIONAL_ODD;
665         case TessEvaluationType::Cw:
666             return GL_CW;
667         case TessEvaluationType::Ccw:
668             return GL_CCW;
669         case TessEvaluationType::PointMode:
670             return GL_TESS_GEN_POINT_MODE;
671         default:
672             return GL_INVALID_ENUM;
673     }
674 }
675 
676 ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, Triangles, GL_TRIANGLES);
677 ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, Quads, GL_QUADS);
678 ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, Isolines, GL_ISOLINES);
679 ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, EqualSpacing, GL_EQUAL);
680 ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, FractionalEvenSpacing, GL_FRACTIONAL_EVEN);
681 ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, FractionalOddSpacing, GL_FRACTIONAL_ODD);
682 ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, Cw, GL_CW);
683 ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, Ccw, GL_CCW);
684 ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, PointMode, GL_TESS_GEN_POINT_MODE);
685 
686 std::ostream &operator<<(std::ostream &os, TessEvaluationType value);
687 
688 // Typesafe object handles.
689 
690 template <typename T>
691 struct ResourceTypeToID;
692 
693 template <typename T>
694 struct IsResourceIDType;
695 
696 #define ANGLE_GL_ID_TYPES_OP(X) \
697     X(Buffer)                   \
698     X(Context)                  \
699     X(FenceNV)                  \
700     X(Framebuffer)              \
701     X(MemoryObject)             \
702     X(Path)                     \
703     X(ProgramPipeline)          \
704     X(Query)                    \
705     X(Renderbuffer)             \
706     X(Sampler)                  \
707     X(Semaphore)                \
708     X(Sync)                     \
709     X(Texture)                  \
710     X(TransformFeedback)        \
711     X(VertexArray)
712 
713 ANGLE_GL_ID_TYPES_OP(ANGLE_DEFINE_ID_TYPE)
714 
715 #undef ANGLE_GL_ID_TYPES_OP
716 
717 // Shaders and programs are a bit special as they share IDs.
718 struct ShaderProgramID
719 {
720     GLuint value;
721 };
722 
723 template <>
724 struct IsResourceIDType<ShaderProgramID>
725 {
726     constexpr static bool value = true;
727 };
728 
729 class Shader;
730 template <>
731 struct ResourceTypeToID<Shader>
732 {
733     using IDType = ShaderProgramID;
734 };
735 
736 class Program;
737 template <>
738 struct ResourceTypeToID<Program>
739 {
740     using IDType = ShaderProgramID;
741 };
742 
743 template <typename T>
744 struct ResourceTypeToID
745 {
746     using IDType = void;
747 };
748 
749 template <typename T>
750 struct IsResourceIDType
751 {
752     static constexpr bool value = false;
753 };
754 
755 template <typename T>
756 bool ValueEquals(T lhs, T rhs)
757 {
758     return lhs.value == rhs.value;
759 }
760 
761 // Util funcs for resourceIDs
762 template <typename T>
763 typename std::enable_if<IsResourceIDType<T>::value, bool>::type operator==(const T &lhs,
764                                                                            const T &rhs)
765 {
766     return lhs.value == rhs.value;
767 }
768 
769 template <typename T>
770 typename std::enable_if<IsResourceIDType<T>::value, bool>::type operator!=(const T &lhs,
771                                                                            const T &rhs)
772 {
773     return lhs.value != rhs.value;
774 }
775 
776 template <typename T>
777 typename std::enable_if<IsResourceIDType<T>::value, bool>::type operator<(const T &lhs,
778                                                                           const T &rhs)
779 {
780     return lhs.value < rhs.value;
781 }
782 
783 // Used to unbox typed values.
784 template <typename ResourceIDType>
785 GLuint GetIDValue(ResourceIDType id);
786 
787 template <>
788 inline GLuint GetIDValue(GLuint id)
789 {
790     return id;
791 }
792 
793 template <typename ResourceIDType>
794 inline GLuint GetIDValue(ResourceIDType id)
795 {
796     return id.value;
797 }
798 
799 struct UniformLocation
800 {
801     int value;
802 };
803 
804 bool operator<(const UniformLocation &lhs, const UniformLocation &rhs);
805 
806 struct UniformBlockIndex
807 {
808     uint32_t value;
809 };
810 
811 bool IsEmulatedCompressedFormat(GLenum format);
812 }  // namespace gl
813 
814 namespace egl
815 {
816 MessageType ErrorCodeToMessageType(EGLint errorCode);
817 
818 struct Config;
819 class Device;
820 class Display;
821 class Image;
822 class Surface;
823 class Stream;
824 class Sync;
825 
826 #define ANGLE_EGL_ID_TYPES_OP(X) \
827     X(Image)                     \
828     X(Surface)                   \
829     X(Sync)
830 
831 template <typename T>
832 struct ResourceTypeToID;
833 
834 template <typename T>
835 struct IsResourceIDType;
836 
837 ANGLE_EGL_ID_TYPES_OP(ANGLE_DEFINE_ID_TYPE)
838 
839 #undef ANGLE_EGL_ID_TYPES_OP
840 
841 template <>
842 struct IsResourceIDType<gl::ContextID>
843 {
844     static constexpr bool value = true;
845 };
846 
847 template <typename T>
848 struct IsResourceIDType
849 {
850     static constexpr bool value = false;
851 };
852 
853 // Util funcs for resourceIDs
854 template <typename T>
855 typename std::enable_if<IsResourceIDType<T>::value && !std::is_same<T, gl::ContextID>::value,
856                         bool>::type
857 operator==(const T &lhs, const T &rhs)
858 {
859     return lhs.value == rhs.value;
860 }
861 
862 template <typename T>
863 typename std::enable_if<IsResourceIDType<T>::value && !std::is_same<T, gl::ContextID>::value,
864                         bool>::type
865 operator<(const T &lhs, const T &rhs)
866 {
867     return lhs.value < rhs.value;
868 }
869 }  // namespace egl
870 
871 #undef ANGLE_DEFINE_ID_TYPE
872 
873 namespace egl_gl
874 {
875 gl::TextureTarget EGLCubeMapTargetToCubeMapTarget(EGLenum eglTarget);
876 gl::TextureTarget EGLImageTargetToTextureTarget(EGLenum eglTarget);
877 gl::TextureType EGLTextureTargetToTextureType(EGLenum eglTarget);
878 }  // namespace egl_gl
879 
880 namespace gl
881 {
882 // First case: handling packed enums.
883 template <typename EnumT, typename FromT>
884 typename std::enable_if<std::is_enum<EnumT>::value, EnumT>::type PackParam(FromT from)
885 {
886     return FromGLenum<EnumT>(from);
887 }
888 
889 // Second case: handling non-pointer resource ids.
890 template <typename EnumT, typename FromT>
891 typename std::enable_if<!std::is_pointer<FromT>::value && !std::is_enum<EnumT>::value, EnumT>::type
892 PackParam(FromT from)
893 {
894     return {from};
895 }
896 
897 template <typename EnumT>
898 using IsEGLImage = std::is_same<EnumT, egl::ImageID>;
899 
900 template <typename EnumT>
901 using IsGLSync = std::is_same<EnumT, gl::SyncID>;
902 
903 template <typename EnumT>
904 using IsEGLSync = std::is_same<EnumT, egl::SyncID>;
905 
906 // Third case: handling EGLImage, GLSync and EGLSync pointer resource ids.
907 template <typename EnumT, typename FromT>
908 typename std::enable_if<IsEGLImage<EnumT>::value || IsGLSync<EnumT>::value ||
909                             IsEGLSync<EnumT>::value,
910                         EnumT>::type
911 PackParam(FromT from)
912 {
913     return {static_cast<GLuint>(reinterpret_cast<uintptr_t>(from))};
914 }
915 
916 // Fourth case: handling non-EGLImage non-GLsync resource ids.
917 template <typename EnumT, typename FromT>
918 typename std::enable_if<std::is_pointer<FromT>::value && !std::is_enum<EnumT>::value &&
919                             !IsEGLImage<EnumT>::value && !IsGLSync<EnumT>::value,
920                         EnumT>::type
921 PackParam(FromT from)
922 {
923     static_assert(sizeof(typename std::remove_pointer<EnumT>::type) ==
924                       sizeof(typename std::remove_pointer<FromT>::type),
925                   "Types have different sizes");
926     static_assert(
927         std::is_same<
928             decltype(std::remove_pointer<EnumT>::type::value),
929             typename std::remove_const<typename std::remove_pointer<FromT>::type>::type>::value,
930         "Data types are different");
931     return reinterpret_cast<EnumT>(from);
932 }
933 }  // namespace gl
934 
935 #endif  // COMMON_PACKEDGLENUMS_H_
936