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>
62 struct AllEnums
63 {
beginAllEnums64 EnumIterator<E> begin() const { return {static_cast<E>(0)}; }
endAllEnums65 EnumIterator<E> end() const { return {E::InvalidEnum}; }
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 private:
160 Storage mPrivateData;
161 };
162
163 // PackedEnumBitSetE> is like an std::bitset<E::EnumCount> but is indexed with enum values. It
164 // implements the std::bitset interface except with enum values instead of indices.
165 template <typename E, typename DataT = uint32_t>
166 using PackedEnumBitSet = BitSetT<EnumSize<E>(), DataT, E>;
167
168 } // namespace angle
169
170 namespace gl
171 {
172
173 TextureType TextureTargetToType(TextureTarget target);
174 TextureTarget NonCubeTextureTypeToTarget(TextureType type);
175
176 TextureTarget CubeFaceIndexToTextureTarget(size_t face);
177 size_t CubeMapTextureTargetToFaceIndex(TextureTarget target);
178 bool IsCubeMapFaceTarget(TextureTarget target);
179
180 constexpr TextureTarget kCubeMapTextureTargetMin = TextureTarget::CubeMapPositiveX;
181 constexpr TextureTarget kCubeMapTextureTargetMax = TextureTarget::CubeMapNegativeZ;
182 constexpr TextureTarget kAfterCubeMapTextureTargetMax =
183 static_cast<TextureTarget>(static_cast<uint8_t>(kCubeMapTextureTargetMax) + 1);
184 struct AllCubeFaceTextureTargets
185 {
beginAllCubeFaceTextureTargets186 angle::EnumIterator<TextureTarget> begin() const { return kCubeMapTextureTargetMin; }
endAllCubeFaceTextureTargets187 angle::EnumIterator<TextureTarget> end() const { return kAfterCubeMapTextureTargetMax; }
188 };
189
190 constexpr ShaderType kGLES2ShaderTypeMin = ShaderType::Vertex;
191 constexpr ShaderType kGLES2ShaderTypeMax = ShaderType::Fragment;
192 constexpr ShaderType kAfterGLES2ShaderTypeMax =
193 static_cast<ShaderType>(static_cast<uint8_t>(kGLES2ShaderTypeMax) + 1);
194 struct AllGLES2ShaderTypes
195 {
beginAllGLES2ShaderTypes196 angle::EnumIterator<ShaderType> begin() const { return kGLES2ShaderTypeMin; }
endAllGLES2ShaderTypes197 angle::EnumIterator<ShaderType> end() const { return kAfterGLES2ShaderTypeMax; }
198 };
199
200 constexpr ShaderType kShaderTypeMin = ShaderType::Vertex;
201 constexpr ShaderType kShaderTypeMax = ShaderType::Compute;
202 constexpr ShaderType kAfterShaderTypeMax =
203 static_cast<ShaderType>(static_cast<uint8_t>(kShaderTypeMax) + 1);
204 struct AllShaderTypes
205 {
beginAllShaderTypes206 angle::EnumIterator<ShaderType> begin() const { return kShaderTypeMin; }
endAllShaderTypes207 angle::EnumIterator<ShaderType> end() const { return kAfterShaderTypeMax; }
208 };
209
210 constexpr size_t kGraphicsShaderCount = static_cast<size_t>(ShaderType::EnumCount) - 1u;
211 // Arrange the shader types in the order of rendering pipeline
212 constexpr std::array<ShaderType, kGraphicsShaderCount> kAllGraphicsShaderTypes = {
213 ShaderType::Vertex, ShaderType::Geometry, ShaderType::Fragment};
214
215 using ShaderBitSet = angle::PackedEnumBitSet<ShaderType, uint8_t>;
216 static_assert(sizeof(ShaderBitSet) == sizeof(uint8_t), "Unexpected size");
217
218 template <typename T>
219 using ShaderMap = angle::PackedEnumMap<ShaderType, T>;
220
221 TextureType SamplerTypeToTextureType(GLenum samplerType);
222
223 bool IsMultisampled(gl::TextureType type);
224 bool IsArrayTextureType(gl::TextureType type);
225
226 enum class PrimitiveMode : uint8_t
227 {
228 Points = 0x0,
229 Lines = 0x1,
230 LineLoop = 0x2,
231 LineStrip = 0x3,
232 Triangles = 0x4,
233 TriangleStrip = 0x5,
234 TriangleFan = 0x6,
235 Unused1 = 0x7,
236 Unused2 = 0x8,
237 Unused3 = 0x9,
238 LinesAdjacency = 0xA,
239 LineStripAdjacency = 0xB,
240 TrianglesAdjacency = 0xC,
241 TriangleStripAdjacency = 0xD,
242
243 InvalidEnum = 0xE,
244 EnumCount = 0xE,
245 };
246
247 template <>
248 constexpr PrimitiveMode FromGLenum<PrimitiveMode>(GLenum from)
249 {
250 if (from >= static_cast<GLenum>(PrimitiveMode::EnumCount))
251 {
252 return PrimitiveMode::InvalidEnum;
253 }
254
255 return static_cast<PrimitiveMode>(from);
256 }
257
ToGLenum(PrimitiveMode from)258 constexpr GLenum ToGLenum(PrimitiveMode from)
259 {
260 return static_cast<GLenum>(from);
261 }
262
263 static_assert(ToGLenum(PrimitiveMode::Points) == GL_POINTS, "PrimitiveMode violation");
264 static_assert(ToGLenum(PrimitiveMode::Lines) == GL_LINES, "PrimitiveMode violation");
265 static_assert(ToGLenum(PrimitiveMode::LineLoop) == GL_LINE_LOOP, "PrimitiveMode violation");
266 static_assert(ToGLenum(PrimitiveMode::LineStrip) == GL_LINE_STRIP, "PrimitiveMode violation");
267 static_assert(ToGLenum(PrimitiveMode::Triangles) == GL_TRIANGLES, "PrimitiveMode violation");
268 static_assert(ToGLenum(PrimitiveMode::TriangleStrip) == GL_TRIANGLE_STRIP,
269 "PrimitiveMode violation");
270 static_assert(ToGLenum(PrimitiveMode::TriangleFan) == GL_TRIANGLE_FAN, "PrimitiveMode violation");
271 static_assert(ToGLenum(PrimitiveMode::LinesAdjacency) == GL_LINES_ADJACENCY,
272 "PrimitiveMode violation");
273 static_assert(ToGLenum(PrimitiveMode::LineStripAdjacency) == GL_LINE_STRIP_ADJACENCY,
274 "PrimitiveMode violation");
275 static_assert(ToGLenum(PrimitiveMode::TrianglesAdjacency) == GL_TRIANGLES_ADJACENCY,
276 "PrimitiveMode violation");
277 static_assert(ToGLenum(PrimitiveMode::TriangleStripAdjacency) == GL_TRIANGLE_STRIP_ADJACENCY,
278 "PrimitiveMode violation");
279
280 std::ostream &operator<<(std::ostream &os, PrimitiveMode value);
281
282 enum class DrawElementsType : size_t
283 {
284 UnsignedByte = 0,
285 UnsignedShort = 1,
286 UnsignedInt = 2,
287 InvalidEnum = 3,
288 EnumCount = 3,
289 };
290
291 template <>
292 constexpr DrawElementsType FromGLenum<DrawElementsType>(GLenum from)
293 {
294
295 GLenum scaled = (from - GL_UNSIGNED_BYTE);
296 // This code sequence generates a ROR instruction on x86/arm. We want to check if the lowest bit
297 // of scaled is set and if (scaled >> 1) is greater than a non-pot value. If we rotate the
298 // lowest bit to the hightest bit both conditions can be checked with a single test.
299 static_assert(sizeof(GLenum) == 4, "Update (scaled << 31) to sizeof(GLenum) * 8 - 1");
300 GLenum packed = (scaled >> 1) | (scaled << 31);
301
302 // operator ? with a simple assignment usually translates to a cmov instruction and thus avoids
303 // a branch.
304 packed = (packed >= static_cast<GLenum>(DrawElementsType::EnumCount))
305 ? static_cast<GLenum>(DrawElementsType::InvalidEnum)
306 : packed;
307
308 return static_cast<DrawElementsType>(packed);
309 }
310
ToGLenum(DrawElementsType from)311 constexpr GLenum ToGLenum(DrawElementsType from)
312 {
313 return ((static_cast<GLenum>(from) << 1) + GL_UNSIGNED_BYTE);
314 }
315
316 #define ANGLE_VALIDATE_PACKED_ENUM(type, packed, glenum) \
317 static_assert(ToGLenum(type::packed) == glenum, #type " violation"); \
318 static_assert(FromGLenum<type>(glenum) == type::packed, #type " violation")
319
320 ANGLE_VALIDATE_PACKED_ENUM(DrawElementsType, UnsignedByte, GL_UNSIGNED_BYTE);
321 ANGLE_VALIDATE_PACKED_ENUM(DrawElementsType, UnsignedShort, GL_UNSIGNED_SHORT);
322 ANGLE_VALIDATE_PACKED_ENUM(DrawElementsType, UnsignedInt, GL_UNSIGNED_INT);
323
324 std::ostream &operator<<(std::ostream &os, DrawElementsType value);
325
326 enum class BlendEquationType
327 {
328 Add = 0, // GLenum == 0x8006
329 Min = 1, // GLenum == 0x8007
330 Max = 2, // GLenum == 0x8008
331 Unused = 3,
332 Subtract = 4, // GLenum == 0x800A
333 ReverseSubtract = 5, // GLenum == 0x800B
334 InvalidEnum = 6,
335 EnumCount = 6
336 };
337
338 template <>
339 constexpr BlendEquationType FromGLenum<BlendEquationType>(GLenum from)
340 {
341 const GLenum scaled = (from - GL_FUNC_ADD);
342 return (scaled == static_cast<GLenum>(BlendEquationType::Unused) ||
343 scaled >= static_cast<GLenum>(BlendEquationType::EnumCount))
344 ? BlendEquationType::InvalidEnum
345 : static_cast<BlendEquationType>(scaled);
346 }
347
ToGLenum(BlendEquationType from)348 constexpr GLenum ToGLenum(BlendEquationType from)
349 {
350 return static_cast<GLenum>(from) + GL_FUNC_ADD;
351 }
352
353 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Add, GL_FUNC_ADD);
354 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Min, GL_MIN);
355 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Max, GL_MAX);
356 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Subtract, GL_FUNC_SUBTRACT);
357 ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, ReverseSubtract, GL_FUNC_REVERSE_SUBTRACT);
358
359 std::ostream &operator<<(std::ostream &os, BlendEquationType value);
360
361 enum class BlendFactorType
362 {
363 Zero = 0, // GLenum == 0
364 One = 1, // GLenum == 1
365
366 MinSrcDstType = 2,
367 SrcColor = 2, // GLenum == 0x0300
368 OneMinusSrcColor = 3, // GLenum == 0x0301
369 SrcAlpha = 4, // GLenum == 0x0302
370 OneMinusSrcAlpha = 5, // GLenum == 0x0303
371 DstAlpha = 6, // GLenum == 0x0304
372 OneMinusDstAlpha = 7, // GLenum == 0x0305
373 DstColor = 8, // GLenum == 0x0306
374 OneMinusDstColor = 9, // GLenum == 0x0307
375 SrcAlphaSaturate = 10, // GLenum == 0x0308
376 MaxSrcDstType = 10,
377
378 MinConstantType = 11,
379 ConstantColor = 11, // GLenum == 0x8001
380 OneMinusConstantColor = 12, // GLenum == 0x8002
381 ConstantAlpha = 13, // GLenum == 0x8003
382 OneMinusConstantAlpha = 14, // GLenum == 0x8004
383 MaxConstantType = 14,
384
385 // GL_EXT_blend_func_extended
386
387 Src1Alpha = 15, // GLenum == 0x8589
388
389 Src1Color = 16, // GLenum == 0x88F9
390 OneMinusSrc1Color = 17, // GLenum == 0x88FA
391 OneMinusSrc1Alpha = 18, // GLenum == 0x88FB
392
393 InvalidEnum = 19,
394 EnumCount = 19
395 };
396
397 template <>
398 constexpr BlendFactorType FromGLenum<BlendFactorType>(GLenum from)
399 {
400 if (from <= 1)
401 return static_cast<BlendFactorType>(from);
402 if (from >= GL_SRC_COLOR && from <= GL_SRC_ALPHA_SATURATE)
403 return static_cast<BlendFactorType>(from - GL_SRC_COLOR + 2);
404 if (from >= GL_CONSTANT_COLOR && from <= GL_ONE_MINUS_CONSTANT_ALPHA)
405 return static_cast<BlendFactorType>(from - GL_CONSTANT_COLOR + 11);
406 if (from == GL_SRC1_ALPHA_EXT)
407 return BlendFactorType::Src1Alpha;
408 if (from >= GL_SRC1_COLOR_EXT && from <= GL_ONE_MINUS_SRC1_ALPHA_EXT)
409 return static_cast<BlendFactorType>(from - GL_SRC1_COLOR_EXT + 16);
410 return BlendFactorType::InvalidEnum;
411 }
412
ToGLenum(BlendFactorType from)413 constexpr GLenum ToGLenum(BlendFactorType from)
414 {
415 const GLenum value = static_cast<GLenum>(from);
416 if (value <= 1)
417 return value;
418 if (from >= BlendFactorType::MinSrcDstType && from <= BlendFactorType::MaxSrcDstType)
419 return value - 2 + GL_SRC_COLOR;
420 if (from >= BlendFactorType::MinConstantType && from <= BlendFactorType::MaxConstantType)
421 return value - 11 + GL_CONSTANT_COLOR;
422 if (from == BlendFactorType::Src1Alpha)
423 return GL_SRC1_ALPHA_EXT;
424 return value - 16 + GL_SRC1_COLOR_EXT;
425 }
426
427 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, Zero, GL_ZERO);
428 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, One, GL_ONE);
429 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, SrcColor, GL_SRC_COLOR);
430 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusSrcColor, GL_ONE_MINUS_SRC_COLOR);
431 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, SrcAlpha, GL_SRC_ALPHA);
432 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusSrcAlpha, GL_ONE_MINUS_SRC_ALPHA);
433 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, DstAlpha, GL_DST_ALPHA);
434 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusDstAlpha, GL_ONE_MINUS_DST_ALPHA);
435 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, DstColor, GL_DST_COLOR);
436 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusDstColor, GL_ONE_MINUS_DST_COLOR);
437 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, SrcAlphaSaturate, GL_SRC_ALPHA_SATURATE);
438 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, ConstantColor, GL_CONSTANT_COLOR);
439 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusConstantColor, GL_ONE_MINUS_CONSTANT_COLOR);
440 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, ConstantAlpha, GL_CONSTANT_ALPHA);
441 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusConstantAlpha, GL_ONE_MINUS_CONSTANT_ALPHA);
442 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, Src1Alpha, GL_SRC1_ALPHA_EXT);
443 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, Src1Color, GL_SRC1_COLOR_EXT);
444 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusSrc1Color, GL_ONE_MINUS_SRC1_COLOR_EXT);
445 ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusSrc1Alpha, GL_ONE_MINUS_SRC1_ALPHA_EXT);
446
447 std::ostream &operator<<(std::ostream &os, BlendFactorType value);
448
449 enum class VertexAttribType
450 {
451 Byte = 0, // GLenum == 0x1400
452 UnsignedByte = 1, // GLenum == 0x1401
453 Short = 2, // GLenum == 0x1402
454 UnsignedShort = 3, // GLenum == 0x1403
455 Int = 4, // GLenum == 0x1404
456 UnsignedInt = 5, // GLenum == 0x1405
457 Float = 6, // GLenum == 0x1406
458 Unused1 = 7, // GLenum == 0x1407
459 Unused2 = 8, // GLenum == 0x1408
460 Unused3 = 9, // GLenum == 0x1409
461 Unused4 = 10, // GLenum == 0x140A
462 HalfFloat = 11, // GLenum == 0x140B
463 Fixed = 12, // GLenum == 0x140C
464 MaxBasicType = 12,
465 UnsignedInt2101010 = 13, // GLenum == 0x8368
466 HalfFloatOES = 14, // GLenum == 0x8D61
467 Int2101010 = 15, // GLenum == 0x8D9F
468 UnsignedInt1010102 = 16, // GLenum == 0x8DF6
469 Int1010102 = 17, // GLenum == 0x8DF7
470 InvalidEnum = 18,
471 EnumCount = 18,
472 };
473
474 template <>
475 constexpr VertexAttribType FromGLenum<VertexAttribType>(GLenum from)
476 {
477 GLenum packed = from - GL_BYTE;
478 if (packed <= static_cast<GLenum>(VertexAttribType::MaxBasicType))
479 return static_cast<VertexAttribType>(packed);
480 if (from == GL_UNSIGNED_INT_2_10_10_10_REV)
481 return VertexAttribType::UnsignedInt2101010;
482 if (from == GL_HALF_FLOAT_OES)
483 return VertexAttribType::HalfFloatOES;
484 if (from == GL_INT_2_10_10_10_REV)
485 return VertexAttribType::Int2101010;
486 if (from == GL_UNSIGNED_INT_10_10_10_2_OES)
487 return VertexAttribType::UnsignedInt1010102;
488 if (from == GL_INT_10_10_10_2_OES)
489 return VertexAttribType::Int1010102;
490 return VertexAttribType::InvalidEnum;
491 }
492
ToGLenum(VertexAttribType from)493 constexpr GLenum ToGLenum(VertexAttribType from)
494 {
495 // This could be optimized using a constexpr table.
496 if (from == VertexAttribType::Int2101010)
497 return GL_INT_2_10_10_10_REV;
498 if (from == VertexAttribType::HalfFloatOES)
499 return GL_HALF_FLOAT_OES;
500 if (from == VertexAttribType::UnsignedInt2101010)
501 return GL_UNSIGNED_INT_2_10_10_10_REV;
502 if (from == VertexAttribType::UnsignedInt1010102)
503 return GL_UNSIGNED_INT_10_10_10_2_OES;
504 if (from == VertexAttribType::Int1010102)
505 return GL_INT_10_10_10_2_OES;
506 return static_cast<GLenum>(from) + GL_BYTE;
507 }
508
509 ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Byte, GL_BYTE);
510 ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, UnsignedByte, GL_UNSIGNED_BYTE);
511 ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Short, GL_SHORT);
512 ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, UnsignedShort, GL_UNSIGNED_SHORT);
513 ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Int, GL_INT);
514 ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, UnsignedInt, GL_UNSIGNED_INT);
515 ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Float, GL_FLOAT);
516 ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, HalfFloat, GL_HALF_FLOAT);
517 ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Fixed, GL_FIXED);
518 ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Int2101010, GL_INT_2_10_10_10_REV);
519 ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, HalfFloatOES, GL_HALF_FLOAT_OES);
520 ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, UnsignedInt2101010, GL_UNSIGNED_INT_2_10_10_10_REV);
521 ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Int1010102, GL_INT_10_10_10_2_OES);
522 ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, UnsignedInt1010102, GL_UNSIGNED_INT_10_10_10_2_OES);
523
524 std::ostream &operator<<(std::ostream &os, VertexAttribType value);
525
526 // Typesafe object handles.
527
528 template <typename T>
529 struct ResourceTypeToID;
530
531 template <typename T>
532 struct IsResourceIDType;
533
534 // Clang Format doesn't like the following X macro.
535 // clang-format off
536 #define ANGLE_ID_TYPES_OP(X) \
537 X(Buffer) \
538 X(FenceNV) \
539 X(Framebuffer) \
540 X(MemoryObject) \
541 X(Path) \
542 X(ProgramPipeline) \
543 X(Query) \
544 X(Renderbuffer) \
545 X(Sampler) \
546 X(Semaphore) \
547 X(Texture) \
548 X(TransformFeedback) \
549 X(VertexArray)
550 // clang-format on
551
552 #define ANGLE_DEFINE_ID_TYPE(Type) \
553 class Type; \
554 struct Type##ID \
555 { \
556 GLuint value; \
557 }; \
558 template <> \
559 struct ResourceTypeToID<Type> \
560 { \
561 using IDType = Type##ID; \
562 }; \
563 template <> \
564 struct IsResourceIDType<Type##ID> \
565 { \
566 static constexpr bool value = true; \
567 };
568
569 ANGLE_ID_TYPES_OP(ANGLE_DEFINE_ID_TYPE)
570
571 #undef ANGLE_DEFINE_ID_TYPE
572 #undef ANGLE_ID_TYPES_OP
573
574 // Shaders and programs are a bit special as they share IDs.
575 struct ShaderProgramID
576 {
577 GLuint value;
578 };
579
580 template <>
581 struct IsResourceIDType<ShaderProgramID>
582 {
583 constexpr static bool value = true;
584 };
585
586 class Shader;
587 template <>
588 struct ResourceTypeToID<Shader>
589 {
590 using IDType = ShaderProgramID;
591 };
592
593 class Program;
594 template <>
595 struct ResourceTypeToID<Program>
596 {
597 using IDType = ShaderProgramID;
598 };
599
600 template <typename T>
601 struct ResourceTypeToID
602 {
603 using IDType = void;
604 };
605
606 template <typename T>
607 struct IsResourceIDType
608 {
609 static constexpr bool value = false;
610 };
611
612 template <typename T>
613 bool ValueEquals(T lhs, T rhs)
614 {
615 return lhs.value == rhs.value;
616 }
617
618 // Util funcs for resourceIDs
619 template <typename T>
620 typename std::enable_if<IsResourceIDType<T>::value, bool>::type operator==(const T &lhs,
621 const T &rhs)
622 {
623 return lhs.value == rhs.value;
624 }
625
626 template <typename T>
627 typename std::enable_if<IsResourceIDType<T>::value, bool>::type operator!=(const T &lhs,
628 const T &rhs)
629 {
630 return lhs.value != rhs.value;
631 }
632
633 template <typename T>
634 typename std::enable_if<IsResourceIDType<T>::value, bool>::type operator<(const T &lhs,
635 const T &rhs)
636 {
637 return lhs.value < rhs.value;
638 }
639
640 // Used to unbox typed values.
641 template <typename ResourceIDType>
642 GLuint GetIDValue(ResourceIDType id);
643
644 template <>
645 inline GLuint GetIDValue(GLuint id)
646 {
647 return id;
648 }
649
650 template <typename ResourceIDType>
651 inline GLuint GetIDValue(ResourceIDType id)
652 {
653 return id.value;
654 }
655
656 // First case: handling packed enums.
657 template <typename EnumT, typename FromT>
658 typename std::enable_if<std::is_enum<EnumT>::value, EnumT>::type FromGL(FromT from)
659 {
660 return FromGLenum<EnumT>(from);
661 }
662
663 // Second case: handling non-pointer resource ids.
664 template <typename EnumT, typename FromT>
665 typename std::enable_if<!std::is_pointer<FromT>::value && !std::is_enum<EnumT>::value, EnumT>::type
666 FromGL(FromT from)
667 {
668 return {from};
669 }
670
671 // Third case: handling pointer resource ids.
672 template <typename EnumT, typename FromT>
673 typename std::enable_if<std::is_pointer<FromT>::value && !std::is_enum<EnumT>::value, EnumT>::type
674 FromGL(FromT from)
675 {
676 return reinterpret_cast<EnumT>(from);
677 }
678
679 struct UniformLocation
680 {
681 int value;
682 };
683 } // namespace gl
684
685 namespace egl
686 {
687 MessageType ErrorCodeToMessageType(EGLint errorCode);
688 } // namespace egl
689
690 namespace egl_gl
691 {
692 gl::TextureTarget EGLCubeMapTargetToCubeMapTarget(EGLenum eglTarget);
693 gl::TextureTarget EGLImageTargetToTextureTarget(EGLenum eglTarget);
694 gl::TextureType EGLTextureTargetToTextureType(EGLenum eglTarget);
695 } // namespace egl_gl
696
697 #endif // COMMON_PACKEDGLENUMS_H_
698