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