tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

PackedEnums.h (31517B)


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