blob: 2a099324383bf13b3c7008b15e6be0e5d641f272 [file] [log] [blame]
// Copyright 2017 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// PackedGLEnums_autogen.h:
// Declares ANGLE-specific enums classes for GLEnum and functions operating
// on them.
#ifndef COMMON_PACKEDGLENUMS_H_
#define COMMON_PACKEDGLENUMS_H_
#include "common/PackedEGLEnums_autogen.h"
#include "common/PackedGLEnums_autogen.h"
#include <array>
#include <bitset>
#include <cstddef>
#include <EGL/egl.h>
#include "common/bitset_utils.h"
namespace angle
{
// Return the number of elements of a packed enum, including the InvalidEnum element.
template <typename E>
constexpr size_t EnumSize()
{
using UnderlyingType = typename std::underlying_type<E>::type;
return static_cast<UnderlyingType>(E::EnumCount);
}
// Implementation of AllEnums which allows iterating over all the possible values for a packed enums
// like so:
// for (auto value : AllEnums<MyPackedEnum>()) {
// // Do something with the enum.
// }
template <typename E>
class EnumIterator final
{
private:
using UnderlyingType = typename std::underlying_type<E>::type;
public:
EnumIterator(E value) : mValue(static_cast<UnderlyingType>(value)) {}
EnumIterator &operator++()
{
mValue++;
return *this;
}
bool operator==(const EnumIterator &other) const { return mValue == other.mValue; }
bool operator!=(const EnumIterator &other) const { return mValue != other.mValue; }
E operator*() const { return static_cast<E>(mValue); }
private:
UnderlyingType mValue;
};
template <typename E, size_t MaxSize = EnumSize<E>()>
struct AllEnums
{
EnumIterator<E> begin() const { return {static_cast<E>(0)}; }
EnumIterator<E> end() const { return {static_cast<E>(MaxSize)}; }
};
// PackedEnumMap<E, T> is like an std::array<T, E::EnumCount> but is indexed with enum values. It
// implements all of the std::array interface except with enum values instead of indices.
template <typename E, typename T, size_t MaxSize = EnumSize<E>()>
class PackedEnumMap
{
using UnderlyingType = typename std::underlying_type<E>::type;
using Storage = std::array<T, MaxSize>;
public:
using InitPair = std::pair<E, T>;
constexpr PackedEnumMap() = default;
constexpr PackedEnumMap(std::initializer_list<InitPair> init) : mPrivateData{}
{
// We use a for loop instead of range-for to work around a limitation in MSVC.
for (const InitPair *it = init.begin(); it != init.end(); ++it)
{
#if (__cplusplus < 201703L)
// This horrible const_cast pattern is necessary to work around a constexpr limitation.
// See https://stackoverflow.com/q/34199774/ . Note that it should be fixed with C++17.
const_cast<T &>(const_cast<const Storage &>(
mPrivateData)[static_cast<UnderlyingType>(it->first)]) = it->second;
#else
mPrivateData[static_cast<UnderlyingType>(it->first)] = it->second;
#endif
}
}
// types:
using value_type = T;
using pointer = T *;
using const_pointer = const T *;
using reference = T &;
using const_reference = const T &;
using size_type = size_t;
using difference_type = ptrdiff_t;
using iterator = typename Storage::iterator;
using const_iterator = typename Storage::const_iterator;
using reverse_iterator = std::reverse_iterator<iterator>;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
// No explicit construct/copy/destroy for aggregate type
void fill(const T &u) { mPrivateData.fill(u); }
void swap(PackedEnumMap<E, T, MaxSize> &a) noexcept { mPrivateData.swap(a.mPrivateData); }
// iterators:
iterator begin() noexcept { return mPrivateData.begin(); }
const_iterator begin() const noexcept { return mPrivateData.begin(); }
iterator end() noexcept { return mPrivateData.end(); }
const_iterator end() const noexcept { return mPrivateData.end(); }
reverse_iterator rbegin() noexcept { return mPrivateData.rbegin(); }
const_reverse_iterator rbegin() const noexcept { return mPrivateData.rbegin(); }
reverse_iterator rend() noexcept { return mPrivateData.rend(); }
const_reverse_iterator rend() const noexcept { return mPrivateData.rend(); }
// capacity:
constexpr size_type size() const noexcept { return mPrivateData.size(); }
constexpr size_type max_size() const noexcept { return mPrivateData.max_size(); }
constexpr bool empty() const noexcept { return mPrivateData.empty(); }
// element access:
reference operator[](E n)
{
ASSERT(static_cast<size_t>(n) < mPrivateData.size());
return mPrivateData[static_cast<UnderlyingType>(n)];
}
constexpr const_reference operator[](E n) const
{
ASSERT(static_cast<size_t>(n) < mPrivateData.size());
return mPrivateData[static_cast<UnderlyingType>(n)];
}
const_reference at(E n) const { return mPrivateData.at(static_cast<UnderlyingType>(n)); }
reference at(E n) { return mPrivateData.at(static_cast<UnderlyingType>(n)); }
reference front() { return mPrivateData.front(); }
const_reference front() const { return mPrivateData.front(); }
reference back() { return mPrivateData.back(); }
const_reference back() const { return mPrivateData.back(); }
T *data() noexcept { return mPrivateData.data(); }
const T *data() const noexcept { return mPrivateData.data(); }
bool operator==(const PackedEnumMap &rhs) const { return mPrivateData == rhs.mPrivateData; }
bool operator!=(const PackedEnumMap &rhs) const { return mPrivateData != rhs.mPrivateData; }
template <typename SubT = T>
typename std::enable_if<std::is_integral<SubT>::value>::type operator+=(
const PackedEnumMap<E, SubT, MaxSize> &rhs)
{
for (E e : AllEnums<E, MaxSize>())
{
at(e) += rhs[e];
}
}
private:
Storage mPrivateData;
};
// PackedEnumBitSetE> is like an std::bitset<E::EnumCount> but is indexed with enum values. It
// implements the std::bitset interface except with enum values instead of indices.
template <typename E, typename DataT = uint32_t>
using PackedEnumBitSet = BitSetT<EnumSize<E>(), DataT, E>;
} // namespace angle
namespace gl
{
TextureType TextureTargetToType(TextureTarget target);
TextureTarget NonCubeTextureTypeToTarget(TextureType type);
TextureTarget CubeFaceIndexToTextureTarget(size_t face);
size_t CubeMapTextureTargetToFaceIndex(TextureTarget target);
bool IsCubeMapFaceTarget(TextureTarget target);
constexpr TextureTarget kCubeMapTextureTargetMin = TextureTarget::CubeMapPositiveX;
constexpr TextureTarget kCubeMapTextureTargetMax = TextureTarget::CubeMapNegativeZ;
constexpr TextureTarget kAfterCubeMapTextureTargetMax =
static_cast<TextureTarget>(static_cast<uint8_t>(kCubeMapTextureTargetMax) + 1);
struct AllCubeFaceTextureTargets
{
angle::EnumIterator<TextureTarget> begin() const { return kCubeMapTextureTargetMin; }
angle::EnumIterator<TextureTarget> end() const { return kAfterCubeMapTextureTargetMax; }
};
constexpr std::array<ShaderType, 2> kAllGLES2ShaderTypes = {ShaderType::Vertex,
ShaderType::Fragment};
constexpr ShaderType kShaderTypeMin = ShaderType::Vertex;
constexpr ShaderType kShaderTypeMax = ShaderType::Compute;
constexpr ShaderType kAfterShaderTypeMax =
static_cast<ShaderType>(static_cast<uint8_t>(kShaderTypeMax) + 1);
struct AllShaderTypes
{
angle::EnumIterator<ShaderType> begin() const { return kShaderTypeMin; }
angle::EnumIterator<ShaderType> end() const { return kAfterShaderTypeMax; }
};
constexpr size_t kGraphicsShaderCount = static_cast<size_t>(ShaderType::EnumCount) - 1u;
// Arrange the shader types in the order of rendering pipeline
constexpr std::array<ShaderType, kGraphicsShaderCount> kAllGraphicsShaderTypes = {
ShaderType::Vertex, ShaderType::TessControl, ShaderType::TessEvaluation, ShaderType::Geometry,
ShaderType::Fragment};
using ShaderBitSet = angle::PackedEnumBitSet<ShaderType, uint8_t>;
static_assert(sizeof(ShaderBitSet) == sizeof(uint8_t), "Unexpected size");
template <typename T>
using ShaderMap = angle::PackedEnumMap<ShaderType, T>;
const char *ShaderTypeToString(ShaderType shaderType);
TextureType SamplerTypeToTextureType(GLenum samplerType);
TextureType ImageTypeToTextureType(GLenum imageType);
bool IsMultisampled(gl::TextureType type);
bool IsArrayTextureType(gl::TextureType type);
bool IsStaticBufferUsage(BufferUsage useage);
enum class PrimitiveMode : uint8_t
{
Points = 0x0,
Lines = 0x1,
LineLoop = 0x2,
LineStrip = 0x3,
Triangles = 0x4,
TriangleStrip = 0x5,
TriangleFan = 0x6,
Unused1 = 0x7,
Unused2 = 0x8,
Unused3 = 0x9,
LinesAdjacency = 0xA,
LineStripAdjacency = 0xB,
TrianglesAdjacency = 0xC,
TriangleStripAdjacency = 0xD,
Patches = 0xE,
InvalidEnum = 0xF,
EnumCount = 0xF,
};
template <>
constexpr PrimitiveMode FromGLenum<PrimitiveMode>(GLenum from)
{
if (from >= static_cast<GLenum>(PrimitiveMode::EnumCount))
{
return PrimitiveMode::InvalidEnum;
}
return static_cast<PrimitiveMode>(from);
}
constexpr GLenum ToGLenum(PrimitiveMode from)
{
return static_cast<GLenum>(from);
}
static_assert(ToGLenum(PrimitiveMode::Points) == GL_POINTS, "PrimitiveMode violation");
static_assert(ToGLenum(PrimitiveMode::Lines) == GL_LINES, "PrimitiveMode violation");
static_assert(ToGLenum(PrimitiveMode::LineLoop) == GL_LINE_LOOP, "PrimitiveMode violation");
static_assert(ToGLenum(PrimitiveMode::LineStrip) == GL_LINE_STRIP, "PrimitiveMode violation");
static_assert(ToGLenum(PrimitiveMode::Triangles) == GL_TRIANGLES, "PrimitiveMode violation");
static_assert(ToGLenum(PrimitiveMode::TriangleStrip) == GL_TRIANGLE_STRIP,
"PrimitiveMode violation");
static_assert(ToGLenum(PrimitiveMode::TriangleFan) == GL_TRIANGLE_FAN, "PrimitiveMode violation");
static_assert(ToGLenum(PrimitiveMode::LinesAdjacency) == GL_LINES_ADJACENCY,
"PrimitiveMode violation");
static_assert(ToGLenum(PrimitiveMode::LineStripAdjacency) == GL_LINE_STRIP_ADJACENCY,
"PrimitiveMode violation");
static_assert(ToGLenum(PrimitiveMode::TrianglesAdjacency) == GL_TRIANGLES_ADJACENCY,
"PrimitiveMode violation");
static_assert(ToGLenum(PrimitiveMode::TriangleStripAdjacency) == GL_TRIANGLE_STRIP_ADJACENCY,
"PrimitiveMode violation");
std::ostream &operator<<(std::ostream &os, PrimitiveMode value);
enum class DrawElementsType : size_t
{
UnsignedByte = 0,
UnsignedShort = 1,
UnsignedInt = 2,
InvalidEnum = 3,
EnumCount = 3,
};
template <>
constexpr DrawElementsType FromGLenum<DrawElementsType>(GLenum from)
{
GLenum scaled = (from - GL_UNSIGNED_BYTE);
// This code sequence generates a ROR instruction on x86/arm. We want to check if the lowest bit
// of scaled is set and if (scaled >> 1) is greater than a non-pot value. If we rotate the
// lowest bit to the hightest bit both conditions can be checked with a single test.
static_assert(sizeof(GLenum) == 4, "Update (scaled << 31) to sizeof(GLenum) * 8 - 1");
GLenum packed = (scaled >> 1) | (scaled << 31);
// operator ? with a simple assignment usually translates to a cmov instruction and thus avoids
// a branch.
packed = (packed >= static_cast<GLenum>(DrawElementsType::EnumCount))
? static_cast<GLenum>(DrawElementsType::InvalidEnum)
: packed;
return static_cast<DrawElementsType>(packed);
}
constexpr GLenum ToGLenum(DrawElementsType from)
{
return ((static_cast<GLenum>(from) << 1) + GL_UNSIGNED_BYTE);
}
#define ANGLE_VALIDATE_PACKED_ENUM(type, packed, glenum) \
static_assert(ToGLenum(type::packed) == glenum, #type " violation"); \
static_assert(FromGLenum<type>(glenum) == type::packed, #type " violation")
ANGLE_VALIDATE_PACKED_ENUM(DrawElementsType, UnsignedByte, GL_UNSIGNED_BYTE);
ANGLE_VALIDATE_PACKED_ENUM(DrawElementsType, UnsignedShort, GL_UNSIGNED_SHORT);
ANGLE_VALIDATE_PACKED_ENUM(DrawElementsType, UnsignedInt, GL_UNSIGNED_INT);
std::ostream &operator<<(std::ostream &os, DrawElementsType value);
enum class BlendEquationType
{
Add = 0, // GLenum == 0x8006
Min = 1, // GLenum == 0x8007
Max = 2, // GLenum == 0x8008
Unused = 3,
Subtract = 4, // GLenum == 0x800A
ReverseSubtract = 5, // GLenum == 0x800B
Multiply = 6, // GLenum == 0x9294
Screen = 7, // GLenum == 0x9295
Overlay = 8, // GLenum == 0x9296
Darken = 9, // GLenum == 0x9297
Lighten = 10, // GLenum == 0x9298
Colordodge = 11, // GLenum == 0x9299
Colorburn = 12, // GLenum == 0x929A
Hardlight = 13, // GLenum == 0x929B
Softlight = 14, // GLenum == 0x929C
Unused2 = 15,
Difference = 16, // GLenum == 0x929E
Unused3 = 17,
Exclusion = 18, // GLenum == 0x92A0
HslHue = 19, // GLenum == 0x92AD
HslSaturation = 20, // GLenum == 0x92AE
HslColor = 21, // GLenum == 0x92AF
HslLuminosity = 22, // GLenum == 0x92B0
InvalidEnum = 23,
EnumCount = InvalidEnum
};
using BlendEquationBitSet = angle::PackedEnumBitSet<gl::BlendEquationType>;
template <>
constexpr BlendEquationType FromGLenum<BlendEquationType>(GLenum from)
{
if (from <= GL_FUNC_REVERSE_SUBTRACT)
{
const GLenum scaled = (from - GL_FUNC_ADD);
return (scaled == static_cast<GLenum>(BlendEquationType::Unused))
? BlendEquationType::InvalidEnum
: static_cast<BlendEquationType>(scaled);
}
if (from <= GL_EXCLUSION_KHR)
{
const GLenum scaled =
(from - GL_MULTIPLY_KHR + static_cast<uint32_t>(BlendEquationType::Multiply));
return (scaled == static_cast<GLenum>(BlendEquationType::Unused2) ||
scaled == static_cast<GLenum>(BlendEquationType::Unused3))
? BlendEquationType::InvalidEnum
: static_cast<BlendEquationType>(scaled);
}
if (from <= GL_HSL_LUMINOSITY_KHR)
{
return static_cast<BlendEquationType>(from - GL_HSL_HUE_KHR +
static_cast<uint32_t>(BlendEquationType::HslHue));
}
return BlendEquationType::InvalidEnum;
}
constexpr GLenum ToGLenum(BlendEquationType from)
{
if (from <= BlendEquationType::ReverseSubtract)
{
return static_cast<GLenum>(from) + GL_FUNC_ADD;
}
if (from <= BlendEquationType::Exclusion)
{
return static_cast<GLenum>(from) - static_cast<GLenum>(BlendEquationType::Multiply) +
GL_MULTIPLY_KHR;
}
return static_cast<GLenum>(from) - static_cast<GLenum>(BlendEquationType::HslHue) +
GL_HSL_HUE_KHR;
}
ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Add, GL_FUNC_ADD);
ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Min, GL_MIN);
ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Max, GL_MAX);
ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Subtract, GL_FUNC_SUBTRACT);
ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, ReverseSubtract, GL_FUNC_REVERSE_SUBTRACT);
ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Multiply, GL_MULTIPLY_KHR);
ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Screen, GL_SCREEN_KHR);
ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Overlay, GL_OVERLAY_KHR);
ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Darken, GL_DARKEN_KHR);
ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Lighten, GL_LIGHTEN_KHR);
ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Colordodge, GL_COLORDODGE_KHR);
ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Colorburn, GL_COLORBURN_KHR);
ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Hardlight, GL_HARDLIGHT_KHR);
ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Softlight, GL_SOFTLIGHT_KHR);
ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Difference, GL_DIFFERENCE_KHR);
ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Exclusion, GL_EXCLUSION_KHR);
ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, HslHue, GL_HSL_HUE_KHR);
ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, HslSaturation, GL_HSL_SATURATION_KHR);
ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, HslColor, GL_HSL_COLOR_KHR);
ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, HslLuminosity, GL_HSL_LUMINOSITY_KHR);
std::ostream &operator<<(std::ostream &os, BlendEquationType value);
enum class BlendFactorType
{
Zero = 0, // GLenum == 0
One = 1, // GLenum == 1
MinSrcDstType = 2,
SrcColor = 2, // GLenum == 0x0300
OneMinusSrcColor = 3, // GLenum == 0x0301
SrcAlpha = 4, // GLenum == 0x0302
OneMinusSrcAlpha = 5, // GLenum == 0x0303
DstAlpha = 6, // GLenum == 0x0304
OneMinusDstAlpha = 7, // GLenum == 0x0305
DstColor = 8, // GLenum == 0x0306
OneMinusDstColor = 9, // GLenum == 0x0307
SrcAlphaSaturate = 10, // GLenum == 0x0308
MaxSrcDstType = 10,
MinConstantType = 11,
ConstantColor = 11, // GLenum == 0x8001
OneMinusConstantColor = 12, // GLenum == 0x8002
ConstantAlpha = 13, // GLenum == 0x8003
OneMinusConstantAlpha = 14, // GLenum == 0x8004
MaxConstantType = 14,
// GL_EXT_blend_func_extended
Src1Alpha = 15, // GLenum == 0x8589
Src1Color = 16, // GLenum == 0x88F9
OneMinusSrc1Color = 17, // GLenum == 0x88FA
OneMinusSrc1Alpha = 18, // GLenum == 0x88FB
InvalidEnum = 19,
EnumCount = 19
};
template <>
constexpr BlendFactorType FromGLenum<BlendFactorType>(GLenum from)
{
if (from <= 1)
return static_cast<BlendFactorType>(from);
if (from >= GL_SRC_COLOR && from <= GL_SRC_ALPHA_SATURATE)
return static_cast<BlendFactorType>(from - GL_SRC_COLOR + 2);
if (from >= GL_CONSTANT_COLOR && from <= GL_ONE_MINUS_CONSTANT_ALPHA)
return static_cast<BlendFactorType>(from - GL_CONSTANT_COLOR + 11);
if (from == GL_SRC1_ALPHA_EXT)
return BlendFactorType::Src1Alpha;
if (from >= GL_SRC1_COLOR_EXT && from <= GL_ONE_MINUS_SRC1_ALPHA_EXT)
return static_cast<BlendFactorType>(from - GL_SRC1_COLOR_EXT + 16);
return BlendFactorType::InvalidEnum;
}
constexpr GLenum ToGLenum(BlendFactorType from)
{
const GLenum value = static_cast<GLenum>(from);
if (value <= 1)
return value;
if (from >= BlendFactorType::MinSrcDstType && from <= BlendFactorType::MaxSrcDstType)
return value - 2 + GL_SRC_COLOR;
if (from >= BlendFactorType::MinConstantType && from <= BlendFactorType::MaxConstantType)
return value - 11 + GL_CONSTANT_COLOR;
if (from == BlendFactorType::Src1Alpha)
return GL_SRC1_ALPHA_EXT;
return value - 16 + GL_SRC1_COLOR_EXT;
}
ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, Zero, GL_ZERO);
ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, One, GL_ONE);
ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, SrcColor, GL_SRC_COLOR);
ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusSrcColor, GL_ONE_MINUS_SRC_COLOR);
ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, SrcAlpha, GL_SRC_ALPHA);
ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusSrcAlpha, GL_ONE_MINUS_SRC_ALPHA);
ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, DstAlpha, GL_DST_ALPHA);
ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusDstAlpha, GL_ONE_MINUS_DST_ALPHA);
ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, DstColor, GL_DST_COLOR);
ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusDstColor, GL_ONE_MINUS_DST_COLOR);
ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, SrcAlphaSaturate, GL_SRC_ALPHA_SATURATE);
ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, ConstantColor, GL_CONSTANT_COLOR);
ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusConstantColor, GL_ONE_MINUS_CONSTANT_COLOR);
ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, ConstantAlpha, GL_CONSTANT_ALPHA);
ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusConstantAlpha, GL_ONE_MINUS_CONSTANT_ALPHA);
ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, Src1Alpha, GL_SRC1_ALPHA_EXT);
ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, Src1Color, GL_SRC1_COLOR_EXT);
ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusSrc1Color, GL_ONE_MINUS_SRC1_COLOR_EXT);
ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusSrc1Alpha, GL_ONE_MINUS_SRC1_ALPHA_EXT);
std::ostream &operator<<(std::ostream &os, BlendFactorType value);
enum class VertexAttribType
{
Byte = 0, // GLenum == 0x1400
UnsignedByte = 1, // GLenum == 0x1401
Short = 2, // GLenum == 0x1402
UnsignedShort = 3, // GLenum == 0x1403
Int = 4, // GLenum == 0x1404
UnsignedInt = 5, // GLenum == 0x1405
Float = 6, // GLenum == 0x1406
Unused1 = 7, // GLenum == 0x1407
Unused2 = 8, // GLenum == 0x1408
Unused3 = 9, // GLenum == 0x1409
Unused4 = 10, // GLenum == 0x140A
HalfFloat = 11, // GLenum == 0x140B
Fixed = 12, // GLenum == 0x140C
MaxBasicType = 12,
UnsignedInt2101010 = 13, // GLenum == 0x8368
HalfFloatOES = 14, // GLenum == 0x8D61
Int2101010 = 15, // GLenum == 0x8D9F
UnsignedInt1010102 = 16, // GLenum == 0x8DF6
Int1010102 = 17, // GLenum == 0x8DF7
InvalidEnum = 18,
EnumCount = 18,
};
template <>
constexpr VertexAttribType FromGLenum<VertexAttribType>(GLenum from)
{
GLenum packed = from - GL_BYTE;
if (packed <= static_cast<GLenum>(VertexAttribType::MaxBasicType))
return static_cast<VertexAttribType>(packed);
if (from == GL_UNSIGNED_INT_2_10_10_10_REV)
return VertexAttribType::UnsignedInt2101010;
if (from == GL_HALF_FLOAT_OES)
return VertexAttribType::HalfFloatOES;
if (from == GL_INT_2_10_10_10_REV)
return VertexAttribType::Int2101010;
if (from == GL_UNSIGNED_INT_10_10_10_2_OES)
return VertexAttribType::UnsignedInt1010102;
if (from == GL_INT_10_10_10_2_OES)
return VertexAttribType::Int1010102;
return VertexAttribType::InvalidEnum;
}
constexpr GLenum ToGLenum(VertexAttribType from)
{
// This could be optimized using a constexpr table.
if (from == VertexAttribType::Int2101010)
return GL_INT_2_10_10_10_REV;
if (from == VertexAttribType::HalfFloatOES)
return GL_HALF_FLOAT_OES;
if (from == VertexAttribType::UnsignedInt2101010)
return GL_UNSIGNED_INT_2_10_10_10_REV;
if (from == VertexAttribType::UnsignedInt1010102)
return GL_UNSIGNED_INT_10_10_10_2_OES;
if (from == VertexAttribType::Int1010102)
return GL_INT_10_10_10_2_OES;
return static_cast<GLenum>(from) + GL_BYTE;
}
ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Byte, GL_BYTE);
ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, UnsignedByte, GL_UNSIGNED_BYTE);
ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Short, GL_SHORT);
ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, UnsignedShort, GL_UNSIGNED_SHORT);
ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Int, GL_INT);
ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, UnsignedInt, GL_UNSIGNED_INT);
ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Float, GL_FLOAT);
ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, HalfFloat, GL_HALF_FLOAT);
ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Fixed, GL_FIXED);
ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Int2101010, GL_INT_2_10_10_10_REV);
ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, HalfFloatOES, GL_HALF_FLOAT_OES);
ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, UnsignedInt2101010, GL_UNSIGNED_INT_2_10_10_10_REV);
ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Int1010102, GL_INT_10_10_10_2_OES);
ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, UnsignedInt1010102, GL_UNSIGNED_INT_10_10_10_2_OES);
std::ostream &operator<<(std::ostream &os, VertexAttribType value);
enum class TessEvaluationType
{
Triangles = 0,
Quads = 1,
Isolines = 2,
EqualSpacing = 3,
FractionalEvenSpacing = 4,
FractionalOddSpacing = 5,
Cw = 6,
Ccw = 7,
PointMode = 8,
InvalidEnum = 9,
EnumCount = 9
};
template <>
constexpr TessEvaluationType FromGLenum<TessEvaluationType>(GLenum from)
{
if (from == GL_TRIANGLES)
return TessEvaluationType::Triangles;
if (from == GL_QUADS)
return TessEvaluationType::Quads;
if (from == GL_ISOLINES)
return TessEvaluationType::Isolines;
if (from == GL_EQUAL)
return TessEvaluationType::EqualSpacing;
if (from == GL_FRACTIONAL_EVEN)
return TessEvaluationType::FractionalEvenSpacing;
if (from == GL_FRACTIONAL_ODD)
return TessEvaluationType::FractionalOddSpacing;
if (from == GL_CW)
return TessEvaluationType::Cw;
if (from == GL_CCW)
return TessEvaluationType::Ccw;
if (from == GL_TESS_GEN_POINT_MODE)
return TessEvaluationType::PointMode;
return TessEvaluationType::InvalidEnum;
}
constexpr GLenum ToGLenum(TessEvaluationType from)
{
switch (from)
{
case TessEvaluationType::Triangles:
return GL_TRIANGLES;
case TessEvaluationType::Quads:
return GL_QUADS;
case TessEvaluationType::Isolines:
return GL_ISOLINES;
case TessEvaluationType::EqualSpacing:
return GL_EQUAL;
case TessEvaluationType::FractionalEvenSpacing:
return GL_FRACTIONAL_EVEN;
case TessEvaluationType::FractionalOddSpacing:
return GL_FRACTIONAL_ODD;
case TessEvaluationType::Cw:
return GL_CW;
case TessEvaluationType::Ccw:
return GL_CCW;
case TessEvaluationType::PointMode:
return GL_TESS_GEN_POINT_MODE;
default:
return GL_INVALID_ENUM;
}
}
ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, Triangles, GL_TRIANGLES);
ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, Quads, GL_QUADS);
ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, Isolines, GL_ISOLINES);
ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, EqualSpacing, GL_EQUAL);
ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, FractionalEvenSpacing, GL_FRACTIONAL_EVEN);
ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, FractionalOddSpacing, GL_FRACTIONAL_ODD);
ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, Cw, GL_CW);
ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, Ccw, GL_CCW);
ANGLE_VALIDATE_PACKED_ENUM(TessEvaluationType, PointMode, GL_TESS_GEN_POINT_MODE);
std::ostream &operator<<(std::ostream &os, TessEvaluationType value);
// Typesafe object handles.
template <typename T>
struct ResourceTypeToID;
template <typename T>
struct IsResourceIDType;
// Clang Format doesn't like the following X macro.
// clang-format off
#define ANGLE_ID_TYPES_OP(X) \
X(Buffer) \
X(FenceNV) \
X(Framebuffer) \
X(MemoryObject) \
X(Path) \
X(ProgramPipeline) \
X(Query) \
X(Renderbuffer) \
X(Sampler) \
X(Semaphore) \
X(Texture) \
X(TransformFeedback) \
X(VertexArray)
// clang-format on
#define ANGLE_DEFINE_ID_TYPE(Type) \
class Type; \
struct Type##ID \
{ \
GLuint value; \
}; \
template <> \
struct ResourceTypeToID<Type> \
{ \
using IDType = Type##ID; \
}; \
template <> \
struct IsResourceIDType<Type##ID> \
{ \
static constexpr bool value = true; \
};
ANGLE_ID_TYPES_OP(ANGLE_DEFINE_ID_TYPE)
#undef ANGLE_DEFINE_ID_TYPE
#undef ANGLE_ID_TYPES_OP
// Shaders and programs are a bit special as they share IDs.
struct ShaderProgramID
{
GLuint value;
};
template <>
struct IsResourceIDType<ShaderProgramID>
{
constexpr static bool value = true;
};
class Shader;
template <>
struct ResourceTypeToID<Shader>
{
using IDType = ShaderProgramID;
};
class Program;
template <>
struct ResourceTypeToID<Program>
{
using IDType = ShaderProgramID;
};
template <typename T>
struct ResourceTypeToID
{
using IDType = void;
};
template <typename T>
struct IsResourceIDType
{
static constexpr bool value = false;
};
template <typename T>
bool ValueEquals(T lhs, T rhs)
{
return lhs.value == rhs.value;
}
// Util funcs for resourceIDs
template <typename T>
typename std::enable_if<IsResourceIDType<T>::value, bool>::type operator==(const T &lhs,
const T &rhs)
{
return lhs.value == rhs.value;
}
template <typename T>
typename std::enable_if<IsResourceIDType<T>::value, bool>::type operator!=(const T &lhs,
const T &rhs)
{
return lhs.value != rhs.value;
}
template <typename T>
typename std::enable_if<IsResourceIDType<T>::value, bool>::type operator<(const T &lhs,
const T &rhs)
{
return lhs.value < rhs.value;
}
// Used to unbox typed values.
template <typename ResourceIDType>
GLuint GetIDValue(ResourceIDType id);
template <>
inline GLuint GetIDValue(GLuint id)
{
return id;
}
template <typename ResourceIDType>
inline GLuint GetIDValue(ResourceIDType id)
{
return id.value;
}
// First case: handling packed enums.
template <typename EnumT, typename FromT>
typename std::enable_if<std::is_enum<EnumT>::value, EnumT>::type PackParam(FromT from)
{
return FromGLenum<EnumT>(from);
}
// Second case: handling non-pointer resource ids.
template <typename EnumT, typename FromT>
typename std::enable_if<!std::is_pointer<FromT>::value && !std::is_enum<EnumT>::value, EnumT>::type
PackParam(FromT from)
{
return {from};
}
// Third case: handling pointer resource ids.
template <typename EnumT, typename FromT>
typename std::enable_if<std::is_pointer<FromT>::value && !std::is_enum<EnumT>::value, EnumT>::type
PackParam(FromT from)
{
static_assert(sizeof(typename std::remove_pointer<EnumT>::type) ==
sizeof(typename std::remove_pointer<FromT>::type),
"Types have different sizes");
static_assert(
std::is_same<
decltype(std::remove_pointer<EnumT>::type::value),
typename std::remove_const<typename std::remove_pointer<FromT>::type>::type>::value,
"Data types are different");
return reinterpret_cast<EnumT>(from);
}
struct UniformLocation
{
int value;
};
struct UniformBlockIndex
{
uint32_t value;
};
} // namespace gl
namespace egl
{
MessageType ErrorCodeToMessageType(EGLint errorCode);
} // namespace egl
namespace egl_gl
{
gl::TextureTarget EGLCubeMapTargetToCubeMapTarget(EGLenum eglTarget);
gl::TextureTarget EGLImageTargetToTextureTarget(EGLenum eglTarget);
gl::TextureType EGLTextureTargetToTextureType(EGLenum eglTarget);
} // namespace egl_gl
#endif // COMMON_PACKEDGLENUMS_H_