summaryrefslogtreecommitdiffstats
path: root/gfx/angle/checkout/src/common/PackedEnums.h
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/angle/checkout/src/common/PackedEnums.h')
-rw-r--r--gfx/angle/checkout/src/common/PackedEnums.h798
1 files changed, 798 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/common/PackedEnums.h b/gfx/angle/checkout/src/common/PackedEnums.h
new file mode 100644
index 0000000000..5295b9b971
--- /dev/null
+++ b/gfx/angle/checkout/src/common/PackedEnums.h
@@ -0,0 +1,798 @@
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// PackedGLEnums_autogen.h:
+// Declares ANGLE-specific enums classes for GLEnum and functions operating
+// on them.
+
+#ifndef COMMON_PACKEDGLENUMS_H_
+#define COMMON_PACKEDGLENUMS_H_
+
+#include "common/PackedEGLEnums_autogen.h"
+#include "common/PackedGLEnums_autogen.h"
+
+#include <array>
+#include <bitset>
+#include <cstddef>
+
+#include <EGL/egl.h>
+
+#include "common/bitset_utils.h"
+
+namespace angle
+{
+
+// Return the number of elements of a packed enum, including the InvalidEnum element.
+template <typename E>
+constexpr size_t EnumSize()
+{
+ using UnderlyingType = typename std::underlying_type<E>::type;
+ return static_cast<UnderlyingType>(E::EnumCount);
+}
+
+// Implementation of AllEnums which allows iterating over all the possible values for a packed enums
+// like so:
+// for (auto value : AllEnums<MyPackedEnum>()) {
+// // Do something with the enum.
+// }
+
+template <typename E>
+class EnumIterator final
+{
+ private:
+ using UnderlyingType = typename std::underlying_type<E>::type;
+
+ public:
+ EnumIterator(E value) : mValue(static_cast<UnderlyingType>(value)) {}
+ EnumIterator &operator++()
+ {
+ mValue++;
+ return *this;
+ }
+ bool operator==(const EnumIterator &other) const { return mValue == other.mValue; }
+ bool operator!=(const EnumIterator &other) const { return mValue != other.mValue; }
+ E operator*() const { return static_cast<E>(mValue); }
+
+ private:
+ UnderlyingType mValue;
+};
+
+template <typename E, size_t MaxSize = EnumSize<E>()>
+struct AllEnums
+{
+ EnumIterator<E> begin() const { return {static_cast<E>(0)}; }
+ EnumIterator<E> end() const { return {static_cast<E>(MaxSize)}; }
+};
+
+// PackedEnumMap<E, T> is like an std::array<T, E::EnumCount> but is indexed with enum values. It
+// implements all of the std::array interface except with enum values instead of indices.
+template <typename E, typename T, size_t MaxSize = EnumSize<E>()>
+class PackedEnumMap
+{
+ using UnderlyingType = typename std::underlying_type<E>::type;
+ using Storage = std::array<T, MaxSize>;
+
+ public:
+ using InitPair = std::pair<E, T>;
+
+ constexpr PackedEnumMap() = default;
+
+ constexpr PackedEnumMap(std::initializer_list<InitPair> init) : mPrivateData{}
+ {
+ // We use a for loop instead of range-for to work around a limitation in MSVC.
+ for (const InitPair *it = init.begin(); it != init.end(); ++it)
+ {
+#if (__cplusplus < 201703L)
+ // This horrible const_cast pattern is necessary to work around a constexpr limitation.
+ // See https://stackoverflow.com/q/34199774/ . Note that it should be fixed with C++17.
+ const_cast<T &>(const_cast<const Storage &>(
+ mPrivateData)[static_cast<UnderlyingType>(it->first)]) = it->second;
+#else
+ mPrivateData[static_cast<UnderlyingType>(it->first)] = it->second;
+#endif
+ }
+ }
+
+ // types:
+ using value_type = T;
+ using pointer = T *;
+ using const_pointer = const T *;
+ using reference = T &;
+ using const_reference = const T &;
+
+ using size_type = size_t;
+ using difference_type = ptrdiff_t;
+
+ using iterator = typename Storage::iterator;
+ using const_iterator = typename Storage::const_iterator;
+ using reverse_iterator = std::reverse_iterator<iterator>;
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+
+ // No explicit construct/copy/destroy for aggregate type
+ void fill(const T &u) { mPrivateData.fill(u); }
+ void swap(PackedEnumMap<E, T, MaxSize> &a) noexcept { mPrivateData.swap(a.mPrivateData); }
+
+ // iterators:
+ iterator begin() noexcept { return mPrivateData.begin(); }
+ const_iterator begin() const noexcept { return mPrivateData.begin(); }
+ iterator end() noexcept { return mPrivateData.end(); }
+ const_iterator end() const noexcept { return mPrivateData.end(); }
+
+ reverse_iterator rbegin() noexcept { return mPrivateData.rbegin(); }
+ const_reverse_iterator rbegin() const noexcept { return mPrivateData.rbegin(); }
+ reverse_iterator rend() noexcept { return mPrivateData.rend(); }
+ const_reverse_iterator rend() const noexcept { return mPrivateData.rend(); }
+
+ // capacity:
+ constexpr size_type size() const noexcept { return mPrivateData.size(); }
+ constexpr size_type max_size() const noexcept { return mPrivateData.max_size(); }
+ constexpr bool empty() const noexcept { return mPrivateData.empty(); }
+
+ // element access:
+ reference operator[](E n)
+ {
+ ASSERT(static_cast<size_t>(n) < mPrivateData.size());
+ return mPrivateData[static_cast<UnderlyingType>(n)];
+ }
+
+ constexpr const_reference operator[](E n) const
+ {
+ ASSERT(static_cast<size_t>(n) < mPrivateData.size());
+ return mPrivateData[static_cast<UnderlyingType>(n)];
+ }
+
+ const_reference at(E n) const { return mPrivateData.at(static_cast<UnderlyingType>(n)); }
+ reference at(E n) { return mPrivateData.at(static_cast<UnderlyingType>(n)); }
+
+ reference front() { return mPrivateData.front(); }
+ const_reference front() const { return mPrivateData.front(); }
+ reference back() { return mPrivateData.back(); }
+ const_reference back() const { return mPrivateData.back(); }
+
+ T *data() noexcept { return mPrivateData.data(); }
+ const T *data() const noexcept { return mPrivateData.data(); }
+
+ bool operator==(const PackedEnumMap &rhs) const { return mPrivateData == rhs.mPrivateData; }
+ bool operator!=(const PackedEnumMap &rhs) const { return mPrivateData != rhs.mPrivateData; }
+
+ template <typename SubT = T>
+ typename std::enable_if<std::is_integral<SubT>::value>::type operator+=(
+ const PackedEnumMap<E, SubT, MaxSize> &rhs)
+ {
+ for (E e : AllEnums<E, MaxSize>())
+ {
+ at(e) += rhs[e];
+ }
+ }
+
+ private:
+ Storage mPrivateData;
+};
+
+// PackedEnumBitSetE> is like an std::bitset<E::EnumCount> but is indexed with enum values. It
+// implements the std::bitset interface except with enum values instead of indices.
+template <typename E, typename DataT = uint32_t>
+using PackedEnumBitSet = BitSetT<EnumSize<E>(), DataT, E>;
+
+} // namespace angle
+
+namespace gl
+{
+
+TextureType TextureTargetToType(TextureTarget target);
+TextureTarget NonCubeTextureTypeToTarget(TextureType type);
+
+TextureTarget CubeFaceIndexToTextureTarget(size_t face);
+size_t CubeMapTextureTargetToFaceIndex(TextureTarget target);
+bool IsCubeMapFaceTarget(TextureTarget target);
+
+constexpr TextureTarget kCubeMapTextureTargetMin = TextureTarget::CubeMapPositiveX;
+constexpr TextureTarget kCubeMapTextureTargetMax = TextureTarget::CubeMapNegativeZ;
+constexpr TextureTarget kAfterCubeMapTextureTargetMax =
+ static_cast<TextureTarget>(static_cast<uint8_t>(kCubeMapTextureTargetMax) + 1);
+struct AllCubeFaceTextureTargets
+{
+ angle::EnumIterator<TextureTarget> begin() const { return kCubeMapTextureTargetMin; }
+ angle::EnumIterator<TextureTarget> end() const { return kAfterCubeMapTextureTargetMax; }
+};
+
+constexpr std::array<ShaderType, 2> kAllGLES2ShaderTypes = {ShaderType::Vertex,
+ ShaderType::Fragment};
+
+constexpr ShaderType kShaderTypeMin = ShaderType::Vertex;
+constexpr ShaderType kShaderTypeMax = ShaderType::Compute;
+constexpr ShaderType kAfterShaderTypeMax =
+ static_cast<ShaderType>(static_cast<uint8_t>(kShaderTypeMax) + 1);
+struct AllShaderTypes
+{
+ angle::EnumIterator<ShaderType> begin() const { return kShaderTypeMin; }
+ angle::EnumIterator<ShaderType> end() const { return kAfterShaderTypeMax; }
+};
+
+constexpr size_t kGraphicsShaderCount = static_cast<size_t>(ShaderType::EnumCount) - 1u;
+// Arrange the shader types in the order of rendering pipeline
+constexpr std::array<ShaderType, kGraphicsShaderCount> kAllGraphicsShaderTypes = {
+ ShaderType::Vertex, ShaderType::TessControl, ShaderType::TessEvaluation, ShaderType::Geometry,
+ ShaderType::Fragment};
+
+using ShaderBitSet = angle::PackedEnumBitSet<ShaderType, uint8_t>;
+static_assert(sizeof(ShaderBitSet) == sizeof(uint8_t), "Unexpected size");
+
+template <typename T>
+using ShaderMap = angle::PackedEnumMap<ShaderType, T>;
+
+const char *ShaderTypeToString(ShaderType shaderType);
+
+TextureType SamplerTypeToTextureType(GLenum samplerType);
+TextureType ImageTypeToTextureType(GLenum imageType);
+
+bool IsMultisampled(gl::TextureType type);
+bool IsArrayTextureType(gl::TextureType type);
+
+bool IsStaticBufferUsage(BufferUsage useage);
+
+enum class PrimitiveMode : uint8_t
+{
+ Points = 0x0,
+ Lines = 0x1,
+ LineLoop = 0x2,
+ LineStrip = 0x3,
+ Triangles = 0x4,
+ TriangleStrip = 0x5,
+ TriangleFan = 0x6,
+ Unused1 = 0x7,
+ Unused2 = 0x8,
+ Unused3 = 0x9,
+ LinesAdjacency = 0xA,
+ LineStripAdjacency = 0xB,
+ TrianglesAdjacency = 0xC,
+ TriangleStripAdjacency = 0xD,
+ Patches = 0xE,
+
+ InvalidEnum = 0xF,
+ EnumCount = 0xF,
+};
+
+template <>
+constexpr PrimitiveMode FromGLenum<PrimitiveMode>(GLenum from)
+{
+ if (from >= static_cast<GLenum>(PrimitiveMode::EnumCount))
+ {
+ return PrimitiveMode::InvalidEnum;
+ }
+
+ return static_cast<PrimitiveMode>(from);
+}
+
+constexpr GLenum ToGLenum(PrimitiveMode from)
+{
+ return static_cast<GLenum>(from);
+}
+
+static_assert(ToGLenum(PrimitiveMode::Points) == GL_POINTS, "PrimitiveMode violation");
+static_assert(ToGLenum(PrimitiveMode::Lines) == GL_LINES, "PrimitiveMode violation");
+static_assert(ToGLenum(PrimitiveMode::LineLoop) == GL_LINE_LOOP, "PrimitiveMode violation");
+static_assert(ToGLenum(PrimitiveMode::LineStrip) == GL_LINE_STRIP, "PrimitiveMode violation");
+static_assert(ToGLenum(PrimitiveMode::Triangles) == GL_TRIANGLES, "PrimitiveMode violation");
+static_assert(ToGLenum(PrimitiveMode::TriangleStrip) == GL_TRIANGLE_STRIP,
+ "PrimitiveMode violation");
+static_assert(ToGLenum(PrimitiveMode::TriangleFan) == GL_TRIANGLE_FAN, "PrimitiveMode violation");
+static_assert(ToGLenum(PrimitiveMode::LinesAdjacency) == GL_LINES_ADJACENCY,
+ "PrimitiveMode violation");
+static_assert(ToGLenum(PrimitiveMode::LineStripAdjacency) == GL_LINE_STRIP_ADJACENCY,
+ "PrimitiveMode violation");
+static_assert(ToGLenum(PrimitiveMode::TrianglesAdjacency) == GL_TRIANGLES_ADJACENCY,
+ "PrimitiveMode violation");
+static_assert(ToGLenum(PrimitiveMode::TriangleStripAdjacency) == GL_TRIANGLE_STRIP_ADJACENCY,
+ "PrimitiveMode violation");
+
+std::ostream &operator<<(std::ostream &os, PrimitiveMode value);
+
+enum class DrawElementsType : size_t
+{
+ UnsignedByte = 0,
+ UnsignedShort = 1,
+ UnsignedInt = 2,
+ InvalidEnum = 3,
+ EnumCount = 3,
+};
+
+template <>
+constexpr DrawElementsType FromGLenum<DrawElementsType>(GLenum from)
+{
+
+ GLenum scaled = (from - GL_UNSIGNED_BYTE);
+ // This code sequence generates a ROR instruction on x86/arm. We want to check if the lowest bit
+ // of scaled is set and if (scaled >> 1) is greater than a non-pot value. If we rotate the
+ // lowest bit to the hightest bit both conditions can be checked with a single test.
+ static_assert(sizeof(GLenum) == 4, "Update (scaled << 31) to sizeof(GLenum) * 8 - 1");
+ GLenum packed = (scaled >> 1) | (scaled << 31);
+
+ // operator ? with a simple assignment usually translates to a cmov instruction and thus avoids
+ // a branch.
+ packed = (packed >= static_cast<GLenum>(DrawElementsType::EnumCount))
+ ? static_cast<GLenum>(DrawElementsType::InvalidEnum)
+ : packed;
+
+ return static_cast<DrawElementsType>(packed);
+}
+
+constexpr GLenum ToGLenum(DrawElementsType from)
+{
+ return ((static_cast<GLenum>(from) << 1) + GL_UNSIGNED_BYTE);
+}
+
+#define ANGLE_VALIDATE_PACKED_ENUM(type, packed, glenum) \
+ static_assert(ToGLenum(type::packed) == glenum, #type " violation"); \
+ static_assert(FromGLenum<type>(glenum) == type::packed, #type " violation")
+
+ANGLE_VALIDATE_PACKED_ENUM(DrawElementsType, UnsignedByte, GL_UNSIGNED_BYTE);
+ANGLE_VALIDATE_PACKED_ENUM(DrawElementsType, UnsignedShort, GL_UNSIGNED_SHORT);
+ANGLE_VALIDATE_PACKED_ENUM(DrawElementsType, UnsignedInt, GL_UNSIGNED_INT);
+
+std::ostream &operator<<(std::ostream &os, DrawElementsType value);
+
+enum class BlendEquationType
+{
+ Add = 0, // GLenum == 0x8006
+ Min = 1, // GLenum == 0x8007
+ Max = 2, // GLenum == 0x8008
+ Unused = 3,
+ Subtract = 4, // GLenum == 0x800A
+ ReverseSubtract = 5, // GLenum == 0x800B
+ InvalidEnum = 6,
+ EnumCount = 6
+};
+
+template <>
+constexpr BlendEquationType FromGLenum<BlendEquationType>(GLenum from)
+{
+ const GLenum scaled = (from - GL_FUNC_ADD);
+ return (scaled == static_cast<GLenum>(BlendEquationType::Unused) ||
+ scaled >= static_cast<GLenum>(BlendEquationType::EnumCount))
+ ? BlendEquationType::InvalidEnum
+ : static_cast<BlendEquationType>(scaled);
+}
+
+constexpr GLenum ToGLenum(BlendEquationType from)
+{
+ return static_cast<GLenum>(from) + GL_FUNC_ADD;
+}
+
+ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Add, GL_FUNC_ADD);
+ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Min, GL_MIN);
+ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Max, GL_MAX);
+ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Subtract, GL_FUNC_SUBTRACT);
+ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, ReverseSubtract, GL_FUNC_REVERSE_SUBTRACT);
+
+std::ostream &operator<<(std::ostream &os, BlendEquationType value);
+
+enum class BlendFactorType
+{
+ Zero = 0, // GLenum == 0
+ One = 1, // GLenum == 1
+
+ MinSrcDstType = 2,
+ SrcColor = 2, // GLenum == 0x0300
+ OneMinusSrcColor = 3, // GLenum == 0x0301
+ SrcAlpha = 4, // GLenum == 0x0302
+ OneMinusSrcAlpha = 5, // GLenum == 0x0303
+ DstAlpha = 6, // GLenum == 0x0304
+ OneMinusDstAlpha = 7, // GLenum == 0x0305
+ DstColor = 8, // GLenum == 0x0306
+ OneMinusDstColor = 9, // GLenum == 0x0307
+ SrcAlphaSaturate = 10, // GLenum == 0x0308
+ MaxSrcDstType = 10,
+
+ MinConstantType = 11,
+ ConstantColor = 11, // GLenum == 0x8001
+ OneMinusConstantColor = 12, // GLenum == 0x8002
+ ConstantAlpha = 13, // GLenum == 0x8003
+ OneMinusConstantAlpha = 14, // GLenum == 0x8004
+ MaxConstantType = 14,
+
+ // GL_EXT_blend_func_extended
+
+ Src1Alpha = 15, // GLenum == 0x8589
+
+ Src1Color = 16, // GLenum == 0x88F9
+ OneMinusSrc1Color = 17, // GLenum == 0x88FA
+ OneMinusSrc1Alpha = 18, // GLenum == 0x88FB
+
+ InvalidEnum = 19,
+ EnumCount = 19
+};
+
+template <>
+constexpr BlendFactorType FromGLenum<BlendFactorType>(GLenum from)
+{
+ if (from <= 1)
+ return static_cast<BlendFactorType>(from);
+ if (from >= GL_SRC_COLOR && from <= GL_SRC_ALPHA_SATURATE)
+ return static_cast<BlendFactorType>(from - GL_SRC_COLOR + 2);
+ if (from >= GL_CONSTANT_COLOR && from <= GL_ONE_MINUS_CONSTANT_ALPHA)
+ return static_cast<BlendFactorType>(from - GL_CONSTANT_COLOR + 11);
+ if (from == GL_SRC1_ALPHA_EXT)
+ return BlendFactorType::Src1Alpha;
+ if (from >= GL_SRC1_COLOR_EXT && from <= GL_ONE_MINUS_SRC1_ALPHA_EXT)
+ return static_cast<BlendFactorType>(from - GL_SRC1_COLOR_EXT + 16);
+ return BlendFactorType::InvalidEnum;
+}
+
+constexpr GLenum ToGLenum(BlendFactorType from)
+{
+ const GLenum value = static_cast<GLenum>(from);
+ if (value <= 1)
+ return value;
+ if (from >= BlendFactorType::MinSrcDstType && from <= BlendFactorType::MaxSrcDstType)
+ return value - 2 + GL_SRC_COLOR;
+ if (from >= BlendFactorType::MinConstantType && from <= BlendFactorType::MaxConstantType)
+ return value - 11 + GL_CONSTANT_COLOR;
+ if (from == BlendFactorType::Src1Alpha)
+ return GL_SRC1_ALPHA_EXT;
+ return value - 16 + GL_SRC1_COLOR_EXT;
+}
+
+ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, Zero, GL_ZERO);
+ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, One, GL_ONE);
+ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, SrcColor, GL_SRC_COLOR);
+ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusSrcColor, GL_ONE_MINUS_SRC_COLOR);
+ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, SrcAlpha, GL_SRC_ALPHA);
+ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusSrcAlpha, GL_ONE_MINUS_SRC_ALPHA);
+ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, DstAlpha, GL_DST_ALPHA);
+ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusDstAlpha, GL_ONE_MINUS_DST_ALPHA);
+ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, DstColor, GL_DST_COLOR);
+ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusDstColor, GL_ONE_MINUS_DST_COLOR);
+ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, SrcAlphaSaturate, GL_SRC_ALPHA_SATURATE);
+ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, ConstantColor, GL_CONSTANT_COLOR);
+ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusConstantColor, GL_ONE_MINUS_CONSTANT_COLOR);
+ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, ConstantAlpha, GL_CONSTANT_ALPHA);
+ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusConstantAlpha, GL_ONE_MINUS_CONSTANT_ALPHA);
+ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, Src1Alpha, GL_SRC1_ALPHA_EXT);
+ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, Src1Color, GL_SRC1_COLOR_EXT);
+ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusSrc1Color, GL_ONE_MINUS_SRC1_COLOR_EXT);
+ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusSrc1Alpha, GL_ONE_MINUS_SRC1_ALPHA_EXT);
+
+std::ostream &operator<<(std::ostream &os, BlendFactorType value);
+
+enum class VertexAttribType
+{
+ Byte = 0, // GLenum == 0x1400
+ UnsignedByte = 1, // GLenum == 0x1401
+ Short = 2, // GLenum == 0x1402
+ UnsignedShort = 3, // GLenum == 0x1403
+ Int = 4, // GLenum == 0x1404
+ UnsignedInt = 5, // GLenum == 0x1405
+ Float = 6, // GLenum == 0x1406
+ Unused1 = 7, // GLenum == 0x1407
+ Unused2 = 8, // GLenum == 0x1408
+ Unused3 = 9, // GLenum == 0x1409
+ Unused4 = 10, // GLenum == 0x140A
+ HalfFloat = 11, // GLenum == 0x140B
+ Fixed = 12, // GLenum == 0x140C
+ MaxBasicType = 12,
+ UnsignedInt2101010 = 13, // GLenum == 0x8368
+ HalfFloatOES = 14, // GLenum == 0x8D61
+ Int2101010 = 15, // GLenum == 0x8D9F
+ UnsignedInt1010102 = 16, // GLenum == 0x8DF6
+ Int1010102 = 17, // GLenum == 0x8DF7
+ InvalidEnum = 18,
+ EnumCount = 18,
+};
+
+template <>
+constexpr VertexAttribType FromGLenum<VertexAttribType>(GLenum from)
+{
+ GLenum packed = from - GL_BYTE;
+ if (packed <= static_cast<GLenum>(VertexAttribType::MaxBasicType))
+ return static_cast<VertexAttribType>(packed);
+ if (from == GL_UNSIGNED_INT_2_10_10_10_REV)
+ return VertexAttribType::UnsignedInt2101010;
+ if (from == GL_HALF_FLOAT_OES)
+ return VertexAttribType::HalfFloatOES;
+ if (from == GL_INT_2_10_10_10_REV)
+ return VertexAttribType::Int2101010;
+ if (from == GL_UNSIGNED_INT_10_10_10_2_OES)
+ return VertexAttribType::UnsignedInt1010102;
+ if (from == GL_INT_10_10_10_2_OES)
+ return VertexAttribType::Int1010102;
+ return VertexAttribType::InvalidEnum;
+}
+
+constexpr GLenum ToGLenum(VertexAttribType from)
+{
+ // This could be optimized using a constexpr table.
+ if (from == VertexAttribType::Int2101010)
+ return GL_INT_2_10_10_10_REV;
+ if (from == VertexAttribType::HalfFloatOES)
+ return GL_HALF_FLOAT_OES;
+ if (from == VertexAttribType::UnsignedInt2101010)
+ return GL_UNSIGNED_INT_2_10_10_10_REV;
+ if (from == VertexAttribType::UnsignedInt1010102)
+ return GL_UNSIGNED_INT_10_10_10_2_OES;
+ if (from == VertexAttribType::Int1010102)
+ return GL_INT_10_10_10_2_OES;
+ return static_cast<GLenum>(from) + GL_BYTE;
+}
+
+ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Byte, GL_BYTE);
+ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, UnsignedByte, GL_UNSIGNED_BYTE);
+ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Short, GL_SHORT);
+ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, UnsignedShort, GL_UNSIGNED_SHORT);
+ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Int, GL_INT);
+ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, UnsignedInt, GL_UNSIGNED_INT);
+ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Float, GL_FLOAT);
+ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, HalfFloat, GL_HALF_FLOAT);
+ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Fixed, GL_FIXED);
+ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Int2101010, GL_INT_2_10_10_10_REV);
+ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, HalfFloatOES, GL_HALF_FLOAT_OES);
+ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, UnsignedInt2101010, GL_UNSIGNED_INT_2_10_10_10_REV);
+ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Int1010102, GL_INT_10_10_10_2_OES);
+ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, UnsignedInt1010102, GL_UNSIGNED_INT_10_10_10_2_OES);
+
+std::ostream &operator<<(std::ostream &os, VertexAttribType value);
+
+enum class TessEvaluationType
+{
+ Triangles = 0,
+ Quads = 1,
+ Isolines = 2,
+ EqualSpacing = 3,
+ FractionalEvenSpacing = 4,
+ FractionalOddSpacing = 5,
+ Cw = 6,
+ Ccw = 7,
+ PointMode = 8,
+ InvalidEnum = 9,
+ EnumCount = 9
+};
+
+template <>
+constexpr TessEvaluationType FromGLenum<TessEvaluationType>(GLenum from)
+{
+ if (from == GL_TRIANGLES)
+ return TessEvaluationType::Triangles;
+ if (from == GL_QUADS)
+ return TessEvaluationType::Quads;
+ if (from == GL_ISOLINES)
+ return TessEvaluationType::Isolines;
+ if (from == GL_EQUAL)
+ return TessEvaluationType::EqualSpacing;
+ if (from == GL_FRACTIONAL_EVEN)
+ return TessEvaluationType::FractionalEvenSpacing;
+ if (from == GL_FRACTIONAL_ODD)
+ return TessEvaluationType::FractionalOddSpacing;
+ if (from == GL_CW)
+ return TessEvaluationType::Cw;
+ if (from == GL_CCW)
+ return TessEvaluationType::Ccw;
+ if (from == GL_TESS_GEN_POINT_MODE)
+ return TessEvaluationType::PointMode;
+ return TessEvaluationType::InvalidEnum;
+}
+
+constexpr GLenum ToGLenum(TessEvaluationType from)
+{
+ switch (from)
+ {
+ case TessEvaluationType::Triangles:
+ return GL_TRIANGLES;
+ case TessEvaluationType::Quads:
+ return GL_QUADS;
+ case TessEvaluationType::Isolines:
+ return GL_ISOLINES;
+ case TessEvaluationType::EqualSpacing:
+ return GL_EQUAL;
+ case TessEvaluationType::FractionalEvenSpacing:
+ return GL_FRACTIONAL_EVEN;
+ case TessEvaluationType::FractionalOddSpacing:
+ return GL_FRACTIONAL_ODD;
+ case TessEvaluationType::Cw:
+ return GL_CW;
+ case TessEvaluationType::Ccw:
+ return GL_CCW;
+ case TessEvaluationType::PointMode:
+ return GL_TESS_GEN_POINT_MODE;
+ default:
+ return GL_INVALID_ENUM;
+ }
+}
+
+ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, Triangles, GL_TRIANGLES);
+ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, Quads, GL_QUADS);
+ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, Isolines, GL_ISOLINES);
+ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, EqualSpacing, GL_EQUAL);
+ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, FractionalEvenSpacing, GL_FRACTIONAL_EVEN);
+ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, FractionalOddSpacing, GL_FRACTIONAL_ODD);
+ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, Cw, GL_CW);
+ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, Ccw, GL_CCW);
+ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, PointMode, GL_TESS_GEN_POINT_MODE);
+
+std::ostream &operator<<(std::ostream &os, TessEvaluationType value);
+
+// Typesafe object handles.
+
+template <typename T>
+struct ResourceTypeToID;
+
+template <typename T>
+struct IsResourceIDType;
+
+// Clang Format doesn't like the following X macro.
+// clang-format off
+#define ANGLE_ID_TYPES_OP(X) \
+ X(Buffer) \
+ X(FenceNV) \
+ X(Framebuffer) \
+ X(MemoryObject) \
+ X(Path) \
+ X(ProgramPipeline) \
+ X(Query) \
+ X(Renderbuffer) \
+ X(Sampler) \
+ X(Semaphore) \
+ X(Texture) \
+ X(TransformFeedback) \
+ X(VertexArray)
+// clang-format on
+
+#define ANGLE_DEFINE_ID_TYPE(Type) \
+ class Type; \
+ struct Type##ID \
+ { \
+ GLuint value; \
+ }; \
+ template <> \
+ struct ResourceTypeToID<Type> \
+ { \
+ using IDType = Type##ID; \
+ }; \
+ template <> \
+ struct IsResourceIDType<Type##ID> \
+ { \
+ static constexpr bool value = true; \
+ };
+
+ANGLE_ID_TYPES_OP(ANGLE_DEFINE_ID_TYPE)
+
+#undef ANGLE_DEFINE_ID_TYPE
+#undef ANGLE_ID_TYPES_OP
+
+// Shaders and programs are a bit special as they share IDs.
+struct ShaderProgramID
+{
+ GLuint value;
+};
+
+template <>
+struct IsResourceIDType<ShaderProgramID>
+{
+ constexpr static bool value = true;
+};
+
+class Shader;
+template <>
+struct ResourceTypeToID<Shader>
+{
+ using IDType = ShaderProgramID;
+};
+
+class Program;
+template <>
+struct ResourceTypeToID<Program>
+{
+ using IDType = ShaderProgramID;
+};
+
+template <typename T>
+struct ResourceTypeToID
+{
+ using IDType = void;
+};
+
+template <typename T>
+struct IsResourceIDType
+{
+ static constexpr bool value = false;
+};
+
+template <typename T>
+bool ValueEquals(T lhs, T rhs)
+{
+ return lhs.value == rhs.value;
+}
+
+// Util funcs for resourceIDs
+template <typename T>
+typename std::enable_if<IsResourceIDType<T>::value, bool>::type operator==(const T &lhs,
+ const T &rhs)
+{
+ return lhs.value == rhs.value;
+}
+
+template <typename T>
+typename std::enable_if<IsResourceIDType<T>::value, bool>::type operator!=(const T &lhs,
+ const T &rhs)
+{
+ return lhs.value != rhs.value;
+}
+
+template <typename T>
+typename std::enable_if<IsResourceIDType<T>::value, bool>::type operator<(const T &lhs,
+ const T &rhs)
+{
+ return lhs.value < rhs.value;
+}
+
+// Used to unbox typed values.
+template <typename ResourceIDType>
+GLuint GetIDValue(ResourceIDType id);
+
+template <>
+inline GLuint GetIDValue(GLuint id)
+{
+ return id;
+}
+
+template <typename ResourceIDType>
+inline GLuint GetIDValue(ResourceIDType id)
+{
+ return id.value;
+}
+
+// First case: handling packed enums.
+template <typename EnumT, typename FromT>
+typename std::enable_if<std::is_enum<EnumT>::value, EnumT>::type PackParam(FromT from)
+{
+ return FromGLenum<EnumT>(from);
+}
+
+// Second case: handling non-pointer resource ids.
+template <typename EnumT, typename FromT>
+typename std::enable_if<!std::is_pointer<FromT>::value && !std::is_enum<EnumT>::value, EnumT>::type
+PackParam(FromT from)
+{
+ return {from};
+}
+
+// Third case: handling pointer resource ids.
+template <typename EnumT, typename FromT>
+typename std::enable_if<std::is_pointer<FromT>::value && !std::is_enum<EnumT>::value, EnumT>::type
+PackParam(FromT from)
+{
+ static_assert(sizeof(typename std::remove_pointer<EnumT>::type) ==
+ sizeof(typename std::remove_pointer<FromT>::type),
+ "Types have different sizes");
+ static_assert(
+ std::is_same<
+ decltype(std::remove_pointer<EnumT>::type::value),
+ typename std::remove_const<typename std::remove_pointer<FromT>::type>::type>::value,
+ "Data types are different");
+ return reinterpret_cast<EnumT>(from);
+}
+
+struct UniformLocation
+{
+ int value;
+};
+
+struct UniformBlockIndex
+{
+ uint32_t value;
+};
+} // namespace gl
+
+namespace egl
+{
+MessageType ErrorCodeToMessageType(EGLint errorCode);
+} // namespace egl
+
+namespace egl_gl
+{
+gl::TextureTarget EGLCubeMapTargetToCubeMapTarget(EGLenum eglTarget);
+gl::TextureTarget EGLImageTargetToTextureTarget(EGLenum eglTarget);
+gl::TextureType EGLTextureTargetToTextureType(EGLenum eglTarget);
+} // namespace egl_gl
+
+#endif // COMMON_PACKEDGLENUMS_H_