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 "common/Color.h"
13 #include "common/FixedVector.h"
14 #include "common/PackedEnums.h"
15 #include "common/bitset_utils.h"
16 #include "common/vector_utils.h"
17 #include "libANGLE/Constants.h"
18 #include "libANGLE/Error.h"
19 #include "libANGLE/RefCountObject.h"
20 
21 #include <inttypes.h>
22 #include <stdint.h>
23 
24 #include <bitset>
25 #include <map>
26 #include <unordered_map>
27 
28 namespace gl
29 {
30 class Buffer;
31 class Texture;
32 
33 enum class Command
34 {
35     Blit,
36     Clear,
37     CopyImage,
38     Dispatch,
39     Draw,
40     GenerateMipmap,
41     ReadPixels,
42     TexImage,
43     Other
44 };
45 
46 enum class InitState
47 {
48     MayNeedInit,
49     Initialized,
50 };
51 
52 struct Rectangle
53 {
RectangleRectangle54     Rectangle() : x(0), y(0), width(0), height(0) {}
RectangleRectangle55     constexpr Rectangle(int x_in, int y_in, int width_in, int height_in)
56         : x(x_in), y(y_in), width(width_in), height(height_in)
57     {}
58 
x0Rectangle59     int x0() const { return x; }
y0Rectangle60     int y0() const { return y; }
x1Rectangle61     int x1() const { return x + width; }
y1Rectangle62     int y1() const { return y + height; }
63 
isReversedXRectangle64     bool isReversedX() const { return width < 0; }
isReversedYRectangle65     bool isReversedY() const { return height < 0; }
66 
67     // Returns a rectangle with the same area but flipped in X, Y, neither or both.
68     Rectangle flip(bool flipX, bool flipY) const;
69 
70     // Returns a rectangle with the same area but with height and width guaranteed to be positive.
71     Rectangle removeReversal() const;
72 
73     bool encloses(const gl::Rectangle &inside) const;
74 
emptyRectangle75     bool empty() const { return width == 0 && height == 0; }
76 
77     int x;
78     int y;
79     int width;
80     int height;
81 };
82 
83 bool operator==(const Rectangle &a, const Rectangle &b);
84 bool operator!=(const Rectangle &a, const Rectangle &b);
85 
86 enum class ClipSpaceOrigin
87 {
88     LowerLeft = 0,
89     UpperLeft = 1
90 };
91 
92 // Calculate the intersection of two rectangles.  Returns false if the intersection is empty.
93 ANGLE_NO_DISCARD bool ClipRectangle(const Rectangle &source,
94                                     const Rectangle &clip,
95                                     Rectangle *intersection);
96 // Calculate the smallest rectangle that covers both rectangles.  This rectangle may cover areas
97 // not covered by the two rectangles, for example in this situation:
98 //
99 //   +--+        +----+
100 //   | ++-+  ->  |    |
101 //   +-++ |      |    |
102 //     +--+      +----+
103 //
104 void GetEnclosingRectangle(const Rectangle &rect1, const Rectangle &rect2, Rectangle *rectUnion);
105 // Extend the source rectangle to cover parts (or all of) the second rectangle, in such a way that
106 // no area is covered that isn't covered by both rectangles.  For example:
107 //
108 //             +--+        +--+
109 //  source --> |  |        |  |
110 //            ++--+-+  ->  |  |
111 //            |+--+ |      |  |
112 //            +-----+      +--+
113 //
114 void ExtendRectangle(const Rectangle &source, const Rectangle &extend, Rectangle *extended);
115 
116 struct Offset
117 {
OffsetOffset118     constexpr Offset() : x(0), y(0), z(0) {}
OffsetOffset119     constexpr Offset(int x_in, int y_in, int z_in) : x(x_in), y(y_in), z(z_in) {}
120 
121     int x;
122     int y;
123     int z;
124 };
125 
126 constexpr Offset kOffsetZero(0, 0, 0);
127 
128 bool operator==(const Offset &a, const Offset &b);
129 bool operator!=(const Offset &a, const Offset &b);
130 
131 struct Extents
132 {
ExtentsExtents133     Extents() : width(0), height(0), depth(0) {}
ExtentsExtents134     Extents(int width_, int height_, int depth_) : width(width_), height(height_), depth(depth_) {}
135 
136     Extents(const Extents &other) = default;
137     Extents &operator=(const Extents &other) = default;
138 
emptyExtents139     bool empty() const { return (width * height * depth) == 0; }
140 
141     int width;
142     int height;
143     int depth;
144 };
145 
146 bool operator==(const Extents &lhs, const Extents &rhs);
147 bool operator!=(const Extents &lhs, const Extents &rhs);
148 
149 struct Box
150 {
BoxBox151     Box() : x(0), y(0), z(0), width(0), height(0), depth(0) {}
BoxBox152     Box(int x_in, int y_in, int z_in, int width_in, int height_in, int depth_in)
153         : x(x_in), y(y_in), z(z_in), width(width_in), height(height_in), depth(depth_in)
154     {}
155     template <typename O, typename E>
BoxBox156     Box(const O &offset, const E &size)
157         : x(offset.x),
158           y(offset.y),
159           z(offset.z),
160           width(size.width),
161           height(size.height),
162           depth(size.depth)
163     {}
164     bool operator==(const Box &other) const;
165     bool operator!=(const Box &other) const;
166     Rectangle toRect() const;
167 
168     // Whether the Box has offset 0 and the same extents as argument.
169     bool coversSameExtent(const Extents &size) const;
170 
171     int x;
172     int y;
173     int z;
174     int width;
175     int height;
176     int depth;
177 };
178 
179 struct RasterizerState final
180 {
181     // This will zero-initialize the struct, including padding.
182     RasterizerState();
183     RasterizerState(const RasterizerState &other);
184 
185     bool cullFace;
186     CullFaceMode cullMode;
187     GLenum frontFace;
188 
189     bool polygonOffsetFill;
190     GLfloat polygonOffsetFactor;
191     GLfloat polygonOffsetUnits;
192 
193     // pointDrawMode/multiSample are only used in the D3D back-end right now.
194     bool pointDrawMode;
195     bool multiSample;
196 
197     bool rasterizerDiscard;
198 
199     bool dither;
200 };
201 
202 bool operator==(const RasterizerState &a, const RasterizerState &b);
203 bool operator!=(const RasterizerState &a, const RasterizerState &b);
204 
205 struct BlendState final
206 {
207     // This will zero-initialize the struct, including padding.
208     BlendState();
209     BlendState(const BlendState &other);
210 
211     bool blend;
212     GLenum sourceBlendRGB;
213     GLenum destBlendRGB;
214     GLenum sourceBlendAlpha;
215     GLenum destBlendAlpha;
216     GLenum blendEquationRGB;
217     GLenum blendEquationAlpha;
218 
219     bool colorMaskRed;
220     bool colorMaskGreen;
221     bool colorMaskBlue;
222     bool colorMaskAlpha;
223 };
224 
225 bool operator==(const BlendState &a, const BlendState &b);
226 bool operator!=(const BlendState &a, const BlendState &b);
227 
228 struct DepthStencilState final
229 {
230     // This will zero-initialize the struct, including padding.
231     DepthStencilState();
232     DepthStencilState(const DepthStencilState &other);
233 
234     bool isDepthMaskedOut() const;
235     bool isStencilMaskedOut() const;
236     bool isStencilNoOp() const;
237     bool isStencilBackNoOp() const;
238 
239     bool depthTest;
240     GLenum depthFunc;
241     bool depthMask;
242 
243     bool stencilTest;
244     GLenum stencilFunc;
245     GLuint stencilMask;
246     GLenum stencilFail;
247     GLenum stencilPassDepthFail;
248     GLenum stencilPassDepthPass;
249     GLuint stencilWritemask;
250     GLenum stencilBackFunc;
251     GLuint stencilBackMask;
252     GLenum stencilBackFail;
253     GLenum stencilBackPassDepthFail;
254     GLenum stencilBackPassDepthPass;
255     GLuint stencilBackWritemask;
256 };
257 
258 bool operator==(const DepthStencilState &a, const DepthStencilState &b);
259 bool operator!=(const DepthStencilState &a, const DepthStencilState &b);
260 
261 // Packs a sampler state for completeness checks:
262 // * minFilter: 5 values (3 bits)
263 // * magFilter: 2 values (1 bit)
264 // * wrapS:     3 values (2 bits)
265 // * wrapT:     3 values (2 bits)
266 // * compareMode: 1 bit (for == GL_NONE).
267 // This makes a total of 9 bits. We can pack this easily into 32 bits:
268 // * minFilter: 8 bits
269 // * magFilter: 8 bits
270 // * wrapS:     8 bits
271 // * wrapT:     4 bits
272 // * compareMode: 4 bits
273 
274 struct PackedSamplerCompleteness
275 {
276     uint8_t minFilter;
277     uint8_t magFilter;
278     uint8_t wrapS;
279     uint8_t wrapTCompareMode;
280 };
281 
282 static_assert(sizeof(PackedSamplerCompleteness) == sizeof(uint32_t), "Unexpected size");
283 
284 // State from Table 6.10 (state per sampler object)
285 class SamplerState final
286 {
287   public:
288     // This will zero-initialize the struct, including padding.
289     SamplerState();
290     SamplerState(const SamplerState &other);
291 
292     SamplerState &operator=(const SamplerState &other);
293 
294     static SamplerState CreateDefaultForTarget(TextureType type);
295 
getMinFilter()296     GLenum getMinFilter() const { return mMinFilter; }
297 
298     bool setMinFilter(GLenum minFilter);
299 
getMagFilter()300     GLenum getMagFilter() const { return mMagFilter; }
301 
302     bool setMagFilter(GLenum magFilter);
303 
getWrapS()304     GLenum getWrapS() const { return mWrapS; }
305 
306     bool setWrapS(GLenum wrapS);
307 
getWrapT()308     GLenum getWrapT() const { return mWrapT; }
309 
310     bool setWrapT(GLenum wrapT);
311 
getWrapR()312     GLenum getWrapR() const { return mWrapR; }
313 
314     bool setWrapR(GLenum wrapR);
315 
getMaxAnisotropy()316     float getMaxAnisotropy() const { return mMaxAnisotropy; }
317 
318     bool setMaxAnisotropy(float maxAnisotropy);
319 
getMinLod()320     GLfloat getMinLod() const { return mMinLod; }
321 
322     bool setMinLod(GLfloat minLod);
323 
getMaxLod()324     GLfloat getMaxLod() const { return mMaxLod; }
325 
326     bool setMaxLod(GLfloat maxLod);
327 
getCompareMode()328     GLenum getCompareMode() const { return mCompareMode; }
329 
330     bool setCompareMode(GLenum compareMode);
331 
getCompareFunc()332     GLenum getCompareFunc() const { return mCompareFunc; }
333 
334     bool setCompareFunc(GLenum compareFunc);
335 
getSRGBDecode()336     GLenum getSRGBDecode() const { return mSRGBDecode; }
337 
338     bool setSRGBDecode(GLenum sRGBDecode);
339 
340     bool setBorderColor(const ColorGeneric &color);
341 
getBorderColor()342     const ColorGeneric &getBorderColor() const { return mBorderColor; }
343 
sameCompleteness(const SamplerState & samplerState)344     bool sameCompleteness(const SamplerState &samplerState) const
345     {
346         return mCompleteness.packed == samplerState.mCompleteness.packed;
347     }
348 
349   private:
350     void updateWrapTCompareMode();
351 
352     GLenum mMinFilter;
353     GLenum mMagFilter;
354 
355     GLenum mWrapS;
356     GLenum mWrapT;
357     GLenum mWrapR;
358 
359     // From EXT_texture_filter_anisotropic
360     float mMaxAnisotropy;
361 
362     GLfloat mMinLod;
363     GLfloat mMaxLod;
364 
365     GLenum mCompareMode;
366     GLenum mCompareFunc;
367 
368     GLenum mSRGBDecode;
369 
370     ColorGeneric mBorderColor;
371 
372     union Completeness
373     {
374         uint32_t packed;
375         PackedSamplerCompleteness typed;
376     };
377 
378     Completeness mCompleteness;
379 };
380 
381 bool operator==(const SamplerState &a, const SamplerState &b);
382 bool operator!=(const SamplerState &a, const SamplerState &b);
383 
384 struct DrawArraysIndirectCommand
385 {
386     GLuint count;
387     GLuint instanceCount;
388     GLuint first;
389     GLuint baseInstance;
390 };
391 static_assert(sizeof(DrawArraysIndirectCommand) == 16,
392               "Unexpected size of DrawArraysIndirectCommand");
393 
394 struct DrawElementsIndirectCommand
395 {
396     GLuint count;
397     GLuint primCount;
398     GLuint firstIndex;
399     GLint baseVertex;
400     GLuint baseInstance;
401 };
402 static_assert(sizeof(DrawElementsIndirectCommand) == 20,
403               "Unexpected size of DrawElementsIndirectCommand");
404 
405 struct ImageUnit
406 {
407     ImageUnit();
408     ImageUnit(const ImageUnit &other);
409     ~ImageUnit();
410 
411     BindingPointer<Texture> texture;
412     GLint level;
413     GLboolean layered;
414     GLint layer;
415     GLenum access;
416     GLenum format;
417 };
418 
419 using ImageUnitTextureTypeMap = std::map<unsigned int, gl::TextureType>;
420 
421 struct PixelStoreStateBase
422 {
423     GLint alignment   = 4;
424     GLint rowLength   = 0;
425     GLint skipRows    = 0;
426     GLint skipPixels  = 0;
427     GLint imageHeight = 0;
428     GLint skipImages  = 0;
429 };
430 
431 struct PixelUnpackState : PixelStoreStateBase
432 {};
433 
434 struct PixelPackState : PixelStoreStateBase
435 {
436     bool reverseRowOrder = false;
437 };
438 
439 // Used in Program and VertexArray.
440 using AttributesMask = angle::BitSet<MAX_VERTEX_ATTRIBS>;
441 
442 // Used in Program
443 using UniformBlockBindingMask = angle::BitSet<IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS>;
444 
445 // Used in Framebuffer / Program
446 using DrawBufferMask = angle::BitSet8<IMPLEMENTATION_MAX_DRAW_BUFFERS>;
447 
448 class BlendStateExt final
449 {
450     static_assert(IMPLEMENTATION_MAX_DRAW_BUFFERS == 8, "Only up to 8 draw buffers supported.");
451 
452   public:
453     template <typename ElementType, size_t ElementCount>
454     struct StorageType final
455     {
456         static_assert(ElementCount <= 256, "ElementCount cannot exceed 256.");
457 
458 #if defined(ANGLE_IS_64_BIT_CPU)
459         // Always use uint64_t on 64-bit systems
460         static constexpr size_t kBits = 8;
461 #else
462         static constexpr size_t kBits = ElementCount > 16 ? 8 : 4;
463 #endif
464 
465         using Type = typename std::conditional<kBits == 8, uint64_t, uint32_t>::type;
466 
467         static constexpr Type kMaxValueMask = (kBits == 8) ? 0xFF : 0xF;
468 
GetMaskfinal469         static constexpr Type GetMask(const size_t drawBuffers)
470         {
471             ASSERT(drawBuffers > 0);
472             ASSERT(drawBuffers <= IMPLEMENTATION_MAX_DRAW_BUFFERS);
473             return static_cast<Type>(0xFFFFFFFFFFFFFFFFull >> (64 - drawBuffers * kBits));
474         }
475 
476         // A multiplier that is used to replicate 4- or 8-bit value 8 times.
477         static constexpr Type kReplicator = (kBits == 8) ? 0x0101010101010101ull : 0x11111111;
478 
479         // Extract packed `Bits`-bit value of index `index`. `values` variable contains up to 8
480         // packed values.
GetValueIndexedfinal481         static constexpr ElementType GetValueIndexed(const size_t index, const Type values)
482         {
483             ASSERT(index < IMPLEMENTATION_MAX_DRAW_BUFFERS);
484 
485             return static_cast<ElementType>((values >> (index * kBits)) & kMaxValueMask);
486         }
487 
488         // Replicate `Bits`-bit value 8 times and mask the result.
GetReplicatedValuefinal489         static constexpr Type GetReplicatedValue(const ElementType value, const Type mask)
490         {
491             ASSERT(static_cast<size_t>(value) <= kMaxValueMask);
492             return (static_cast<size_t>(value) * kReplicator) & mask;
493         }
494 
495         // Replace `Bits`-bit value of index `index` in `target` with `value`.
SetValueIndexedfinal496         static constexpr void SetValueIndexed(const size_t index,
497                                               const ElementType value,
498                                               Type *target)
499         {
500             ASSERT(static_cast<size_t>(value) <= kMaxValueMask);
501             ASSERT(index < IMPLEMENTATION_MAX_DRAW_BUFFERS);
502 
503             // Bitmask with set bits that contain the value of index `index`.
504             const Type selector = kMaxValueMask << (index * kBits);
505 
506             // Shift the new `value` to its position in the packed value.
507             const Type builtValue = static_cast<Type>(value) << (index * kBits);
508 
509             // Mark differing bits of `target` and `builtValue`, then flip the bits on those
510             // positions in `target`.
511             // Taken from https://graphics.stanford.edu/~seander/bithacks.html#MaskedMerge
512             *target = *target ^ ((*target ^ builtValue) & selector);
513         }
514 
515         // Compare two packed sets of eight 4-bit values and return an 8-bit diff mask.
GetDiffMaskfinal516         static constexpr DrawBufferMask GetDiffMask(const uint32_t packedValue1,
517                                                     const uint32_t packedValue2)
518         {
519             uint32_t diff = packedValue1 ^ packedValue2;
520 
521             // For each 4-bit value that is different between inputs, set the msb to 1 and other
522             // bits to 0.
523             diff = (diff | ((diff & 0x77777777) + 0x77777777)) & 0x88888888;
524 
525             // By this point, `diff` looks like a...b...c...d...e...f...g...h... (dots mean zeros).
526             // To get DrawBufferMask, we need to compress this 32-bit value to 8 bits, i.e. abcdefgh
527 
528             // Multiplying the lower half of `diff` by 0x249 (0x200 + 0x40 + 0x8 + 0x1) produces:
529             // ................e...f...g...h... +
530             // .............e...f...g...h...... +
531             // ..........e...f...g...h......... +
532             // .......e...f...g...h............
533             // ________________________________ =
534             // .......e..ef.efgefghfgh.gh..h...
535             //                 ^^^^
536             // Similar operation is applied to the upper word.
537             // This calculation could be replaced with a single PEXT instruction from BMI2 set.
538             diff = ((((diff & 0xFFFF0000) * 0x249) >> 24) & 0xF0) | (((diff * 0x249) >> 12) & 0xF);
539 
540             return DrawBufferMask(static_cast<uint8_t>(diff));
541         }
542 
543         // Compare two packed sets of eight 8-bit values and return an 8-bit diff mask.
GetDiffMaskfinal544         static constexpr DrawBufferMask GetDiffMask(const uint64_t packedValue1,
545                                                     const uint64_t packedValue2)
546         {
547             uint64_t diff = packedValue1 ^ packedValue2;
548 
549             // For each 8-bit value that is different between inputs, set the msb to 1 and other
550             // bits to 0.
551             diff = (diff | ((diff & 0x7F7F7F7F7F7F7F7F) + 0x7F7F7F7F7F7F7F7F)) & 0x8080808080808080;
552 
553             // By this point, `diff` looks like (dots mean zeros):
554             // a.......b.......c.......d.......e.......f.......g.......h.......
555             // To get DrawBufferMask, we need to compress this 64-bit value to 8 bits, i.e. abcdefgh
556 
557             // Multiplying `diff` by 0x0002040810204081 produces:
558             // a.......b.......c.......d.......e.......f.......g.......h....... +
559             // .b.......c.......d.......e.......f.......g.......h.............. +
560             // ..c.......d.......e.......f.......g.......h..................... +
561             // ...d.......e.......f.......g.......h............................ +
562             // ....e.......f.......g.......h................................... +
563             // .....f.......g.......h.......................................... +
564             // ......g.......h................................................. +
565             // .......h........................................................
566             // ________________________________________________________________ =
567             // abcdefghbcdefgh.cdefgh..defgh...efgh....fgh.....gh......h.......
568             // ^^^^^^^^
569             // This operation could be replaced with a single PEXT instruction from BMI2 set.
570             diff = 0x0002040810204081 * diff >> 56;
571 
572             return DrawBufferMask(static_cast<uint8_t>(diff));
573         }
574     };
575 
576     using FactorStorage    = StorageType<BlendFactorType, angle::EnumSize<BlendFactorType>()>;
577     using EquationStorage  = StorageType<BlendEquationType, angle::EnumSize<BlendEquationType>()>;
578     using ColorMaskStorage = StorageType<uint8_t, 16>;
579 
580     BlendStateExt(const size_t drawBuffers = 1);
581 
582     BlendStateExt(const BlendStateExt &other);
583     BlendStateExt &operator=(const BlendStateExt &other);
584 
585     ///////// Blending Toggle /////////
586 
587     void setEnabled(const bool enabled);
588     void setEnabledIndexed(const size_t index, const bool enabled);
589 
590     ///////// Color Write Mask /////////
591 
PackColorMask(const bool red,const bool green,const bool blue,const bool alpha)592     static constexpr size_t PackColorMask(const bool red,
593                                           const bool green,
594                                           const bool blue,
595                                           const bool alpha)
596     {
597         return (red ? 1 : 0) | (green ? 2 : 0) | (blue ? 4 : 0) | (alpha ? 8 : 0);
598     }
599 
UnpackColorMask(const size_t value,bool * red,bool * green,bool * blue,bool * alpha)600     static constexpr void UnpackColorMask(const size_t value,
601                                           bool *red,
602                                           bool *green,
603                                           bool *blue,
604                                           bool *alpha)
605     {
606         *red   = static_cast<bool>(value & 1);
607         *green = static_cast<bool>(value & 2);
608         *blue  = static_cast<bool>(value & 4);
609         *alpha = static_cast<bool>(value & 8);
610     }
611 
612     ColorMaskStorage::Type expandColorMaskValue(const bool red,
613                                                 const bool green,
614                                                 const bool blue,
615                                                 const bool alpha) const;
616     ColorMaskStorage::Type expandColorMaskIndexed(const size_t index) const;
617     void setColorMask(const bool red, const bool green, const bool blue, const bool alpha);
618     void setColorMaskIndexed(const size_t index, const uint8_t value);
619     void setColorMaskIndexed(const size_t index,
620                              const bool red,
621                              const bool green,
622                              const bool blue,
623                              const bool alpha);
624     uint8_t getColorMaskIndexed(const size_t index) const;
625     void getColorMaskIndexed(const size_t index,
626                              bool *red,
627                              bool *green,
628                              bool *blue,
629                              bool *alpha) const;
630     DrawBufferMask compareColorMask(ColorMaskStorage::Type other) const;
631 
632     ///////// Blend Equation /////////
633 
634     EquationStorage::Type expandEquationValue(const GLenum mode) const;
635     EquationStorage::Type expandEquationColorIndexed(const size_t index) const;
636     EquationStorage::Type expandEquationAlphaIndexed(const size_t index) const;
637     void setEquations(const GLenum modeColor, const GLenum modeAlpha);
638     void setEquationsIndexed(const size_t index, const GLenum modeColor, const GLenum modeAlpha);
639     void setEquationsIndexed(const size_t index,
640                              const size_t otherIndex,
641                              const BlendStateExt &other);
642     GLenum getEquationColorIndexed(size_t index) const;
643     GLenum getEquationAlphaIndexed(size_t index) const;
644     DrawBufferMask compareEquations(const EquationStorage::Type color,
645                                     const EquationStorage::Type alpha) const;
646 
647     ///////// Blend Factors /////////
648 
649     FactorStorage::Type expandFactorValue(const GLenum func) const;
650     FactorStorage::Type expandSrcColorIndexed(const size_t index) const;
651     FactorStorage::Type expandDstColorIndexed(const size_t index) const;
652     FactorStorage::Type expandSrcAlphaIndexed(const size_t index) const;
653     FactorStorage::Type expandDstAlphaIndexed(const size_t index) const;
654     void setFactors(const GLenum srcColor,
655                     const GLenum dstColor,
656                     const GLenum srcAlpha,
657                     const GLenum dstAlpha);
658     void setFactorsIndexed(const size_t index,
659                            const GLenum srcColor,
660                            const GLenum dstColor,
661                            const GLenum srcAlpha,
662                            const GLenum dstAlpha);
663     void setFactorsIndexed(const size_t index, const size_t otherIndex, const BlendStateExt &other);
664     GLenum getSrcColorIndexed(size_t index) const;
665     GLenum getDstColorIndexed(size_t index) const;
666     GLenum getSrcAlphaIndexed(size_t index) const;
667     GLenum getDstAlphaIndexed(size_t index) const;
668     DrawBufferMask compareFactors(const FactorStorage::Type srcColor,
669                                   const FactorStorage::Type dstColor,
670                                   const FactorStorage::Type srcAlpha,
671                                   const FactorStorage::Type dstAlpha) const;
672 
673     ///////// Data Members /////////
674 
675     FactorStorage::Type mMaxFactorMask;
676     FactorStorage::Type mSrcColor;
677     FactorStorage::Type mDstColor;
678     FactorStorage::Type mSrcAlpha;
679     FactorStorage::Type mDstAlpha;
680 
681     EquationStorage::Type mMaxEquationMask;
682     EquationStorage::Type mEquationColor;
683     EquationStorage::Type mEquationAlpha;
684 
685     ColorMaskStorage::Type mMaxColorMask;
686     ColorMaskStorage::Type mColorMask;
687 
688     DrawBufferMask mMaxEnabledMask;
689     DrawBufferMask mEnabledMask;
690 
691     size_t mMaxDrawBuffers;
692 };
693 
694 // Used in StateCache
695 using StorageBuffersMask = angle::BitSet<IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS>;
696 
697 template <typename T>
698 using TexLevelArray = std::array<T, IMPLEMENTATION_MAX_TEXTURE_LEVELS>;
699 
700 using TexLevelMask = angle::BitSet<IMPLEMENTATION_MAX_TEXTURE_LEVELS>;
701 
702 enum class ComponentType
703 {
704     Float       = 0,
705     Int         = 1,
706     UnsignedInt = 2,
707     NoType      = 3,
708     EnumCount   = 4,
709     InvalidEnum = 4,
710 };
711 
GLenumToComponentType(GLenum componentType)712 constexpr ComponentType GLenumToComponentType(GLenum componentType)
713 {
714     switch (componentType)
715     {
716         case GL_FLOAT:
717             return ComponentType::Float;
718         case GL_INT:
719             return ComponentType::Int;
720         case GL_UNSIGNED_INT:
721             return ComponentType::UnsignedInt;
722         case GL_NONE:
723             return ComponentType::NoType;
724         default:
725             return ComponentType::InvalidEnum;
726     }
727 }
728 
729 constexpr angle::PackedEnumMap<ComponentType, uint32_t> kComponentMasks = {{
730     {ComponentType::Float, 0x10001},
731     {ComponentType::Int, 0x00001},
732     {ComponentType::UnsignedInt, 0x10000},
733 }};
734 
735 constexpr size_t kMaxComponentTypeMaskIndex = 16;
736 using ComponentTypeMask                     = angle::BitSet<kMaxComponentTypeMaskIndex * 2>;
737 
SetComponentTypeMask(ComponentType type,size_t index,ComponentTypeMask * mask)738 ANGLE_INLINE void SetComponentTypeMask(ComponentType type, size_t index, ComponentTypeMask *mask)
739 {
740     ASSERT(index <= kMaxComponentTypeMaskIndex);
741     *mask &= ~(0x10001 << index);
742     *mask |= kComponentMasks[type] << index;
743 }
744 
GetComponentTypeMask(const ComponentTypeMask & mask,size_t index)745 ANGLE_INLINE ComponentType GetComponentTypeMask(const ComponentTypeMask &mask, size_t index)
746 {
747     ASSERT(index <= kMaxComponentTypeMaskIndex);
748     uint32_t mask_bits = static_cast<uint32_t>((mask.to_ulong() >> index) & 0x10001);
749     switch (mask_bits)
750     {
751         case 0x10001:
752             return ComponentType::Float;
753         case 0x00001:
754             return ComponentType::Int;
755         case 0x10000:
756             return ComponentType::UnsignedInt;
757         default:
758             return ComponentType::InvalidEnum;
759     }
760 }
761 
762 bool ValidateComponentTypeMasks(unsigned long outputTypes,
763                                 unsigned long inputTypes,
764                                 unsigned long outputMask,
765                                 unsigned long inputMask);
766 
767 enum class RenderToTextureImageIndex
768 {
769     // The default image of the texture, where data is expected to be.
770     Default = 0,
771 
772     // Intermediate multisampled images for EXT_multisampled_render_to_texture.
773     // These values must match log2(SampleCount).
774     IntermediateImage2xMultisampled  = 1,
775     IntermediateImage4xMultisampled  = 2,
776     IntermediateImage8xMultisampled  = 3,
777     IntermediateImage16xMultisampled = 4,
778 
779     // We currently only support up to 16xMSAA in backends that use this enum.
780     InvalidEnum = 5,
781     EnumCount   = 5,
782 };
783 
784 template <typename T>
785 using RenderToTextureImageMap = angle::PackedEnumMap<RenderToTextureImageIndex, T>;
786 
787 struct ContextID
788 {
789     uint32_t value;
790 };
791 
792 inline bool operator==(ContextID lhs, ContextID rhs)
793 {
794     return lhs.value == rhs.value;
795 }
796 
797 inline bool operator!=(ContextID lhs, ContextID rhs)
798 {
799     return lhs.value != rhs.value;
800 }
801 
802 inline bool operator<(ContextID lhs, ContextID rhs)
803 {
804     return lhs.value < rhs.value;
805 }
806 
807 constexpr size_t kCubeFaceCount = 6;
808 
809 template <typename T>
810 using TextureTypeMap = angle::PackedEnumMap<TextureType, T>;
811 using TextureMap     = TextureTypeMap<BindingPointer<Texture>>;
812 
813 // ShaderVector can contain one item per shader.  It differs from ShaderMap in that the values are
814 // not indexed by ShaderType.
815 template <typename T>
816 using ShaderVector = angle::FixedVector<T, static_cast<size_t>(ShaderType::EnumCount)>;
817 
818 template <typename T>
819 using AttachmentArray = std::array<T, IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS>;
820 
821 template <typename T>
822 using AttachmentVector = angle::FixedVector<T, IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS>;
823 
824 using AttachmentsMask = angle::BitSet<IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS>;
825 
826 template <typename T>
827 using DrawBuffersArray = std::array<T, IMPLEMENTATION_MAX_DRAW_BUFFERS>;
828 
829 template <typename T>
830 using DrawBuffersVector = angle::FixedVector<T, IMPLEMENTATION_MAX_DRAW_BUFFERS>;
831 
832 template <typename T>
833 using AttribArray = std::array<T, MAX_VERTEX_ATTRIBS>;
834 
835 using ActiveTextureMask = angle::BitSet<IMPLEMENTATION_MAX_ACTIVE_TEXTURES>;
836 
837 template <typename T>
838 using ActiveTextureArray = std::array<T, IMPLEMENTATION_MAX_ACTIVE_TEXTURES>;
839 
840 using ActiveTextureTypeArray = ActiveTextureArray<TextureType>;
841 
842 template <typename T>
843 using UniformBuffersArray = std::array<T, IMPLEMENTATION_MAX_UNIFORM_BUFFER_BINDINGS>;
844 template <typename T>
845 using StorageBuffersArray = std::array<T, IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS>;
846 template <typename T>
847 using AtomicCounterBuffersArray = std::array<T, IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS>;
848 using AtomicCounterBufferMask   = angle::BitSet<IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS>;
849 template <typename T>
850 using ImagesArray = std::array<T, IMPLEMENTATION_MAX_IMAGE_UNITS>;
851 
852 using ImageUnitMask = angle::BitSet<IMPLEMENTATION_MAX_IMAGE_UNITS>;
853 
854 using SupportedSampleSet = std::set<GLuint>;
855 
856 template <typename T>
857 using TransformFeedbackBuffersArray =
858     std::array<T, gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS>;
859 
860 template <typename T>
861 using QueryTypeMap = angle::PackedEnumMap<QueryType, T>;
862 
863 constexpr size_t kBarrierVectorDefaultSize = 16;
864 
865 template <typename T>
866 using BarrierVector = angle::FastVector<T, kBarrierVectorDefaultSize>;
867 
868 using BufferBarrierVector = BarrierVector<Buffer *>;
869 
870 struct TextureAndLayout
871 {
872     Texture *texture;
873     GLenum layout;
874 };
875 using TextureBarrierVector = BarrierVector<TextureAndLayout>;
876 
877 // OffsetBindingPointer.getSize() returns the size specified by the user, which may be larger than
878 // the size of the bound buffer. This function reduces the returned size to fit the bound buffer if
879 // necessary. Returns 0 if no buffer is bound or if integer overflow occurs.
880 GLsizeiptr GetBoundBufferAvailableSize(const OffsetBindingPointer<Buffer> &binding);
881 
882 // A texture level index.
883 template <typename T>
884 class LevelIndexWrapper
885 {
886   public:
887     LevelIndexWrapper() = default;
LevelIndexWrapper(T levelIndex)888     explicit constexpr LevelIndexWrapper(T levelIndex) : mLevelIndex(levelIndex) {}
889     constexpr LevelIndexWrapper(const LevelIndexWrapper &other) = default;
890     constexpr LevelIndexWrapper &operator=(const LevelIndexWrapper &other) = default;
891 
get()892     constexpr T get() const { return mLevelIndex; }
893 
894     LevelIndexWrapper &operator++()
895     {
896         ++mLevelIndex;
897         return *this;
898     }
899     constexpr bool operator<(const LevelIndexWrapper &other) const
900     {
901         return mLevelIndex < other.mLevelIndex;
902     }
903     constexpr bool operator<=(const LevelIndexWrapper &other) const
904     {
905         return mLevelIndex <= other.mLevelIndex;
906     }
907     constexpr bool operator>(const LevelIndexWrapper &other) const
908     {
909         return mLevelIndex > other.mLevelIndex;
910     }
911     constexpr bool operator>=(const LevelIndexWrapper &other) const
912     {
913         return mLevelIndex >= other.mLevelIndex;
914     }
915     constexpr bool operator==(const LevelIndexWrapper &other) const
916     {
917         return mLevelIndex == other.mLevelIndex;
918     }
919     constexpr bool operator!=(const LevelIndexWrapper &other) const
920     {
921         return mLevelIndex != other.mLevelIndex;
922     }
923     constexpr LevelIndexWrapper operator+(T other) const
924     {
925         return LevelIndexWrapper(mLevelIndex + other);
926     }
927     constexpr LevelIndexWrapper operator-(T other) const
928     {
929         return LevelIndexWrapper(mLevelIndex - other);
930     }
931     constexpr T operator-(LevelIndexWrapper other) const { return mLevelIndex - other.mLevelIndex; }
932 
933   private:
934     T mLevelIndex;
935 };
936 
937 // A GL texture level index.
938 using LevelIndex = LevelIndexWrapper<GLint>;
939 
940 enum class MultisamplingMode
941 {
942     // Regular multisampling
943     Regular = 0,
944     // GL_EXT_multisampled_render_to_texture renderbuffer/texture attachments which perform implicit
945     // resolve of multisampled data.
946     MultisampledRenderToTexture,
947 };
948 }  // namespace gl
949 
950 namespace rx
951 {
952 // A macro that determines whether an object has a given runtime type.
953 #if defined(__clang__)
954 #    if __has_feature(cxx_rtti)
955 #        define ANGLE_HAS_DYNAMIC_CAST 1
956 #    endif
957 #elif !defined(NDEBUG) && (!defined(_MSC_VER) || defined(_CPPRTTI)) &&              \
958     (!defined(__GNUC__) || __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 3) || \
959      defined(__GXX_RTTI))
960 #    define ANGLE_HAS_DYNAMIC_CAST 1
961 #endif
962 
963 #ifdef ANGLE_HAS_DYNAMIC_CAST
964 #    define ANGLE_HAS_DYNAMIC_TYPE(type, obj) (dynamic_cast<type>(obj) != nullptr)
965 #    undef ANGLE_HAS_DYNAMIC_CAST
966 #else
967 #    define ANGLE_HAS_DYNAMIC_TYPE(type, obj) (obj != nullptr)
968 #endif
969 
970 // Downcast a base implementation object (EG TextureImpl to TextureD3D)
971 template <typename DestT, typename SrcT>
GetAs(SrcT * src)972 inline DestT *GetAs(SrcT *src)
973 {
974     ASSERT(ANGLE_HAS_DYNAMIC_TYPE(DestT *, src));
975     return static_cast<DestT *>(src);
976 }
977 
978 template <typename DestT, typename SrcT>
GetAs(const SrcT * src)979 inline const DestT *GetAs(const SrcT *src)
980 {
981     ASSERT(ANGLE_HAS_DYNAMIC_TYPE(const DestT *, src));
982     return static_cast<const DestT *>(src);
983 }
984 
985 #undef ANGLE_HAS_DYNAMIC_TYPE
986 
987 // Downcast a GL object to an Impl (EG gl::Texture to rx::TextureD3D)
988 template <typename DestT, typename SrcT>
GetImplAs(SrcT * src)989 inline DestT *GetImplAs(SrcT *src)
990 {
991     return GetAs<DestT>(src->getImplementation());
992 }
993 
994 template <typename DestT, typename SrcT>
SafeGetImplAs(SrcT * src)995 inline DestT *SafeGetImplAs(SrcT *src)
996 {
997     return src != nullptr ? GetAs<DestT>(src->getImplementation()) : nullptr;
998 }
999 
1000 }  // namespace rx
1001 
1002 #include "angletypes.inc"
1003 
1004 namespace angle
1005 {
1006 // Zero-based for better array indexing
1007 enum FramebufferBinding
1008 {
1009     FramebufferBindingRead = 0,
1010     FramebufferBindingDraw,
1011     FramebufferBindingSingletonMax,
1012     FramebufferBindingBoth = FramebufferBindingSingletonMax,
1013     FramebufferBindingMax,
1014     FramebufferBindingUnknown = FramebufferBindingMax,
1015 };
1016 
EnumToFramebufferBinding(GLenum enumValue)1017 inline FramebufferBinding EnumToFramebufferBinding(GLenum enumValue)
1018 {
1019     switch (enumValue)
1020     {
1021         case GL_READ_FRAMEBUFFER:
1022             return FramebufferBindingRead;
1023         case GL_DRAW_FRAMEBUFFER:
1024             return FramebufferBindingDraw;
1025         case GL_FRAMEBUFFER:
1026             return FramebufferBindingBoth;
1027         default:
1028             UNREACHABLE();
1029             return FramebufferBindingUnknown;
1030     }
1031 }
1032 
FramebufferBindingToEnum(FramebufferBinding binding)1033 inline GLenum FramebufferBindingToEnum(FramebufferBinding binding)
1034 {
1035     switch (binding)
1036     {
1037         case FramebufferBindingRead:
1038             return GL_READ_FRAMEBUFFER;
1039         case FramebufferBindingDraw:
1040             return GL_DRAW_FRAMEBUFFER;
1041         case FramebufferBindingBoth:
1042             return GL_FRAMEBUFFER;
1043         default:
1044             UNREACHABLE();
1045             return GL_NONE;
1046     }
1047 }
1048 
1049 template <typename ObjT, typename ContextT>
1050 class DestroyThenDelete
1051 {
1052   public:
DestroyThenDelete(const ContextT * context)1053     DestroyThenDelete(const ContextT *context) : mContext(context) {}
1054 
operator()1055     void operator()(ObjT *obj)
1056     {
1057         (void)(obj->onDestroy(mContext));
1058         delete obj;
1059     }
1060 
1061   private:
1062     const ContextT *mContext;
1063 };
1064 
1065 // Helper class for wrapping an onDestroy function.
1066 template <typename ObjT, typename DeleterT>
1067 class UniqueObjectPointerBase : angle::NonCopyable
1068 {
1069   public:
1070     template <typename ContextT>
UniqueObjectPointerBase(const ContextT * context)1071     UniqueObjectPointerBase(const ContextT *context) : mObject(nullptr), mDeleter(context)
1072     {}
1073 
1074     template <typename ContextT>
UniqueObjectPointerBase(ObjT * obj,const ContextT * context)1075     UniqueObjectPointerBase(ObjT *obj, const ContextT *context) : mObject(obj), mDeleter(context)
1076     {}
1077 
~UniqueObjectPointerBase()1078     ~UniqueObjectPointerBase()
1079     {
1080         if (mObject)
1081         {
1082             mDeleter(mObject);
1083         }
1084     }
1085 
1086     ObjT *operator->() const { return mObject; }
1087 
release()1088     ObjT *release()
1089     {
1090         auto obj = mObject;
1091         mObject  = nullptr;
1092         return obj;
1093     }
1094 
get()1095     ObjT *get() const { return mObject; }
1096 
reset(ObjT * obj)1097     void reset(ObjT *obj)
1098     {
1099         if (mObject)
1100         {
1101             mDeleter(mObject);
1102         }
1103         mObject = obj;
1104     }
1105 
1106   private:
1107     ObjT *mObject;
1108     DeleterT mDeleter;
1109 };
1110 
1111 template <typename ObjT, typename ContextT>
1112 using UniqueObjectPointer = UniqueObjectPointerBase<ObjT, DestroyThenDelete<ObjT, ContextT>>;
1113 
1114 }  // namespace angle
1115 
1116 namespace gl
1117 {
1118 class State;
1119 }  // namespace gl
1120 
1121 #endif  // LIBANGLE_ANGLETYPES_H_
1122