• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2012 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // angletypes.h : Defines a variety of structures and enum types that are used throughout libGLESv2
8 
9 #ifndef LIBANGLE_ANGLETYPES_H_
10 #define LIBANGLE_ANGLETYPES_H_
11 
12 #include <anglebase/sha1.h>
13 #include "common/Color.h"
14 #include "common/FixedVector.h"
15 #include "common/MemoryBuffer.h"
16 #include "common/PackedEnums.h"
17 #include "common/bitset_utils.h"
18 #include "common/hash_utils.h"
19 #include "common/vector_utils.h"
20 #include "libANGLE/Constants.h"
21 #include "libANGLE/Error.h"
22 #include "libANGLE/RefCountObject.h"
23 
24 #include <inttypes.h>
25 #include <stdint.h>
26 
27 #include <bitset>
28 #include <functional>
29 #include <map>
30 #include <memory>
31 #include <unordered_map>
32 
33 namespace gl
34 {
35 class Buffer;
36 class Texture;
37 
38 enum class Command
39 {
40     // The Blit command carries the bitmask of which buffers are being blit.  The command passed to
41     // the backends is:
42     //
43     //     Blit + (Color?0x1) + (Depth?0x2) + (Stencil?0x4)
44     Blit,
45     BlitAll = Blit + 0x7,
46     Clear,
47     CopyImage,
48     Dispatch,
49     Draw,
50     GenerateMipmap,
51     Invalidate,
52     ReadPixels,
53     TexImage,
54     Other,
55 };
56 
57 enum CommandBlitBuffer
58 {
59     CommandBlitBufferColor   = 0x1,
60     CommandBlitBufferDepth   = 0x2,
61     CommandBlitBufferStencil = 0x4,
62 };
63 
64 enum class InitState
65 {
66     MayNeedInit,
67     Initialized,
68 };
69 
70 template <typename T>
71 struct RectangleImpl
72 {
RectangleImplRectangleImpl73     RectangleImpl() : x(T(0)), y(T(0)), width(T(0)), height(T(0)) {}
RectangleImplRectangleImpl74     constexpr RectangleImpl(T x_in, T y_in, T width_in, T height_in)
75         : x(x_in), y(y_in), width(width_in), height(height_in)
76     {}
RectangleImplRectangleImpl77     explicit constexpr RectangleImpl(const T corners[4])
78         : x(corners[0]),
79           y(corners[1]),
80           width(corners[2] - corners[0]),
81           height(corners[3] - corners[1])
82     {}
83     template <typename S>
RectangleImplRectangleImpl84     explicit constexpr RectangleImpl(const RectangleImpl<S> rect)
85         : x(rect.x), y(rect.y), width(rect.width), height(rect.height)
86     {}
87 
x0RectangleImpl88     T x0() const { return x; }
y0RectangleImpl89     T y0() const { return y; }
x1RectangleImpl90     T x1() const { return x + width; }
y1RectangleImpl91     T y1() const { return y + height; }
92 
isReversedXRectangleImpl93     bool isReversedX() const { return width < T(0); }
isReversedYRectangleImpl94     bool isReversedY() const { return height < T(0); }
95 
96     // Returns a rectangle with the same area but flipped in X, Y, neither or both.
flipRectangleImpl97     RectangleImpl<T> flip(bool flipX, bool flipY) const
98     {
99         RectangleImpl flipped = *this;
100         if (flipX)
101         {
102             flipped.x     = flipped.x + flipped.width;
103             flipped.width = -flipped.width;
104         }
105         if (flipY)
106         {
107             flipped.y      = flipped.y + flipped.height;
108             flipped.height = -flipped.height;
109         }
110         return flipped;
111     }
112 
113     // Returns a rectangle with the same area but with height and width guaranteed to be positive.
removeReversalRectangleImpl114     RectangleImpl<T> removeReversal() const { return flip(isReversedX(), isReversedY()); }
115 
enclosesRectangleImpl116     bool encloses(const RectangleImpl<T> &inside) const
117     {
118         return x0() <= inside.x0() && y0() <= inside.y0() && x1() >= inside.x1() &&
119                y1() >= inside.y1();
120     }
121 
122     bool empty() const;
123 
124     T x;
125     T y;
126     T width;
127     T height;
128 };
129 
130 template <typename T>
131 bool operator==(const RectangleImpl<T> &a, const RectangleImpl<T> &b);
132 template <typename T>
133 bool operator!=(const RectangleImpl<T> &a, const RectangleImpl<T> &b);
134 
135 using Rectangle = RectangleImpl<int>;
136 
137 // Calculate the intersection of two rectangles.  Returns false if the intersection is empty.
138 [[nodiscard]] bool ClipRectangle(const Rectangle &source,
139                                  const Rectangle &clip,
140                                  Rectangle *intersection);
141 // Calculate the smallest rectangle that covers both rectangles.  This rectangle may cover areas
142 // not covered by the two rectangles, for example in this situation:
143 //
144 //   +--+        +----+
145 //   | ++-+  ->  |    |
146 //   +-++ |      |    |
147 //     +--+      +----+
148 //
149 void GetEnclosingRectangle(const Rectangle &rect1, const Rectangle &rect2, Rectangle *rectUnion);
150 // Extend the source rectangle to cover parts (or all of) the second rectangle, in such a way that
151 // no area is covered that isn't covered by both rectangles.  For example:
152 //
153 //             +--+        +--+
154 //  source --> |  |        |  |
155 //            ++--+-+  ->  |  |
156 //            |+--+ |      |  |
157 //            +-----+      +--+
158 //
159 void ExtendRectangle(const Rectangle &source, const Rectangle &extend, Rectangle *extended);
160 
161 struct Offset
162 {
OffsetOffset163     constexpr Offset() : x(0), y(0), z(0) {}
OffsetOffset164     constexpr Offset(int x_in, int y_in, int z_in) : x(x_in), y(y_in), z(z_in) {}
165 
166     int x;
167     int y;
168     int z;
169 };
170 
171 constexpr Offset kOffsetZero(0, 0, 0);
172 
173 bool operator==(const Offset &a, const Offset &b);
174 bool operator!=(const Offset &a, const Offset &b);
175 
176 struct Extents
177 {
ExtentsExtents178     Extents() : width(0), height(0), depth(0) {}
ExtentsExtents179     Extents(int width_, int height_, int depth_) : width(width_), height(height_), depth(depth_) {}
180 
181     Extents(const Extents &other)            = default;
182     Extents &operator=(const Extents &other) = default;
183 
emptyExtents184     bool empty() const { return (width * height * depth) == 0; }
185 
186     int width;
187     int height;
188     int depth;
189 };
190 
191 bool operator==(const Extents &lhs, const Extents &rhs);
192 bool operator!=(const Extents &lhs, const Extents &rhs);
193 
194 struct Box
195 {
BoxBox196     Box() : x(0), y(0), z(0), width(0), height(0), depth(0) {}
BoxBox197     Box(int x_in, int y_in, int z_in, int width_in, int height_in, int depth_in)
198         : x(x_in), y(y_in), z(z_in), width(width_in), height(height_in), depth(depth_in)
199     {}
200     template <typename O, typename E>
BoxBox201     Box(const O &offset, const E &size)
202         : x(offset.x),
203           y(offset.y),
204           z(offset.z),
205           width(size.width),
206           height(size.height),
207           depth(size.depth)
208     {}
209     bool valid() const;
210     bool operator==(const Box &other) const;
211     bool operator!=(const Box &other) const;
212     Rectangle toRect() const;
213 
214     // Whether the Box has offset 0 and the same extents as argument.
215     bool coversSameExtent(const Extents &size) const;
216 
217     bool contains(const Box &other) const;
218     size_t volume() const;
219     void extend(const Box &other);
220 
221     int x;
222     int y;
223     int z;
224     int width;
225     int height;
226     int depth;
227 };
228 
229 struct RasterizerState final
230 {
231     // This will zero-initialize the struct, including padding.
232     RasterizerState();
233     RasterizerState(const RasterizerState &other);
234     RasterizerState &operator=(const RasterizerState &other);
235 
236     bool cullFace;
237     CullFaceMode cullMode;
238     GLenum frontFace;
239 
240     PolygonMode polygonMode;
241 
242     bool polygonOffsetPoint;
243     bool polygonOffsetLine;
244     bool polygonOffsetFill;
245     GLfloat polygonOffsetFactor;
246     GLfloat polygonOffsetUnits;
247     GLfloat polygonOffsetClamp;
248 
249     bool depthClamp;
250 
251     // pointDrawMode/multiSample are only used in the D3D back-end right now.
252     bool pointDrawMode;
253     bool multiSample;
254 
255     bool rasterizerDiscard;
256 
257     bool dither;
258 
isPolygonOffsetEnabledfinal259     bool isPolygonOffsetEnabled() const
260     {
261         static_assert(static_cast<int>(PolygonMode::Point) == 0, "PolygonMode::Point");
262         static_assert(static_cast<int>(PolygonMode::Line) == 1, "PolygonMode::Line");
263         static_assert(static_cast<int>(PolygonMode::Fill) == 2, "PolygonMode::Fill");
264         return (1 << static_cast<int>(polygonMode)) &
265                ((polygonOffsetPoint << 0) | (polygonOffsetLine << 1) | (polygonOffsetFill << 2));
266     }
267 };
268 
269 bool operator==(const RasterizerState &a, const RasterizerState &b);
270 bool operator!=(const RasterizerState &a, const RasterizerState &b);
271 
272 struct BlendState final
273 {
274     // This will zero-initialize the struct, including padding.
275     BlendState();
276     BlendState(const BlendState &other);
277 
278     bool blend;
279     GLenum sourceBlendRGB;
280     GLenum destBlendRGB;
281     GLenum sourceBlendAlpha;
282     GLenum destBlendAlpha;
283     GLenum blendEquationRGB;
284     GLenum blendEquationAlpha;
285 
286     bool colorMaskRed;
287     bool colorMaskGreen;
288     bool colorMaskBlue;
289     bool colorMaskAlpha;
290 };
291 
292 bool operator==(const BlendState &a, const BlendState &b);
293 bool operator!=(const BlendState &a, const BlendState &b);
294 
295 struct DepthStencilState final
296 {
297     // This will zero-initialize the struct, including padding.
298     DepthStencilState();
299     DepthStencilState(const DepthStencilState &other);
300     DepthStencilState &operator=(const DepthStencilState &other);
301 
302     bool isDepthMaskedOut() const;
303     bool isStencilMaskedOut() const;
304     bool isStencilNoOp() const;
305     bool isStencilBackNoOp() const;
306 
307     bool depthTest;
308     GLenum depthFunc;
309     bool depthMask;
310 
311     bool stencilTest;
312     GLenum stencilFunc;
313     GLuint stencilMask;
314     GLenum stencilFail;
315     GLenum stencilPassDepthFail;
316     GLenum stencilPassDepthPass;
317     GLuint stencilWritemask;
318     GLenum stencilBackFunc;
319     GLuint stencilBackMask;
320     GLenum stencilBackFail;
321     GLenum stencilBackPassDepthFail;
322     GLenum stencilBackPassDepthPass;
323     GLuint stencilBackWritemask;
324 };
325 
326 bool operator==(const DepthStencilState &a, const DepthStencilState &b);
327 bool operator!=(const DepthStencilState &a, const DepthStencilState &b);
328 
329 // Packs a sampler state for completeness checks:
330 // * minFilter: 5 values (3 bits)
331 // * magFilter: 2 values (1 bit)
332 // * wrapS:     3 values (2 bits)
333 // * wrapT:     3 values (2 bits)
334 // * compareMode: 1 bit (for == GL_NONE).
335 // This makes a total of 9 bits. We can pack this easily into 32 bits:
336 // * minFilter: 8 bits
337 // * magFilter: 8 bits
338 // * wrapS:     8 bits
339 // * wrapT:     4 bits
340 // * compareMode: 4 bits
341 
342 struct PackedSamplerCompleteness
343 {
344     uint8_t minFilter;
345     uint8_t magFilter;
346     uint8_t wrapS;
347     uint8_t wrapTCompareMode;
348 };
349 
350 static_assert(sizeof(PackedSamplerCompleteness) == sizeof(uint32_t), "Unexpected size");
351 
352 // State from Table 6.10 (state per sampler object)
353 class SamplerState final
354 {
355   public:
356     // This will zero-initialize the struct, including padding.
357     SamplerState();
358     SamplerState(const SamplerState &other);
359 
360     SamplerState &operator=(const SamplerState &other);
361 
362     static SamplerState CreateDefaultForTarget(TextureType type);
363 
getMinFilter()364     GLenum getMinFilter() const { return mMinFilter; }
365 
366     bool setMinFilter(GLenum minFilter);
367 
getMagFilter()368     GLenum getMagFilter() const { return mMagFilter; }
369 
370     bool setMagFilter(GLenum magFilter);
371 
getWrapS()372     GLenum getWrapS() const { return mWrapS; }
373 
374     bool setWrapS(GLenum wrapS);
375 
getWrapT()376     GLenum getWrapT() const { return mWrapT; }
377 
378     bool setWrapT(GLenum wrapT);
379 
getWrapR()380     GLenum getWrapR() const { return mWrapR; }
381 
382     bool setWrapR(GLenum wrapR);
383 
usesBorderColor()384     bool usesBorderColor() const
385     {
386         return mWrapS == GL_CLAMP_TO_BORDER || mWrapT == GL_CLAMP_TO_BORDER ||
387                mWrapR == GL_CLAMP_TO_BORDER;
388     }
389 
getMaxAnisotropy()390     float getMaxAnisotropy() const { return mMaxAnisotropy; }
391 
392     bool setMaxAnisotropy(float maxAnisotropy);
393 
getMinLod()394     GLfloat getMinLod() const { return mMinLod; }
395 
396     bool setMinLod(GLfloat minLod);
397 
getMaxLod()398     GLfloat getMaxLod() const { return mMaxLod; }
399 
400     bool setMaxLod(GLfloat maxLod);
401 
getCompareMode()402     GLenum getCompareMode() const { return mCompareMode; }
403 
404     bool setCompareMode(GLenum compareMode);
405 
getCompareFunc()406     GLenum getCompareFunc() const { return mCompareFunc; }
407 
408     bool setCompareFunc(GLenum compareFunc);
409 
getSRGBDecode()410     GLenum getSRGBDecode() const { return mSRGBDecode; }
411 
412     bool setSRGBDecode(GLenum sRGBDecode);
413 
414     bool setBorderColor(const ColorGeneric &color);
415 
getBorderColor()416     const ColorGeneric &getBorderColor() const { return mBorderColor; }
417 
sameCompleteness(const SamplerState & samplerState)418     bool sameCompleteness(const SamplerState &samplerState) const
419     {
420         return mCompleteness.packed == samplerState.mCompleteness.packed;
421     }
422 
423   private:
424     void updateWrapTCompareMode();
425 
426     GLenum mMinFilter;
427     GLenum mMagFilter;
428 
429     GLenum mWrapS;
430     GLenum mWrapT;
431     GLenum mWrapR;
432 
433     // From EXT_texture_filter_anisotropic
434     float mMaxAnisotropy;
435 
436     GLfloat mMinLod;
437     GLfloat mMaxLod;
438 
439     GLenum mCompareMode;
440     GLenum mCompareFunc;
441 
442     GLenum mSRGBDecode;
443 
444     ColorGeneric mBorderColor;
445 
446     union Completeness
447     {
448         uint32_t packed;
449         PackedSamplerCompleteness typed;
450     };
451 
452     Completeness mCompleteness;
453 };
454 
455 bool operator==(const SamplerState &a, const SamplerState &b);
456 bool operator!=(const SamplerState &a, const SamplerState &b);
457 
458 struct DrawArraysIndirectCommand
459 {
460     GLuint count;
461     GLuint instanceCount;
462     GLuint first;
463     GLuint baseInstance;
464 };
465 static_assert(sizeof(DrawArraysIndirectCommand) == 16,
466               "Unexpected size of DrawArraysIndirectCommand");
467 
468 struct DrawElementsIndirectCommand
469 {
470     GLuint count;
471     GLuint primCount;
472     GLuint firstIndex;
473     GLint baseVertex;
474     GLuint baseInstance;
475 };
476 static_assert(sizeof(DrawElementsIndirectCommand) == 20,
477               "Unexpected size of DrawElementsIndirectCommand");
478 
479 struct ImageUnit
480 {
481     ImageUnit();
482     ImageUnit(const ImageUnit &other);
483     ~ImageUnit();
484 
485     BindingPointer<Texture> texture;
486     GLint level;
487     GLboolean layered;
488     GLint layer;
489     GLenum access;
490     GLenum format;
491 };
492 
493 using ImageUnitTextureTypeMap = std::map<unsigned int, gl::TextureType>;
494 
495 struct PixelStoreStateBase
496 {
497     GLint alignment   = 4;
498     GLint rowLength   = 0;
499     GLint skipRows    = 0;
500     GLint skipPixels  = 0;
501     GLint imageHeight = 0;
502     GLint skipImages  = 0;
503 };
504 
505 struct PixelUnpackState : PixelStoreStateBase
506 {};
507 
508 struct PixelPackState : PixelStoreStateBase
509 {
510     bool reverseRowOrder = false;
511 };
512 
513 // Used in VertexArray.
514 using VertexArrayBufferBindingMask = angle::BitSet<MAX_VERTEX_ATTRIB_BINDINGS>;
515 
516 // Used in Program and VertexArray.
517 using AttributesMask = angle::BitSet<MAX_VERTEX_ATTRIBS>;
518 
519 // Used in Program
520 using ProgramUniformBlockMask = angle::BitSet<IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS>;
521 template <typename T>
522 using ProgramUniformBlockArray = std::array<T, IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS>;
523 template <typename T>
524 using UniformBufferBindingArray = std::array<T, IMPLEMENTATION_MAX_UNIFORM_BUFFER_BINDINGS>;
525 
526 // Used in Framebuffer / Program
527 using DrawBufferMask = angle::BitSet8<IMPLEMENTATION_MAX_DRAW_BUFFERS>;
528 
529 class BlendStateExt final
530 {
531     static_assert(IMPLEMENTATION_MAX_DRAW_BUFFERS == 8, "Only up to 8 draw buffers supported.");
532 
533   public:
534     template <typename ElementType, size_t ElementCount>
535     struct StorageType final
536     {
537         static_assert(ElementCount <= 256, "ElementCount cannot exceed 256.");
538 
539 #if defined(ANGLE_IS_64_BIT_CPU)
540         // Always use uint64_t on 64-bit systems
541         static constexpr size_t kBits = 8;
542 #else
543         static constexpr size_t kBits = ElementCount > 16 ? 8 : 4;
544 #endif
545 
546         using Type = typename std::conditional<kBits == 8, uint64_t, uint32_t>::type;
547 
548         static constexpr Type kMaxValueMask = (kBits == 8) ? 0xFF : 0xF;
549 
GetMaskfinal550         static constexpr Type GetMask(const size_t drawBuffers)
551         {
552             ASSERT(drawBuffers > 0);
553             ASSERT(drawBuffers <= IMPLEMENTATION_MAX_DRAW_BUFFERS);
554             return static_cast<Type>(0xFFFFFFFFFFFFFFFFull >> (64 - drawBuffers * kBits));
555         }
556 
557         // A multiplier that is used to replicate 4- or 8-bit value 8 times.
558         static constexpr Type kReplicator = (kBits == 8) ? 0x0101010101010101ull : 0x11111111;
559 
560         // Extract packed `Bits`-bit value of index `index`. `values` variable contains up to 8
561         // packed values.
GetValueIndexedfinal562         static constexpr ElementType GetValueIndexed(const size_t index, const Type values)
563         {
564             ASSERT(index < IMPLEMENTATION_MAX_DRAW_BUFFERS);
565 
566             return static_cast<ElementType>((values >> (index * kBits)) & kMaxValueMask);
567         }
568 
569         // Replicate `Bits`-bit value 8 times and mask the result.
GetReplicatedValuefinal570         static constexpr Type GetReplicatedValue(const ElementType value, const Type mask)
571         {
572             ASSERT(static_cast<size_t>(value) <= kMaxValueMask);
573             return (static_cast<size_t>(value) * kReplicator) & mask;
574         }
575 
576         // Replace `Bits`-bit value of index `index` in `target` with `value`.
SetValueIndexedfinal577         static constexpr void SetValueIndexed(const size_t index,
578                                               const ElementType value,
579                                               Type *target)
580         {
581             ASSERT(static_cast<size_t>(value) <= kMaxValueMask);
582             ASSERT(index < IMPLEMENTATION_MAX_DRAW_BUFFERS);
583 
584             // Bitmask with set bits that contain the value of index `index`.
585             const Type selector = kMaxValueMask << (index * kBits);
586 
587             // Shift the new `value` to its position in the packed value.
588             const Type builtValue = static_cast<Type>(value) << (index * kBits);
589 
590             // Mark differing bits of `target` and `builtValue`, then flip the bits on those
591             // positions in `target`.
592             // Taken from https://graphics.stanford.edu/~seander/bithacks.html#MaskedMerge
593             *target = *target ^ ((*target ^ builtValue) & selector);
594         }
595 
596         // Compare two packed sets of eight 4-bit values and return an 8-bit diff mask.
GetDiffMaskfinal597         static constexpr DrawBufferMask GetDiffMask(const uint32_t packedValue1,
598                                                     const uint32_t packedValue2)
599         {
600             uint32_t diff = packedValue1 ^ packedValue2;
601 
602             // For each 4-bit value that is different between inputs, set the msb to 1 and other
603             // bits to 0.
604             diff = (diff | ((diff & 0x77777777) + 0x77777777)) & 0x88888888;
605 
606             // By this point, `diff` looks like a...b...c...d...e...f...g...h... (dots mean zeros).
607             // To get DrawBufferMask, we need to compress this 32-bit value to 8 bits, i.e. abcdefgh
608 
609             // Multiplying the lower half of `diff` by 0x249 (0x200 + 0x40 + 0x8 + 0x1) produces:
610             // ................e...f...g...h... +
611             // .............e...f...g...h...... +
612             // ..........e...f...g...h......... +
613             // .......e...f...g...h............
614             // ________________________________ =
615             // .......e..ef.efgefghfgh.gh..h...
616             //                 ^^^^
617             // Similar operation is applied to the upper word.
618             // This calculation could be replaced with a single PEXT instruction from BMI2 set.
619             diff = ((((diff & 0xFFFF0000) * 0x249) >> 24) & 0xF0) | (((diff * 0x249) >> 12) & 0xF);
620 
621             return DrawBufferMask(static_cast<uint8_t>(diff));
622         }
623 
624         // Compare two packed sets of eight 8-bit values and return an 8-bit diff mask.
GetDiffMaskfinal625         static constexpr DrawBufferMask GetDiffMask(const uint64_t packedValue1,
626                                                     const uint64_t packedValue2)
627         {
628             uint64_t diff = packedValue1 ^ packedValue2;
629 
630             // For each 8-bit value that is different between inputs, set the msb to 1 and other
631             // bits to 0.
632             diff = (diff | ((diff & 0x7F7F7F7F7F7F7F7F) + 0x7F7F7F7F7F7F7F7F)) & 0x8080808080808080;
633 
634             // By this point, `diff` looks like (dots mean zeros):
635             // a.......b.......c.......d.......e.......f.......g.......h.......
636             // To get DrawBufferMask, we need to compress this 64-bit value to 8 bits, i.e. abcdefgh
637 
638             // Multiplying `diff` by 0x0002040810204081 produces:
639             // a.......b.......c.......d.......e.......f.......g.......h....... +
640             // .b.......c.......d.......e.......f.......g.......h.............. +
641             // ..c.......d.......e.......f.......g.......h..................... +
642             // ...d.......e.......f.......g.......h............................ +
643             // ....e.......f.......g.......h................................... +
644             // .....f.......g.......h.......................................... +
645             // ......g.......h................................................. +
646             // .......h........................................................
647             // ________________________________________________________________ =
648             // abcdefghbcdefgh.cdefgh..defgh...efgh....fgh.....gh......h.......
649             // ^^^^^^^^
650             // This operation could be replaced with a single PEXT instruction from BMI2 set.
651             diff = 0x0002040810204081 * diff >> 56;
652 
653             return DrawBufferMask(static_cast<uint8_t>(diff));
654         }
655     };
656 
657     using FactorStorage    = StorageType<BlendFactorType, angle::EnumSize<BlendFactorType>()>;
658     using EquationStorage  = StorageType<BlendEquationType, angle::EnumSize<BlendEquationType>()>;
659     using ColorMaskStorage = StorageType<uint8_t, 16>;
660     static_assert(std::is_same<FactorStorage::Type, uint64_t>::value &&
661                       std::is_same<EquationStorage::Type, uint64_t>::value,
662                   "Factor and Equation storage must be 64-bit.");
663 
664     BlendStateExt(const size_t drawBuffers = 1);
665 
666     BlendStateExt(const BlendStateExt &other);
667     BlendStateExt &operator=(const BlendStateExt &other);
668 
669     ///////// Blending Toggle /////////
670 
671     void setEnabled(const bool enabled);
672     void setEnabledIndexed(const size_t index, const bool enabled);
673 
674     ///////// Color Write Mask /////////
675 
PackColorMask(const bool red,const bool green,const bool blue,const bool alpha)676     static constexpr size_t PackColorMask(const bool red,
677                                           const bool green,
678                                           const bool blue,
679                                           const bool alpha)
680     {
681         return (red ? 1 : 0) | (green ? 2 : 0) | (blue ? 4 : 0) | (alpha ? 8 : 0);
682     }
683 
UnpackColorMask(const size_t value,bool * red,bool * green,bool * blue,bool * alpha)684     static constexpr void UnpackColorMask(const size_t value,
685                                           bool *red,
686                                           bool *green,
687                                           bool *blue,
688                                           bool *alpha)
689     {
690         *red   = static_cast<bool>(value & 1);
691         *green = static_cast<bool>(value & 2);
692         *blue  = static_cast<bool>(value & 4);
693         *alpha = static_cast<bool>(value & 8);
694     }
695 
696     ColorMaskStorage::Type expandColorMaskValue(const bool red,
697                                                 const bool green,
698                                                 const bool blue,
699                                                 const bool alpha) const;
700     ColorMaskStorage::Type expandColorMaskIndexed(const size_t index) const;
701     void setColorMask(const bool red, const bool green, const bool blue, const bool alpha);
702     void setColorMaskIndexed(const size_t index, const uint8_t value);
703     void setColorMaskIndexed(const size_t index,
704                              const bool red,
705                              const bool green,
706                              const bool blue,
707                              const bool alpha);
708     uint8_t getColorMaskIndexed(const size_t index) const;
709     void getColorMaskIndexed(const size_t index,
710                              bool *red,
711                              bool *green,
712                              bool *blue,
713                              bool *alpha) const;
714     DrawBufferMask compareColorMask(ColorMaskStorage::Type other) const;
715 
716     ///////// Blend Equation /////////
717 
718     EquationStorage::Type expandEquationValue(const GLenum mode) const;
719     EquationStorage::Type expandEquationValue(const gl::BlendEquationType equation) const;
720     EquationStorage::Type expandEquationColorIndexed(const size_t index) const;
721     EquationStorage::Type expandEquationAlphaIndexed(const size_t index) const;
722     void setEquations(const GLenum modeColor, const GLenum modeAlpha);
723     void setEquationsIndexed(const size_t index, const GLenum modeColor, const GLenum modeAlpha);
724     void setEquationsIndexed(const size_t index,
725                              const size_t otherIndex,
726                              const BlendStateExt &other);
getEquationColorIndexed(size_t index)727     BlendEquationType getEquationColorIndexed(size_t index) const
728     {
729         ASSERT(index < mDrawBufferCount);
730         return EquationStorage::GetValueIndexed(index, mEquationColor);
731     }
getEquationAlphaIndexed(size_t index)732     BlendEquationType getEquationAlphaIndexed(size_t index) const
733     {
734         ASSERT(index < mDrawBufferCount);
735         return EquationStorage::GetValueIndexed(index, mEquationAlpha);
736     }
737     DrawBufferMask compareEquations(const EquationStorage::Type color,
738                                     const EquationStorage::Type alpha) const;
compareEquations(const BlendStateExt & other)739     DrawBufferMask compareEquations(const BlendStateExt &other) const
740     {
741         return compareEquations(other.mEquationColor, other.mEquationAlpha);
742     }
743 
744     ///////// Blend Factors /////////
745 
746     FactorStorage::Type expandFactorValue(const GLenum func) const;
747     FactorStorage::Type expandFactorValue(const gl::BlendFactorType func) const;
748     FactorStorage::Type expandSrcColorIndexed(const size_t index) const;
749     FactorStorage::Type expandDstColorIndexed(const size_t index) const;
750     FactorStorage::Type expandSrcAlphaIndexed(const size_t index) const;
751     FactorStorage::Type expandDstAlphaIndexed(const size_t index) const;
752     void setFactors(const GLenum srcColor,
753                     const GLenum dstColor,
754                     const GLenum srcAlpha,
755                     const GLenum dstAlpha);
756     void setFactorsIndexed(const size_t index,
757                            const gl::BlendFactorType srcColorFactor,
758                            const gl::BlendFactorType dstColorFactor,
759                            const gl::BlendFactorType srcAlphaFactor,
760                            const gl::BlendFactorType dstAlphaFactor);
761     void setFactorsIndexed(const size_t index,
762                            const GLenum srcColor,
763                            const GLenum dstColor,
764                            const GLenum srcAlpha,
765                            const GLenum dstAlpha);
766     void setFactorsIndexed(const size_t index, const size_t otherIndex, const BlendStateExt &other);
getSrcColorIndexed(size_t index)767     BlendFactorType getSrcColorIndexed(size_t index) const
768     {
769         ASSERT(index < mDrawBufferCount);
770         return FactorStorage::GetValueIndexed(index, mSrcColor);
771     }
getDstColorIndexed(size_t index)772     BlendFactorType getDstColorIndexed(size_t index) const
773     {
774         ASSERT(index < mDrawBufferCount);
775         return FactorStorage::GetValueIndexed(index, mDstColor);
776     }
getSrcAlphaIndexed(size_t index)777     BlendFactorType getSrcAlphaIndexed(size_t index) const
778     {
779         ASSERT(index < mDrawBufferCount);
780         return FactorStorage::GetValueIndexed(index, mSrcAlpha);
781     }
getDstAlphaIndexed(size_t index)782     BlendFactorType getDstAlphaIndexed(size_t index) const
783     {
784         ASSERT(index < mDrawBufferCount);
785         return FactorStorage::GetValueIndexed(index, mDstAlpha);
786     }
787     DrawBufferMask compareFactors(const FactorStorage::Type srcColor,
788                                   const FactorStorage::Type dstColor,
789                                   const FactorStorage::Type srcAlpha,
790                                   const FactorStorage::Type dstAlpha) const;
compareFactors(const BlendStateExt & other)791     DrawBufferMask compareFactors(const BlendStateExt &other) const
792     {
793         return compareFactors(other.mSrcColor, other.mDstColor, other.mSrcAlpha, other.mDstAlpha);
794     }
795 
getSrcColorBits()796     constexpr FactorStorage::Type getSrcColorBits() const { return mSrcColor; }
getSrcAlphaBits()797     constexpr FactorStorage::Type getSrcAlphaBits() const { return mSrcAlpha; }
getDstColorBits()798     constexpr FactorStorage::Type getDstColorBits() const { return mDstColor; }
getDstAlphaBits()799     constexpr FactorStorage::Type getDstAlphaBits() const { return mDstAlpha; }
800 
getEquationColorBits()801     constexpr EquationStorage::Type getEquationColorBits() const { return mEquationColor; }
getEquationAlphaBits()802     constexpr EquationStorage::Type getEquationAlphaBits() const { return mEquationAlpha; }
803 
getAllColorMaskBits()804     constexpr ColorMaskStorage::Type getAllColorMaskBits() const { return mAllColorMask; }
getColorMaskBits()805     constexpr ColorMaskStorage::Type getColorMaskBits() const { return mColorMask; }
806 
getAllEnabledMask()807     constexpr DrawBufferMask getAllEnabledMask() const { return mAllEnabledMask; }
getEnabledMask()808     constexpr DrawBufferMask getEnabledMask() const { return mEnabledMask; }
809 
getUsesAdvancedBlendEquationMask()810     constexpr DrawBufferMask getUsesAdvancedBlendEquationMask() const
811     {
812         return mUsesAdvancedBlendEquationMask;
813     }
814 
getUsesExtendedBlendFactorMask()815     constexpr DrawBufferMask getUsesExtendedBlendFactorMask() const
816     {
817         return mUsesExtendedBlendFactorMask;
818     }
819 
getDrawBufferCount()820     constexpr uint8_t getDrawBufferCount() const { return mDrawBufferCount; }
821 
setSrcColorBits(const FactorStorage::Type srcColor)822     constexpr void setSrcColorBits(const FactorStorage::Type srcColor) { mSrcColor = srcColor; }
setSrcAlphaBits(const FactorStorage::Type srcAlpha)823     constexpr void setSrcAlphaBits(const FactorStorage::Type srcAlpha) { mSrcAlpha = srcAlpha; }
setDstColorBits(const FactorStorage::Type dstColor)824     constexpr void setDstColorBits(const FactorStorage::Type dstColor) { mDstColor = dstColor; }
setDstAlphaBits(const FactorStorage::Type dstAlpha)825     constexpr void setDstAlphaBits(const FactorStorage::Type dstAlpha) { mDstAlpha = dstAlpha; }
826 
setEquationColorBits(const EquationStorage::Type equationColor)827     constexpr void setEquationColorBits(const EquationStorage::Type equationColor)
828     {
829         mEquationColor = equationColor;
830     }
setEquationAlphaBits(const EquationStorage::Type equationAlpha)831     constexpr void setEquationAlphaBits(const EquationStorage::Type equationAlpha)
832     {
833         mEquationAlpha = equationAlpha;
834     }
835 
setColorMaskBits(const ColorMaskStorage::Type colorMask)836     constexpr void setColorMaskBits(const ColorMaskStorage::Type colorMask)
837     {
838         mColorMask = colorMask;
839     }
840 
setEnabledMask(const DrawBufferMask enabledMask)841     constexpr void setEnabledMask(const DrawBufferMask enabledMask) { mEnabledMask = enabledMask; }
842 
843     ///////// Data Members /////////
844   private:
845     uint64_t mParameterMask;
846 
847     FactorStorage::Type mSrcColor;
848     FactorStorage::Type mDstColor;
849     FactorStorage::Type mSrcAlpha;
850     FactorStorage::Type mDstAlpha;
851 
852     EquationStorage::Type mEquationColor;
853     EquationStorage::Type mEquationAlpha;
854 
855     ColorMaskStorage::Type mAllColorMask;
856     ColorMaskStorage::Type mColorMask;
857 
858     DrawBufferMask mAllEnabledMask;
859     DrawBufferMask mEnabledMask;
860 
861     // Cache of whether the blend equation for each index is from KHR_blend_equation_advanced.
862     DrawBufferMask mUsesAdvancedBlendEquationMask;
863 
864     // Cache of whether the blend factor for each index is from EXT_blend_func_extended.
865     DrawBufferMask mUsesExtendedBlendFactorMask;
866 
867     uint8_t mDrawBufferCount;
868 
869     ANGLE_MAYBE_UNUSED_PRIVATE_FIELD uint8_t kUnused[3] = {};
870 };
871 
872 static_assert(sizeof(BlendStateExt) == sizeof(uint64_t) +
873                                            (sizeof(BlendStateExt::FactorStorage::Type) * 4 +
874                                             sizeof(BlendStateExt::EquationStorage::Type) * 2 +
875                                             sizeof(BlendStateExt::ColorMaskStorage::Type) * 2 +
876                                             sizeof(DrawBufferMask) * 4 + sizeof(uint8_t)) +
877                                            sizeof(uint8_t) * 3,
878               "The BlendStateExt class must not contain gaps.");
879 
880 // Used in StateCache
881 using StorageBuffersMask = angle::BitSet<IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS>;
882 
883 template <typename T>
884 using SampleMaskArray = std::array<T, IMPLEMENTATION_MAX_SAMPLE_MASK_WORDS>;
885 
886 template <typename T>
887 using TexLevelArray = std::array<T, IMPLEMENTATION_MAX_TEXTURE_LEVELS>;
888 
889 using TexLevelMask = angle::BitSet<IMPLEMENTATION_MAX_TEXTURE_LEVELS>;
890 
891 enum class ComponentType
892 {
893     Float       = 0,
894     Int         = 1,
895     UnsignedInt = 2,
896     NoType      = 3,
897     EnumCount   = 4,
898     InvalidEnum = 4,
899 };
900 
GLenumToComponentType(GLenum componentType)901 constexpr ComponentType GLenumToComponentType(GLenum componentType)
902 {
903     switch (componentType)
904     {
905         case GL_FLOAT:
906             return ComponentType::Float;
907         case GL_INT:
908             return ComponentType::Int;
909         case GL_UNSIGNED_INT:
910             return ComponentType::UnsignedInt;
911         case GL_NONE:
912             return ComponentType::NoType;
913         default:
914             return ComponentType::InvalidEnum;
915     }
916 }
917 
918 constexpr angle::PackedEnumMap<ComponentType, uint32_t> kComponentMasks = {{
919     {ComponentType::Float, 0x10001},
920     {ComponentType::Int, 0x00001},
921     {ComponentType::UnsignedInt, 0x10000},
922 }};
923 
924 constexpr size_t kMaxComponentTypeMaskIndex = 16;
925 using ComponentTypeMask                     = angle::BitSet<kMaxComponentTypeMaskIndex * 2>;
926 
SetComponentTypeMask(ComponentType type,size_t index,ComponentTypeMask * mask)927 ANGLE_INLINE void SetComponentTypeMask(ComponentType type, size_t index, ComponentTypeMask *mask)
928 {
929     ASSERT(index <= kMaxComponentTypeMaskIndex);
930     *mask &= ~(0x10001 << index);
931     *mask |= kComponentMasks[type] << index;
932 }
933 
GetComponentTypeMask(ComponentTypeMask mask,size_t index)934 ANGLE_INLINE ComponentType GetComponentTypeMask(ComponentTypeMask mask, size_t index)
935 {
936     ASSERT(index <= kMaxComponentTypeMaskIndex);
937     uint32_t mask_bits = mask.bits() >> index & 0x10001;
938     switch (mask_bits)
939     {
940         case 0x10001:
941             return ComponentType::Float;
942         case 0x00001:
943             return ComponentType::Int;
944         case 0x10000:
945             return ComponentType::UnsignedInt;
946         default:
947             return ComponentType::InvalidEnum;
948     }
949 }
950 
GetActiveComponentTypeMask(gl::AttributesMask activeAttribLocations)951 ANGLE_INLINE ComponentTypeMask GetActiveComponentTypeMask(gl::AttributesMask activeAttribLocations)
952 {
953     const uint32_t activeAttribs = static_cast<uint32_t>(activeAttribLocations.bits());
954 
955     // Ever attrib index takes one bit from the lower 16-bits and another bit from the upper
956     // 16-bits at the same index.
957     return ComponentTypeMask(activeAttribs << kMaxComponentTypeMaskIndex | activeAttribs);
958 }
959 
GetComponentTypeMaskDiff(ComponentTypeMask mask1,ComponentTypeMask mask2)960 ANGLE_INLINE DrawBufferMask GetComponentTypeMaskDiff(ComponentTypeMask mask1,
961                                                      ComponentTypeMask mask2)
962 {
963     const uint32_t diff = static_cast<uint32_t>((mask1 ^ mask2).bits());
964     return DrawBufferMask(static_cast<uint8_t>(diff | (diff >> gl::kMaxComponentTypeMaskIndex)));
965 }
966 
967 bool ValidateComponentTypeMasks(unsigned long outputTypes,
968                                 unsigned long inputTypes,
969                                 unsigned long outputMask,
970                                 unsigned long inputMask);
971 
972 // Helpers for performing WebGL 2.0 clear validation
973 // Extracted component type has always one of these four values:
974 // * 0x10001 - float or normalized
975 // * 0x00001 - int
976 // * 0x10000 - unsigned int
977 // * 0x00000 - unused or disabled
978 
979 // The following functions rely on these.
980 static_assert(kComponentMasks[ComponentType::Float] == 0x10001);
981 static_assert(kComponentMasks[ComponentType::Int] == 0x00001);
982 static_assert(kComponentMasks[ComponentType::UnsignedInt] == 0x10000);
983 
984 // Used for clearBufferuiv
IsComponentTypeFloatOrInt(ComponentTypeMask mask,size_t index)985 ANGLE_INLINE bool IsComponentTypeFloatOrInt(ComponentTypeMask mask, size_t index)
986 {
987     ASSERT(index <= kMaxComponentTypeMaskIndex);
988     // 0x10001 or 0x00001
989     return ((mask.bits() >> index) & 0x00001) != 0;
990 }
991 
992 // Used for clearBufferiv
IsComponentTypeFloatOrUnsignedInt(ComponentTypeMask mask,size_t index)993 ANGLE_INLINE bool IsComponentTypeFloatOrUnsignedInt(ComponentTypeMask mask, size_t index)
994 {
995     ASSERT(index <= kMaxComponentTypeMaskIndex);
996     // 0x10001 or 0x10000
997     return ((mask.bits() >> index) & 0x10000) != 0;
998 }
999 
1000 // Used for clearBufferfv
IsComponentTypeIntOrUnsignedInt(ComponentTypeMask mask,size_t index)1001 ANGLE_INLINE bool IsComponentTypeIntOrUnsignedInt(ComponentTypeMask mask, size_t index)
1002 {
1003     ASSERT(index <= kMaxComponentTypeMaskIndex);
1004     // 0x00001 or 0x10000; this expression is more efficient than two explicit comparisons
1005     return ((((mask.bits() >> kMaxComponentTypeMaskIndex) ^ mask.bits()) >> index) & 1) != 0;
1006 }
1007 
1008 // Used for clear
GetIntOrUnsignedIntDrawBufferMask(ComponentTypeMask mask)1009 ANGLE_INLINE DrawBufferMask GetIntOrUnsignedIntDrawBufferMask(ComponentTypeMask mask)
1010 {
1011     static_assert(DrawBufferMask::size() <= 8);
1012     return DrawBufferMask(
1013         static_cast<uint8_t>((mask.bits() >> kMaxComponentTypeMaskIndex) ^ mask.bits()));
1014 }
1015 
1016 enum class RenderToTextureImageIndex
1017 {
1018     // The default image of the texture, where data is expected to be.
1019     Default = 0,
1020 
1021     // Intermediate multisampled images for EXT_multisampled_render_to_texture.
1022     // These values must match log2(SampleCount).
1023     IntermediateImage2xMultisampled  = 1,
1024     IntermediateImage4xMultisampled  = 2,
1025     IntermediateImage8xMultisampled  = 3,
1026     IntermediateImage16xMultisampled = 4,
1027 
1028     // We currently only support up to 16xMSAA in backends that use this enum.
1029     InvalidEnum = 5,
1030     EnumCount   = 5,
1031 };
1032 
1033 template <typename T>
1034 using RenderToTextureImageMap = angle::PackedEnumMap<RenderToTextureImageIndex, T>;
1035 
1036 constexpr size_t kCubeFaceCount = 6;
1037 
1038 template <typename T>
1039 using CubeFaceArray = std::array<T, kCubeFaceCount>;
1040 
1041 template <typename T>
1042 using TextureTypeMap = angle::PackedEnumMap<TextureType, T>;
1043 using TextureMap     = TextureTypeMap<BindingPointer<Texture>>;
1044 
1045 // ShaderVector can contain one item per shader.  It differs from ShaderMap in that the values are
1046 // not indexed by ShaderType.
1047 template <typename T>
1048 using ShaderVector = angle::FixedVector<T, static_cast<size_t>(ShaderType::EnumCount)>;
1049 
1050 template <typename T>
1051 using AttachmentArray = std::array<T, IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS>;
1052 
1053 template <typename T>
1054 using AttachmentVector = angle::FixedVector<T, IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS>;
1055 
1056 using AttachmentsMask = angle::BitSet<IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS>;
1057 
1058 template <typename T>
1059 using DrawBuffersArray = std::array<T, IMPLEMENTATION_MAX_DRAW_BUFFERS>;
1060 
1061 template <typename T>
1062 using DrawBuffersVector = angle::FixedVector<T, IMPLEMENTATION_MAX_DRAW_BUFFERS>;
1063 
1064 template <typename T>
1065 using AttribArray = std::array<T, MAX_VERTEX_ATTRIBS>;
1066 
1067 template <typename T>
1068 using AttribVector = angle::FixedVector<T, MAX_VERTEX_ATTRIBS>;
1069 
1070 using ActiveTextureMask = angle::BitSet<IMPLEMENTATION_MAX_ACTIVE_TEXTURES>;
1071 
1072 template <typename T>
1073 using ActiveTextureArray = std::array<T, IMPLEMENTATION_MAX_ACTIVE_TEXTURES>;
1074 
1075 using ActiveTextureTypeArray = ActiveTextureArray<TextureType>;
1076 
1077 using ImageUnitMask = angle::BitSet<IMPLEMENTATION_MAX_IMAGE_UNITS>;
1078 
1079 using SupportedSampleSet = std::set<GLuint>;
1080 
1081 template <typename T>
1082 using TransformFeedbackBuffersArray =
1083     std::array<T, gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS>;
1084 
1085 using ClipDistanceEnableBits = angle::BitSet32<IMPLEMENTATION_MAX_CLIP_DISTANCES>;
1086 
1087 template <typename T>
1088 using QueryTypeMap = angle::PackedEnumMap<QueryType, T>;
1089 
1090 constexpr size_t kBarrierVectorDefaultSize = 16;
1091 
1092 template <typename T>
1093 using BarrierVector = angle::FastVector<T, kBarrierVectorDefaultSize>;
1094 
1095 using BufferBarrierVector = BarrierVector<Buffer *>;
1096 
1097 using SamplerBindingVector = std::vector<BindingPointer<Sampler>>;
1098 using BufferVector         = std::vector<OffsetBindingPointer<Buffer>>;
1099 
1100 struct TextureAndLayout
1101 {
1102     Texture *texture;
1103     GLenum layout;
1104 };
1105 using TextureBarrierVector = BarrierVector<TextureAndLayout>;
1106 
1107 // OffsetBindingPointer.getSize() returns the size specified by the user, which may be larger than
1108 // the size of the bound buffer. This function reduces the returned size to fit the bound buffer if
1109 // necessary. Returns 0 if no buffer is bound or if integer overflow occurs.
1110 GLsizeiptr GetBoundBufferAvailableSize(const OffsetBindingPointer<Buffer> &binding);
1111 
1112 // A texture level index.
1113 template <typename T>
1114 class LevelIndexWrapper
1115 {
1116   public:
1117     LevelIndexWrapper() = default;
LevelIndexWrapper(T levelIndex)1118     explicit constexpr LevelIndexWrapper(T levelIndex) : mLevelIndex(levelIndex) {}
1119     constexpr LevelIndexWrapper(const LevelIndexWrapper &other)            = default;
1120     constexpr LevelIndexWrapper &operator=(const LevelIndexWrapper &other) = default;
1121 
get()1122     constexpr T get() const { return mLevelIndex; }
1123 
1124     LevelIndexWrapper &operator++()
1125     {
1126         ++mLevelIndex;
1127         return *this;
1128     }
1129     constexpr bool operator<(const LevelIndexWrapper &other) const
1130     {
1131         return mLevelIndex < other.mLevelIndex;
1132     }
1133     constexpr bool operator<=(const LevelIndexWrapper &other) const
1134     {
1135         return mLevelIndex <= other.mLevelIndex;
1136     }
1137     constexpr bool operator>(const LevelIndexWrapper &other) const
1138     {
1139         return mLevelIndex > other.mLevelIndex;
1140     }
1141     constexpr bool operator>=(const LevelIndexWrapper &other) const
1142     {
1143         return mLevelIndex >= other.mLevelIndex;
1144     }
1145     constexpr bool operator==(const LevelIndexWrapper &other) const
1146     {
1147         return mLevelIndex == other.mLevelIndex;
1148     }
1149     constexpr bool operator!=(const LevelIndexWrapper &other) const
1150     {
1151         return mLevelIndex != other.mLevelIndex;
1152     }
1153     constexpr LevelIndexWrapper operator+(T other) const
1154     {
1155         return LevelIndexWrapper(mLevelIndex + other);
1156     }
1157     constexpr LevelIndexWrapper operator-(T other) const
1158     {
1159         return LevelIndexWrapper(mLevelIndex - other);
1160     }
1161     constexpr T operator-(LevelIndexWrapper other) const { return mLevelIndex - other.mLevelIndex; }
1162 
1163   private:
1164     T mLevelIndex;
1165 };
1166 
1167 // A GL texture level index.
1168 using LevelIndex = LevelIndexWrapper<GLint>;
1169 
1170 enum class MultisamplingMode
1171 {
1172     // Regular multisampling
1173     Regular = 0,
1174     // GL_EXT_multisampled_render_to_texture renderbuffer/texture attachments which perform implicit
1175     // resolve of multisampled data.
1176     MultisampledRenderToTexture,
1177 };
1178 }  // namespace gl
1179 
1180 namespace rx
1181 {
1182 // A macro that determines whether an object has a given runtime type.
1183 #if defined(__clang__)
1184 #    if __has_feature(cxx_rtti)
1185 #        define ANGLE_HAS_DYNAMIC_CAST 1
1186 #    endif
1187 #elif !defined(NDEBUG) && (!defined(_MSC_VER) || defined(_CPPRTTI)) &&              \
1188     (!defined(__GNUC__) || __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 3) || \
1189      defined(__GXX_RTTI))
1190 #    define ANGLE_HAS_DYNAMIC_CAST 1
1191 #endif
1192 
1193 #ifdef ANGLE_HAS_DYNAMIC_CAST
1194 #    define ANGLE_HAS_DYNAMIC_TYPE(type, obj) (dynamic_cast<type>(obj) != nullptr)
1195 #    undef ANGLE_HAS_DYNAMIC_CAST
1196 #else
1197 #    define ANGLE_HAS_DYNAMIC_TYPE(type, obj) (obj != nullptr)
1198 #endif
1199 
1200 // Downcast a base implementation object (EG TextureImpl to TextureD3D)
1201 template <typename DestT, typename SrcT>
GetAs(SrcT * src)1202 inline DestT *GetAs(SrcT *src)
1203 {
1204     ASSERT(ANGLE_HAS_DYNAMIC_TYPE(DestT *, src));
1205     return static_cast<DestT *>(src);
1206 }
1207 
1208 template <typename DestT, typename SrcT>
GetAs(const SrcT * src)1209 inline const DestT *GetAs(const SrcT *src)
1210 {
1211     ASSERT(ANGLE_HAS_DYNAMIC_TYPE(const DestT *, src));
1212     return static_cast<const DestT *>(src);
1213 }
1214 
1215 #undef ANGLE_HAS_DYNAMIC_TYPE
1216 
1217 // Downcast a GL object to an Impl (EG gl::Texture to rx::TextureD3D)
1218 template <typename DestT, typename SrcT>
GetImplAs(SrcT * src)1219 inline DestT *GetImplAs(SrcT *src)
1220 {
1221     return GetAs<DestT>(src->getImplementation());
1222 }
1223 
1224 template <typename DestT, typename SrcT>
SafeGetImplAs(SrcT * src)1225 inline DestT *SafeGetImplAs(SrcT *src)
1226 {
1227     return src != nullptr ? GetAs<DestT>(src->getImplementation()) : nullptr;
1228 }
1229 
1230 }  // namespace rx
1231 
1232 #include "angletypes.inc"
1233 
1234 namespace angle
1235 {
1236 enum class NativeWindowSystem
1237 {
1238     X11,
1239     Wayland,
1240     Gbm,
1241     Other,
1242 };
1243 
1244 struct FeatureOverrides
1245 {
1246     std::vector<std::string> enabled;
1247     std::vector<std::string> disabled;
1248     bool allDisabled = false;
1249 };
1250 
1251 // 160-bit SHA-1 hash key used for hasing a program.  BlobCache opts in using fixed keys for
1252 // simplicity and efficiency.
1253 static constexpr size_t kBlobCacheKeyLength = angle::base::kSHA1Length;
1254 using BlobCacheKey                          = std::array<uint8_t, kBlobCacheKeyLength>;
1255 class BlobCacheValue  // To be replaced with std::span when C++20 is required
1256 {
1257   public:
BlobCacheValue()1258     BlobCacheValue() : mPtr(nullptr), mSize(0) {}
BlobCacheValue(const uint8_t * ptr,size_t size)1259     BlobCacheValue(const uint8_t *ptr, size_t size) : mPtr(ptr), mSize(size) {}
1260 
1261     // A very basic struct to hold the pointer and size together.  The objects of this class
1262     // don't own the memory.
data()1263     const uint8_t *data() { return mPtr; }
size()1264     size_t size() { return mSize; }
1265 
1266     const uint8_t &operator[](size_t pos) const
1267     {
1268         ASSERT(pos < mSize);
1269         return mPtr[pos];
1270     }
1271 
1272   private:
1273     const uint8_t *mPtr;
1274     size_t mSize;
1275 };
1276 
1277 bool CompressBlob(const size_t cacheSize, const uint8_t *cacheData, MemoryBuffer *compressedData);
1278 bool DecompressBlob(const uint8_t *compressedData,
1279                     const size_t compressedSize,
1280                     size_t maxUncompressedDataSize,
1281                     MemoryBuffer *uncompressedData);
1282 uint32_t GenerateCrc(const uint8_t *data, size_t size);
1283 }  // namespace angle
1284 
1285 namespace std
1286 {
1287 template <>
1288 struct hash<angle::BlobCacheKey>
1289 {
1290     // Simple routine to hash four ints.
1291     size_t operator()(const angle::BlobCacheKey &key) const
1292     {
1293         return angle::ComputeGenericHash(key.data(), key.size());
1294     }
1295 };
1296 }  // namespace std
1297 
1298 namespace angle
1299 {
1300 // Under certain circumstances, such as for increased parallelism, the backend may defer an
1301 // operation to be done at the end of a call after the locks have been unlocked.  The entry point
1302 // function passes an |UnlockedTailCall| through the frontend to the backend.  If it is set, the
1303 // entry point would execute it at the end of the call.
1304 //
1305 // Since the function is called without any locks, care must be taken to minimize the amount of work
1306 // in such calls and ensure thread safety (for example by using fine grained locks inside the call
1307 // itself).
1308 //
1309 // Some entry points pass a void pointer argument to UnlockedTailCall::run method intended to
1310 // contain the return value filled by the backend, the rest of the entry points pass in a
1311 // nullptr.  Regardless, Display::terminate runs pending tail calls passing in a nullptr, so
1312 // the tail calls that return a value in the argument still have to guard against a nullptr
1313 // parameter.
1314 class UnlockedTailCall final : angle::NonCopyable
1315 {
1316   public:
1317     using CallType = std::function<void(void *)>;
1318 
1319     UnlockedTailCall();
1320     ~UnlockedTailCall();
1321 
1322     void add(CallType &&call);
1323     ANGLE_INLINE void run(void *resultOut)
1324     {
1325         if (!mCalls.empty())
1326         {
1327             runImpl(resultOut);
1328         }
1329     }
1330 
1331     bool any() const { return !mCalls.empty(); }
1332 
1333   private:
1334     void runImpl(void *resultOut);
1335 
1336     // Typically, there is only one tail call.  It is possible to end up with 2 tail calls currently
1337     // with unMakeCurrent destroying both the read and draw surfaces, each adding a tail call in the
1338     // Vulkan backend.
1339     //
1340     // The max count can be increased as necessary.  An assertion would fire inside FixedVector if
1341     // the max count is surpassed.
1342     static constexpr size_t kMaxCallCount = 2;
1343     angle::FixedVector<CallType, kMaxCallCount> mCalls;
1344 };
1345 
1346 enum class JobThreadSafety
1347 {
1348     Safe,
1349     Unsafe,
1350 };
1351 
1352 enum class JobResultExpectancy
1353 {
1354     // Whether the compile or link job's results are immediately needed.  This is the case for GLES1
1355     // programs for example, or shader compilation in glCreateShaderProgramv.
1356     Immediate,
1357     // Whether the compile or link job's results are needed after the end of the current entry point
1358     // call.  In this case, the job may be done in an unlocked tail call.
1359     Future,
1360 };
1361 
1362 // Zero-based for better array indexing
1363 enum FramebufferBinding
1364 {
1365     FramebufferBindingRead = 0,
1366     FramebufferBindingDraw,
1367     FramebufferBindingSingletonMax,
1368     FramebufferBindingBoth = FramebufferBindingSingletonMax,
1369     FramebufferBindingMax,
1370     FramebufferBindingUnknown = FramebufferBindingMax,
1371 };
1372 
1373 inline FramebufferBinding EnumToFramebufferBinding(GLenum enumValue)
1374 {
1375     switch (enumValue)
1376     {
1377         case GL_READ_FRAMEBUFFER:
1378             return FramebufferBindingRead;
1379         case GL_DRAW_FRAMEBUFFER:
1380             return FramebufferBindingDraw;
1381         case GL_FRAMEBUFFER:
1382             return FramebufferBindingBoth;
1383         default:
1384             UNREACHABLE();
1385             return FramebufferBindingUnknown;
1386     }
1387 }
1388 
1389 inline GLenum FramebufferBindingToEnum(FramebufferBinding binding)
1390 {
1391     switch (binding)
1392     {
1393         case FramebufferBindingRead:
1394             return GL_READ_FRAMEBUFFER;
1395         case FramebufferBindingDraw:
1396             return GL_DRAW_FRAMEBUFFER;
1397         case FramebufferBindingBoth:
1398             return GL_FRAMEBUFFER;
1399         default:
1400             UNREACHABLE();
1401             return GL_NONE;
1402     }
1403 }
1404 
1405 template <typename ObjT, typename ContextT>
1406 class DestroyThenDelete
1407 {
1408   public:
1409     DestroyThenDelete() = default;
1410     DestroyThenDelete(const ContextT *context) : mContext(context) {}
1411 
1412     void operator()(ObjT *obj)
1413     {
1414         (void)(obj->onDestroy(mContext));
1415         delete obj;
1416     }
1417 
1418   private:
1419     const ContextT *mContext = nullptr;
1420 };
1421 
1422 template <typename ObjT, typename ContextT>
1423 using UniqueObjectPointer = std::unique_ptr<ObjT, DestroyThenDelete<ObjT, ContextT>>;
1424 
1425 }  // namespace angle
1426 
1427 namespace gl
1428 {
1429 class State;
1430 
1431 // Focal Point information for foveated rendering
1432 struct FocalPoint
1433 {
1434     float focalX;
1435     float focalY;
1436     float gainX;
1437     float gainY;
1438     float foveaArea;
1439 
1440     constexpr FocalPoint() : focalX(0), focalY(0), gainX(0), gainY(0), foveaArea(0) {}
1441 
1442     FocalPoint(float fX, float fY, float gX, float gY, float fArea)
1443         : focalX(fX), focalY(fY), gainX(gX), gainY(gY), foveaArea(fArea)
1444     {}
1445     FocalPoint(const FocalPoint &other)            = default;
1446     FocalPoint &operator=(const FocalPoint &other) = default;
1447 
1448     bool operator==(const FocalPoint &other) const
1449     {
1450         return focalX == other.focalX && focalY == other.focalY && gainX == other.gainX &&
1451                gainY == other.gainY && foveaArea == other.foveaArea;
1452     }
1453     bool operator!=(const FocalPoint &other) const { return !(*this == other); }
1454 };
1455 
1456 constexpr FocalPoint kInvalidFocalPoint = FocalPoint();
1457 
1458 class FoveationState
1459 {
1460   public:
1461     FoveationState()
1462     {
1463         mConfigured          = false;
1464         mFoveatedFeatureBits = 0;
1465         mMinPixelDensity     = 0.0f;
1466         mFocalPoints.fill(kInvalidFocalPoint);
1467     }
1468     FoveationState &operator=(const FoveationState &other) = default;
1469 
1470     void configure() { mConfigured = true; }
1471     bool isConfigured() const { return mConfigured; }
1472     bool isFoveated() const
1473     {
1474         // Consider foveated if ANY focal point is valid
1475         return std::any_of(
1476             mFocalPoints.begin(), mFocalPoints.end(),
1477             [](const FocalPoint &focalPoint) { return (focalPoint != kInvalidFocalPoint); });
1478     }
1479     bool operator==(const FoveationState &other) const
1480     {
1481         return mConfigured == other.mConfigured &&
1482                mFoveatedFeatureBits == other.mFoveatedFeatureBits &&
1483                mMinPixelDensity == other.mMinPixelDensity && mFocalPoints == other.mFocalPoints;
1484     }
1485     bool operator!=(const FoveationState &other) const { return !(*this == other); }
1486 
1487     void setFoveatedFeatureBits(const GLuint features) { mFoveatedFeatureBits = features; }
1488     GLuint getFoveatedFeatureBits() const { return mFoveatedFeatureBits; }
1489     void setMinPixelDensity(const GLfloat density) { mMinPixelDensity = density; }
1490     GLfloat getMinPixelDensity() const { return mMinPixelDensity; }
1491     GLuint getMaxNumFocalPoints() const { return gl::IMPLEMENTATION_MAX_FOCAL_POINTS; }
1492     void setFocalPoint(uint32_t layer, uint32_t focalPointIndex, const FocalPoint &focalPoint)
1493     {
1494         mFocalPoints[getIndex(layer, focalPointIndex)] = focalPoint;
1495     }
1496     const FocalPoint &getFocalPoint(uint32_t layer, uint32_t focalPointIndex) const
1497     {
1498         return mFocalPoints[getIndex(layer, focalPointIndex)];
1499     }
1500     GLuint getSupportedFoveationFeatures() const { return GL_FOVEATION_ENABLE_BIT_QCOM; }
1501 
1502   private:
1503     size_t getIndex(uint32_t layer, uint32_t focalPointIndex) const
1504     {
1505         ASSERT(layer < IMPLEMENTATION_MAX_NUM_LAYERS &&
1506                focalPointIndex < IMPLEMENTATION_MAX_FOCAL_POINTS);
1507         return (layer * IMPLEMENTATION_MAX_FOCAL_POINTS) + focalPointIndex;
1508     }
1509     bool mConfigured;
1510     GLuint mFoveatedFeatureBits;
1511     GLfloat mMinPixelDensity;
1512 
1513     static constexpr size_t kMaxFocalPoints =
1514         IMPLEMENTATION_MAX_NUM_LAYERS * IMPLEMENTATION_MAX_FOCAL_POINTS;
1515     std::array<FocalPoint, kMaxFocalPoints> mFocalPoints;
1516 };
1517 
1518 }  // namespace gl
1519 
1520 #endif  // LIBANGLE_ANGLETYPES_H_
1521