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