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