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 23namespace angle 24{ 25 26// Return the number of elements of a packed enum, including the InvalidEnum element. 27template <typename E> 28constexpr 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 40template <typename E> 41class 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 61template <typename E, size_t MaxSize = EnumSize<E>()> 62struct 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. 70template <typename E, typename T, size_t MaxSize = EnumSize<E>()> 71class 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#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 113 void fill(const T &u) { mPrivateData.fill(u); } 114 void swap(PackedEnumMap<E, T, MaxSize> &a) noexcept { mPrivateData.swap(a.mPrivateData); } 115 116 // iterators: 117 iterator begin() noexcept { return mPrivateData.begin(); } 118 const_iterator begin() const noexcept { return mPrivateData.begin(); } 119 iterator end() noexcept { return mPrivateData.end(); } 120 const_iterator end() const noexcept { return mPrivateData.end(); } 121 122 reverse_iterator rbegin() noexcept { return mPrivateData.rbegin(); } 123 const_reverse_iterator rbegin() const noexcept { return mPrivateData.rbegin(); } 124 reverse_iterator rend() noexcept { return mPrivateData.rend(); } 125 const_reverse_iterator rend() const noexcept { return mPrivateData.rend(); } 126 127 // capacity: 128 constexpr size_type size() const noexcept { return mPrivateData.size(); } 129 constexpr size_type max_size() const noexcept { return mPrivateData.max_size(); } 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 145 const_reference at(E n) const { return mPrivateData.at(static_cast<UnderlyingType>(n)); } 146 reference at(E n) { return mPrivateData.at(static_cast<UnderlyingType>(n)); } 147 148 reference front() { return mPrivateData.front(); } 149 const_reference front() const { return mPrivateData.front(); } 150 reference back() { return mPrivateData.back(); } 151 const_reference back() const { return mPrivateData.back(); } 152 153 T *data() noexcept { return mPrivateData.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. 175template <typename E, typename DataT = uint32_t> 176using PackedEnumBitSet = BitSetT<EnumSize<E>(), DataT, E>; 177 178} // namespace angle 179 180namespace gl 181{ 182 183TextureType TextureTargetToType(TextureTarget target); 184TextureTarget NonCubeTextureTypeToTarget(TextureType type); 185 186TextureTarget CubeFaceIndexToTextureTarget(size_t face); 187size_t CubeMapTextureTargetToFaceIndex(TextureTarget target); 188bool IsCubeMapFaceTarget(TextureTarget target); 189 190constexpr TextureTarget kCubeMapTextureTargetMin = TextureTarget::CubeMapPositiveX; 191constexpr TextureTarget kCubeMapTextureTargetMax = TextureTarget::CubeMapNegativeZ; 192constexpr TextureTarget kAfterCubeMapTextureTargetMax = 193 static_cast<TextureTarget>(static_cast<uint8_t>(kCubeMapTextureTargetMax) + 1); 194struct AllCubeFaceTextureTargets 195{ 196 angle::EnumIterator<TextureTarget> begin() const { return kCubeMapTextureTargetMin; } 197 angle::EnumIterator<TextureTarget> end() const { return kAfterCubeMapTextureTargetMax; } 198}; 199 200constexpr std::array<ShaderType, 2> kAllGLES2ShaderTypes = {ShaderType::Vertex, 201 ShaderType::Fragment}; 202 203constexpr ShaderType kShaderTypeMin = ShaderType::Vertex; 204constexpr ShaderType kShaderTypeMax = ShaderType::Compute; 205constexpr ShaderType kAfterShaderTypeMax = 206 static_cast<ShaderType>(static_cast<uint8_t>(kShaderTypeMax) + 1); 207struct AllShaderTypes 208{ 209 angle::EnumIterator<ShaderType> begin() const { return kShaderTypeMin; } 210 angle::EnumIterator<ShaderType> end() const { return kAfterShaderTypeMax; } 211}; 212 213constexpr size_t kGraphicsShaderCount = static_cast<size_t>(ShaderType::EnumCount) - 1u; 214// Arrange the shader types in the order of rendering pipeline 215constexpr std::array<ShaderType, kGraphicsShaderCount> kAllGraphicsShaderTypes = { 216 ShaderType::Vertex, ShaderType::TessControl, ShaderType::TessEvaluation, ShaderType::Geometry, 217 ShaderType::Fragment}; 218 219using ShaderBitSet = angle::PackedEnumBitSet<ShaderType, uint8_t>; 220static_assert(sizeof(ShaderBitSet) == sizeof(uint8_t), "Unexpected size"); 221 222template <typename T> 223using ShaderMap = angle::PackedEnumMap<ShaderType, T>; 224 225const char *ShaderTypeToString(ShaderType shaderType); 226 227TextureType SamplerTypeToTextureType(GLenum samplerType); 228TextureType ImageTypeToTextureType(GLenum imageType); 229 230bool IsMultisampled(gl::TextureType type); 231bool IsArrayTextureType(gl::TextureType type); 232 233bool IsStaticBufferUsage(BufferUsage useage); 234 235enum 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 257template <> 258constexpr 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 268constexpr GLenum ToGLenum(PrimitiveMode from) 269{ 270 return static_cast<GLenum>(from); 271} 272 273static_assert(ToGLenum(PrimitiveMode::Points) == GL_POINTS, "PrimitiveMode violation"); 274static_assert(ToGLenum(PrimitiveMode::Lines) == GL_LINES, "PrimitiveMode violation"); 275static_assert(ToGLenum(PrimitiveMode::LineLoop) == GL_LINE_LOOP, "PrimitiveMode violation"); 276static_assert(ToGLenum(PrimitiveMode::LineStrip) == GL_LINE_STRIP, "PrimitiveMode violation"); 277static_assert(ToGLenum(PrimitiveMode::Triangles) == GL_TRIANGLES, "PrimitiveMode violation"); 278static_assert(ToGLenum(PrimitiveMode::TriangleStrip) == GL_TRIANGLE_STRIP, 279 "PrimitiveMode violation"); 280static_assert(ToGLenum(PrimitiveMode::TriangleFan) == GL_TRIANGLE_FAN, "PrimitiveMode violation"); 281static_assert(ToGLenum(PrimitiveMode::LinesAdjacency) == GL_LINES_ADJACENCY, 282 "PrimitiveMode violation"); 283static_assert(ToGLenum(PrimitiveMode::LineStripAdjacency) == GL_LINE_STRIP_ADJACENCY, 284 "PrimitiveMode violation"); 285static_assert(ToGLenum(PrimitiveMode::TrianglesAdjacency) == GL_TRIANGLES_ADJACENCY, 286 "PrimitiveMode violation"); 287static_assert(ToGLenum(PrimitiveMode::TriangleStripAdjacency) == GL_TRIANGLE_STRIP_ADJACENCY, 288 "PrimitiveMode violation"); 289 290std::ostream &operator<<(std::ostream &os, PrimitiveMode value); 291 292enum class DrawElementsType : size_t 293{ 294 UnsignedByte = 0, 295 UnsignedShort = 1, 296 UnsignedInt = 2, 297 InvalidEnum = 3, 298 EnumCount = 3, 299}; 300 301template <> 302constexpr 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 321constexpr 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 330ANGLE_VALIDATE_PACKED_ENUM(DrawElementsType, UnsignedByte, GL_UNSIGNED_BYTE); 331ANGLE_VALIDATE_PACKED_ENUM(DrawElementsType, UnsignedShort, GL_UNSIGNED_SHORT); 332ANGLE_VALIDATE_PACKED_ENUM(DrawElementsType, UnsignedInt, GL_UNSIGNED_INT); 333 334std::ostream &operator<<(std::ostream &os, DrawElementsType value); 335 336enum 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 348template <> 349constexpr 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 358constexpr GLenum ToGLenum(BlendEquationType from) 359{ 360 return static_cast<GLenum>(from) + GL_FUNC_ADD; 361} 362 363ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Add, GL_FUNC_ADD); 364ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Min, GL_MIN); 365ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Max, GL_MAX); 366ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Subtract, GL_FUNC_SUBTRACT); 367ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, ReverseSubtract, GL_FUNC_REVERSE_SUBTRACT); 368 369std::ostream &operator<<(std::ostream &os, BlendEquationType value); 370 371enum 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 407template <> 408constexpr 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 423constexpr 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 437ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, Zero, GL_ZERO); 438ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, One, GL_ONE); 439ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, SrcColor, GL_SRC_COLOR); 440ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusSrcColor, GL_ONE_MINUS_SRC_COLOR); 441ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, SrcAlpha, GL_SRC_ALPHA); 442ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusSrcAlpha, GL_ONE_MINUS_SRC_ALPHA); 443ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, DstAlpha, GL_DST_ALPHA); 444ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusDstAlpha, GL_ONE_MINUS_DST_ALPHA); 445ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, DstColor, GL_DST_COLOR); 446ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusDstColor, GL_ONE_MINUS_DST_COLOR); 447ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, SrcAlphaSaturate, GL_SRC_ALPHA_SATURATE); 448ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, ConstantColor, GL_CONSTANT_COLOR); 449ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusConstantColor, GL_ONE_MINUS_CONSTANT_COLOR); 450ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, ConstantAlpha, GL_CONSTANT_ALPHA); 451ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusConstantAlpha, GL_ONE_MINUS_CONSTANT_ALPHA); 452ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, Src1Alpha, GL_SRC1_ALPHA_EXT); 453ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, Src1Color, GL_SRC1_COLOR_EXT); 454ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusSrc1Color, GL_ONE_MINUS_SRC1_COLOR_EXT); 455ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusSrc1Alpha, GL_ONE_MINUS_SRC1_ALPHA_EXT); 456 457std::ostream &operator<<(std::ostream &os, BlendFactorType value); 458 459enum 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 484template <> 485constexpr 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 503constexpr 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 519ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Byte, GL_BYTE); 520ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, UnsignedByte, GL_UNSIGNED_BYTE); 521ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Short, GL_SHORT); 522ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, UnsignedShort, GL_UNSIGNED_SHORT); 523ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Int, GL_INT); 524ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, UnsignedInt, GL_UNSIGNED_INT); 525ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Float, GL_FLOAT); 526ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, HalfFloat, GL_HALF_FLOAT); 527ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Fixed, GL_FIXED); 528ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Int2101010, GL_INT_2_10_10_10_REV); 529ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, HalfFloatOES, GL_HALF_FLOAT_OES); 530ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, UnsignedInt2101010, GL_UNSIGNED_INT_2_10_10_10_REV); 531ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Int1010102, GL_INT_10_10_10_2_OES); 532ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, UnsignedInt1010102, GL_UNSIGNED_INT_10_10_10_2_OES); 533 534std::ostream &operator<<(std::ostream &os, VertexAttribType value); 535 536enum 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 551template <> 552constexpr 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 575constexpr 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 602ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, Triangles, GL_TRIANGLES); 603ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, Quads, GL_QUADS); 604ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, Isolines, GL_ISOLINES); 605ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, EqualSpacing, GL_EQUAL); 606ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, FractionalEvenSpacing, GL_FRACTIONAL_EVEN); 607ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, FractionalOddSpacing, GL_FRACTIONAL_ODD); 608ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, Cw, GL_CW); 609ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, Ccw, GL_CCW); 610ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, PointMode, GL_TESS_GEN_POINT_MODE); 611 612std::ostream &operator<<(std::ostream &os, TessEvaluationType value); 613 614// Typesafe object handles. 615 616template <typename T> 617struct ResourceTypeToID; 618 619template <typename T> 620struct 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 657ANGLE_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. 663struct ShaderProgramID 664{ 665 GLuint value; 666}; 667 668template <> 669struct IsResourceIDType<ShaderProgramID> 670{ 671 constexpr static bool value = true; 672}; 673 674class Shader; 675template <> 676struct ResourceTypeToID<Shader> 677{ 678 using IDType = ShaderProgramID; 679}; 680 681class Program; 682template <> 683struct ResourceTypeToID<Program> 684{ 685 using IDType = ShaderProgramID; 686}; 687 688template <typename T> 689struct ResourceTypeToID 690{ 691 using IDType = void; 692}; 693 694template <typename T> 695struct IsResourceIDType 696{ 697 static constexpr bool value = false; 698}; 699 700template <typename T> 701bool ValueEquals(T lhs, T rhs) 702{ 703 return lhs.value == rhs.value; 704} 705 706// Util funcs for resourceIDs 707template <typename T> 708typename 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 714template <typename T> 715typename 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 721template <typename T> 722typename 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. 729template <typename ResourceIDType> 730GLuint GetIDValue(ResourceIDType id); 731 732template <> 733inline GLuint GetIDValue(GLuint id) 734{ 735 return id; 736} 737 738template <typename ResourceIDType> 739inline GLuint GetIDValue(ResourceIDType id) 740{ 741 return id.value; 742} 743 744// First case: handling packed enums. 745template <typename EnumT, typename FromT> 746typename 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. 752template <typename EnumT, typename FromT> 753typename std::enable_if<!std::is_pointer<FromT>::value && !std::is_enum<EnumT>::value, EnumT>::type 754PackParam(FromT from) 755{ 756 return {from}; 757} 758 759// Third case: handling pointer resource ids. 760template <typename EnumT, typename FromT> 761typename std::enable_if<std::is_pointer<FromT>::value && !std::is_enum<EnumT>::value, EnumT>::type 762PackParam(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 775struct UniformLocation 776{ 777 int value; 778}; 779 780struct UniformBlockIndex 781{ 782 uint32_t value; 783}; 784} // namespace gl 785 786namespace egl 787{ 788MessageType ErrorCodeToMessageType(EGLint errorCode); 789} // namespace egl 790 791namespace egl_gl 792{ 793gl::TextureTarget EGLCubeMapTargetToCubeMapTarget(EGLenum eglTarget); 794gl::TextureTarget EGLImageTargetToTextureTarget(EGLenum eglTarget); 795gl::TextureType EGLTextureTargetToTextureType(EGLenum eglTarget); 796} // namespace egl_gl 797 798#endif // COMMON_PACKEDGLENUMS_H_ 799