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