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