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