blob: 35e50449a7662c3a1bcd41b20bf7b8ee72d7fedc [file] [log] [blame]
//
// Copyright 2012 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.
//
// angletypes.h : Defines a variety of structures and enum types that are used throughout libGLESv2
#ifndef LIBANGLE_ANGLETYPES_H_
#define LIBANGLE_ANGLETYPES_H_
#include "common/Color.h"
#include "common/FixedVector.h"
#include "common/PackedEnums.h"
#include "common/bitset_utils.h"
#include "common/vector_utils.h"
#include "libANGLE/Constants.h"
#include "libANGLE/Error.h"
#include "libANGLE/RefCountObject.h"
#include "nb/cpp14oncpp11.h"
#include <inttypes.h>
#include <stdint.h>
#include <bitset>
#include <map>
#include <unordered_map>
namespace gl
{
class Buffer;
class Texture;
struct Rectangle
{
Rectangle() : x(0), y(0), width(0), height(0) {}
constexpr Rectangle(int x_in, int y_in, int width_in, int height_in)
: x(x_in), y(y_in), width(width_in), height(height_in)
{}
int x0() const { return x; }
int y0() const { return y; }
int x1() const { return x + width; }
int y1() const { return y + height; }
bool isReversedX() const { return width < 0; }
bool isReversedY() const { return height < 0; }
// Returns a rectangle with the same area but flipped in X, Y, neither or both.
Rectangle flip(bool flipX, bool flipY) const;
// Returns a rectangle with the same area but with height and width guaranteed to be positive.
Rectangle removeReversal() const;
bool encloses(const gl::Rectangle &inside) const;
int x;
int y;
int width;
int height;
};
bool operator==(const Rectangle &a, const Rectangle &b);
bool operator!=(const Rectangle &a, const Rectangle &b);
bool ClipRectangle(const Rectangle &source, const Rectangle &clip, Rectangle *intersection);
struct Offset
{
constexpr Offset() : x(0), y(0), z(0) {}
constexpr Offset(int x_in, int y_in, int z_in) : x(x_in), y(y_in), z(z_in) {}
int x;
int y;
int z;
};
constexpr Offset kOffsetZero(0, 0, 0);
bool operator==(const Offset &a, const Offset &b);
bool operator!=(const Offset &a, const Offset &b);
struct Extents
{
Extents() : width(0), height(0), depth(0) {}
Extents(int width_, int height_, int depth_) : width(width_), height(height_), depth(depth_) {}
Extents(const Extents &other) = default;
Extents &operator=(const Extents &other) = default;
bool empty() const { return (width * height * depth) == 0; }
int width;
int height;
int depth;
};
bool operator==(const Extents &lhs, const Extents &rhs);
bool operator!=(const Extents &lhs, const Extents &rhs);
struct Box
{
Box() : x(0), y(0), z(0), width(0), height(0), depth(0) {}
Box(int x_in, int y_in, int z_in, int width_in, int height_in, int depth_in)
: x(x_in), y(y_in), z(z_in), width(width_in), height(height_in), depth(depth_in)
{}
Box(const Offset &offset, const Extents &size)
: x(offset.x),
y(offset.y),
z(offset.z),
width(size.width),
height(size.height),
depth(size.depth)
{}
bool operator==(const Box &other) const;
bool operator!=(const Box &other) const;
Rectangle toRect() const;
int x;
int y;
int z;
int width;
int height;
int depth;
};
struct RasterizerState final
{
// This will zero-initialize the struct, including padding.
RasterizerState();
bool cullFace;
CullFaceMode cullMode;
GLenum frontFace;
bool polygonOffsetFill;
GLfloat polygonOffsetFactor;
GLfloat polygonOffsetUnits;
bool pointDrawMode;
bool multiSample;
bool rasterizerDiscard;
};
bool operator==(const RasterizerState &a, const RasterizerState &b);
bool operator!=(const RasterizerState &a, const RasterizerState &b);
struct BlendState final
{
// This will zero-initialize the struct, including padding.
BlendState();
BlendState(const BlendState &other);
bool allChannelsMasked() const;
bool blend;
GLenum sourceBlendRGB;
GLenum destBlendRGB;
GLenum sourceBlendAlpha;
GLenum destBlendAlpha;
GLenum blendEquationRGB;
GLenum blendEquationAlpha;
bool colorMaskRed;
bool colorMaskGreen;
bool colorMaskBlue;
bool colorMaskAlpha;
bool sampleAlphaToCoverage;
bool dither;
};
bool operator==(const BlendState &a, const BlendState &b);
bool operator!=(const BlendState &a, const BlendState &b);
struct DepthStencilState final
{
// This will zero-initialize the struct, including padding.
DepthStencilState();
DepthStencilState(const DepthStencilState &other);
bool depthTest;
GLenum depthFunc;
bool depthMask;
bool stencilTest;
GLenum stencilFunc;
GLuint stencilMask;
GLenum stencilFail;
GLenum stencilPassDepthFail;
GLenum stencilPassDepthPass;
GLuint stencilWritemask;
GLenum stencilBackFunc;
GLuint stencilBackMask;
GLenum stencilBackFail;
GLenum stencilBackPassDepthFail;
GLenum stencilBackPassDepthPass;
GLuint stencilBackWritemask;
};
bool operator==(const DepthStencilState &a, const DepthStencilState &b);
bool operator!=(const DepthStencilState &a, const DepthStencilState &b);
// Packs a sampler state for completeness checks:
// * minFilter: 5 values (3 bits)
// * magFilter: 2 values (1 bit)
// * wrapS: 3 values (2 bits)
// * wrapT: 3 values (2 bits)
// * compareMode: 1 bit (for == GL_NONE).
// This makes a total of 9 bits. We can pack this easily into 32 bits:
// * minFilter: 8 bits
// * magFilter: 8 bits
// * wrapS: 8 bits
// * wrapT: 4 bits
// * compareMode: 4 bits
struct PackedSamplerCompleteness
{
uint8_t minFilter;
uint8_t magFilter;
uint8_t wrapS;
uint8_t wrapTCompareMode;
};
static_assert(sizeof(PackedSamplerCompleteness) == sizeof(uint32_t), "Unexpected size");
// State from Table 6.10 (state per sampler object)
class SamplerState final
{
public:
// This will zero-initialize the struct, including padding.
SamplerState();
SamplerState(const SamplerState &other);
static SamplerState CreateDefaultForTarget(TextureType type);
GLenum getMinFilter() const { return mMinFilter; }
void setMinFilter(GLenum minFilter);
GLenum getMagFilter() const { return mMagFilter; }
void setMagFilter(GLenum magFilter);
GLenum getWrapS() const { return mWrapS; }
void setWrapS(GLenum wrapS);
GLenum getWrapT() const { return mWrapT; }
void setWrapT(GLenum wrapT);
GLenum getWrapR() const { return mWrapR; }
void setWrapR(GLenum wrapR);
float getMaxAnisotropy() const { return mMaxAnisotropy; }
void setMaxAnisotropy(float maxAnisotropy);
GLfloat getMinLod() const { return mMinLod; }
void setMinLod(GLfloat minLod);
GLfloat getMaxLod() const { return mMaxLod; }
void setMaxLod(GLfloat maxLod);
GLenum getCompareMode() const { return mCompareMode; }
void setCompareMode(GLenum compareMode);
GLenum getCompareFunc() const { return mCompareFunc; }
void setCompareFunc(GLenum compareFunc);
GLenum getSRGBDecode() const { return mSRGBDecode; }
void setSRGBDecode(GLenum sRGBDecode);
void setBorderColor(const ColorGeneric &color);
const ColorGeneric &getBorderColor() const { return mBorderColor; }
bool sameCompleteness(const SamplerState &samplerState) const
{
return mCompleteness.packed == samplerState.mCompleteness.packed;
}
private:
void updateWrapTCompareMode();
GLenum mMinFilter;
GLenum mMagFilter;
GLenum mWrapS;
GLenum mWrapT;
GLenum mWrapR;
// From EXT_texture_filter_anisotropic
float mMaxAnisotropy;
GLfloat mMinLod;
GLfloat mMaxLod;
GLenum mCompareMode;
GLenum mCompareFunc;
GLenum mSRGBDecode;
ColorGeneric mBorderColor;
union Completeness
{
uint32_t packed;
PackedSamplerCompleteness typed;
};
Completeness mCompleteness;
};
bool operator==(const SamplerState &a, const SamplerState &b);
bool operator!=(const SamplerState &a, const SamplerState &b);
struct DrawArraysIndirectCommand
{
GLuint count;
GLuint instanceCount;
GLuint first;
GLuint baseInstance;
};
static_assert(sizeof(DrawArraysIndirectCommand) == 16,
"Unexpected size of DrawArraysIndirectCommand");
struct DrawElementsIndirectCommand
{
GLuint count;
GLuint primCount;
GLuint firstIndex;
GLint baseVertex;
GLuint baseInstance;
};
static_assert(sizeof(DrawElementsIndirectCommand) == 20,
"Unexpected size of DrawElementsIndirectCommand");
struct ImageUnit
{
ImageUnit();
ImageUnit(const ImageUnit &other);
~ImageUnit();
BindingPointer<Texture> texture;
GLint level;
GLboolean layered;
GLint layer;
GLenum access;
GLenum format;
};
using ImageUnitTextureTypeMap = std::map<unsigned int, gl::TextureType>;
struct PixelStoreStateBase
{
GLint alignment = 4;
GLint rowLength = 0;
GLint skipRows = 0;
GLint skipPixels = 0;
GLint imageHeight = 0;
GLint skipImages = 0;
};
struct PixelUnpackState : PixelStoreStateBase
{};
struct PixelPackState : PixelStoreStateBase
{
bool reverseRowOrder = false;
};
// Used in Program and VertexArray.
using AttributesMask = angle::BitSet<MAX_VERTEX_ATTRIBS>;
// Used in Program
using UniformBlockBindingMask = angle::BitSet<IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS>;
// Used in Framebuffer / Program
using DrawBufferMask = angle::BitSet<IMPLEMENTATION_MAX_DRAW_BUFFERS>;
// Used in StateCache
using StorageBuffersMask = angle::BitSet<IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS>;
template <typename T>
using TexLevelArray = std::array<T, IMPLEMENTATION_MAX_TEXTURE_LEVELS>;
enum class ComponentType
{
Float = 0,
Int = 1,
UnsignedInt = 2,
NoType = 3,
EnumCount = 4,
InvalidEnum = 4,
};
CONSTEXPR_OR_INLINE ComponentType GLenumToComponentType(GLenum componentType)
{
switch (componentType)
{
case GL_FLOAT:
return ComponentType::Float;
case GL_INT:
return ComponentType::Int;
case GL_UNSIGNED_INT:
return ComponentType::UnsignedInt;
case GL_NONE:
return ComponentType::NoType;
default:
return ComponentType::InvalidEnum;
}
}
extern CONSTEXPR angle::PackedEnumMap<ComponentType, uint32_t> kComponentMasks;
constexpr size_t kMaxComponentTypeMaskIndex = 16;
using ComponentTypeMask = angle::BitSet<kMaxComponentTypeMaskIndex * 2>;
ANGLE_INLINE void SetComponentTypeMask(ComponentType type, size_t index, ComponentTypeMask *mask)
{
ASSERT(index <= kMaxComponentTypeMaskIndex);
*mask &= ~(0x10001 << index);
*mask |= kComponentMasks[type] << index;
}
ANGLE_INLINE ComponentType GetComponentTypeMask(const ComponentTypeMask &mask, size_t index)
{
ASSERT(index <= kMaxComponentTypeMaskIndex);
uint32_t mask_bits = static_cast<uint32_t>((mask.to_ulong() >> index) & 0x10001);
switch (mask_bits)
{
case 0x10001:
return ComponentType::Float;
case 0x00001:
return ComponentType::Int;
case 0x10000:
return ComponentType::UnsignedInt;
default:
return ComponentType::InvalidEnum;
}
}
bool ValidateComponentTypeMasks(unsigned long outputTypes,
unsigned long inputTypes,
unsigned long outputMask,
unsigned long inputMask);
using ContextID = uintptr_t;
constexpr size_t kCubeFaceCount = 6;
template <typename T>
using TextureTypeMap = angle::PackedEnumMap<TextureType, T>;
using TextureMap = TextureTypeMap<BindingPointer<Texture>>;
// ShaderVector can contain one item per shader. It differs from ShaderMap in that the values are
// not indexed by ShaderType.
template <typename T>
using ShaderVector = angle::FixedVector<T, static_cast<size_t>(ShaderType::EnumCount)>;
template <typename T>
using AttachmentArray = std::array<T, IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS>;
template <typename T>
using DrawBuffersArray = std::array<T, IMPLEMENTATION_MAX_DRAW_BUFFERS>;
template <typename T>
using DrawBuffersVector = angle::FixedVector<T, IMPLEMENTATION_MAX_DRAW_BUFFERS>;
template <typename T>
using AttribArray = std::array<T, MAX_VERTEX_ATTRIBS>;
using ActiveTextureMask = angle::BitSet<IMPLEMENTATION_MAX_ACTIVE_TEXTURES>;
template <typename T>
using ActiveTextureArray = std::array<T, IMPLEMENTATION_MAX_ACTIVE_TEXTURES>;
using ActiveTexturePointerArray = ActiveTextureArray<Texture *>;
using ActiveTextureTypeArray = ActiveTextureArray<TextureType>;
template <typename T>
using UniformBuffersArray = std::array<T, IMPLEMENTATION_MAX_UNIFORM_BUFFER_BINDINGS>;
template <typename T>
using StorageBuffersArray = std::array<T, IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS>;
template <typename T>
using AtomicCounterBuffersArray = std::array<T, IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS>;
using AtomicCounterBufferMask = angle::BitSet<IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS>;
template <typename T>
using ImagesArray = std::array<T, IMPLEMENTATION_MAX_IMAGE_UNITS>;
using ImageUnitMask = angle::BitSet<IMPLEMENTATION_MAX_IMAGE_UNITS>;
using SupportedSampleSet = std::set<GLuint>;
template <typename T>
using TransformFeedbackBuffersArray =
std::array<T, gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS>;
constexpr size_t kBarrierVectorDefaultSize = 16;
template <typename T>
using BarrierVector = angle::FastVector<T, kBarrierVectorDefaultSize>;
using BufferBarrierVector = BarrierVector<Buffer *>;
struct TextureAndLayout
{
Texture *texture;
GLenum layout;
};
using TextureBarrierVector = BarrierVector<TextureAndLayout>;
// OffsetBindingPointer.getSize() returns the size specified by the user, which may be larger than
// the size of the bound buffer. This function reduces the returned size to fit the bound buffer if
// necessary. Returns 0 if no buffer is bound or if integer overflow occurs.
GLsizeiptr GetBoundBufferAvailableSize(const OffsetBindingPointer<Buffer> &binding);
} // namespace gl
namespace rx
{
// A macro that determines whether an object has a given runtime type.
#if defined(__clang__)
# if __has_feature(cxx_rtti)
# define ANGLE_HAS_DYNAMIC_CAST 1
# endif
#elif !defined(NDEBUG) && (!defined(_MSC_VER) || defined(_CPPRTTI)) && \
(!defined(__GNUC__) || __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 3) || \
defined(__GXX_RTTI))
# define ANGLE_HAS_DYNAMIC_CAST 1
#endif
#ifdef ANGLE_HAS_DYNAMIC_CAST
# define ANGLE_HAS_DYNAMIC_TYPE(type, obj) (dynamic_cast<type>(obj) != nullptr)
# undef ANGLE_HAS_DYNAMIC_CAST
#else
# define ANGLE_HAS_DYNAMIC_TYPE(type, obj) (obj != nullptr)
#endif
// Downcast a base implementation object (EG TextureImpl to TextureD3D)
template <typename DestT, typename SrcT>
inline DestT *GetAs(SrcT *src)
{
ASSERT(ANGLE_HAS_DYNAMIC_TYPE(DestT *, src));
return static_cast<DestT *>(src);
}
template <typename DestT, typename SrcT>
inline const DestT *GetAs(const SrcT *src)
{
ASSERT(ANGLE_HAS_DYNAMIC_TYPE(const DestT *, src));
return static_cast<const DestT *>(src);
}
#undef ANGLE_HAS_DYNAMIC_TYPE
// Downcast a GL object to an Impl (EG gl::Texture to rx::TextureD3D)
template <typename DestT, typename SrcT>
inline DestT *GetImplAs(SrcT *src)
{
return GetAs<DestT>(src->getImplementation());
}
template <typename DestT, typename SrcT>
inline DestT *SafeGetImplAs(SrcT *src)
{
return src != nullptr ? GetAs<DestT>(src->getImplementation()) : nullptr;
}
} // namespace rx
#include "angletypes.inc"
namespace angle
{
// Zero-based for better array indexing
enum FramebufferBinding
{
FramebufferBindingRead = 0,
FramebufferBindingDraw,
FramebufferBindingSingletonMax,
FramebufferBindingBoth = FramebufferBindingSingletonMax,
FramebufferBindingMax,
FramebufferBindingUnknown = FramebufferBindingMax,
};
inline FramebufferBinding EnumToFramebufferBinding(GLenum enumValue)
{
switch (enumValue)
{
case GL_READ_FRAMEBUFFER:
return FramebufferBindingRead;
case GL_DRAW_FRAMEBUFFER:
return FramebufferBindingDraw;
case GL_FRAMEBUFFER:
return FramebufferBindingBoth;
default:
UNREACHABLE();
return FramebufferBindingUnknown;
}
}
inline GLenum FramebufferBindingToEnum(FramebufferBinding binding)
{
switch (binding)
{
case FramebufferBindingRead:
return GL_READ_FRAMEBUFFER;
case FramebufferBindingDraw:
return GL_DRAW_FRAMEBUFFER;
case FramebufferBindingBoth:
return GL_FRAMEBUFFER;
default:
UNREACHABLE();
return GL_NONE;
}
}
template <typename ObjT, typename ContextT>
class DestroyThenDelete
{
public:
DestroyThenDelete(const ContextT *context) : mContext(context) {}
void operator()(ObjT *obj)
{
(void)(obj->onDestroy(mContext));
delete obj;
}
private:
const ContextT *mContext;
};
// Helper class for wrapping an onDestroy function.
template <typename ObjT, typename DeleterT>
class UniqueObjectPointerBase : angle::NonCopyable
{
public:
template <typename ContextT>
UniqueObjectPointerBase(const ContextT *context) : mObject(nullptr), mDeleter(context)
{}
template <typename ContextT>
UniqueObjectPointerBase(ObjT *obj, const ContextT *context) : mObject(obj), mDeleter(context)
{}
~UniqueObjectPointerBase()
{
if (mObject)
{
mDeleter(mObject);
}
}
ObjT *operator->() const { return mObject; }
ObjT *release()
{
auto obj = mObject;
mObject = nullptr;
return obj;
}
ObjT *get() const { return mObject; }
void reset(ObjT *obj)
{
if (mObject)
{
mDeleter(mObject);
}
mObject = obj;
}
private:
ObjT *mObject;
DeleterT mDeleter;
};
template <typename ObjT, typename ContextT>
using UniqueObjectPointer = UniqueObjectPointerBase<ObjT, DestroyThenDelete<ObjT, ContextT>>;
} // namespace angle
namespace gl
{
class State;
} // namespace gl
#endif // LIBANGLE_ANGLETYPES_H_