// 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 #include #include #include #include "common/bitset_utils.h" namespace angle { // Return the number of elements of a packed enum, including the InvalidEnum element. template constexpr size_t EnumSize() { using UnderlyingType = typename std::underlying_type::type; return static_cast(E::EnumCount); } // Implementation of AllEnums which allows iterating over all the possible values for a packed enums // like so: // for (auto value : AllEnums()) { // // Do something with the enum. // } template class EnumIterator final { private: using UnderlyingType = typename std::underlying_type::type; public: EnumIterator(E value) : mValue(static_cast(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(mValue); } private: UnderlyingType mValue; }; template ()> struct AllEnums { EnumIterator begin() const { return {static_cast(0)}; } EnumIterator end() const { return {static_cast(MaxSize)}; } }; // PackedEnumMap is like an std::array but is indexed with enum values. It // implements all of the std::array interface except with enum values instead of indices. template ()> class PackedEnumMap { using UnderlyingType = typename std::underlying_type::type; using Storage = std::array; public: using InitPair = std::pair; constexpr PackedEnumMap() = default; constexpr PackedEnumMap(std::initializer_list 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) { mPrivateData[static_cast(it->first)] = it->second; } } // 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; using const_reverse_iterator = std::reverse_iterator; // No explicit construct/copy/destroy for aggregate type void fill(const T &u) { mPrivateData.fill(u); } void swap(PackedEnumMap &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(n) < mPrivateData.size()); return mPrivateData[static_cast(n)]; } constexpr const_reference operator[](E n) const { ASSERT(static_cast(n) < mPrivateData.size()); return mPrivateData[static_cast(n)]; } const_reference at(E n) const { return mPrivateData.at(static_cast(n)); } reference at(E n) { return mPrivateData.at(static_cast(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 std::enable_if::value>::type operator+=( const PackedEnumMap &rhs) { for (E e : AllEnums()) { at(e) += rhs[e]; } } private: Storage mPrivateData; }; // PackedEnumBitSetE> is like an std::bitset but is indexed with enum values. It // implements the std::bitset interface except with enum values instead of indices. template using PackedEnumBitSet = BitSetT(), 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(static_cast(kCubeMapTextureTargetMax) + 1); struct AllCubeFaceTextureTargets { angle::EnumIterator begin() const { return kCubeMapTextureTargetMin; } angle::EnumIterator end() const { return kAfterCubeMapTextureTargetMax; } }; constexpr std::array kAllGLES2ShaderTypes = {ShaderType::Vertex, ShaderType::Fragment}; constexpr ShaderType kShaderTypeMin = ShaderType::Vertex; constexpr ShaderType kShaderTypeMax = ShaderType::Compute; constexpr ShaderType kAfterShaderTypeMax = static_cast(static_cast(kShaderTypeMax) + 1); struct AllShaderTypes { angle::EnumIterator begin() const { return kShaderTypeMin; } angle::EnumIterator end() const { return kAfterShaderTypeMax; } }; constexpr size_t kGraphicsShaderCount = static_cast(ShaderType::EnumCount) - 1u; // Arrange the shader types in the order of rendering pipeline constexpr std::array kAllGraphicsShaderTypes = { ShaderType::Vertex, ShaderType::TessControl, ShaderType::TessEvaluation, ShaderType::Geometry, ShaderType::Fragment}; using ShaderBitSet = angle::PackedEnumBitSet; static_assert(sizeof(ShaderBitSet) == sizeof(uint8_t), "Unexpected size"); template using ShaderMap = angle::PackedEnumMap; 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(GLenum from) { if (from >= static_cast(PrimitiveMode::EnumCount)) { return PrimitiveMode::InvalidEnum; } return static_cast(from); } constexpr GLenum ToGLenum(PrimitiveMode from) { return static_cast(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(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(DrawElementsType::EnumCount)) ? static_cast(DrawElementsType::InvalidEnum) : packed; return static_cast(packed); } constexpr GLenum ToGLenum(DrawElementsType from) { return ((static_cast(from) << 1) + GL_UNSIGNED_BYTE); } #define ANGLE_VALIDATE_PACKED_ENUM(type, packed, glenum) \ static_assert(ToGLenum(type::packed) == glenum, #type " violation"); \ static_assert(FromGLenum(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 Multiply = 6, // GLenum == 0x9294 Screen = 7, // GLenum == 0x9295 Overlay = 8, // GLenum == 0x9296 Darken = 9, // GLenum == 0x9297 Lighten = 10, // GLenum == 0x9298 Colordodge = 11, // GLenum == 0x9299 Colorburn = 12, // GLenum == 0x929A Hardlight = 13, // GLenum == 0x929B Softlight = 14, // GLenum == 0x929C Unused2 = 15, Difference = 16, // GLenum == 0x929E Unused3 = 17, Exclusion = 18, // GLenum == 0x92A0 HslHue = 19, // GLenum == 0x92AD HslSaturation = 20, // GLenum == 0x92AE HslColor = 21, // GLenum == 0x92AF HslLuminosity = 22, // GLenum == 0x92B0 InvalidEnum = 23, EnumCount = InvalidEnum }; using BlendEquationBitSet = angle::PackedEnumBitSet; template <> constexpr BlendEquationType FromGLenum(GLenum from) { if (from <= GL_FUNC_REVERSE_SUBTRACT) { const GLenum scaled = (from - GL_FUNC_ADD); return (scaled == static_cast(BlendEquationType::Unused)) ? BlendEquationType::InvalidEnum : static_cast(scaled); } if (from <= GL_EXCLUSION_KHR) { const GLenum scaled = (from - GL_MULTIPLY_KHR + static_cast(BlendEquationType::Multiply)); return (scaled == static_cast(BlendEquationType::Unused2) || scaled == static_cast(BlendEquationType::Unused3)) ? BlendEquationType::InvalidEnum : static_cast(scaled); } if (from <= GL_HSL_LUMINOSITY_KHR) { return static_cast(from - GL_HSL_HUE_KHR + static_cast(BlendEquationType::HslHue)); } return BlendEquationType::InvalidEnum; } constexpr GLenum ToGLenum(BlendEquationType from) { if (from <= BlendEquationType::ReverseSubtract) { return static_cast(from) + GL_FUNC_ADD; } if (from <= BlendEquationType::Exclusion) { return static_cast(from) - static_cast(BlendEquationType::Multiply) + GL_MULTIPLY_KHR; } return static_cast(from) - static_cast(BlendEquationType::HslHue) + GL_HSL_HUE_KHR; } 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); ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Multiply, GL_MULTIPLY_KHR); ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Screen, GL_SCREEN_KHR); ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Overlay, GL_OVERLAY_KHR); ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Darken, GL_DARKEN_KHR); ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Lighten, GL_LIGHTEN_KHR); ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Colordodge, GL_COLORDODGE_KHR); ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Colorburn, GL_COLORBURN_KHR); ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Hardlight, GL_HARDLIGHT_KHR); ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Softlight, GL_SOFTLIGHT_KHR); ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Difference, GL_DIFFERENCE_KHR); ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Exclusion, GL_EXCLUSION_KHR); ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, HslHue, GL_HSL_HUE_KHR); ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, HslSaturation, GL_HSL_SATURATION_KHR); ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, HslColor, GL_HSL_COLOR_KHR); ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, HslLuminosity, GL_HSL_LUMINOSITY_KHR); 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(GLenum from) { if (from <= 1) return static_cast(from); if (from >= GL_SRC_COLOR && from <= GL_SRC_ALPHA_SATURATE) return static_cast(from - GL_SRC_COLOR + 2); if (from >= GL_CONSTANT_COLOR && from <= GL_ONE_MINUS_CONSTANT_ALPHA) return static_cast(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(from - GL_SRC1_COLOR_EXT + 16); return BlendFactorType::InvalidEnum; } constexpr GLenum ToGLenum(BlendFactorType from) { const GLenum value = static_cast(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(GLenum from) { GLenum packed = from - GL_BYTE; if (packed <= static_cast(VertexAttribType::MaxBasicType)) return static_cast(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(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(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 struct ResourceTypeToID; template 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 \ { \ using IDType = Type##ID; \ }; \ template <> \ struct IsResourceIDType \ { \ 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 { constexpr static bool value = true; }; class Shader; template <> struct ResourceTypeToID { using IDType = ShaderProgramID; }; class Program; template <> struct ResourceTypeToID { using IDType = ShaderProgramID; }; template struct ResourceTypeToID { using IDType = void; }; template struct IsResourceIDType { static constexpr bool value = false; }; template bool ValueEquals(T lhs, T rhs) { return lhs.value == rhs.value; } // Util funcs for resourceIDs template typename std::enable_if::value, bool>::type operator==(const T &lhs, const T &rhs) { return lhs.value == rhs.value; } template typename std::enable_if::value, bool>::type operator!=(const T &lhs, const T &rhs) { return lhs.value != rhs.value; } template typename std::enable_if::value, bool>::type operator<(const T &lhs, const T &rhs) { return lhs.value < rhs.value; } // Used to unbox typed values. template GLuint GetIDValue(ResourceIDType id); template <> inline GLuint GetIDValue(GLuint id) { return id; } template inline GLuint GetIDValue(ResourceIDType id) { return id.value; } // First case: handling packed enums. template typename std::enable_if::value, EnumT>::type PackParam(FromT from) { return FromGLenum(from); } // Second case: handling non-pointer resource ids. template typename std::enable_if::value && !std::is_enum::value, EnumT>::type PackParam(FromT from) { return {from}; } // Third case: handling pointer resource ids. template typename std::enable_if::value && !std::is_enum::value, EnumT>::type PackParam(FromT from) { static_assert(sizeof(typename std::remove_pointer::type) == sizeof(typename std::remove_pointer::type), "Types have different sizes"); static_assert( std::is_same< decltype(std::remove_pointer::type::value), typename std::remove_const::type>::type>::value, "Data types are different"); return reinterpret_cast(from); } struct UniformLocation { int value; }; bool operator<(const UniformLocation &lhs, const UniformLocation &rhs); struct UniformBlockIndex { uint32_t value; }; bool IsEmulatedCompressedFormat(GLenum format); } // 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_