• 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 GLenum mode) 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 
725     size_t mMaxDrawBuffers;
726 };
727 
728 // Used in StateCache
729 using StorageBuffersMask = angle::BitSet<IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS>;
730 
731 template <typename T>
732 using TexLevelArray = std::array<T, IMPLEMENTATION_MAX_TEXTURE_LEVELS>;
733 
734 using TexLevelMask = angle::BitSet<IMPLEMENTATION_MAX_TEXTURE_LEVELS>;
735 
736 enum class ComponentType
737 {
738     Float       = 0,
739     Int         = 1,
740     UnsignedInt = 2,
741     NoType      = 3,
742     EnumCount   = 4,
743     InvalidEnum = 4,
744 };
745 
GLenumToComponentType(GLenum componentType)746 constexpr ComponentType GLenumToComponentType(GLenum componentType)
747 {
748     switch (componentType)
749     {
750         case GL_FLOAT:
751             return ComponentType::Float;
752         case GL_INT:
753             return ComponentType::Int;
754         case GL_UNSIGNED_INT:
755             return ComponentType::UnsignedInt;
756         case GL_NONE:
757             return ComponentType::NoType;
758         default:
759             return ComponentType::InvalidEnum;
760     }
761 }
762 
763 constexpr angle::PackedEnumMap<ComponentType, uint32_t> kComponentMasks = {{
764     {ComponentType::Float, 0x10001},
765     {ComponentType::Int, 0x00001},
766     {ComponentType::UnsignedInt, 0x10000},
767 }};
768 
769 constexpr size_t kMaxComponentTypeMaskIndex = 16;
770 using ComponentTypeMask                     = angle::BitSet<kMaxComponentTypeMaskIndex * 2>;
771 
SetComponentTypeMask(ComponentType type,size_t index,ComponentTypeMask * mask)772 ANGLE_INLINE void SetComponentTypeMask(ComponentType type, size_t index, ComponentTypeMask *mask)
773 {
774     ASSERT(index <= kMaxComponentTypeMaskIndex);
775     *mask &= ~(0x10001 << index);
776     *mask |= kComponentMasks[type] << index;
777 }
778 
GetComponentTypeMask(const ComponentTypeMask & mask,size_t index)779 ANGLE_INLINE ComponentType GetComponentTypeMask(const ComponentTypeMask &mask, size_t index)
780 {
781     ASSERT(index <= kMaxComponentTypeMaskIndex);
782     uint32_t mask_bits = static_cast<uint32_t>((mask.to_ulong() >> index) & 0x10001);
783     switch (mask_bits)
784     {
785         case 0x10001:
786             return ComponentType::Float;
787         case 0x00001:
788             return ComponentType::Int;
789         case 0x10000:
790             return ComponentType::UnsignedInt;
791         default:
792             return ComponentType::InvalidEnum;
793     }
794 }
795 
796 bool ValidateComponentTypeMasks(unsigned long outputTypes,
797                                 unsigned long inputTypes,
798                                 unsigned long outputMask,
799                                 unsigned long inputMask);
800 
801 enum class RenderToTextureImageIndex
802 {
803     // The default image of the texture, where data is expected to be.
804     Default = 0,
805 
806     // Intermediate multisampled images for EXT_multisampled_render_to_texture.
807     // These values must match log2(SampleCount).
808     IntermediateImage2xMultisampled  = 1,
809     IntermediateImage4xMultisampled  = 2,
810     IntermediateImage8xMultisampled  = 3,
811     IntermediateImage16xMultisampled = 4,
812 
813     // We currently only support up to 16xMSAA in backends that use this enum.
814     InvalidEnum = 5,
815     EnumCount   = 5,
816 };
817 
818 template <typename T>
819 using RenderToTextureImageMap = angle::PackedEnumMap<RenderToTextureImageIndex, T>;
820 
821 struct ContextID
822 {
823     uint32_t value;
824 };
825 
826 inline bool operator==(ContextID lhs, ContextID rhs)
827 {
828     return lhs.value == rhs.value;
829 }
830 
831 inline bool operator!=(ContextID lhs, ContextID rhs)
832 {
833     return lhs.value != rhs.value;
834 }
835 
836 inline bool operator<(ContextID lhs, ContextID rhs)
837 {
838     return lhs.value < rhs.value;
839 }
840 
841 constexpr size_t kCubeFaceCount = 6;
842 
843 template <typename T>
844 using TextureTypeMap = angle::PackedEnumMap<TextureType, T>;
845 using TextureMap     = TextureTypeMap<BindingPointer<Texture>>;
846 
847 // ShaderVector can contain one item per shader.  It differs from ShaderMap in that the values are
848 // not indexed by ShaderType.
849 template <typename T>
850 using ShaderVector = angle::FixedVector<T, static_cast<size_t>(ShaderType::EnumCount)>;
851 
852 template <typename T>
853 using AttachmentArray = std::array<T, IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS>;
854 
855 template <typename T>
856 using AttachmentVector = angle::FixedVector<T, IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS>;
857 
858 using AttachmentsMask = angle::BitSet<IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS>;
859 
860 template <typename T>
861 using DrawBuffersArray = std::array<T, IMPLEMENTATION_MAX_DRAW_BUFFERS>;
862 
863 template <typename T>
864 using DrawBuffersVector = angle::FixedVector<T, IMPLEMENTATION_MAX_DRAW_BUFFERS>;
865 
866 template <typename T>
867 using AttribArray = std::array<T, MAX_VERTEX_ATTRIBS>;
868 
869 using ActiveTextureMask = angle::BitSet<IMPLEMENTATION_MAX_ACTIVE_TEXTURES>;
870 
871 template <typename T>
872 using ActiveTextureArray = std::array<T, IMPLEMENTATION_MAX_ACTIVE_TEXTURES>;
873 
874 using ActiveTextureTypeArray = ActiveTextureArray<TextureType>;
875 
876 template <typename T>
877 using UniformBuffersArray = std::array<T, IMPLEMENTATION_MAX_UNIFORM_BUFFER_BINDINGS>;
878 template <typename T>
879 using StorageBuffersArray = std::array<T, IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS>;
880 template <typename T>
881 using AtomicCounterBuffersArray = std::array<T, IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS>;
882 using AtomicCounterBufferMask   = angle::BitSet<IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS>;
883 template <typename T>
884 using ImagesArray = std::array<T, IMPLEMENTATION_MAX_IMAGE_UNITS>;
885 
886 using ImageUnitMask = angle::BitSet<IMPLEMENTATION_MAX_IMAGE_UNITS>;
887 
888 using SupportedSampleSet = std::set<GLuint>;
889 
890 template <typename T>
891 using TransformFeedbackBuffersArray =
892     std::array<T, gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS>;
893 
894 template <typename T>
895 using QueryTypeMap = angle::PackedEnumMap<QueryType, T>;
896 
897 constexpr size_t kBarrierVectorDefaultSize = 16;
898 
899 template <typename T>
900 using BarrierVector = angle::FastVector<T, kBarrierVectorDefaultSize>;
901 
902 using BufferBarrierVector = BarrierVector<Buffer *>;
903 
904 struct TextureAndLayout
905 {
906     Texture *texture;
907     GLenum layout;
908 };
909 using TextureBarrierVector = BarrierVector<TextureAndLayout>;
910 
911 // OffsetBindingPointer.getSize() returns the size specified by the user, which may be larger than
912 // the size of the bound buffer. This function reduces the returned size to fit the bound buffer if
913 // necessary. Returns 0 if no buffer is bound or if integer overflow occurs.
914 GLsizeiptr GetBoundBufferAvailableSize(const OffsetBindingPointer<Buffer> &binding);
915 
916 // A texture level index.
917 template <typename T>
918 class LevelIndexWrapper
919 {
920   public:
921     LevelIndexWrapper() = default;
LevelIndexWrapper(T levelIndex)922     explicit constexpr LevelIndexWrapper(T levelIndex) : mLevelIndex(levelIndex) {}
923     constexpr LevelIndexWrapper(const LevelIndexWrapper &other) = default;
924     constexpr LevelIndexWrapper &operator=(const LevelIndexWrapper &other) = default;
925 
get()926     constexpr T get() const { return mLevelIndex; }
927 
928     LevelIndexWrapper &operator++()
929     {
930         ++mLevelIndex;
931         return *this;
932     }
933     constexpr bool operator<(const LevelIndexWrapper &other) const
934     {
935         return mLevelIndex < other.mLevelIndex;
936     }
937     constexpr bool operator<=(const LevelIndexWrapper &other) const
938     {
939         return mLevelIndex <= other.mLevelIndex;
940     }
941     constexpr bool operator>(const LevelIndexWrapper &other) const
942     {
943         return mLevelIndex > other.mLevelIndex;
944     }
945     constexpr bool operator>=(const LevelIndexWrapper &other) const
946     {
947         return mLevelIndex >= other.mLevelIndex;
948     }
949     constexpr bool operator==(const LevelIndexWrapper &other) const
950     {
951         return mLevelIndex == other.mLevelIndex;
952     }
953     constexpr bool operator!=(const LevelIndexWrapper &other) const
954     {
955         return mLevelIndex != other.mLevelIndex;
956     }
957     constexpr LevelIndexWrapper operator+(T other) const
958     {
959         return LevelIndexWrapper(mLevelIndex + other);
960     }
961     constexpr LevelIndexWrapper operator-(T other) const
962     {
963         return LevelIndexWrapper(mLevelIndex - other);
964     }
965     constexpr T operator-(LevelIndexWrapper other) const { return mLevelIndex - other.mLevelIndex; }
966 
967   private:
968     T mLevelIndex;
969 };
970 
971 // A GL texture level index.
972 using LevelIndex = LevelIndexWrapper<GLint>;
973 
974 enum class MultisamplingMode
975 {
976     // Regular multisampling
977     Regular = 0,
978     // GL_EXT_multisampled_render_to_texture renderbuffer/texture attachments which perform implicit
979     // resolve of multisampled data.
980     MultisampledRenderToTexture,
981 };
982 }  // namespace gl
983 
984 namespace rx
985 {
986 // A macro that determines whether an object has a given runtime type.
987 #if defined(__clang__)
988 #    if __has_feature(cxx_rtti)
989 #        define ANGLE_HAS_DYNAMIC_CAST 1
990 #    endif
991 #elif !defined(NDEBUG) && (!defined(_MSC_VER) || defined(_CPPRTTI)) &&              \
992     (!defined(__GNUC__) || __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 3) || \
993      defined(__GXX_RTTI))
994 #    define ANGLE_HAS_DYNAMIC_CAST 1
995 #endif
996 
997 #ifdef ANGLE_HAS_DYNAMIC_CAST
998 #    define ANGLE_HAS_DYNAMIC_TYPE(type, obj) (dynamic_cast<type>(obj) != nullptr)
999 #    undef ANGLE_HAS_DYNAMIC_CAST
1000 #else
1001 #    define ANGLE_HAS_DYNAMIC_TYPE(type, obj) (obj != nullptr)
1002 #endif
1003 
1004 // Downcast a base implementation object (EG TextureImpl to TextureD3D)
1005 template <typename DestT, typename SrcT>
GetAs(SrcT * src)1006 inline DestT *GetAs(SrcT *src)
1007 {
1008     ASSERT(ANGLE_HAS_DYNAMIC_TYPE(DestT *, src));
1009     return static_cast<DestT *>(src);
1010 }
1011 
1012 template <typename DestT, typename SrcT>
GetAs(const SrcT * src)1013 inline const DestT *GetAs(const SrcT *src)
1014 {
1015     ASSERT(ANGLE_HAS_DYNAMIC_TYPE(const DestT *, src));
1016     return static_cast<const DestT *>(src);
1017 }
1018 
1019 #undef ANGLE_HAS_DYNAMIC_TYPE
1020 
1021 // Downcast a GL object to an Impl (EG gl::Texture to rx::TextureD3D)
1022 template <typename DestT, typename SrcT>
GetImplAs(SrcT * src)1023 inline DestT *GetImplAs(SrcT *src)
1024 {
1025     return GetAs<DestT>(src->getImplementation());
1026 }
1027 
1028 template <typename DestT, typename SrcT>
SafeGetImplAs(SrcT * src)1029 inline DestT *SafeGetImplAs(SrcT *src)
1030 {
1031     return src != nullptr ? GetAs<DestT>(src->getImplementation()) : nullptr;
1032 }
1033 
1034 }  // namespace rx
1035 
1036 #include "angletypes.inc"
1037 
1038 namespace angle
1039 {
1040 // Zero-based for better array indexing
1041 enum FramebufferBinding
1042 {
1043     FramebufferBindingRead = 0,
1044     FramebufferBindingDraw,
1045     FramebufferBindingSingletonMax,
1046     FramebufferBindingBoth = FramebufferBindingSingletonMax,
1047     FramebufferBindingMax,
1048     FramebufferBindingUnknown = FramebufferBindingMax,
1049 };
1050 
EnumToFramebufferBinding(GLenum enumValue)1051 inline FramebufferBinding EnumToFramebufferBinding(GLenum enumValue)
1052 {
1053     switch (enumValue)
1054     {
1055         case GL_READ_FRAMEBUFFER:
1056             return FramebufferBindingRead;
1057         case GL_DRAW_FRAMEBUFFER:
1058             return FramebufferBindingDraw;
1059         case GL_FRAMEBUFFER:
1060             return FramebufferBindingBoth;
1061         default:
1062             UNREACHABLE();
1063             return FramebufferBindingUnknown;
1064     }
1065 }
1066 
FramebufferBindingToEnum(FramebufferBinding binding)1067 inline GLenum FramebufferBindingToEnum(FramebufferBinding binding)
1068 {
1069     switch (binding)
1070     {
1071         case FramebufferBindingRead:
1072             return GL_READ_FRAMEBUFFER;
1073         case FramebufferBindingDraw:
1074             return GL_DRAW_FRAMEBUFFER;
1075         case FramebufferBindingBoth:
1076             return GL_FRAMEBUFFER;
1077         default:
1078             UNREACHABLE();
1079             return GL_NONE;
1080     }
1081 }
1082 
1083 template <typename ObjT, typename ContextT>
1084 class DestroyThenDelete
1085 {
1086   public:
DestroyThenDelete(const ContextT * context)1087     DestroyThenDelete(const ContextT *context) : mContext(context) {}
1088 
operator()1089     void operator()(ObjT *obj)
1090     {
1091         (void)(obj->onDestroy(mContext));
1092         delete obj;
1093     }
1094 
1095   private:
1096     const ContextT *mContext;
1097 };
1098 
1099 // Helper class for wrapping an onDestroy function.
1100 template <typename ObjT, typename DeleterT>
1101 class UniqueObjectPointerBase : angle::NonCopyable
1102 {
1103   public:
1104     template <typename ContextT>
UniqueObjectPointerBase(const ContextT * context)1105     UniqueObjectPointerBase(const ContextT *context) : mObject(nullptr), mDeleter(context)
1106     {}
1107 
1108     template <typename ContextT>
UniqueObjectPointerBase(ObjT * obj,const ContextT * context)1109     UniqueObjectPointerBase(ObjT *obj, const ContextT *context) : mObject(obj), mDeleter(context)
1110     {}
1111 
~UniqueObjectPointerBase()1112     ~UniqueObjectPointerBase()
1113     {
1114         if (mObject)
1115         {
1116             mDeleter(mObject);
1117         }
1118     }
1119 
1120     ObjT *operator->() const { return mObject; }
1121 
release()1122     ObjT *release()
1123     {
1124         auto obj = mObject;
1125         mObject  = nullptr;
1126         return obj;
1127     }
1128 
get()1129     ObjT *get() const { return mObject; }
1130 
reset(ObjT * obj)1131     void reset(ObjT *obj)
1132     {
1133         if (mObject)
1134         {
1135             mDeleter(mObject);
1136         }
1137         mObject = obj;
1138     }
1139 
1140   private:
1141     ObjT *mObject;
1142     DeleterT mDeleter;
1143 };
1144 
1145 template <typename ObjT, typename ContextT>
1146 using UniqueObjectPointer = UniqueObjectPointerBase<ObjT, DestroyThenDelete<ObjT, ContextT>>;
1147 
1148 }  // namespace angle
1149 
1150 namespace gl
1151 {
1152 class State;
1153 }  // namespace gl
1154 
1155 #endif  // LIBANGLE_ANGLETYPES_H_
1156