summaryrefslogtreecommitdiffstats
path: root/gfx/angle/checkout/src/libANGLE/angletypes.h
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/angle/checkout/src/libANGLE/angletypes.h')
-rw-r--r--gfx/angle/checkout/src/libANGLE/angletypes.h1203
1 files changed, 1203 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/libANGLE/angletypes.h b/gfx/angle/checkout/src/libANGLE/angletypes.h
new file mode 100644
index 0000000000..6ac65a5cf3
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/angletypes.h
@@ -0,0 +1,1203 @@
+//
+// 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 <inttypes.h>
+#include <stdint.h>
+
+#include <bitset>
+#include <map>
+#include <memory>
+#include <unordered_map>
+
+namespace gl
+{
+class Buffer;
+class Texture;
+
+enum class Command
+{
+ // The Blit command carries the bitmask of which buffers are being blit. The command passed to
+ // the backends is:
+ //
+ // Blit + (Color?0x1) + (Depth?0x2) + (Stencil?0x4)
+ Blit,
+ BlitAll = Blit + 0x7,
+ Clear,
+ CopyImage,
+ Dispatch,
+ Draw,
+ GenerateMipmap,
+ Invalidate,
+ ReadPixels,
+ TexImage,
+ Other,
+};
+
+enum CommandBlitBuffer
+{
+ CommandBlitBufferColor = 0x1,
+ CommandBlitBufferDepth = 0x2,
+ CommandBlitBufferStencil = 0x4,
+};
+
+enum class InitState
+{
+ MayNeedInit,
+ Initialized,
+};
+
+template <typename T>
+struct RectangleImpl
+{
+ RectangleImpl() : x(T(0)), y(T(0)), width(T(0)), height(T(0)) {}
+ constexpr RectangleImpl(T x_in, T y_in, T width_in, T height_in)
+ : x(x_in), y(y_in), width(width_in), height(height_in)
+ {}
+ explicit constexpr RectangleImpl(const T corners[4])
+ : x(corners[0]),
+ y(corners[1]),
+ width(corners[2] - corners[0]),
+ height(corners[3] - corners[1])
+ {}
+ template <typename S>
+ explicit constexpr RectangleImpl(const RectangleImpl<S> rect)
+ : x(rect.x), y(rect.y), width(rect.width), height(rect.height)
+ {}
+
+ T x0() const { return x; }
+ T y0() const { return y; }
+ T x1() const { return x + width; }
+ T y1() const { return y + height; }
+
+ bool isReversedX() const { return width < T(0); }
+ bool isReversedY() const { return height < T(0); }
+
+ // Returns a rectangle with the same area but flipped in X, Y, neither or both.
+ RectangleImpl<T> flip(bool flipX, bool flipY) const
+ {
+ RectangleImpl flipped = *this;
+ if (flipX)
+ {
+ flipped.x = flipped.x + flipped.width;
+ flipped.width = -flipped.width;
+ }
+ if (flipY)
+ {
+ flipped.y = flipped.y + flipped.height;
+ flipped.height = -flipped.height;
+ }
+ return flipped;
+ }
+
+ // Returns a rectangle with the same area but with height and width guaranteed to be positive.
+ RectangleImpl<T> removeReversal() const { return flip(isReversedX(), isReversedY()); }
+
+ bool encloses(const RectangleImpl<T> &inside) const
+ {
+ return x0() <= inside.x0() && y0() <= inside.y0() && x1() >= inside.x1() &&
+ y1() >= inside.y1();
+ }
+
+ bool empty() const;
+
+ T x;
+ T y;
+ T width;
+ T height;
+};
+
+template <typename T>
+bool operator==(const RectangleImpl<T> &a, const RectangleImpl<T> &b);
+template <typename T>
+bool operator!=(const RectangleImpl<T> &a, const RectangleImpl<T> &b);
+
+using Rectangle = RectangleImpl<int>;
+
+enum class ClipSpaceOrigin
+{
+ LowerLeft = 0,
+ UpperLeft = 1
+};
+
+// Calculate the intersection of two rectangles. Returns false if the intersection is empty.
+[[nodiscard]] bool ClipRectangle(const Rectangle &source,
+ const Rectangle &clip,
+ Rectangle *intersection);
+// Calculate the smallest rectangle that covers both rectangles. This rectangle may cover areas
+// not covered by the two rectangles, for example in this situation:
+//
+// +--+ +----+
+// | ++-+ -> | |
+// +-++ | | |
+// +--+ +----+
+//
+void GetEnclosingRectangle(const Rectangle &rect1, const Rectangle &rect2, Rectangle *rectUnion);
+// Extend the source rectangle to cover parts (or all of) the second rectangle, in such a way that
+// no area is covered that isn't covered by both rectangles. For example:
+//
+// +--+ +--+
+// source --> | | | |
+// ++--+-+ -> | |
+// |+--+ | | |
+// +-----+ +--+
+//
+void ExtendRectangle(const Rectangle &source, const Rectangle &extend, Rectangle *extended);
+
+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)
+ {}
+ template <typename O, typename E>
+ Box(const O &offset, const E &size)
+ : x(offset.x),
+ y(offset.y),
+ z(offset.z),
+ width(size.width),
+ height(size.height),
+ depth(size.depth)
+ {}
+ bool valid() const;
+ bool operator==(const Box &other) const;
+ bool operator!=(const Box &other) const;
+ Rectangle toRect() const;
+
+ // Whether the Box has offset 0 and the same extents as argument.
+ bool coversSameExtent(const Extents &size) const;
+
+ bool contains(const Box &other) const;
+ size_t volume() const;
+ void extend(const Box &other);
+
+ int x;
+ int y;
+ int z;
+ int width;
+ int height;
+ int depth;
+};
+
+struct RasterizerState final
+{
+ // This will zero-initialize the struct, including padding.
+ RasterizerState();
+ RasterizerState(const RasterizerState &other);
+ RasterizerState &operator=(const RasterizerState &other);
+
+ bool cullFace;
+ CullFaceMode cullMode;
+ GLenum frontFace;
+
+ bool polygonOffsetFill;
+ GLfloat polygonOffsetFactor;
+ GLfloat polygonOffsetUnits;
+
+ // pointDrawMode/multiSample are only used in the D3D back-end right now.
+ bool pointDrawMode;
+ bool multiSample;
+
+ bool rasterizerDiscard;
+
+ bool dither;
+};
+
+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 blend;
+ GLenum sourceBlendRGB;
+ GLenum destBlendRGB;
+ GLenum sourceBlendAlpha;
+ GLenum destBlendAlpha;
+ GLenum blendEquationRGB;
+ GLenum blendEquationAlpha;
+
+ bool colorMaskRed;
+ bool colorMaskGreen;
+ bool colorMaskBlue;
+ bool colorMaskAlpha;
+};
+
+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);
+ DepthStencilState &operator=(const DepthStencilState &other);
+
+ bool isDepthMaskedOut() const;
+ bool isStencilMaskedOut() const;
+ bool isStencilNoOp() const;
+ bool isStencilBackNoOp() const;
+
+ 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);
+
+ SamplerState &operator=(const SamplerState &other);
+
+ static SamplerState CreateDefaultForTarget(TextureType type);
+
+ GLenum getMinFilter() const { return mMinFilter; }
+
+ bool setMinFilter(GLenum minFilter);
+
+ GLenum getMagFilter() const { return mMagFilter; }
+
+ bool setMagFilter(GLenum magFilter);
+
+ GLenum getWrapS() const { return mWrapS; }
+
+ bool setWrapS(GLenum wrapS);
+
+ GLenum getWrapT() const { return mWrapT; }
+
+ bool setWrapT(GLenum wrapT);
+
+ GLenum getWrapR() const { return mWrapR; }
+
+ bool setWrapR(GLenum wrapR);
+
+ float getMaxAnisotropy() const { return mMaxAnisotropy; }
+
+ bool setMaxAnisotropy(float maxAnisotropy);
+
+ GLfloat getMinLod() const { return mMinLod; }
+
+ bool setMinLod(GLfloat minLod);
+
+ GLfloat getMaxLod() const { return mMaxLod; }
+
+ bool setMaxLod(GLfloat maxLod);
+
+ GLenum getCompareMode() const { return mCompareMode; }
+
+ bool setCompareMode(GLenum compareMode);
+
+ GLenum getCompareFunc() const { return mCompareFunc; }
+
+ bool setCompareFunc(GLenum compareFunc);
+
+ GLenum getSRGBDecode() const { return mSRGBDecode; }
+
+ bool setSRGBDecode(GLenum sRGBDecode);
+
+ bool 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::BitSet8<IMPLEMENTATION_MAX_DRAW_BUFFERS>;
+
+class BlendStateExt final
+{
+ static_assert(IMPLEMENTATION_MAX_DRAW_BUFFERS == 8, "Only up to 8 draw buffers supported.");
+
+ public:
+ template <typename ElementType, size_t ElementCount>
+ struct StorageType final
+ {
+ static_assert(ElementCount <= 256, "ElementCount cannot exceed 256.");
+
+#if defined(ANGLE_IS_64_BIT_CPU)
+ // Always use uint64_t on 64-bit systems
+ static constexpr size_t kBits = 8;
+#else
+ static constexpr size_t kBits = ElementCount > 16 ? 8 : 4;
+#endif
+
+ using Type = typename std::conditional<kBits == 8, uint64_t, uint32_t>::type;
+
+ static constexpr Type kMaxValueMask = (kBits == 8) ? 0xFF : 0xF;
+
+ static constexpr Type GetMask(const size_t drawBuffers)
+ {
+ ASSERT(drawBuffers > 0);
+ ASSERT(drawBuffers <= IMPLEMENTATION_MAX_DRAW_BUFFERS);
+ return static_cast<Type>(0xFFFFFFFFFFFFFFFFull >> (64 - drawBuffers * kBits));
+ }
+
+ // A multiplier that is used to replicate 4- or 8-bit value 8 times.
+ static constexpr Type kReplicator = (kBits == 8) ? 0x0101010101010101ull : 0x11111111;
+
+ // Extract packed `Bits`-bit value of index `index`. `values` variable contains up to 8
+ // packed values.
+ static constexpr ElementType GetValueIndexed(const size_t index, const Type values)
+ {
+ ASSERT(index < IMPLEMENTATION_MAX_DRAW_BUFFERS);
+
+ return static_cast<ElementType>((values >> (index * kBits)) & kMaxValueMask);
+ }
+
+ // Replicate `Bits`-bit value 8 times and mask the result.
+ static constexpr Type GetReplicatedValue(const ElementType value, const Type mask)
+ {
+ ASSERT(static_cast<size_t>(value) <= kMaxValueMask);
+ return (static_cast<size_t>(value) * kReplicator) & mask;
+ }
+
+ // Replace `Bits`-bit value of index `index` in `target` with `value`.
+ static constexpr void SetValueIndexed(const size_t index,
+ const ElementType value,
+ Type *target)
+ {
+ ASSERT(static_cast<size_t>(value) <= kMaxValueMask);
+ ASSERT(index < IMPLEMENTATION_MAX_DRAW_BUFFERS);
+
+ // Bitmask with set bits that contain the value of index `index`.
+ const Type selector = kMaxValueMask << (index * kBits);
+
+ // Shift the new `value` to its position in the packed value.
+ const Type builtValue = static_cast<Type>(value) << (index * kBits);
+
+ // Mark differing bits of `target` and `builtValue`, then flip the bits on those
+ // positions in `target`.
+ // Taken from https://graphics.stanford.edu/~seander/bithacks.html#MaskedMerge
+ *target = *target ^ ((*target ^ builtValue) & selector);
+ }
+
+ // Compare two packed sets of eight 4-bit values and return an 8-bit diff mask.
+ static constexpr DrawBufferMask GetDiffMask(const uint32_t packedValue1,
+ const uint32_t packedValue2)
+ {
+ uint32_t diff = packedValue1 ^ packedValue2;
+
+ // For each 4-bit value that is different between inputs, set the msb to 1 and other
+ // bits to 0.
+ diff = (diff | ((diff & 0x77777777) + 0x77777777)) & 0x88888888;
+
+ // By this point, `diff` looks like a...b...c...d...e...f...g...h... (dots mean zeros).
+ // To get DrawBufferMask, we need to compress this 32-bit value to 8 bits, i.e. abcdefgh
+
+ // Multiplying the lower half of `diff` by 0x249 (0x200 + 0x40 + 0x8 + 0x1) produces:
+ // ................e...f...g...h... +
+ // .............e...f...g...h...... +
+ // ..........e...f...g...h......... +
+ // .......e...f...g...h............
+ // ________________________________ =
+ // .......e..ef.efgefghfgh.gh..h...
+ // ^^^^
+ // Similar operation is applied to the upper word.
+ // This calculation could be replaced with a single PEXT instruction from BMI2 set.
+ diff = ((((diff & 0xFFFF0000) * 0x249) >> 24) & 0xF0) | (((diff * 0x249) >> 12) & 0xF);
+
+ return DrawBufferMask(static_cast<uint8_t>(diff));
+ }
+
+ // Compare two packed sets of eight 8-bit values and return an 8-bit diff mask.
+ static constexpr DrawBufferMask GetDiffMask(const uint64_t packedValue1,
+ const uint64_t packedValue2)
+ {
+ uint64_t diff = packedValue1 ^ packedValue2;
+
+ // For each 8-bit value that is different between inputs, set the msb to 1 and other
+ // bits to 0.
+ diff = (diff | ((diff & 0x7F7F7F7F7F7F7F7F) + 0x7F7F7F7F7F7F7F7F)) & 0x8080808080808080;
+
+ // By this point, `diff` looks like (dots mean zeros):
+ // a.......b.......c.......d.......e.......f.......g.......h.......
+ // To get DrawBufferMask, we need to compress this 64-bit value to 8 bits, i.e. abcdefgh
+
+ // Multiplying `diff` by 0x0002040810204081 produces:
+ // a.......b.......c.......d.......e.......f.......g.......h....... +
+ // .b.......c.......d.......e.......f.......g.......h.............. +
+ // ..c.......d.......e.......f.......g.......h..................... +
+ // ...d.......e.......f.......g.......h............................ +
+ // ....e.......f.......g.......h................................... +
+ // .....f.......g.......h.......................................... +
+ // ......g.......h................................................. +
+ // .......h........................................................
+ // ________________________________________________________________ =
+ // abcdefghbcdefgh.cdefgh..defgh...efgh....fgh.....gh......h.......
+ // ^^^^^^^^
+ // This operation could be replaced with a single PEXT instruction from BMI2 set.
+ diff = 0x0002040810204081 * diff >> 56;
+
+ return DrawBufferMask(static_cast<uint8_t>(diff));
+ }
+ };
+
+ using FactorStorage = StorageType<BlendFactorType, angle::EnumSize<BlendFactorType>()>;
+ using EquationStorage = StorageType<BlendEquationType, angle::EnumSize<BlendEquationType>()>;
+ using ColorMaskStorage = StorageType<uint8_t, 16>;
+ static_assert(std::is_same<FactorStorage::Type, uint64_t>::value &&
+ std::is_same<EquationStorage::Type, uint64_t>::value,
+ "Factor and Equation storage must be 64-bit.");
+
+ BlendStateExt(const size_t drawBuffers = 1);
+
+ BlendStateExt(const BlendStateExt &other);
+ BlendStateExt &operator=(const BlendStateExt &other);
+
+ ///////// Blending Toggle /////////
+
+ void setEnabled(const bool enabled);
+ void setEnabledIndexed(const size_t index, const bool enabled);
+
+ ///////// Color Write Mask /////////
+
+ static constexpr size_t PackColorMask(const bool red,
+ const bool green,
+ const bool blue,
+ const bool alpha)
+ {
+ return (red ? 1 : 0) | (green ? 2 : 0) | (blue ? 4 : 0) | (alpha ? 8 : 0);
+ }
+
+ static constexpr void UnpackColorMask(const size_t value,
+ bool *red,
+ bool *green,
+ bool *blue,
+ bool *alpha)
+ {
+ *red = static_cast<bool>(value & 1);
+ *green = static_cast<bool>(value & 2);
+ *blue = static_cast<bool>(value & 4);
+ *alpha = static_cast<bool>(value & 8);
+ }
+
+ ColorMaskStorage::Type expandColorMaskValue(const bool red,
+ const bool green,
+ const bool blue,
+ const bool alpha) const;
+ ColorMaskStorage::Type expandColorMaskIndexed(const size_t index) const;
+ void setColorMask(const bool red, const bool green, const bool blue, const bool alpha);
+ void setColorMaskIndexed(const size_t index, const uint8_t value);
+ void setColorMaskIndexed(const size_t index,
+ const bool red,
+ const bool green,
+ const bool blue,
+ const bool alpha);
+ uint8_t getColorMaskIndexed(const size_t index) const;
+ void getColorMaskIndexed(const size_t index,
+ bool *red,
+ bool *green,
+ bool *blue,
+ bool *alpha) const;
+ DrawBufferMask compareColorMask(ColorMaskStorage::Type other) const;
+
+ ///////// Blend Equation /////////
+
+ EquationStorage::Type expandEquationValue(const GLenum mode) const;
+ EquationStorage::Type expandEquationValue(const gl::BlendEquationType equation) const;
+ EquationStorage::Type expandEquationColorIndexed(const size_t index) const;
+ EquationStorage::Type expandEquationAlphaIndexed(const size_t index) const;
+ void setEquations(const GLenum modeColor, const GLenum modeAlpha);
+ void setEquationsIndexed(const size_t index, const GLenum modeColor, const GLenum modeAlpha);
+ void setEquationsIndexed(const size_t index,
+ const size_t otherIndex,
+ const BlendStateExt &other);
+ GLenum getEquationColorIndexed(size_t index) const;
+ GLenum getEquationAlphaIndexed(size_t index) const;
+ DrawBufferMask compareEquations(const EquationStorage::Type color,
+ const EquationStorage::Type alpha) const;
+ DrawBufferMask compareEquations(const BlendStateExt &other) const
+ {
+ return compareEquations(other.mEquationColor, other.mEquationAlpha);
+ }
+
+ ///////// Blend Factors /////////
+
+ FactorStorage::Type expandFactorValue(const GLenum func) const;
+ FactorStorage::Type expandSrcColorIndexed(const size_t index) const;
+ FactorStorage::Type expandDstColorIndexed(const size_t index) const;
+ FactorStorage::Type expandSrcAlphaIndexed(const size_t index) const;
+ FactorStorage::Type expandDstAlphaIndexed(const size_t index) const;
+ void setFactors(const GLenum srcColor,
+ const GLenum dstColor,
+ const GLenum srcAlpha,
+ const GLenum dstAlpha);
+ void setFactorsIndexed(const size_t index,
+ const GLenum srcColor,
+ const GLenum dstColor,
+ const GLenum srcAlpha,
+ const GLenum dstAlpha);
+ void setFactorsIndexed(const size_t index, const size_t otherIndex, const BlendStateExt &other);
+ GLenum getSrcColorIndexed(size_t index) const;
+ GLenum getDstColorIndexed(size_t index) const;
+ GLenum getSrcAlphaIndexed(size_t index) const;
+ GLenum getDstAlphaIndexed(size_t index) const;
+ DrawBufferMask compareFactors(const FactorStorage::Type srcColor,
+ const FactorStorage::Type dstColor,
+ const FactorStorage::Type srcAlpha,
+ const FactorStorage::Type dstAlpha) const;
+ DrawBufferMask compareFactors(const BlendStateExt &other) const
+ {
+ return compareFactors(other.mSrcColor, other.mDstColor, other.mSrcAlpha, other.mDstAlpha);
+ }
+
+ constexpr FactorStorage::Type getSrcColorBits() const { return mSrcColor; }
+ constexpr FactorStorage::Type getSrcAlphaBits() const { return mSrcAlpha; }
+ constexpr FactorStorage::Type getDstColorBits() const { return mDstColor; }
+ constexpr FactorStorage::Type getDstAlphaBits() const { return mDstAlpha; }
+
+ constexpr EquationStorage::Type getEquationColorBits() const { return mEquationColor; }
+ constexpr EquationStorage::Type getEquationAlphaBits() const { return mEquationAlpha; }
+
+ constexpr ColorMaskStorage::Type getAllColorMaskBits() const { return mAllColorMask; }
+ constexpr ColorMaskStorage::Type getColorMaskBits() const { return mColorMask; }
+
+ constexpr DrawBufferMask getAllEnabledMask() const { return mAllEnabledMask; }
+ constexpr DrawBufferMask getEnabledMask() const { return mEnabledMask; }
+
+ constexpr DrawBufferMask getUsesAdvancedBlendEquationMask() const
+ {
+ return mUsesAdvancedBlendEquationMask;
+ }
+
+ constexpr uint8_t getDrawBufferCount() const { return mDrawBufferCount; }
+
+ constexpr void setSrcColorBits(const FactorStorage::Type srcColor) { mSrcColor = srcColor; }
+ constexpr void setSrcAlphaBits(const FactorStorage::Type srcAlpha) { mSrcAlpha = srcAlpha; }
+ constexpr void setDstColorBits(const FactorStorage::Type dstColor) { mDstColor = dstColor; }
+ constexpr void setDstAlphaBits(const FactorStorage::Type dstAlpha) { mDstAlpha = dstAlpha; }
+
+ constexpr void setEquationColorBits(const EquationStorage::Type equationColor)
+ {
+ mEquationColor = equationColor;
+ }
+ constexpr void setEquationAlphaBits(const EquationStorage::Type equationAlpha)
+ {
+ mEquationAlpha = equationAlpha;
+ }
+
+ constexpr void setColorMaskBits(const ColorMaskStorage::Type colorMask)
+ {
+ mColorMask = colorMask;
+ }
+
+ constexpr void setEnabledMask(const DrawBufferMask enabledMask) { mEnabledMask = enabledMask; }
+
+ ///////// Data Members /////////
+ private:
+ uint64_t mParameterMask;
+
+ FactorStorage::Type mSrcColor;
+ FactorStorage::Type mDstColor;
+ FactorStorage::Type mSrcAlpha;
+ FactorStorage::Type mDstAlpha;
+
+ EquationStorage::Type mEquationColor;
+ EquationStorage::Type mEquationAlpha;
+
+ ColorMaskStorage::Type mAllColorMask;
+ ColorMaskStorage::Type mColorMask;
+
+ DrawBufferMask mAllEnabledMask;
+ DrawBufferMask mEnabledMask;
+
+ // Cache of whether the blend equation for each index is from KHR_blend_equation_advanced.
+ DrawBufferMask mUsesAdvancedBlendEquationMask;
+
+ uint8_t mDrawBufferCount;
+
+ [[maybe_unused]] uint32_t kUnused = 0;
+};
+
+static_assert(sizeof(BlendStateExt) == sizeof(uint64_t) +
+ (sizeof(BlendStateExt::FactorStorage::Type) * 4 +
+ sizeof(BlendStateExt::EquationStorage::Type) * 2 +
+ sizeof(BlendStateExt::ColorMaskStorage::Type) * 2 +
+ sizeof(DrawBufferMask) * 3 + sizeof(uint8_t)) +
+ sizeof(uint32_t),
+ "The BlendStateExt class must not contain gaps.");
+
+// Used in StateCache
+using StorageBuffersMask = angle::BitSet<IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS>;
+
+template <typename T>
+using SampleMaskArray = std::array<T, IMPLEMENTATION_MAX_SAMPLE_MASK_WORDS>;
+
+template <typename T>
+using TexLevelArray = std::array<T, IMPLEMENTATION_MAX_TEXTURE_LEVELS>;
+
+using TexLevelMask = angle::BitSet<IMPLEMENTATION_MAX_TEXTURE_LEVELS>;
+
+enum class ComponentType
+{
+ Float = 0,
+ Int = 1,
+ UnsignedInt = 2,
+ NoType = 3,
+ EnumCount = 4,
+ InvalidEnum = 4,
+};
+
+constexpr 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;
+ }
+}
+
+constexpr angle::PackedEnumMap<ComponentType, uint32_t> kComponentMasks = {{
+ {ComponentType::Float, 0x10001},
+ {ComponentType::Int, 0x00001},
+ {ComponentType::UnsignedInt, 0x10000},
+}};
+
+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);
+
+enum class RenderToTextureImageIndex
+{
+ // The default image of the texture, where data is expected to be.
+ Default = 0,
+
+ // Intermediate multisampled images for EXT_multisampled_render_to_texture.
+ // These values must match log2(SampleCount).
+ IntermediateImage2xMultisampled = 1,
+ IntermediateImage4xMultisampled = 2,
+ IntermediateImage8xMultisampled = 3,
+ IntermediateImage16xMultisampled = 4,
+
+ // We currently only support up to 16xMSAA in backends that use this enum.
+ InvalidEnum = 5,
+ EnumCount = 5,
+};
+
+template <typename T>
+using RenderToTextureImageMap = angle::PackedEnumMap<RenderToTextureImageIndex, T>;
+
+struct ContextID
+{
+ uint32_t value;
+};
+
+inline bool operator==(ContextID lhs, ContextID rhs)
+{
+ return lhs.value == rhs.value;
+}
+
+inline bool operator!=(ContextID lhs, ContextID rhs)
+{
+ return lhs.value != rhs.value;
+}
+
+inline bool operator<(ContextID lhs, ContextID rhs)
+{
+ return lhs.value < rhs.value;
+}
+
+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 AttachmentVector = angle::FixedVector<T, IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS>;
+
+using AttachmentsMask = angle::BitSet<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 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_BUFFER_BINDINGS>;
+using AtomicCounterBufferMask = angle::BitSet<IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS>;
+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>;
+
+template <typename T>
+using QueryTypeMap = angle::PackedEnumMap<QueryType, T>;
+
+constexpr size_t kBarrierVectorDefaultSize = 16;
+
+template <typename T>
+using BarrierVector = angle::FastVector<T, kBarrierVectorDefaultSize>;
+
+using BufferBarrierVector = BarrierVector<Buffer *>;
+
+using SamplerBindingVector = std::vector<BindingPointer<Sampler>>;
+using BufferVector = std::vector<OffsetBindingPointer<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);
+
+// A texture level index.
+template <typename T>
+class LevelIndexWrapper
+{
+ public:
+ LevelIndexWrapper() = default;
+ explicit constexpr LevelIndexWrapper(T levelIndex) : mLevelIndex(levelIndex) {}
+ constexpr LevelIndexWrapper(const LevelIndexWrapper &other) = default;
+ constexpr LevelIndexWrapper &operator=(const LevelIndexWrapper &other) = default;
+
+ constexpr T get() const { return mLevelIndex; }
+
+ LevelIndexWrapper &operator++()
+ {
+ ++mLevelIndex;
+ return *this;
+ }
+ constexpr bool operator<(const LevelIndexWrapper &other) const
+ {
+ return mLevelIndex < other.mLevelIndex;
+ }
+ constexpr bool operator<=(const LevelIndexWrapper &other) const
+ {
+ return mLevelIndex <= other.mLevelIndex;
+ }
+ constexpr bool operator>(const LevelIndexWrapper &other) const
+ {
+ return mLevelIndex > other.mLevelIndex;
+ }
+ constexpr bool operator>=(const LevelIndexWrapper &other) const
+ {
+ return mLevelIndex >= other.mLevelIndex;
+ }
+ constexpr bool operator==(const LevelIndexWrapper &other) const
+ {
+ return mLevelIndex == other.mLevelIndex;
+ }
+ constexpr bool operator!=(const LevelIndexWrapper &other) const
+ {
+ return mLevelIndex != other.mLevelIndex;
+ }
+ constexpr LevelIndexWrapper operator+(T other) const
+ {
+ return LevelIndexWrapper(mLevelIndex + other);
+ }
+ constexpr LevelIndexWrapper operator-(T other) const
+ {
+ return LevelIndexWrapper(mLevelIndex - other);
+ }
+ constexpr T operator-(LevelIndexWrapper other) const { return mLevelIndex - other.mLevelIndex; }
+
+ private:
+ T mLevelIndex;
+};
+
+// A GL texture level index.
+using LevelIndex = LevelIndexWrapper<GLint>;
+
+enum class MultisamplingMode
+{
+ // Regular multisampling
+ Regular = 0,
+ // GL_EXT_multisampled_render_to_texture renderbuffer/texture attachments which perform implicit
+ // resolve of multisampled data.
+ MultisampledRenderToTexture,
+};
+} // 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() = default;
+ DestroyThenDelete(const ContextT *context) : mContext(context) {}
+
+ void operator()(ObjT *obj)
+ {
+ (void)(obj->onDestroy(mContext));
+ delete obj;
+ }
+
+ private:
+ const ContextT *mContext = nullptr;
+};
+
+template <typename ObjT, typename ContextT>
+using UniqueObjectPointer = std::unique_ptr<ObjT, DestroyThenDelete<ObjT, ContextT>>;
+
+} // namespace angle
+
+namespace gl
+{
+class State;
+} // namespace gl
+
+#endif // LIBANGLE_ANGLETYPES_H_