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 &operator=(const BlendStateExt &other);
583 
584     ///////// Blending Toggle /////////
585 
586     void setEnabled(const bool enabled);
587     void setEnabledIndexed(const size_t index, const bool enabled);
588 
589     ///////// Color Write Mask /////////
590 
PackColorMask(const bool red,const bool green,const bool blue,const bool alpha)591     static constexpr size_t PackColorMask(const bool red,
592                                           const bool green,
593                                           const bool blue,
594                                           const bool alpha)
595     {
596         return (red ? 1 : 0) | (green ? 2 : 0) | (blue ? 4 : 0) | (alpha ? 8 : 0);
597     }
598 
UnpackColorMask(const size_t value,bool * red,bool * green,bool * blue,bool * alpha)599     static constexpr void UnpackColorMask(const size_t value,
600                                           bool *red,
601                                           bool *green,
602                                           bool *blue,
603                                           bool *alpha)
604     {
605         *red   = static_cast<bool>(value & 1);
606         *green = static_cast<bool>(value & 2);
607         *blue  = static_cast<bool>(value & 4);
608         *alpha = static_cast<bool>(value & 8);
609     }
610 
611     ColorMaskStorage::Type expandColorMaskValue(const bool red,
612                                                 const bool green,
613                                                 const bool blue,
614                                                 const bool alpha) const;
615     ColorMaskStorage::Type expandColorMaskIndexed(const size_t index) const;
616     void setColorMask(const bool red, const bool green, const bool blue, const bool alpha);
617     void setColorMaskIndexed(const size_t index, const uint8_t value);
618     void setColorMaskIndexed(const size_t index,
619                              const bool red,
620                              const bool green,
621                              const bool blue,
622                              const bool alpha);
623     uint8_t getColorMaskIndexed(const size_t index) const;
624     void getColorMaskIndexed(const size_t index,
625                              bool *red,
626                              bool *green,
627                              bool *blue,
628                              bool *alpha) const;
629     DrawBufferMask compareColorMask(ColorMaskStorage::Type other) const;
630 
631     ///////// Blend Equation /////////
632 
633     EquationStorage::Type expandEquationValue(const GLenum mode) const;
634     EquationStorage::Type expandEquationColorIndexed(const size_t index) const;
635     EquationStorage::Type expandEquationAlphaIndexed(const size_t index) const;
636     void setEquations(const GLenum modeColor, const GLenum modeAlpha);
637     void setEquationsIndexed(const size_t index, const GLenum modeColor, const GLenum modeAlpha);
638     void setEquationsIndexed(const size_t index,
639                              const size_t otherIndex,
640                              const BlendStateExt &other);
641     GLenum getEquationColorIndexed(size_t index) const;
642     GLenum getEquationAlphaIndexed(size_t index) const;
643     DrawBufferMask compareEquations(const EquationStorage::Type color,
644                                     const EquationStorage::Type alpha) const;
645 
646     ///////// Blend Factors /////////
647 
648     FactorStorage::Type expandFactorValue(const GLenum func) const;
649     FactorStorage::Type expandSrcColorIndexed(const size_t index) const;
650     FactorStorage::Type expandDstColorIndexed(const size_t index) const;
651     FactorStorage::Type expandSrcAlphaIndexed(const size_t index) const;
652     FactorStorage::Type expandDstAlphaIndexed(const size_t index) const;
653     void setFactors(const GLenum srcColor,
654                     const GLenum dstColor,
655                     const GLenum srcAlpha,
656                     const GLenum dstAlpha);
657     void setFactorsIndexed(const size_t index,
658                            const GLenum srcColor,
659                            const GLenum dstColor,
660                            const GLenum srcAlpha,
661                            const GLenum dstAlpha);
662     void setFactorsIndexed(const size_t index, const size_t otherIndex, const BlendStateExt &other);
663     GLenum getSrcColorIndexed(size_t index) const;
664     GLenum getDstColorIndexed(size_t index) const;
665     GLenum getSrcAlphaIndexed(size_t index) const;
666     GLenum getDstAlphaIndexed(size_t index) const;
667     DrawBufferMask compareFactors(const FactorStorage::Type srcColor,
668                                   const FactorStorage::Type dstColor,
669                                   const FactorStorage::Type srcAlpha,
670                                   const FactorStorage::Type dstAlpha) const;
671 
672     ///////// Data Members /////////
673 
674     const FactorStorage::Type mMaxFactorMask;
675     FactorStorage::Type mSrcColor;
676     FactorStorage::Type mDstColor;
677     FactorStorage::Type mSrcAlpha;
678     FactorStorage::Type mDstAlpha;
679 
680     const EquationStorage::Type mMaxEquationMask;
681     EquationStorage::Type mEquationColor;
682     EquationStorage::Type mEquationAlpha;
683 
684     const ColorMaskStorage::Type mMaxColorMask;
685     ColorMaskStorage::Type mColorMask;
686 
687     const DrawBufferMask mMaxEnabledMask;
688     DrawBufferMask mEnabledMask;
689 
690     const size_t mMaxDrawBuffers;
691 };
692 
693 // Used in StateCache
694 using StorageBuffersMask = angle::BitSet<IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS>;
695 
696 template <typename T>
697 using TexLevelArray = std::array<T, IMPLEMENTATION_MAX_TEXTURE_LEVELS>;
698 
699 using TexLevelMask = angle::BitSet<IMPLEMENTATION_MAX_TEXTURE_LEVELS>;
700 
701 enum class ComponentType
702 {
703     Float       = 0,
704     Int         = 1,
705     UnsignedInt = 2,
706     NoType      = 3,
707     EnumCount   = 4,
708     InvalidEnum = 4,
709 };
710 
GLenumToComponentType(GLenum componentType)711 constexpr ComponentType GLenumToComponentType(GLenum componentType)
712 {
713     switch (componentType)
714     {
715         case GL_FLOAT:
716             return ComponentType::Float;
717         case GL_INT:
718             return ComponentType::Int;
719         case GL_UNSIGNED_INT:
720             return ComponentType::UnsignedInt;
721         case GL_NONE:
722             return ComponentType::NoType;
723         default:
724             return ComponentType::InvalidEnum;
725     }
726 }
727 
728 constexpr angle::PackedEnumMap<ComponentType, uint32_t> kComponentMasks = {{
729     {ComponentType::Float, 0x10001},
730     {ComponentType::Int, 0x00001},
731     {ComponentType::UnsignedInt, 0x10000},
732 }};
733 
734 constexpr size_t kMaxComponentTypeMaskIndex = 16;
735 using ComponentTypeMask                     = angle::BitSet<kMaxComponentTypeMaskIndex * 2>;
736 
SetComponentTypeMask(ComponentType type,size_t index,ComponentTypeMask * mask)737 ANGLE_INLINE void SetComponentTypeMask(ComponentType type, size_t index, ComponentTypeMask *mask)
738 {
739     ASSERT(index <= kMaxComponentTypeMaskIndex);
740     *mask &= ~(0x10001 << index);
741     *mask |= kComponentMasks[type] << index;
742 }
743 
GetComponentTypeMask(const ComponentTypeMask & mask,size_t index)744 ANGLE_INLINE ComponentType GetComponentTypeMask(const ComponentTypeMask &mask, size_t index)
745 {
746     ASSERT(index <= kMaxComponentTypeMaskIndex);
747     uint32_t mask_bits = static_cast<uint32_t>((mask.to_ulong() >> index) & 0x10001);
748     switch (mask_bits)
749     {
750         case 0x10001:
751             return ComponentType::Float;
752         case 0x00001:
753             return ComponentType::Int;
754         case 0x10000:
755             return ComponentType::UnsignedInt;
756         default:
757             return ComponentType::InvalidEnum;
758     }
759 }
760 
761 bool ValidateComponentTypeMasks(unsigned long outputTypes,
762                                 unsigned long inputTypes,
763                                 unsigned long outputMask,
764                                 unsigned long inputMask);
765 
766 enum class RenderToTextureImageIndex
767 {
768     // The default image of the texture, where data is expected to be.
769     Default = 0,
770 
771     // Intermediate multisampled images for EXT_multisampled_render_to_texture.
772     // These values must match log2(SampleCount).
773     IntermediateImage2xMultisampled  = 1,
774     IntermediateImage4xMultisampled  = 2,
775     IntermediateImage8xMultisampled  = 3,
776     IntermediateImage16xMultisampled = 4,
777 
778     // We currently only support up to 16xMSAA in backends that use this enum.
779     InvalidEnum = 5,
780     EnumCount   = 5,
781 };
782 
783 template <typename T>
784 using RenderToTextureImageMap = angle::PackedEnumMap<RenderToTextureImageIndex, T>;
785 
786 struct ContextID
787 {
788     uint32_t value;
789 };
790 
791 inline bool operator==(ContextID lhs, ContextID rhs)
792 {
793     return lhs.value == rhs.value;
794 }
795 
796 inline bool operator!=(ContextID lhs, ContextID rhs)
797 {
798     return lhs.value != rhs.value;
799 }
800 
801 inline bool operator<(ContextID lhs, ContextID rhs)
802 {
803     return lhs.value < rhs.value;
804 }
805 
806 constexpr size_t kCubeFaceCount = 6;
807 
808 template <typename T>
809 using TextureTypeMap = angle::PackedEnumMap<TextureType, T>;
810 using TextureMap     = TextureTypeMap<BindingPointer<Texture>>;
811 
812 // ShaderVector can contain one item per shader.  It differs from ShaderMap in that the values are
813 // not indexed by ShaderType.
814 template <typename T>
815 using ShaderVector = angle::FixedVector<T, static_cast<size_t>(ShaderType::EnumCount)>;
816 
817 template <typename T>
818 using AttachmentArray = std::array<T, IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS>;
819 
820 template <typename T>
821 using AttachmentVector = angle::FixedVector<T, IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS>;
822 
823 using AttachmentsMask = angle::BitSet<IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS>;
824 
825 template <typename T>
826 using DrawBuffersArray = std::array<T, IMPLEMENTATION_MAX_DRAW_BUFFERS>;
827 
828 template <typename T>
829 using DrawBuffersVector = angle::FixedVector<T, IMPLEMENTATION_MAX_DRAW_BUFFERS>;
830 
831 template <typename T>
832 using AttribArray = std::array<T, MAX_VERTEX_ATTRIBS>;
833 
834 using ActiveTextureMask = angle::BitSet<IMPLEMENTATION_MAX_ACTIVE_TEXTURES>;
835 
836 template <typename T>
837 using ActiveTextureArray = std::array<T, IMPLEMENTATION_MAX_ACTIVE_TEXTURES>;
838 
839 using ActiveTextureTypeArray = ActiveTextureArray<TextureType>;
840 
841 template <typename T>
842 using UniformBuffersArray = std::array<T, IMPLEMENTATION_MAX_UNIFORM_BUFFER_BINDINGS>;
843 template <typename T>
844 using StorageBuffersArray = std::array<T, IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS>;
845 template <typename T>
846 using AtomicCounterBuffersArray = std::array<T, IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS>;
847 using AtomicCounterBufferMask   = angle::BitSet<IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS>;
848 template <typename T>
849 using ImagesArray = std::array<T, IMPLEMENTATION_MAX_IMAGE_UNITS>;
850 
851 using ImageUnitMask = angle::BitSet<IMPLEMENTATION_MAX_IMAGE_UNITS>;
852 
853 using SupportedSampleSet = std::set<GLuint>;
854 
855 template <typename T>
856 using TransformFeedbackBuffersArray =
857     std::array<T, gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS>;
858 
859 template <typename T>
860 using QueryTypeMap = angle::PackedEnumMap<QueryType, T>;
861 
862 constexpr size_t kBarrierVectorDefaultSize = 16;
863 
864 template <typename T>
865 using BarrierVector = angle::FastVector<T, kBarrierVectorDefaultSize>;
866 
867 using BufferBarrierVector = BarrierVector<Buffer *>;
868 
869 struct TextureAndLayout
870 {
871     Texture *texture;
872     GLenum layout;
873 };
874 using TextureBarrierVector = BarrierVector<TextureAndLayout>;
875 
876 // OffsetBindingPointer.getSize() returns the size specified by the user, which may be larger than
877 // the size of the bound buffer. This function reduces the returned size to fit the bound buffer if
878 // necessary. Returns 0 if no buffer is bound or if integer overflow occurs.
879 GLsizeiptr GetBoundBufferAvailableSize(const OffsetBindingPointer<Buffer> &binding);
880 
881 // A texture level index.
882 template <typename T>
883 class LevelIndexWrapper
884 {
885   public:
886     LevelIndexWrapper() = default;
LevelIndexWrapper(T levelIndex)887     explicit constexpr LevelIndexWrapper(T levelIndex) : mLevelIndex(levelIndex) {}
888     constexpr LevelIndexWrapper(const LevelIndexWrapper &other) = default;
889     constexpr LevelIndexWrapper &operator=(const LevelIndexWrapper &other) = default;
890 
get()891     constexpr T get() const { return mLevelIndex; }
892 
893     LevelIndexWrapper &operator++()
894     {
895         ++mLevelIndex;
896         return *this;
897     }
898     constexpr bool operator<(const LevelIndexWrapper &other) const
899     {
900         return mLevelIndex < other.mLevelIndex;
901     }
902     constexpr bool operator<=(const LevelIndexWrapper &other) const
903     {
904         return mLevelIndex <= other.mLevelIndex;
905     }
906     constexpr bool operator>(const LevelIndexWrapper &other) const
907     {
908         return mLevelIndex > other.mLevelIndex;
909     }
910     constexpr bool operator>=(const LevelIndexWrapper &other) const
911     {
912         return mLevelIndex >= other.mLevelIndex;
913     }
914     constexpr bool operator==(const LevelIndexWrapper &other) const
915     {
916         return mLevelIndex == other.mLevelIndex;
917     }
918     constexpr bool operator!=(const LevelIndexWrapper &other) const
919     {
920         return mLevelIndex != other.mLevelIndex;
921     }
922     constexpr LevelIndexWrapper operator+(T other) const
923     {
924         return LevelIndexWrapper(mLevelIndex + other);
925     }
926     constexpr LevelIndexWrapper operator-(T other) const
927     {
928         return LevelIndexWrapper(mLevelIndex - other);
929     }
930     constexpr T operator-(LevelIndexWrapper other) const { return mLevelIndex - other.mLevelIndex; }
931 
932   private:
933     T mLevelIndex;
934 };
935 
936 // A GL texture level index.
937 using LevelIndex = LevelIndexWrapper<GLint>;
938 
939 enum class MultisamplingMode
940 {
941     // Regular multisampling
942     Regular = 0,
943     // GL_EXT_multisampled_render_to_texture renderbuffer/texture attachments which perform implicit
944     // resolve of multisampled data.
945     MultisampledRenderToTexture,
946 };
947 }  // namespace gl
948 
949 namespace rx
950 {
951 // A macro that determines whether an object has a given runtime type.
952 #if defined(__clang__)
953 #    if __has_feature(cxx_rtti)
954 #        define ANGLE_HAS_DYNAMIC_CAST 1
955 #    endif
956 #elif !defined(NDEBUG) && (!defined(_MSC_VER) || defined(_CPPRTTI)) &&              \
957     (!defined(__GNUC__) || __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 3) || \
958      defined(__GXX_RTTI))
959 #    define ANGLE_HAS_DYNAMIC_CAST 1
960 #endif
961 
962 #ifdef ANGLE_HAS_DYNAMIC_CAST
963 #    define ANGLE_HAS_DYNAMIC_TYPE(type, obj) (dynamic_cast<type>(obj) != nullptr)
964 #    undef ANGLE_HAS_DYNAMIC_CAST
965 #else
966 #    define ANGLE_HAS_DYNAMIC_TYPE(type, obj) (obj != nullptr)
967 #endif
968 
969 // Downcast a base implementation object (EG TextureImpl to TextureD3D)
970 template <typename DestT, typename SrcT>
GetAs(SrcT * src)971 inline DestT *GetAs(SrcT *src)
972 {
973     ASSERT(ANGLE_HAS_DYNAMIC_TYPE(DestT *, src));
974     return static_cast<DestT *>(src);
975 }
976 
977 template <typename DestT, typename SrcT>
GetAs(const SrcT * src)978 inline const DestT *GetAs(const SrcT *src)
979 {
980     ASSERT(ANGLE_HAS_DYNAMIC_TYPE(const DestT *, src));
981     return static_cast<const DestT *>(src);
982 }
983 
984 #undef ANGLE_HAS_DYNAMIC_TYPE
985 
986 // Downcast a GL object to an Impl (EG gl::Texture to rx::TextureD3D)
987 template <typename DestT, typename SrcT>
GetImplAs(SrcT * src)988 inline DestT *GetImplAs(SrcT *src)
989 {
990     return GetAs<DestT>(src->getImplementation());
991 }
992 
993 template <typename DestT, typename SrcT>
SafeGetImplAs(SrcT * src)994 inline DestT *SafeGetImplAs(SrcT *src)
995 {
996     return src != nullptr ? GetAs<DestT>(src->getImplementation()) : nullptr;
997 }
998 
999 }  // namespace rx
1000 
1001 #include "angletypes.inc"
1002 
1003 namespace angle
1004 {
1005 // Zero-based for better array indexing
1006 enum FramebufferBinding
1007 {
1008     FramebufferBindingRead = 0,
1009     FramebufferBindingDraw,
1010     FramebufferBindingSingletonMax,
1011     FramebufferBindingBoth = FramebufferBindingSingletonMax,
1012     FramebufferBindingMax,
1013     FramebufferBindingUnknown = FramebufferBindingMax,
1014 };
1015 
EnumToFramebufferBinding(GLenum enumValue)1016 inline FramebufferBinding EnumToFramebufferBinding(GLenum enumValue)
1017 {
1018     switch (enumValue)
1019     {
1020         case GL_READ_FRAMEBUFFER:
1021             return FramebufferBindingRead;
1022         case GL_DRAW_FRAMEBUFFER:
1023             return FramebufferBindingDraw;
1024         case GL_FRAMEBUFFER:
1025             return FramebufferBindingBoth;
1026         default:
1027             UNREACHABLE();
1028             return FramebufferBindingUnknown;
1029     }
1030 }
1031 
FramebufferBindingToEnum(FramebufferBinding binding)1032 inline GLenum FramebufferBindingToEnum(FramebufferBinding binding)
1033 {
1034     switch (binding)
1035     {
1036         case FramebufferBindingRead:
1037             return GL_READ_FRAMEBUFFER;
1038         case FramebufferBindingDraw:
1039             return GL_DRAW_FRAMEBUFFER;
1040         case FramebufferBindingBoth:
1041             return GL_FRAMEBUFFER;
1042         default:
1043             UNREACHABLE();
1044             return GL_NONE;
1045     }
1046 }
1047 
1048 template <typename ObjT, typename ContextT>
1049 class DestroyThenDelete
1050 {
1051   public:
DestroyThenDelete(const ContextT * context)1052     DestroyThenDelete(const ContextT *context) : mContext(context) {}
1053 
operator()1054     void operator()(ObjT *obj)
1055     {
1056         (void)(obj->onDestroy(mContext));
1057         delete obj;
1058     }
1059 
1060   private:
1061     const ContextT *mContext;
1062 };
1063 
1064 // Helper class for wrapping an onDestroy function.
1065 template <typename ObjT, typename DeleterT>
1066 class UniqueObjectPointerBase : angle::NonCopyable
1067 {
1068   public:
1069     template <typename ContextT>
UniqueObjectPointerBase(const ContextT * context)1070     UniqueObjectPointerBase(const ContextT *context) : mObject(nullptr), mDeleter(context)
1071     {}
1072 
1073     template <typename ContextT>
UniqueObjectPointerBase(ObjT * obj,const ContextT * context)1074     UniqueObjectPointerBase(ObjT *obj, const ContextT *context) : mObject(obj), mDeleter(context)
1075     {}
1076 
~UniqueObjectPointerBase()1077     ~UniqueObjectPointerBase()
1078     {
1079         if (mObject)
1080         {
1081             mDeleter(mObject);
1082         }
1083     }
1084 
1085     ObjT *operator->() const { return mObject; }
1086 
release()1087     ObjT *release()
1088     {
1089         auto obj = mObject;
1090         mObject  = nullptr;
1091         return obj;
1092     }
1093 
get()1094     ObjT *get() const { return mObject; }
1095 
reset(ObjT * obj)1096     void reset(ObjT *obj)
1097     {
1098         if (mObject)
1099         {
1100             mDeleter(mObject);
1101         }
1102         mObject = obj;
1103     }
1104 
1105   private:
1106     ObjT *mObject;
1107     DeleterT mDeleter;
1108 };
1109 
1110 template <typename ObjT, typename ContextT>
1111 using UniqueObjectPointer = UniqueObjectPointerBase<ObjT, DestroyThenDelete<ObjT, ContextT>>;
1112 
1113 }  // namespace angle
1114 
1115 namespace gl
1116 {
1117 class State;
1118 }  // namespace gl
1119 
1120 #endif  // LIBANGLE_ANGLETYPES_H_
1121