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