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 <anglebase/sha1.h>
13 #include "common/Color.h"
14 #include "common/FixedVector.h"
15 #include "common/MemoryBuffer.h"
16 #include "common/PackedEnums.h"
17 #include "common/bitset_utils.h"
18 #include "common/hash_utils.h"
19 #include "common/vector_utils.h"
20 #include "libANGLE/Constants.h"
21 #include "libANGLE/Error.h"
22 #include "libANGLE/RefCountObject.h"
23
24 #include <inttypes.h>
25 #include <stdint.h>
26
27 #include <bitset>
28 #include <functional>
29 #include <map>
30 #include <memory>
31 #include <unordered_map>
32
33 namespace angle
34 {
35 template <typename T>
36 struct Extents
37 {
ExtentsExtents38 Extents() : width(0), height(0), depth(0) {}
ExtentsExtents39 Extents(T width_, T height_, T depth_) : width(width_), height(height_), depth(depth_) {}
40
41 Extents(const Extents &other) = default;
42 Extents &operator=(const Extents &other) = default;
43
emptyExtents44 bool empty() const { return (width * height * depth) == 0; }
45
46 T width;
47 T height;
48 T depth;
49 };
50
51 template <typename T>
52 struct Offset
53 {
54 public:
OffsetOffset55 constexpr Offset() : x(0), y(0), z(0) {}
OffsetOffset56 constexpr Offset(T x_in, T y_in, T z_in) : x(x_in), y(y_in), z(z_in) {}
57
58 T x;
59 T y;
60 T z;
61 };
62
63 template <typename T>
64 inline bool operator==(const Extents<T> &lhs, const Extents<T> &rhs)
65 {
66 return lhs.width == rhs.width && lhs.height == rhs.height && lhs.depth == rhs.depth;
67 }
68
69 template <typename T>
70 inline bool operator!=(const Extents<T> &lhs, const Extents<T> &rhs)
71 {
72 return !(lhs == rhs);
73 }
74
75 template <typename T>
76 inline bool operator==(const Offset<T> &a, const Offset<T> &b)
77 {
78 return a.x == b.x && a.y == b.y && a.z == b.z;
79 }
80
81 template <typename T>
82 inline bool operator!=(const Offset<T> &a, const Offset<T> &b)
83 {
84 return !(a == b);
85 }
86
87 } // namespace angle
88
89 namespace gl
90 {
91 class Buffer;
92 class Texture;
93
94 enum class Command
95 {
96 // The Blit command carries the bitmask of which buffers are being blit. The command passed to
97 // the backends is:
98 //
99 // Blit + (Color?0x1) + (Depth?0x2) + (Stencil?0x4)
100 Blit,
101 BlitAll = Blit + 0x7,
102 Clear,
103 ClearTexture,
104 CopyImage,
105 Dispatch,
106 Draw,
107 GenerateMipmap,
108 Invalidate,
109 ReadPixels,
110 TexImage,
111 Other,
112 };
113
114 enum CommandBlitBuffer
115 {
116 CommandBlitBufferColor = 0x1,
117 CommandBlitBufferDepth = 0x2,
118 CommandBlitBufferStencil = 0x4,
119 };
120
121 enum class InitState
122 {
123 MayNeedInit,
124 Initialized,
125 };
126
127 template <typename T>
128 struct RectangleImpl
129 {
RectangleImplRectangleImpl130 RectangleImpl() : x(T(0)), y(T(0)), width(T(0)), height(T(0)) {}
RectangleImplRectangleImpl131 constexpr RectangleImpl(T x_in, T y_in, T width_in, T height_in)
132 : x(x_in), y(y_in), width(width_in), height(height_in)
133 {}
RectangleImplRectangleImpl134 explicit constexpr RectangleImpl(const T corners[4])
135 : x(corners[0]),
136 y(corners[1]),
137 width(corners[2] - corners[0]),
138 height(corners[3] - corners[1])
139 {}
140 template <typename S>
RectangleImplRectangleImpl141 explicit constexpr RectangleImpl(const RectangleImpl<S> rect)
142 : x(rect.x), y(rect.y), width(rect.width), height(rect.height)
143 {}
144
x0RectangleImpl145 T x0() const { return x; }
y0RectangleImpl146 T y0() const { return y; }
x1RectangleImpl147 T x1() const { return x + width; }
y1RectangleImpl148 T y1() const { return y + height; }
149
isReversedXRectangleImpl150 bool isReversedX() const { return width < T(0); }
isReversedYRectangleImpl151 bool isReversedY() const { return height < T(0); }
152
153 // Returns a rectangle with the same area but flipped in X, Y, neither or both.
flipRectangleImpl154 RectangleImpl<T> flip(bool flipX, bool flipY) const
155 {
156 RectangleImpl flipped = *this;
157 if (flipX)
158 {
159 flipped.x = flipped.x + flipped.width;
160 flipped.width = -flipped.width;
161 }
162 if (flipY)
163 {
164 flipped.y = flipped.y + flipped.height;
165 flipped.height = -flipped.height;
166 }
167 return flipped;
168 }
169
170 // Returns a rectangle with the same area but with height and width guaranteed to be positive.
removeReversalRectangleImpl171 RectangleImpl<T> removeReversal() const { return flip(isReversedX(), isReversedY()); }
172
enclosesRectangleImpl173 bool encloses(const RectangleImpl<T> &inside) const
174 {
175 return x0() <= inside.x0() && y0() <= inside.y0() && x1() >= inside.x1() &&
176 y1() >= inside.y1();
177 }
178
179 bool empty() const;
180
181 T x;
182 T y;
183 T width;
184 T height;
185 };
186
187 template <typename T>
188 bool operator==(const RectangleImpl<T> &a, const RectangleImpl<T> &b);
189 template <typename T>
190 bool operator!=(const RectangleImpl<T> &a, const RectangleImpl<T> &b);
191
192 using Rectangle = RectangleImpl<int>;
193
194 // Calculate the intersection of two rectangles. Returns false if the intersection is empty.
195 [[nodiscard]] bool ClipRectangle(const Rectangle &source,
196 const Rectangle &clip,
197 Rectangle *intersection);
198 // Calculate the smallest rectangle that covers both rectangles. This rectangle may cover areas
199 // not covered by the two rectangles, for example in this situation:
200 //
201 // +--+ +----+
202 // | ++-+ -> | |
203 // +-++ | | |
204 // +--+ +----+
205 //
206 void GetEnclosingRectangle(const Rectangle &rect1, const Rectangle &rect2, Rectangle *rectUnion);
207 // Extend the source rectangle to cover parts (or all of) the second rectangle, in such a way that
208 // no area is covered that isn't covered by both rectangles. For example:
209 //
210 // +--+ +--+
211 // source --> | | | |
212 // ++--+-+ -> | |
213 // |+--+ | | |
214 // +-----+ +--+
215 //
216 void ExtendRectangle(const Rectangle &source, const Rectangle &extend, Rectangle *extended);
217
218 using Extents = angle::Extents<int>;
219 using Offset = angle::Offset<int>;
220 constexpr Offset kOffsetZero(0, 0, 0);
221
222 struct Box
223 {
BoxBox224 Box() : x(0), y(0), z(0), width(0), height(0), depth(0) {}
BoxBox225 Box(int x_in, int y_in, int z_in, int width_in, int height_in, int depth_in)
226 : x(x_in), y(y_in), z(z_in), width(width_in), height(height_in), depth(depth_in)
227 {}
228 template <typename O, typename E>
BoxBox229 Box(const O &offset, const E &size)
230 : x(offset.x),
231 y(offset.y),
232 z(offset.z),
233 width(size.width),
234 height(size.height),
235 depth(size.depth)
236 {}
237 bool valid() const;
238 bool operator==(const Box &other) const;
239 bool operator!=(const Box &other) const;
240 Rectangle toRect() const;
241
242 // Whether the Box has offset 0 and the same extents as argument.
243 bool coversSameExtent(const Extents &size) const;
244
245 bool contains(const Box &other) const;
246 size_t volume() const;
247 void extend(const Box &other);
248
249 int x;
250 int y;
251 int z;
252 int width;
253 int height;
254 int depth;
255 };
256
257 struct RasterizerState final
258 {
259 // This will zero-initialize the struct, including padding.
260 RasterizerState();
261 RasterizerState(const RasterizerState &other);
262 RasterizerState &operator=(const RasterizerState &other);
263
264 bool cullFace;
265 CullFaceMode cullMode;
266 GLenum frontFace;
267
268 PolygonMode polygonMode;
269
270 bool polygonOffsetPoint;
271 bool polygonOffsetLine;
272 bool polygonOffsetFill;
273 GLfloat polygonOffsetFactor;
274 GLfloat polygonOffsetUnits;
275 GLfloat polygonOffsetClamp;
276
277 bool depthClamp;
278
279 // pointDrawMode/multiSample are only used in the D3D back-end right now.
280 bool pointDrawMode;
281 bool multiSample;
282
283 bool rasterizerDiscard;
284
285 bool dither;
286
isPolygonOffsetEnabledfinal287 bool isPolygonOffsetEnabled() const
288 {
289 static_assert(static_cast<int>(PolygonMode::Point) == 0, "PolygonMode::Point");
290 static_assert(static_cast<int>(PolygonMode::Line) == 1, "PolygonMode::Line");
291 static_assert(static_cast<int>(PolygonMode::Fill) == 2, "PolygonMode::Fill");
292 return (1 << static_cast<int>(polygonMode)) &
293 ((polygonOffsetPoint << 0) | (polygonOffsetLine << 1) | (polygonOffsetFill << 2));
294 }
295 };
296
297 bool operator==(const RasterizerState &a, const RasterizerState &b);
298 bool operator!=(const RasterizerState &a, const RasterizerState &b);
299
300 struct BlendState final
301 {
302 // This will zero-initialize the struct, including padding.
303 BlendState();
304 BlendState(const BlendState &other);
305
306 bool blend;
307 GLenum sourceBlendRGB;
308 GLenum destBlendRGB;
309 GLenum sourceBlendAlpha;
310 GLenum destBlendAlpha;
311 GLenum blendEquationRGB;
312 GLenum blendEquationAlpha;
313
314 bool colorMaskRed;
315 bool colorMaskGreen;
316 bool colorMaskBlue;
317 bool colorMaskAlpha;
318 };
319
320 bool operator==(const BlendState &a, const BlendState &b);
321 bool operator!=(const BlendState &a, const BlendState &b);
322
323 struct DepthStencilState final
324 {
325 // This will zero-initialize the struct, including padding.
326 DepthStencilState();
327 DepthStencilState(const DepthStencilState &other);
328 DepthStencilState &operator=(const DepthStencilState &other);
329
330 bool isDepthMaskedOut() const;
331 bool isStencilMaskedOut(GLuint framebufferStencilSize) const;
332 bool isStencilNoOp(GLuint framebufferStencilSize) const;
333 bool isStencilBackNoOp(GLuint framebufferStencilSize) const;
334
335 bool depthTest;
336 GLenum depthFunc;
337 bool depthMask;
338
339 bool stencilTest;
340 GLenum stencilFunc;
341 GLuint stencilMask;
342 GLenum stencilFail;
343 GLenum stencilPassDepthFail;
344 GLenum stencilPassDepthPass;
345 GLuint stencilWritemask;
346 GLenum stencilBackFunc;
347 GLuint stencilBackMask;
348 GLenum stencilBackFail;
349 GLenum stencilBackPassDepthFail;
350 GLenum stencilBackPassDepthPass;
351 GLuint stencilBackWritemask;
352 };
353
354 bool operator==(const DepthStencilState &a, const DepthStencilState &b);
355 bool operator!=(const DepthStencilState &a, const DepthStencilState &b);
356
357 // Packs a sampler state for completeness checks:
358 // * minFilter: 5 values (3 bits)
359 // * magFilter: 2 values (1 bit)
360 // * wrapS: 3 values (2 bits)
361 // * wrapT: 3 values (2 bits)
362 // * compareMode: 1 bit (for == GL_NONE).
363 // This makes a total of 9 bits. We can pack this easily into 32 bits:
364 // * minFilter: 8 bits
365 // * magFilter: 8 bits
366 // * wrapS: 8 bits
367 // * wrapT: 4 bits
368 // * compareMode: 4 bits
369
370 struct PackedSamplerCompleteness
371 {
372 uint8_t minFilter;
373 uint8_t magFilter;
374 uint8_t wrapS;
375 uint8_t wrapTCompareMode;
376 };
377
378 static_assert(sizeof(PackedSamplerCompleteness) == sizeof(uint32_t), "Unexpected size");
379
380 // State from Table 6.10 (state per sampler object)
381 class SamplerState final
382 {
383 public:
384 // This will zero-initialize the struct, including padding.
385 SamplerState();
386 SamplerState(const SamplerState &other);
387
388 SamplerState &operator=(const SamplerState &other);
389
390 static SamplerState CreateDefaultForTarget(TextureType type);
391
getMinFilter()392 GLenum getMinFilter() const { return mMinFilter; }
393
394 bool setMinFilter(GLenum minFilter);
395
getMagFilter()396 GLenum getMagFilter() const { return mMagFilter; }
397
398 bool setMagFilter(GLenum magFilter);
399
getWrapS()400 GLenum getWrapS() const { return mWrapS; }
401
402 bool setWrapS(GLenum wrapS);
403
getWrapT()404 GLenum getWrapT() const { return mWrapT; }
405
406 bool setWrapT(GLenum wrapT);
407
getWrapR()408 GLenum getWrapR() const { return mWrapR; }
409
410 bool setWrapR(GLenum wrapR);
411
usesBorderColor()412 bool usesBorderColor() const
413 {
414 return mWrapS == GL_CLAMP_TO_BORDER || mWrapT == GL_CLAMP_TO_BORDER ||
415 mWrapR == GL_CLAMP_TO_BORDER;
416 }
417
getMaxAnisotropy()418 float getMaxAnisotropy() const { return mMaxAnisotropy; }
419
420 bool setMaxAnisotropy(float maxAnisotropy);
421
getMinLod()422 GLfloat getMinLod() const { return mMinLod; }
423
424 bool setMinLod(GLfloat minLod);
425
getMaxLod()426 GLfloat getMaxLod() const { return mMaxLod; }
427
428 bool setMaxLod(GLfloat maxLod);
429
getCompareMode()430 GLenum getCompareMode() const { return mCompareMode; }
431
432 bool setCompareMode(GLenum compareMode);
433
getCompareFunc()434 GLenum getCompareFunc() const { return mCompareFunc; }
435
436 bool setCompareFunc(GLenum compareFunc);
437
getSRGBDecode()438 GLenum getSRGBDecode() const { return mSRGBDecode; }
439
440 bool setSRGBDecode(GLenum sRGBDecode);
441
442 bool setBorderColor(const ColorGeneric &color);
443
getBorderColor()444 const ColorGeneric &getBorderColor() const { return mBorderColor; }
445
sameCompleteness(const SamplerState & samplerState)446 bool sameCompleteness(const SamplerState &samplerState) const
447 {
448 return mCompleteness.packed == samplerState.mCompleteness.packed;
449 }
450
451 private:
452 void updateWrapTCompareMode();
453
454 GLenum mMinFilter;
455 GLenum mMagFilter;
456
457 GLenum mWrapS;
458 GLenum mWrapT;
459 GLenum mWrapR;
460
461 // From EXT_texture_filter_anisotropic
462 float mMaxAnisotropy;
463
464 GLfloat mMinLod;
465 GLfloat mMaxLod;
466
467 GLenum mCompareMode;
468 GLenum mCompareFunc;
469
470 GLenum mSRGBDecode;
471
472 ColorGeneric mBorderColor;
473
474 union Completeness
475 {
476 uint32_t packed;
477 PackedSamplerCompleteness typed;
478 };
479
480 Completeness mCompleteness;
481 };
482
483 bool operator==(const SamplerState &a, const SamplerState &b);
484 bool operator!=(const SamplerState &a, const SamplerState &b);
485
486 struct DrawArraysIndirectCommand
487 {
488 GLuint count;
489 GLuint instanceCount;
490 GLuint first;
491 GLuint baseInstance;
492 };
493 static_assert(sizeof(DrawArraysIndirectCommand) == 16,
494 "Unexpected size of DrawArraysIndirectCommand");
495
496 struct DrawElementsIndirectCommand
497 {
498 GLuint count;
499 GLuint primCount;
500 GLuint firstIndex;
501 GLint baseVertex;
502 GLuint baseInstance;
503 };
504 static_assert(sizeof(DrawElementsIndirectCommand) == 20,
505 "Unexpected size of DrawElementsIndirectCommand");
506
507 struct ImageUnit
508 {
509 ImageUnit();
510 ImageUnit(const ImageUnit &other);
511 ~ImageUnit();
512
513 BindingPointer<Texture> texture;
514 GLint level;
515 GLboolean layered;
516 GLint layer;
517 GLenum access;
518 GLenum format;
519 };
520
521 using ImageUnitTextureTypeMap = std::map<unsigned int, gl::TextureType>;
522
523 struct PixelStoreStateBase
524 {
525 GLint alignment = 4;
526 GLint rowLength = 0;
527 GLint skipRows = 0;
528 GLint skipPixels = 0;
529 GLint imageHeight = 0;
530 GLint skipImages = 0;
531 };
532
533 struct PixelUnpackState : PixelStoreStateBase
534 {};
535
536 struct PixelPackState : PixelStoreStateBase
537 {
538 bool reverseRowOrder = false;
539 };
540
541 // Used in VertexArray.
542 using VertexArrayBufferBindingMask = angle::BitSet<MAX_VERTEX_ATTRIB_BINDINGS>;
543
544 // Used in Program and VertexArray.
545 using AttributesMask = angle::BitSet<MAX_VERTEX_ATTRIBS>;
546
547 // Used in Program
548 using ProgramUniformBlockMask = angle::BitSet<IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS>;
549 template <typename T>
550 using ProgramUniformBlockArray = std::array<T, IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS>;
551 template <typename T>
552 using UniformBufferBindingArray = std::array<T, IMPLEMENTATION_MAX_UNIFORM_BUFFER_BINDINGS>;
553
554 // Used in Framebuffer / Program
555 using DrawBufferMask = angle::BitSet8<IMPLEMENTATION_MAX_DRAW_BUFFERS>;
556
557 class BlendStateExt final
558 {
559 static_assert(IMPLEMENTATION_MAX_DRAW_BUFFERS == 8, "Only up to 8 draw buffers supported.");
560
561 public:
562 template <typename ElementType, size_t ElementCount>
563 struct StorageType final
564 {
565 static_assert(ElementCount <= 256, "ElementCount cannot exceed 256.");
566
567 #if defined(ANGLE_IS_64_BIT_CPU)
568 // Always use uint64_t on 64-bit systems
569 static constexpr size_t kBits = 8;
570 #else
571 static constexpr size_t kBits = ElementCount > 16 ? 8 : 4;
572 #endif
573
574 using Type = typename std::conditional<kBits == 8, uint64_t, uint32_t>::type;
575
576 static constexpr Type kMaxValueMask = (kBits == 8) ? 0xFF : 0xF;
577
GetMaskfinal578 static constexpr Type GetMask(const size_t drawBuffers)
579 {
580 ASSERT(drawBuffers > 0);
581 ASSERT(drawBuffers <= IMPLEMENTATION_MAX_DRAW_BUFFERS);
582 return static_cast<Type>(0xFFFFFFFFFFFFFFFFull >> (64 - drawBuffers * kBits));
583 }
584
585 // A multiplier that is used to replicate 4- or 8-bit value 8 times.
586 static constexpr Type kReplicator = (kBits == 8) ? 0x0101010101010101ull : 0x11111111;
587
588 // Extract packed `Bits`-bit value of index `index`. `values` variable contains up to 8
589 // packed values.
GetValueIndexedfinal590 static constexpr ElementType GetValueIndexed(const size_t index, const Type values)
591 {
592 ASSERT(index < IMPLEMENTATION_MAX_DRAW_BUFFERS);
593
594 return static_cast<ElementType>((values >> (index * kBits)) & kMaxValueMask);
595 }
596
597 // Replicate `Bits`-bit value 8 times and mask the result.
GetReplicatedValuefinal598 static constexpr Type GetReplicatedValue(const ElementType value, const Type mask)
599 {
600 ASSERT(static_cast<size_t>(value) <= kMaxValueMask);
601 return (static_cast<size_t>(value) * kReplicator) & mask;
602 }
603
604 // Replace `Bits`-bit value of index `index` in `target` with `value`.
SetValueIndexedfinal605 static constexpr void SetValueIndexed(const size_t index,
606 const ElementType value,
607 Type *target)
608 {
609 ASSERT(static_cast<size_t>(value) <= kMaxValueMask);
610 ASSERT(index < IMPLEMENTATION_MAX_DRAW_BUFFERS);
611
612 // Bitmask with set bits that contain the value of index `index`.
613 const Type selector = kMaxValueMask << (index * kBits);
614
615 // Shift the new `value` to its position in the packed value.
616 const Type builtValue = static_cast<Type>(value) << (index * kBits);
617
618 // Mark differing bits of `target` and `builtValue`, then flip the bits on those
619 // positions in `target`.
620 // Taken from https://graphics.stanford.edu/~seander/bithacks.html#MaskedMerge
621 *target = *target ^ ((*target ^ builtValue) & selector);
622 }
623
624 // Compare two packed sets of eight 4-bit values and return an 8-bit diff mask.
GetDiffMaskfinal625 static constexpr DrawBufferMask GetDiffMask(const uint32_t packedValue1,
626 const uint32_t packedValue2)
627 {
628 uint32_t diff = packedValue1 ^ packedValue2;
629
630 // For each 4-bit value that is different between inputs, set the msb to 1 and other
631 // bits to 0.
632 diff = (diff | ((diff & 0x77777777) + 0x77777777)) & 0x88888888;
633
634 // By this point, `diff` looks like a...b...c...d...e...f...g...h... (dots mean zeros).
635 // To get DrawBufferMask, we need to compress this 32-bit value to 8 bits, i.e. abcdefgh
636
637 // Multiplying the lower half of `diff` by 0x249 (0x200 + 0x40 + 0x8 + 0x1) produces:
638 // ................e...f...g...h... +
639 // .............e...f...g...h...... +
640 // ..........e...f...g...h......... +
641 // .......e...f...g...h............
642 // ________________________________ =
643 // .......e..ef.efgefghfgh.gh..h...
644 // ^^^^
645 // Similar operation is applied to the upper word.
646 // This calculation could be replaced with a single PEXT instruction from BMI2 set.
647 diff = ((((diff & 0xFFFF0000) * 0x249) >> 24) & 0xF0) | (((diff * 0x249) >> 12) & 0xF);
648
649 return DrawBufferMask(static_cast<uint8_t>(diff));
650 }
651
652 // Compare two packed sets of eight 8-bit values and return an 8-bit diff mask.
GetDiffMaskfinal653 static constexpr DrawBufferMask GetDiffMask(const uint64_t packedValue1,
654 const uint64_t packedValue2)
655 {
656 uint64_t diff = packedValue1 ^ packedValue2;
657
658 // For each 8-bit value that is different between inputs, set the msb to 1 and other
659 // bits to 0.
660 diff = (diff | ((diff & 0x7F7F7F7F7F7F7F7F) + 0x7F7F7F7F7F7F7F7F)) & 0x8080808080808080;
661
662 // By this point, `diff` looks like (dots mean zeros):
663 // a.......b.......c.......d.......e.......f.......g.......h.......
664 // To get DrawBufferMask, we need to compress this 64-bit value to 8 bits, i.e. abcdefgh
665
666 // Multiplying `diff` by 0x0002040810204081 produces:
667 // a.......b.......c.......d.......e.......f.......g.......h....... +
668 // .b.......c.......d.......e.......f.......g.......h.............. +
669 // ..c.......d.......e.......f.......g.......h..................... +
670 // ...d.......e.......f.......g.......h............................ +
671 // ....e.......f.......g.......h................................... +
672 // .....f.......g.......h.......................................... +
673 // ......g.......h................................................. +
674 // .......h........................................................
675 // ________________________________________________________________ =
676 // abcdefghbcdefgh.cdefgh..defgh...efgh....fgh.....gh......h.......
677 // ^^^^^^^^
678 // This operation could be replaced with a single PEXT instruction from BMI2 set.
679 diff = 0x0002040810204081 * diff >> 56;
680
681 return DrawBufferMask(static_cast<uint8_t>(diff));
682 }
683 };
684
685 using FactorStorage = StorageType<BlendFactorType, angle::EnumSize<BlendFactorType>()>;
686 using EquationStorage = StorageType<BlendEquationType, angle::EnumSize<BlendEquationType>()>;
687 using ColorMaskStorage = StorageType<uint8_t, 16>;
688 static_assert(std::is_same<FactorStorage::Type, uint64_t>::value &&
689 std::is_same<EquationStorage::Type, uint64_t>::value,
690 "Factor and Equation storage must be 64-bit.");
691
692 BlendStateExt(const size_t drawBuffers = 1);
693
694 BlendStateExt(const BlendStateExt &other);
695 BlendStateExt &operator=(const BlendStateExt &other);
696
697 ///////// Blending Toggle /////////
698
699 void setEnabled(const bool enabled);
700 void setEnabledIndexed(const size_t index, const bool enabled);
701
702 ///////// Color Write Mask /////////
703
PackColorMask(const bool red,const bool green,const bool blue,const bool alpha)704 static constexpr size_t PackColorMask(const bool red,
705 const bool green,
706 const bool blue,
707 const bool alpha)
708 {
709 return (red ? 1 : 0) | (green ? 2 : 0) | (blue ? 4 : 0) | (alpha ? 8 : 0);
710 }
711
UnpackColorMask(const size_t value,bool * red,bool * green,bool * blue,bool * alpha)712 static constexpr void UnpackColorMask(const size_t value,
713 bool *red,
714 bool *green,
715 bool *blue,
716 bool *alpha)
717 {
718 *red = static_cast<bool>(value & 1);
719 *green = static_cast<bool>(value & 2);
720 *blue = static_cast<bool>(value & 4);
721 *alpha = static_cast<bool>(value & 8);
722 }
723
724 ColorMaskStorage::Type expandColorMaskValue(const bool red,
725 const bool green,
726 const bool blue,
727 const bool alpha) const;
728 ColorMaskStorage::Type expandColorMaskIndexed(const size_t index) const;
729 void setColorMask(const bool red, const bool green, const bool blue, const bool alpha);
730 void setColorMaskIndexed(const size_t index, const uint8_t value);
731 void setColorMaskIndexed(const size_t index,
732 const bool red,
733 const bool green,
734 const bool blue,
735 const bool alpha);
736 uint8_t getColorMaskIndexed(const size_t index) const;
737 void getColorMaskIndexed(const size_t index,
738 bool *red,
739 bool *green,
740 bool *blue,
741 bool *alpha) const;
742 DrawBufferMask compareColorMask(ColorMaskStorage::Type other) const;
743
744 ///////// Blend Equation /////////
745
746 EquationStorage::Type expandEquationValue(const GLenum mode) const;
747 EquationStorage::Type expandEquationValue(const gl::BlendEquationType equation) const;
748 EquationStorage::Type expandEquationColorIndexed(const size_t index) const;
749 EquationStorage::Type expandEquationAlphaIndexed(const size_t index) const;
750 void setEquations(const GLenum modeColor, const GLenum modeAlpha);
751 void setEquationsIndexed(const size_t index, const GLenum modeColor, const GLenum modeAlpha);
752 void setEquationsIndexed(const size_t index,
753 const size_t otherIndex,
754 const BlendStateExt &other);
getEquationColorIndexed(size_t index)755 BlendEquationType getEquationColorIndexed(size_t index) const
756 {
757 ASSERT(index < mDrawBufferCount);
758 return EquationStorage::GetValueIndexed(index, mEquationColor);
759 }
getEquationAlphaIndexed(size_t index)760 BlendEquationType getEquationAlphaIndexed(size_t index) const
761 {
762 ASSERT(index < mDrawBufferCount);
763 return EquationStorage::GetValueIndexed(index, mEquationAlpha);
764 }
765 DrawBufferMask compareEquations(const EquationStorage::Type color,
766 const EquationStorage::Type alpha) const;
compareEquations(const BlendStateExt & other)767 DrawBufferMask compareEquations(const BlendStateExt &other) const
768 {
769 return compareEquations(other.mEquationColor, other.mEquationAlpha);
770 }
771
772 ///////// Blend Factors /////////
773
774 FactorStorage::Type expandFactorValue(const GLenum func) const;
775 FactorStorage::Type expandFactorValue(const gl::BlendFactorType func) const;
776 FactorStorage::Type expandSrcColorIndexed(const size_t index) const;
777 FactorStorage::Type expandDstColorIndexed(const size_t index) const;
778 FactorStorage::Type expandSrcAlphaIndexed(const size_t index) const;
779 FactorStorage::Type expandDstAlphaIndexed(const size_t index) const;
780 void setFactors(const GLenum srcColor,
781 const GLenum dstColor,
782 const GLenum srcAlpha,
783 const GLenum dstAlpha);
784 void setFactorsIndexed(const size_t index,
785 const gl::BlendFactorType srcColorFactor,
786 const gl::BlendFactorType dstColorFactor,
787 const gl::BlendFactorType srcAlphaFactor,
788 const gl::BlendFactorType dstAlphaFactor);
789 void setFactorsIndexed(const size_t index,
790 const GLenum srcColor,
791 const GLenum dstColor,
792 const GLenum srcAlpha,
793 const GLenum dstAlpha);
794 void setFactorsIndexed(const size_t index, const size_t otherIndex, const BlendStateExt &other);
getSrcColorIndexed(size_t index)795 BlendFactorType getSrcColorIndexed(size_t index) const
796 {
797 ASSERT(index < mDrawBufferCount);
798 return FactorStorage::GetValueIndexed(index, mSrcColor);
799 }
getDstColorIndexed(size_t index)800 BlendFactorType getDstColorIndexed(size_t index) const
801 {
802 ASSERT(index < mDrawBufferCount);
803 return FactorStorage::GetValueIndexed(index, mDstColor);
804 }
getSrcAlphaIndexed(size_t index)805 BlendFactorType getSrcAlphaIndexed(size_t index) const
806 {
807 ASSERT(index < mDrawBufferCount);
808 return FactorStorage::GetValueIndexed(index, mSrcAlpha);
809 }
getDstAlphaIndexed(size_t index)810 BlendFactorType getDstAlphaIndexed(size_t index) const
811 {
812 ASSERT(index < mDrawBufferCount);
813 return FactorStorage::GetValueIndexed(index, mDstAlpha);
814 }
815 DrawBufferMask compareFactors(const FactorStorage::Type srcColor,
816 const FactorStorage::Type dstColor,
817 const FactorStorage::Type srcAlpha,
818 const FactorStorage::Type dstAlpha) const;
compareFactors(const BlendStateExt & other)819 DrawBufferMask compareFactors(const BlendStateExt &other) const
820 {
821 return compareFactors(other.mSrcColor, other.mDstColor, other.mSrcAlpha, other.mDstAlpha);
822 }
823
getSrcColorBits()824 constexpr FactorStorage::Type getSrcColorBits() const { return mSrcColor; }
getSrcAlphaBits()825 constexpr FactorStorage::Type getSrcAlphaBits() const { return mSrcAlpha; }
getDstColorBits()826 constexpr FactorStorage::Type getDstColorBits() const { return mDstColor; }
getDstAlphaBits()827 constexpr FactorStorage::Type getDstAlphaBits() const { return mDstAlpha; }
828
getEquationColorBits()829 constexpr EquationStorage::Type getEquationColorBits() const { return mEquationColor; }
getEquationAlphaBits()830 constexpr EquationStorage::Type getEquationAlphaBits() const { return mEquationAlpha; }
831
getAllColorMaskBits()832 constexpr ColorMaskStorage::Type getAllColorMaskBits() const { return mAllColorMask; }
getColorMaskBits()833 constexpr ColorMaskStorage::Type getColorMaskBits() const { return mColorMask; }
834
getAllEnabledMask()835 constexpr DrawBufferMask getAllEnabledMask() const { return mAllEnabledMask; }
getEnabledMask()836 constexpr DrawBufferMask getEnabledMask() const { return mEnabledMask; }
837
getUsesAdvancedBlendEquationMask()838 constexpr DrawBufferMask getUsesAdvancedBlendEquationMask() const
839 {
840 return mUsesAdvancedBlendEquationMask;
841 }
842
getUsesExtendedBlendFactorMask()843 constexpr DrawBufferMask getUsesExtendedBlendFactorMask() const
844 {
845 return mUsesExtendedBlendFactorMask;
846 }
847
getDrawBufferCount()848 constexpr uint8_t getDrawBufferCount() const { return mDrawBufferCount; }
849
setSrcColorBits(const FactorStorage::Type srcColor)850 constexpr void setSrcColorBits(const FactorStorage::Type srcColor) { mSrcColor = srcColor; }
setSrcAlphaBits(const FactorStorage::Type srcAlpha)851 constexpr void setSrcAlphaBits(const FactorStorage::Type srcAlpha) { mSrcAlpha = srcAlpha; }
setDstColorBits(const FactorStorage::Type dstColor)852 constexpr void setDstColorBits(const FactorStorage::Type dstColor) { mDstColor = dstColor; }
setDstAlphaBits(const FactorStorage::Type dstAlpha)853 constexpr void setDstAlphaBits(const FactorStorage::Type dstAlpha) { mDstAlpha = dstAlpha; }
854
setEquationColorBits(const EquationStorage::Type equationColor)855 constexpr void setEquationColorBits(const EquationStorage::Type equationColor)
856 {
857 mEquationColor = equationColor;
858 }
setEquationAlphaBits(const EquationStorage::Type equationAlpha)859 constexpr void setEquationAlphaBits(const EquationStorage::Type equationAlpha)
860 {
861 mEquationAlpha = equationAlpha;
862 }
863
setColorMaskBits(const ColorMaskStorage::Type colorMask)864 constexpr void setColorMaskBits(const ColorMaskStorage::Type colorMask)
865 {
866 mColorMask = colorMask;
867 }
868
setEnabledMask(const DrawBufferMask enabledMask)869 constexpr void setEnabledMask(const DrawBufferMask enabledMask) { mEnabledMask = enabledMask; }
870
871 ///////// Data Members /////////
872 private:
873 uint64_t mParameterMask;
874
875 FactorStorage::Type mSrcColor;
876 FactorStorage::Type mDstColor;
877 FactorStorage::Type mSrcAlpha;
878 FactorStorage::Type mDstAlpha;
879
880 EquationStorage::Type mEquationColor;
881 EquationStorage::Type mEquationAlpha;
882
883 ColorMaskStorage::Type mAllColorMask;
884 ColorMaskStorage::Type mColorMask;
885
886 DrawBufferMask mAllEnabledMask;
887 DrawBufferMask mEnabledMask;
888
889 // Cache of whether the blend equation for each index is from KHR_blend_equation_advanced.
890 DrawBufferMask mUsesAdvancedBlendEquationMask;
891
892 // Cache of whether the blend factor for each index is from EXT_blend_func_extended.
893 DrawBufferMask mUsesExtendedBlendFactorMask;
894
895 uint8_t mDrawBufferCount;
896
897 ANGLE_MAYBE_UNUSED_PRIVATE_FIELD uint8_t kUnused[3] = {};
898 };
899
900 static_assert(sizeof(BlendStateExt) == sizeof(uint64_t) +
901 (sizeof(BlendStateExt::FactorStorage::Type) * 4 +
902 sizeof(BlendStateExt::EquationStorage::Type) * 2 +
903 sizeof(BlendStateExt::ColorMaskStorage::Type) * 2 +
904 sizeof(DrawBufferMask) * 4 + sizeof(uint8_t)) +
905 sizeof(uint8_t) * 3,
906 "The BlendStateExt class must not contain gaps.");
907
908 // Used in StateCache
909 using StorageBuffersMask = angle::BitSet<IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS>;
910
911 template <typename T>
912 using SampleMaskArray = std::array<T, IMPLEMENTATION_MAX_SAMPLE_MASK_WORDS>;
913
914 template <typename T>
915 using TexLevelArray = std::array<T, IMPLEMENTATION_MAX_TEXTURE_LEVELS>;
916
917 using TexLevelMask = angle::BitSet<IMPLEMENTATION_MAX_TEXTURE_LEVELS>;
918
919 enum class ComponentType
920 {
921 Float = 0,
922 Int = 1,
923 UnsignedInt = 2,
924 NoType = 3,
925 EnumCount = 4,
926 InvalidEnum = 4,
927 };
928
GLenumToComponentType(GLenum componentType)929 constexpr ComponentType GLenumToComponentType(GLenum componentType)
930 {
931 switch (componentType)
932 {
933 case GL_FLOAT:
934 return ComponentType::Float;
935 case GL_INT:
936 return ComponentType::Int;
937 case GL_UNSIGNED_INT:
938 return ComponentType::UnsignedInt;
939 case GL_NONE:
940 return ComponentType::NoType;
941 default:
942 return ComponentType::InvalidEnum;
943 }
944 }
945
946 constexpr angle::PackedEnumMap<ComponentType, uint32_t> kComponentMasks = {{
947 {ComponentType::Float, 0x10001},
948 {ComponentType::Int, 0x00001},
949 {ComponentType::UnsignedInt, 0x10000},
950 }};
951
952 constexpr size_t kMaxComponentTypeMaskIndex = 16;
953 using ComponentTypeMask = angle::BitSet<kMaxComponentTypeMaskIndex * 2>;
954
SetComponentTypeMask(ComponentType type,size_t index,ComponentTypeMask * mask)955 ANGLE_INLINE void SetComponentTypeMask(ComponentType type, size_t index, ComponentTypeMask *mask)
956 {
957 ASSERT(index <= kMaxComponentTypeMaskIndex);
958 *mask &= ~(0x10001 << index);
959 *mask |= kComponentMasks[type] << index;
960 }
961
GetComponentTypeMask(ComponentTypeMask mask,size_t index)962 ANGLE_INLINE ComponentType GetComponentTypeMask(ComponentTypeMask mask, size_t index)
963 {
964 ASSERT(index <= kMaxComponentTypeMaskIndex);
965 uint32_t mask_bits = mask.bits() >> index & 0x10001;
966 switch (mask_bits)
967 {
968 case 0x10001:
969 return ComponentType::Float;
970 case 0x00001:
971 return ComponentType::Int;
972 case 0x10000:
973 return ComponentType::UnsignedInt;
974 default:
975 return ComponentType::InvalidEnum;
976 }
977 }
978
GetActiveComponentTypeMask(gl::AttributesMask activeAttribLocations)979 ANGLE_INLINE ComponentTypeMask GetActiveComponentTypeMask(gl::AttributesMask activeAttribLocations)
980 {
981 const uint32_t activeAttribs = static_cast<uint32_t>(activeAttribLocations.bits());
982
983 // Ever attrib index takes one bit from the lower 16-bits and another bit from the upper
984 // 16-bits at the same index.
985 return ComponentTypeMask(activeAttribs << kMaxComponentTypeMaskIndex | activeAttribs);
986 }
987
GetComponentTypeMaskDiff(ComponentTypeMask mask1,ComponentTypeMask mask2)988 ANGLE_INLINE DrawBufferMask GetComponentTypeMaskDiff(ComponentTypeMask mask1,
989 ComponentTypeMask mask2)
990 {
991 const uint32_t diff = static_cast<uint32_t>((mask1 ^ mask2).bits());
992 return DrawBufferMask(static_cast<uint8_t>(diff | (diff >> gl::kMaxComponentTypeMaskIndex)));
993 }
994
995 bool ValidateComponentTypeMasks(unsigned long outputTypes,
996 unsigned long inputTypes,
997 unsigned long outputMask,
998 unsigned long inputMask);
999
1000 // Helpers for performing WebGL 2.0 clear validation
1001 // Extracted component type has always one of these four values:
1002 // * 0x10001 - float or normalized
1003 // * 0x00001 - int
1004 // * 0x10000 - unsigned int
1005 // * 0x00000 - unused or disabled
1006
1007 // The following functions rely on these.
1008 static_assert(kComponentMasks[ComponentType::Float] == 0x10001);
1009 static_assert(kComponentMasks[ComponentType::Int] == 0x00001);
1010 static_assert(kComponentMasks[ComponentType::UnsignedInt] == 0x10000);
1011
1012 // Used for clearBufferuiv
IsComponentTypeFloatOrInt(ComponentTypeMask mask,size_t index)1013 ANGLE_INLINE bool IsComponentTypeFloatOrInt(ComponentTypeMask mask, size_t index)
1014 {
1015 ASSERT(index <= kMaxComponentTypeMaskIndex);
1016 // 0x10001 or 0x00001
1017 return ((mask.bits() >> index) & 0x00001) != 0;
1018 }
1019
1020 // Used for clearBufferiv
IsComponentTypeFloatOrUnsignedInt(ComponentTypeMask mask,size_t index)1021 ANGLE_INLINE bool IsComponentTypeFloatOrUnsignedInt(ComponentTypeMask mask, size_t index)
1022 {
1023 ASSERT(index <= kMaxComponentTypeMaskIndex);
1024 // 0x10001 or 0x10000
1025 return ((mask.bits() >> index) & 0x10000) != 0;
1026 }
1027
1028 // Used for clearBufferfv
IsComponentTypeIntOrUnsignedInt(ComponentTypeMask mask,size_t index)1029 ANGLE_INLINE bool IsComponentTypeIntOrUnsignedInt(ComponentTypeMask mask, size_t index)
1030 {
1031 ASSERT(index <= kMaxComponentTypeMaskIndex);
1032 // 0x00001 or 0x10000; this expression is more efficient than two explicit comparisons
1033 return ((((mask.bits() >> kMaxComponentTypeMaskIndex) ^ mask.bits()) >> index) & 1) != 0;
1034 }
1035
1036 // Used for clear
GetIntOrUnsignedIntDrawBufferMask(ComponentTypeMask mask)1037 ANGLE_INLINE DrawBufferMask GetIntOrUnsignedIntDrawBufferMask(ComponentTypeMask mask)
1038 {
1039 static_assert(DrawBufferMask::size() <= 8);
1040 return DrawBufferMask(
1041 static_cast<uint8_t>((mask.bits() >> kMaxComponentTypeMaskIndex) ^ mask.bits()));
1042 }
1043
1044 // GL_ANGLE_blob_cache state
1045 struct BlobCacheCallbacks
1046 {
1047 GLSETBLOBPROCANGLE setFunction = nullptr;
1048 GLGETBLOBPROCANGLE getFunction = nullptr;
1049 const void *userParam = nullptr;
1050 };
1051
1052 enum class RenderToTextureImageIndex
1053 {
1054 // The default image of the texture, where data is expected to be.
1055 Default = 0,
1056
1057 // Intermediate multisampled images for EXT_multisampled_render_to_texture.
1058 // These values must match log2(SampleCount).
1059 IntermediateImage2xMultisampled = 1,
1060 IntermediateImage4xMultisampled = 2,
1061 IntermediateImage8xMultisampled = 3,
1062 IntermediateImage16xMultisampled = 4,
1063
1064 // We currently only support up to 16xMSAA in backends that use this enum.
1065 InvalidEnum = 5,
1066 EnumCount = 5,
1067 };
1068
1069 template <typename T>
1070 using RenderToTextureImageMap = angle::PackedEnumMap<RenderToTextureImageIndex, T>;
1071
1072 constexpr size_t kCubeFaceCount = 6;
1073
1074 template <typename T>
1075 using CubeFaceArray = std::array<T, kCubeFaceCount>;
1076
1077 template <typename T>
1078 using TextureTypeMap = angle::PackedEnumMap<TextureType, T>;
1079 using TextureMap = TextureTypeMap<BindingPointer<Texture>>;
1080
1081 // ShaderVector can contain one item per shader. It differs from ShaderMap in that the values are
1082 // not indexed by ShaderType.
1083 template <typename T>
1084 using ShaderVector = angle::FixedVector<T, static_cast<size_t>(ShaderType::EnumCount)>;
1085
1086 template <typename T>
1087 using AttachmentArray = std::array<T, IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS>;
1088
1089 template <typename T>
1090 using AttachmentVector = angle::FixedVector<T, IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS>;
1091
1092 using AttachmentsMask = angle::BitSet<IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS>;
1093
1094 template <typename T>
1095 using DrawBuffersArray = std::array<T, IMPLEMENTATION_MAX_DRAW_BUFFERS>;
1096
1097 template <typename T>
1098 using DrawBuffersVector = angle::FixedVector<T, IMPLEMENTATION_MAX_DRAW_BUFFERS>;
1099
1100 template <typename T>
1101 using AttribArray = std::array<T, MAX_VERTEX_ATTRIBS>;
1102
1103 template <typename T>
1104 using AttribVector = angle::FixedVector<T, MAX_VERTEX_ATTRIBS>;
1105
1106 using ActiveTextureMask = angle::BitSet<IMPLEMENTATION_MAX_ACTIVE_TEXTURES>;
1107
1108 template <typename T>
1109 using ActiveTextureArray = std::array<T, IMPLEMENTATION_MAX_ACTIVE_TEXTURES>;
1110
1111 using ActiveTextureTypeArray = ActiveTextureArray<TextureType>;
1112
1113 using ImageUnitMask = angle::BitSet<IMPLEMENTATION_MAX_IMAGE_UNITS>;
1114
1115 using SupportedSampleSet = std::set<GLuint>;
1116
1117 template <typename T>
1118 using TransformFeedbackBuffersArray =
1119 std::array<T, gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS>;
1120
1121 using ClipDistanceEnableBits = angle::BitSet32<IMPLEMENTATION_MAX_CLIP_DISTANCES>;
1122
1123 template <typename T>
1124 using QueryTypeMap = angle::PackedEnumMap<QueryType, T>;
1125
1126 constexpr size_t kBarrierVectorDefaultSize = 16;
1127
1128 template <typename T>
1129 using BarrierVector = angle::FastVector<T, kBarrierVectorDefaultSize>;
1130
1131 using BufferBarrierVector = BarrierVector<Buffer *>;
1132
1133 using SamplerBindingVector = std::vector<BindingPointer<Sampler>>;
1134 using BufferVector = std::vector<OffsetBindingPointer<Buffer>>;
1135
1136 struct TextureAndLayout
1137 {
1138 Texture *texture;
1139 GLenum layout;
1140 };
1141 using TextureBarrierVector = BarrierVector<TextureAndLayout>;
1142
1143 // OffsetBindingPointer.getSize() returns the size specified by the user, which may be larger than
1144 // the size of the bound buffer. This function reduces the returned size to fit the bound buffer if
1145 // necessary. Returns 0 if no buffer is bound or if integer overflow occurs.
1146 GLsizeiptr GetBoundBufferAvailableSize(const OffsetBindingPointer<Buffer> &binding);
1147
1148 // A texture level index.
1149 template <typename T>
1150 class LevelIndexWrapper
1151 {
1152 public:
1153 LevelIndexWrapper() = default;
LevelIndexWrapper(T levelIndex)1154 explicit constexpr LevelIndexWrapper(T levelIndex) : mLevelIndex(levelIndex) {}
1155 constexpr LevelIndexWrapper(const LevelIndexWrapper &other) = default;
1156 constexpr LevelIndexWrapper &operator=(const LevelIndexWrapper &other) = default;
1157
get()1158 constexpr T get() const { return mLevelIndex; }
1159
1160 LevelIndexWrapper &operator++()
1161 {
1162 ++mLevelIndex;
1163 return *this;
1164 }
1165 constexpr bool operator<(const LevelIndexWrapper &other) const
1166 {
1167 return mLevelIndex < other.mLevelIndex;
1168 }
1169 constexpr bool operator<=(const LevelIndexWrapper &other) const
1170 {
1171 return mLevelIndex <= other.mLevelIndex;
1172 }
1173 constexpr bool operator>(const LevelIndexWrapper &other) const
1174 {
1175 return mLevelIndex > other.mLevelIndex;
1176 }
1177 constexpr bool operator>=(const LevelIndexWrapper &other) const
1178 {
1179 return mLevelIndex >= other.mLevelIndex;
1180 }
1181 constexpr bool operator==(const LevelIndexWrapper &other) const
1182 {
1183 return mLevelIndex == other.mLevelIndex;
1184 }
1185 constexpr bool operator!=(const LevelIndexWrapper &other) const
1186 {
1187 return mLevelIndex != other.mLevelIndex;
1188 }
1189 constexpr LevelIndexWrapper operator+(T other) const
1190 {
1191 return LevelIndexWrapper(mLevelIndex + other);
1192 }
1193 constexpr LevelIndexWrapper operator-(T other) const
1194 {
1195 return LevelIndexWrapper(mLevelIndex - other);
1196 }
1197 constexpr T operator-(LevelIndexWrapper other) const { return mLevelIndex - other.mLevelIndex; }
1198
1199 private:
1200 T mLevelIndex;
1201 };
1202
1203 // A GL texture level index.
1204 using LevelIndex = LevelIndexWrapper<GLint>;
1205
1206 enum class MultisamplingMode
1207 {
1208 // Regular multisampling
1209 Regular = 0,
1210 // GL_EXT_multisampled_render_to_texture renderbuffer/texture attachments which perform implicit
1211 // resolve of multisampled data.
1212 MultisampledRenderToTexture,
1213 };
1214 } // namespace gl
1215
1216 namespace rx
1217 {
1218 // A macro that determines whether an object has a given runtime type.
1219 #if defined(__clang__)
1220 # if __has_feature(cxx_rtti)
1221 # define ANGLE_HAS_DYNAMIC_CAST 1
1222 # endif
1223 #elif !defined(NDEBUG) && (!defined(_MSC_VER) || defined(_CPPRTTI)) && \
1224 (!defined(__GNUC__) || __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 3) || \
1225 defined(__GXX_RTTI))
1226 # define ANGLE_HAS_DYNAMIC_CAST 1
1227 #endif
1228
1229 #ifdef ANGLE_HAS_DYNAMIC_CAST
1230 # define ANGLE_HAS_DYNAMIC_TYPE(type, obj) (dynamic_cast<type>(obj) != nullptr)
1231 # undef ANGLE_HAS_DYNAMIC_CAST
1232 #else
1233 # define ANGLE_HAS_DYNAMIC_TYPE(type, obj) (obj != nullptr)
1234 #endif
1235
1236 // Downcast a base implementation object (EG TextureImpl to TextureD3D)
1237 template <typename DestT, typename SrcT>
GetAs(SrcT * src)1238 inline DestT *GetAs(SrcT *src)
1239 {
1240 ASSERT(ANGLE_HAS_DYNAMIC_TYPE(DestT *, src));
1241 return static_cast<DestT *>(src);
1242 }
1243
1244 template <typename DestT, typename SrcT>
GetAs(const SrcT * src)1245 inline const DestT *GetAs(const SrcT *src)
1246 {
1247 ASSERT(ANGLE_HAS_DYNAMIC_TYPE(const DestT *, src));
1248 return static_cast<const DestT *>(src);
1249 }
1250
1251 #undef ANGLE_HAS_DYNAMIC_TYPE
1252
1253 // Downcast a GL object to an Impl (EG gl::Texture to rx::TextureD3D)
1254 template <typename DestT, typename SrcT>
GetImplAs(SrcT * src)1255 inline DestT *GetImplAs(SrcT *src)
1256 {
1257 return GetAs<DestT>(src->getImplementation());
1258 }
1259
1260 template <typename DestT, typename SrcT>
SafeGetImplAs(SrcT * src)1261 inline DestT *SafeGetImplAs(SrcT *src)
1262 {
1263 return src != nullptr ? GetAs<DestT>(src->getImplementation()) : nullptr;
1264 }
1265
1266 } // namespace rx
1267
1268 #include "angletypes.inc"
1269
1270 namespace angle
1271 {
1272 enum class NativeWindowSystem
1273 {
1274 X11,
1275 Wayland,
1276 Gbm,
1277 Other,
1278 };
1279
1280 struct FeatureOverrides
1281 {
1282 std::vector<std::string> enabled;
1283 std::vector<std::string> disabled;
1284 bool allDisabled = false;
1285 };
1286
1287 // 160-bit SHA-1 hash key used for hasing a program. BlobCache opts in using fixed keys for
1288 // simplicity and efficiency.
1289 static constexpr size_t kBlobCacheKeyLength = angle::base::kSHA1Length;
1290 using BlobCacheKey = std::array<uint8_t, kBlobCacheKeyLength>;
1291 class BlobCacheValue // To be replaced with std::span when C++20 is required
1292 {
1293 public:
BlobCacheValue()1294 BlobCacheValue() : mPtr(nullptr), mSize(0) {}
BlobCacheValue(const uint8_t * ptr,size_t size)1295 BlobCacheValue(const uint8_t *ptr, size_t size) : mPtr(ptr), mSize(size) {}
1296
1297 // A very basic struct to hold the pointer and size together. The objects of this class
1298 // don't own the memory.
data()1299 const uint8_t *data() { return mPtr; }
size()1300 size_t size() { return mSize; }
1301
1302 const uint8_t &operator[](size_t pos) const
1303 {
1304 ASSERT(pos < mSize);
1305 return mPtr[pos];
1306 }
1307
1308 private:
1309 const uint8_t *mPtr;
1310 size_t mSize;
1311 };
1312
1313 bool CompressBlob(const size_t cacheSize, const uint8_t *cacheData, MemoryBuffer *compressedData);
1314 bool DecompressBlob(const uint8_t *compressedData,
1315 const size_t compressedSize,
1316 size_t maxUncompressedDataSize,
1317 MemoryBuffer *uncompressedData);
1318 uint32_t GenerateCRC32(const uint8_t *data, size_t size);
1319 uint32_t InitCRC32();
1320 uint32_t UpdateCRC32(uint32_t prevCrc32, const uint8_t *data, size_t size);
1321 } // namespace angle
1322
1323 namespace std
1324 {
1325 template <>
1326 struct hash<angle::BlobCacheKey>
1327 {
1328 // Simple routine to hash four ints.
1329 size_t operator()(const angle::BlobCacheKey &key) const
1330 {
1331 return angle::ComputeGenericHash(key.data(), key.size());
1332 }
1333 };
1334 } // namespace std
1335
1336 namespace angle
1337 {
1338 // Under certain circumstances, such as for increased parallelism, the backend may defer an
1339 // operation to be done at the end of a call after the locks have been unlocked. The entry point
1340 // function passes an |UnlockedTailCall| through the frontend to the backend. If it is set, the
1341 // entry point would execute it at the end of the call.
1342 //
1343 // Since the function is called without any locks, care must be taken to minimize the amount of work
1344 // in such calls and ensure thread safety (for example by using fine grained locks inside the call
1345 // itself).
1346 //
1347 // Some entry points pass a void pointer argument to UnlockedTailCall::run method intended to
1348 // contain the return value filled by the backend, the rest of the entry points pass in a
1349 // nullptr. Regardless, Display::terminate runs pending tail calls passing in a nullptr, so
1350 // the tail calls that return a value in the argument still have to guard against a nullptr
1351 // parameter.
1352 class UnlockedTailCall final : angle::NonCopyable
1353 {
1354 public:
1355 using CallType = std::function<void(void *)>;
1356
1357 UnlockedTailCall();
1358 ~UnlockedTailCall();
1359
1360 void add(CallType &&call);
1361 ANGLE_INLINE void run(void *resultOut)
1362 {
1363 if (!mCalls.empty())
1364 {
1365 runImpl(resultOut);
1366 }
1367 }
1368
1369 bool any() const { return !mCalls.empty(); }
1370
1371 private:
1372 void runImpl(void *resultOut);
1373
1374 // Typically, there is only one tail call. It is possible to end up with 2 tail calls currently
1375 // with unMakeCurrent destroying both the read and draw surfaces, each adding a tail call in the
1376 // Vulkan backend.
1377 //
1378 // Some apps will create multiple windows surfaces and not call corresponding destroy api, which
1379 // cause many tail calls been added, so remove the max call count limitations.
1380 std::vector<CallType> mCalls;
1381 };
1382
1383 enum class JobThreadSafety
1384 {
1385 Safe,
1386 Unsafe,
1387 };
1388
1389 enum class JobResultExpectancy
1390 {
1391 // Whether the compile or link job's results are immediately needed. This is the case for GLES1
1392 // programs for example, or shader compilation in glCreateShaderProgramv.
1393 Immediate,
1394 // Whether the compile or link job's results are needed after the end of the current entry point
1395 // call. In this case, the job may be done in an unlocked tail call.
1396 Future,
1397 };
1398
1399 // Zero-based for better array indexing
1400 enum FramebufferBinding
1401 {
1402 FramebufferBindingRead = 0,
1403 FramebufferBindingDraw,
1404 FramebufferBindingSingletonMax,
1405 FramebufferBindingBoth = FramebufferBindingSingletonMax,
1406 FramebufferBindingMax,
1407 FramebufferBindingUnknown = FramebufferBindingMax,
1408 };
1409
1410 inline FramebufferBinding EnumToFramebufferBinding(GLenum enumValue)
1411 {
1412 switch (enumValue)
1413 {
1414 case GL_READ_FRAMEBUFFER:
1415 return FramebufferBindingRead;
1416 case GL_DRAW_FRAMEBUFFER:
1417 return FramebufferBindingDraw;
1418 case GL_FRAMEBUFFER:
1419 return FramebufferBindingBoth;
1420 default:
1421 UNREACHABLE();
1422 return FramebufferBindingUnknown;
1423 }
1424 }
1425
1426 inline GLenum FramebufferBindingToEnum(FramebufferBinding binding)
1427 {
1428 switch (binding)
1429 {
1430 case FramebufferBindingRead:
1431 return GL_READ_FRAMEBUFFER;
1432 case FramebufferBindingDraw:
1433 return GL_DRAW_FRAMEBUFFER;
1434 case FramebufferBindingBoth:
1435 return GL_FRAMEBUFFER;
1436 default:
1437 UNREACHABLE();
1438 return GL_NONE;
1439 }
1440 }
1441
1442 template <typename ObjT, typename ContextT>
1443 class DestroyThenDelete
1444 {
1445 public:
1446 DestroyThenDelete() = default;
1447 DestroyThenDelete(const ContextT *context) : mContext(context) {}
1448
1449 void operator()(ObjT *obj)
1450 {
1451 (void)(obj->onDestroy(mContext));
1452 delete obj;
1453 }
1454
1455 private:
1456 const ContextT *mContext = nullptr;
1457 };
1458
1459 template <typename ObjT, typename ContextT>
1460 using UniqueObjectPointer = std::unique_ptr<ObjT, DestroyThenDelete<ObjT, ContextT>>;
1461
1462 } // namespace angle
1463
1464 namespace gl
1465 {
1466 class State;
1467
1468 // Focal Point information for foveated rendering
1469 struct FocalPoint
1470 {
1471 float focalX;
1472 float focalY;
1473 float gainX;
1474 float gainY;
1475 float foveaArea;
1476
1477 constexpr FocalPoint() : focalX(0), focalY(0), gainX(0), gainY(0), foveaArea(0) {}
1478
1479 FocalPoint(float fX, float fY, float gX, float gY, float fArea)
1480 : focalX(fX), focalY(fY), gainX(gX), gainY(gY), foveaArea(fArea)
1481 {}
1482 FocalPoint(const FocalPoint &other) = default;
1483 FocalPoint &operator=(const FocalPoint &other) = default;
1484
1485 bool operator==(const FocalPoint &other) const
1486 {
1487 return focalX == other.focalX && focalY == other.focalY && gainX == other.gainX &&
1488 gainY == other.gainY && foveaArea == other.foveaArea;
1489 }
1490 bool operator!=(const FocalPoint &other) const { return !(*this == other); }
1491
1492 bool valid() const { return gainX > 0 && gainY > 0; }
1493 };
1494
1495 constexpr FocalPoint kDefaultFocalPoint = FocalPoint();
1496
1497 class FoveationState
1498 {
1499 public:
1500 FoveationState()
1501 {
1502 mConfigured = false;
1503 mFoveatedFeatureBits = 0;
1504 mMinPixelDensity = 0.0f;
1505 mFocalPoints.fill(kDefaultFocalPoint);
1506 }
1507 FoveationState &operator=(const FoveationState &other) = default;
1508
1509 void configure() { mConfigured = true; }
1510 bool isConfigured() const { return mConfigured; }
1511 bool isFoveated() const
1512 {
1513 // Consider foveated if at least 1 focal point is valid
1514 return std::any_of(mFocalPoints.begin(), mFocalPoints.end(),
1515 [](const FocalPoint &focalPoint) { return focalPoint.valid(); });
1516 }
1517 bool operator==(const FoveationState &other) const
1518 {
1519 return mConfigured == other.mConfigured &&
1520 mFoveatedFeatureBits == other.mFoveatedFeatureBits &&
1521 mMinPixelDensity == other.mMinPixelDensity && mFocalPoints == other.mFocalPoints;
1522 }
1523 bool operator!=(const FoveationState &other) const { return !(*this == other); }
1524
1525 void setFoveatedFeatureBits(const GLuint features) { mFoveatedFeatureBits = features; }
1526 GLuint getFoveatedFeatureBits() const { return mFoveatedFeatureBits; }
1527 void setMinPixelDensity(const GLfloat density) { mMinPixelDensity = density; }
1528 GLfloat getMinPixelDensity() const { return mMinPixelDensity; }
1529 GLuint getMaxNumFocalPoints() const { return gl::IMPLEMENTATION_MAX_FOCAL_POINTS; }
1530 void setFocalPoint(uint32_t layer, uint32_t focalPointIndex, const FocalPoint &focalPoint)
1531 {
1532 mFocalPoints[getIndex(layer, focalPointIndex)] = focalPoint;
1533 }
1534 const FocalPoint &getFocalPoint(uint32_t layer, uint32_t focalPointIndex) const
1535 {
1536 return mFocalPoints[getIndex(layer, focalPointIndex)];
1537 }
1538 GLuint getSupportedFoveationFeatures() const { return GL_FOVEATION_ENABLE_BIT_QCOM; }
1539
1540 private:
1541 size_t getIndex(uint32_t layer, uint32_t focalPointIndex) const
1542 {
1543 ASSERT(layer < IMPLEMENTATION_MAX_NUM_LAYERS &&
1544 focalPointIndex < IMPLEMENTATION_MAX_FOCAL_POINTS);
1545 return (layer * IMPLEMENTATION_MAX_FOCAL_POINTS) + focalPointIndex;
1546 }
1547 bool mConfigured;
1548 GLuint mFoveatedFeatureBits;
1549 GLfloat mMinPixelDensity;
1550
1551 static constexpr size_t kMaxFocalPoints =
1552 IMPLEMENTATION_MAX_NUM_LAYERS * IMPLEMENTATION_MAX_FOCAL_POINTS;
1553 std::array<FocalPoint, kMaxFocalPoints> mFocalPoints;
1554 };
1555
1556 } // namespace gl
1557
1558 #endif // LIBANGLE_ANGLETYPES_H_
1559