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