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