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