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