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