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 &operator=(const BlendStateExt &other);
583
584 ///////// Blending Toggle /////////
585
586 void setEnabled(const bool enabled);
587 void setEnabledIndexed(const size_t index, const bool enabled);
588
589 ///////// Color Write Mask /////////
590
PackColorMask(const bool red,const bool green,const bool blue,const bool alpha)591 static constexpr size_t PackColorMask(const bool red,
592 const bool green,
593 const bool blue,
594 const bool alpha)
595 {
596 return (red ? 1 : 0) | (green ? 2 : 0) | (blue ? 4 : 0) | (alpha ? 8 : 0);
597 }
598
UnpackColorMask(const size_t value,bool * red,bool * green,bool * blue,bool * alpha)599 static constexpr void UnpackColorMask(const size_t value,
600 bool *red,
601 bool *green,
602 bool *blue,
603 bool *alpha)
604 {
605 *red = static_cast<bool>(value & 1);
606 *green = static_cast<bool>(value & 2);
607 *blue = static_cast<bool>(value & 4);
608 *alpha = static_cast<bool>(value & 8);
609 }
610
611 ColorMaskStorage::Type expandColorMaskValue(const bool red,
612 const bool green,
613 const bool blue,
614 const bool alpha) const;
615 ColorMaskStorage::Type expandColorMaskIndexed(const size_t index) const;
616 void setColorMask(const bool red, const bool green, const bool blue, const bool alpha);
617 void setColorMaskIndexed(const size_t index, const uint8_t value);
618 void setColorMaskIndexed(const size_t index,
619 const bool red,
620 const bool green,
621 const bool blue,
622 const bool alpha);
623 uint8_t getColorMaskIndexed(const size_t index) const;
624 void getColorMaskIndexed(const size_t index,
625 bool *red,
626 bool *green,
627 bool *blue,
628 bool *alpha) const;
629 DrawBufferMask compareColorMask(ColorMaskStorage::Type other) const;
630
631 ///////// Blend Equation /////////
632
633 EquationStorage::Type expandEquationValue(const GLenum mode) const;
634 EquationStorage::Type expandEquationColorIndexed(const size_t index) const;
635 EquationStorage::Type expandEquationAlphaIndexed(const size_t index) const;
636 void setEquations(const GLenum modeColor, const GLenum modeAlpha);
637 void setEquationsIndexed(const size_t index, const GLenum modeColor, const GLenum modeAlpha);
638 void setEquationsIndexed(const size_t index,
639 const size_t otherIndex,
640 const BlendStateExt &other);
641 GLenum getEquationColorIndexed(size_t index) const;
642 GLenum getEquationAlphaIndexed(size_t index) const;
643 DrawBufferMask compareEquations(const EquationStorage::Type color,
644 const EquationStorage::Type alpha) const;
645
646 ///////// Blend Factors /////////
647
648 FactorStorage::Type expandFactorValue(const GLenum func) const;
649 FactorStorage::Type expandSrcColorIndexed(const size_t index) const;
650 FactorStorage::Type expandDstColorIndexed(const size_t index) const;
651 FactorStorage::Type expandSrcAlphaIndexed(const size_t index) const;
652 FactorStorage::Type expandDstAlphaIndexed(const size_t index) const;
653 void setFactors(const GLenum srcColor,
654 const GLenum dstColor,
655 const GLenum srcAlpha,
656 const GLenum dstAlpha);
657 void setFactorsIndexed(const size_t index,
658 const GLenum srcColor,
659 const GLenum dstColor,
660 const GLenum srcAlpha,
661 const GLenum dstAlpha);
662 void setFactorsIndexed(const size_t index, const size_t otherIndex, const BlendStateExt &other);
663 GLenum getSrcColorIndexed(size_t index) const;
664 GLenum getDstColorIndexed(size_t index) const;
665 GLenum getSrcAlphaIndexed(size_t index) const;
666 GLenum getDstAlphaIndexed(size_t index) const;
667 DrawBufferMask compareFactors(const FactorStorage::Type srcColor,
668 const FactorStorage::Type dstColor,
669 const FactorStorage::Type srcAlpha,
670 const FactorStorage::Type dstAlpha) const;
671
672 ///////// Data Members /////////
673
674 const FactorStorage::Type mMaxFactorMask;
675 FactorStorage::Type mSrcColor;
676 FactorStorage::Type mDstColor;
677 FactorStorage::Type mSrcAlpha;
678 FactorStorage::Type mDstAlpha;
679
680 const EquationStorage::Type mMaxEquationMask;
681 EquationStorage::Type mEquationColor;
682 EquationStorage::Type mEquationAlpha;
683
684 const ColorMaskStorage::Type mMaxColorMask;
685 ColorMaskStorage::Type mColorMask;
686
687 const DrawBufferMask mMaxEnabledMask;
688 DrawBufferMask mEnabledMask;
689
690 const size_t mMaxDrawBuffers;
691 };
692
693 // Used in StateCache
694 using StorageBuffersMask = angle::BitSet<IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS>;
695
696 template <typename T>
697 using TexLevelArray = std::array<T, IMPLEMENTATION_MAX_TEXTURE_LEVELS>;
698
699 using TexLevelMask = angle::BitSet<IMPLEMENTATION_MAX_TEXTURE_LEVELS>;
700
701 enum class ComponentType
702 {
703 Float = 0,
704 Int = 1,
705 UnsignedInt = 2,
706 NoType = 3,
707 EnumCount = 4,
708 InvalidEnum = 4,
709 };
710
GLenumToComponentType(GLenum componentType)711 constexpr ComponentType GLenumToComponentType(GLenum componentType)
712 {
713 switch (componentType)
714 {
715 case GL_FLOAT:
716 return ComponentType::Float;
717 case GL_INT:
718 return ComponentType::Int;
719 case GL_UNSIGNED_INT:
720 return ComponentType::UnsignedInt;
721 case GL_NONE:
722 return ComponentType::NoType;
723 default:
724 return ComponentType::InvalidEnum;
725 }
726 }
727
728 constexpr angle::PackedEnumMap<ComponentType, uint32_t> kComponentMasks = {{
729 {ComponentType::Float, 0x10001},
730 {ComponentType::Int, 0x00001},
731 {ComponentType::UnsignedInt, 0x10000},
732 }};
733
734 constexpr size_t kMaxComponentTypeMaskIndex = 16;
735 using ComponentTypeMask = angle::BitSet<kMaxComponentTypeMaskIndex * 2>;
736
SetComponentTypeMask(ComponentType type,size_t index,ComponentTypeMask * mask)737 ANGLE_INLINE void SetComponentTypeMask(ComponentType type, size_t index, ComponentTypeMask *mask)
738 {
739 ASSERT(index <= kMaxComponentTypeMaskIndex);
740 *mask &= ~(0x10001 << index);
741 *mask |= kComponentMasks[type] << index;
742 }
743
GetComponentTypeMask(const ComponentTypeMask & mask,size_t index)744 ANGLE_INLINE ComponentType GetComponentTypeMask(const ComponentTypeMask &mask, size_t index)
745 {
746 ASSERT(index <= kMaxComponentTypeMaskIndex);
747 uint32_t mask_bits = static_cast<uint32_t>((mask.to_ulong() >> index) & 0x10001);
748 switch (mask_bits)
749 {
750 case 0x10001:
751 return ComponentType::Float;
752 case 0x00001:
753 return ComponentType::Int;
754 case 0x10000:
755 return ComponentType::UnsignedInt;
756 default:
757 return ComponentType::InvalidEnum;
758 }
759 }
760
761 bool ValidateComponentTypeMasks(unsigned long outputTypes,
762 unsigned long inputTypes,
763 unsigned long outputMask,
764 unsigned long inputMask);
765
766 enum class RenderToTextureImageIndex
767 {
768 // The default image of the texture, where data is expected to be.
769 Default = 0,
770
771 // Intermediate multisampled images for EXT_multisampled_render_to_texture.
772 // These values must match log2(SampleCount).
773 IntermediateImage2xMultisampled = 1,
774 IntermediateImage4xMultisampled = 2,
775 IntermediateImage8xMultisampled = 3,
776 IntermediateImage16xMultisampled = 4,
777
778 // We currently only support up to 16xMSAA in backends that use this enum.
779 InvalidEnum = 5,
780 EnumCount = 5,
781 };
782
783 template <typename T>
784 using RenderToTextureImageMap = angle::PackedEnumMap<RenderToTextureImageIndex, T>;
785
786 struct ContextID
787 {
788 uint32_t value;
789 };
790
791 inline bool operator==(ContextID lhs, ContextID rhs)
792 {
793 return lhs.value == rhs.value;
794 }
795
796 inline bool operator!=(ContextID lhs, ContextID rhs)
797 {
798 return lhs.value != rhs.value;
799 }
800
801 inline bool operator<(ContextID lhs, ContextID rhs)
802 {
803 return lhs.value < rhs.value;
804 }
805
806 constexpr size_t kCubeFaceCount = 6;
807
808 template <typename T>
809 using TextureTypeMap = angle::PackedEnumMap<TextureType, T>;
810 using TextureMap = TextureTypeMap<BindingPointer<Texture>>;
811
812 // ShaderVector can contain one item per shader. It differs from ShaderMap in that the values are
813 // not indexed by ShaderType.
814 template <typename T>
815 using ShaderVector = angle::FixedVector<T, static_cast<size_t>(ShaderType::EnumCount)>;
816
817 template <typename T>
818 using AttachmentArray = std::array<T, IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS>;
819
820 template <typename T>
821 using AttachmentVector = angle::FixedVector<T, IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS>;
822
823 using AttachmentsMask = angle::BitSet<IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS>;
824
825 template <typename T>
826 using DrawBuffersArray = std::array<T, IMPLEMENTATION_MAX_DRAW_BUFFERS>;
827
828 template <typename T>
829 using DrawBuffersVector = angle::FixedVector<T, IMPLEMENTATION_MAX_DRAW_BUFFERS>;
830
831 template <typename T>
832 using AttribArray = std::array<T, MAX_VERTEX_ATTRIBS>;
833
834 using ActiveTextureMask = angle::BitSet<IMPLEMENTATION_MAX_ACTIVE_TEXTURES>;
835
836 template <typename T>
837 using ActiveTextureArray = std::array<T, IMPLEMENTATION_MAX_ACTIVE_TEXTURES>;
838
839 using ActiveTextureTypeArray = ActiveTextureArray<TextureType>;
840
841 template <typename T>
842 using UniformBuffersArray = std::array<T, IMPLEMENTATION_MAX_UNIFORM_BUFFER_BINDINGS>;
843 template <typename T>
844 using StorageBuffersArray = std::array<T, IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS>;
845 template <typename T>
846 using AtomicCounterBuffersArray = std::array<T, IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS>;
847 using AtomicCounterBufferMask = angle::BitSet<IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS>;
848 template <typename T>
849 using ImagesArray = std::array<T, IMPLEMENTATION_MAX_IMAGE_UNITS>;
850
851 using ImageUnitMask = angle::BitSet<IMPLEMENTATION_MAX_IMAGE_UNITS>;
852
853 using SupportedSampleSet = std::set<GLuint>;
854
855 template <typename T>
856 using TransformFeedbackBuffersArray =
857 std::array<T, gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS>;
858
859 template <typename T>
860 using QueryTypeMap = angle::PackedEnumMap<QueryType, T>;
861
862 constexpr size_t kBarrierVectorDefaultSize = 16;
863
864 template <typename T>
865 using BarrierVector = angle::FastVector<T, kBarrierVectorDefaultSize>;
866
867 using BufferBarrierVector = BarrierVector<Buffer *>;
868
869 struct TextureAndLayout
870 {
871 Texture *texture;
872 GLenum layout;
873 };
874 using TextureBarrierVector = BarrierVector<TextureAndLayout>;
875
876 // OffsetBindingPointer.getSize() returns the size specified by the user, which may be larger than
877 // the size of the bound buffer. This function reduces the returned size to fit the bound buffer if
878 // necessary. Returns 0 if no buffer is bound or if integer overflow occurs.
879 GLsizeiptr GetBoundBufferAvailableSize(const OffsetBindingPointer<Buffer> &binding);
880
881 // A texture level index.
882 template <typename T>
883 class LevelIndexWrapper
884 {
885 public:
886 LevelIndexWrapper() = default;
LevelIndexWrapper(T levelIndex)887 explicit constexpr LevelIndexWrapper(T levelIndex) : mLevelIndex(levelIndex) {}
888 constexpr LevelIndexWrapper(const LevelIndexWrapper &other) = default;
889 constexpr LevelIndexWrapper &operator=(const LevelIndexWrapper &other) = default;
890
get()891 constexpr T get() const { return mLevelIndex; }
892
893 LevelIndexWrapper &operator++()
894 {
895 ++mLevelIndex;
896 return *this;
897 }
898 constexpr bool operator<(const LevelIndexWrapper &other) const
899 {
900 return mLevelIndex < other.mLevelIndex;
901 }
902 constexpr bool operator<=(const LevelIndexWrapper &other) const
903 {
904 return mLevelIndex <= other.mLevelIndex;
905 }
906 constexpr bool operator>(const LevelIndexWrapper &other) const
907 {
908 return mLevelIndex > other.mLevelIndex;
909 }
910 constexpr bool operator>=(const LevelIndexWrapper &other) const
911 {
912 return mLevelIndex >= other.mLevelIndex;
913 }
914 constexpr bool operator==(const LevelIndexWrapper &other) const
915 {
916 return mLevelIndex == other.mLevelIndex;
917 }
918 constexpr bool operator!=(const LevelIndexWrapper &other) const
919 {
920 return mLevelIndex != other.mLevelIndex;
921 }
922 constexpr LevelIndexWrapper operator+(T other) const
923 {
924 return LevelIndexWrapper(mLevelIndex + other);
925 }
926 constexpr LevelIndexWrapper operator-(T other) const
927 {
928 return LevelIndexWrapper(mLevelIndex - other);
929 }
930 constexpr T operator-(LevelIndexWrapper other) const { return mLevelIndex - other.mLevelIndex; }
931
932 private:
933 T mLevelIndex;
934 };
935
936 // A GL texture level index.
937 using LevelIndex = LevelIndexWrapper<GLint>;
938
939 enum class MultisamplingMode
940 {
941 // Regular multisampling
942 Regular = 0,
943 // GL_EXT_multisampled_render_to_texture renderbuffer/texture attachments which perform implicit
944 // resolve of multisampled data.
945 MultisampledRenderToTexture,
946 };
947 } // namespace gl
948
949 namespace rx
950 {
951 // A macro that determines whether an object has a given runtime type.
952 #if defined(__clang__)
953 # if __has_feature(cxx_rtti)
954 # define ANGLE_HAS_DYNAMIC_CAST 1
955 # endif
956 #elif !defined(NDEBUG) && (!defined(_MSC_VER) || defined(_CPPRTTI)) && \
957 (!defined(__GNUC__) || __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 3) || \
958 defined(__GXX_RTTI))
959 # define ANGLE_HAS_DYNAMIC_CAST 1
960 #endif
961
962 #ifdef ANGLE_HAS_DYNAMIC_CAST
963 # define ANGLE_HAS_DYNAMIC_TYPE(type, obj) (dynamic_cast<type>(obj) != nullptr)
964 # undef ANGLE_HAS_DYNAMIC_CAST
965 #else
966 # define ANGLE_HAS_DYNAMIC_TYPE(type, obj) (obj != nullptr)
967 #endif
968
969 // Downcast a base implementation object (EG TextureImpl to TextureD3D)
970 template <typename DestT, typename SrcT>
GetAs(SrcT * src)971 inline DestT *GetAs(SrcT *src)
972 {
973 ASSERT(ANGLE_HAS_DYNAMIC_TYPE(DestT *, src));
974 return static_cast<DestT *>(src);
975 }
976
977 template <typename DestT, typename SrcT>
GetAs(const SrcT * src)978 inline const DestT *GetAs(const SrcT *src)
979 {
980 ASSERT(ANGLE_HAS_DYNAMIC_TYPE(const DestT *, src));
981 return static_cast<const DestT *>(src);
982 }
983
984 #undef ANGLE_HAS_DYNAMIC_TYPE
985
986 // Downcast a GL object to an Impl (EG gl::Texture to rx::TextureD3D)
987 template <typename DestT, typename SrcT>
GetImplAs(SrcT * src)988 inline DestT *GetImplAs(SrcT *src)
989 {
990 return GetAs<DestT>(src->getImplementation());
991 }
992
993 template <typename DestT, typename SrcT>
SafeGetImplAs(SrcT * src)994 inline DestT *SafeGetImplAs(SrcT *src)
995 {
996 return src != nullptr ? GetAs<DestT>(src->getImplementation()) : nullptr;
997 }
998
999 } // namespace rx
1000
1001 #include "angletypes.inc"
1002
1003 namespace angle
1004 {
1005 // Zero-based for better array indexing
1006 enum FramebufferBinding
1007 {
1008 FramebufferBindingRead = 0,
1009 FramebufferBindingDraw,
1010 FramebufferBindingSingletonMax,
1011 FramebufferBindingBoth = FramebufferBindingSingletonMax,
1012 FramebufferBindingMax,
1013 FramebufferBindingUnknown = FramebufferBindingMax,
1014 };
1015
EnumToFramebufferBinding(GLenum enumValue)1016 inline FramebufferBinding EnumToFramebufferBinding(GLenum enumValue)
1017 {
1018 switch (enumValue)
1019 {
1020 case GL_READ_FRAMEBUFFER:
1021 return FramebufferBindingRead;
1022 case GL_DRAW_FRAMEBUFFER:
1023 return FramebufferBindingDraw;
1024 case GL_FRAMEBUFFER:
1025 return FramebufferBindingBoth;
1026 default:
1027 UNREACHABLE();
1028 return FramebufferBindingUnknown;
1029 }
1030 }
1031
FramebufferBindingToEnum(FramebufferBinding binding)1032 inline GLenum FramebufferBindingToEnum(FramebufferBinding binding)
1033 {
1034 switch (binding)
1035 {
1036 case FramebufferBindingRead:
1037 return GL_READ_FRAMEBUFFER;
1038 case FramebufferBindingDraw:
1039 return GL_DRAW_FRAMEBUFFER;
1040 case FramebufferBindingBoth:
1041 return GL_FRAMEBUFFER;
1042 default:
1043 UNREACHABLE();
1044 return GL_NONE;
1045 }
1046 }
1047
1048 template <typename ObjT, typename ContextT>
1049 class DestroyThenDelete
1050 {
1051 public:
DestroyThenDelete(const ContextT * context)1052 DestroyThenDelete(const ContextT *context) : mContext(context) {}
1053
operator()1054 void operator()(ObjT *obj)
1055 {
1056 (void)(obj->onDestroy(mContext));
1057 delete obj;
1058 }
1059
1060 private:
1061 const ContextT *mContext;
1062 };
1063
1064 // Helper class for wrapping an onDestroy function.
1065 template <typename ObjT, typename DeleterT>
1066 class UniqueObjectPointerBase : angle::NonCopyable
1067 {
1068 public:
1069 template <typename ContextT>
UniqueObjectPointerBase(const ContextT * context)1070 UniqueObjectPointerBase(const ContextT *context) : mObject(nullptr), mDeleter(context)
1071 {}
1072
1073 template <typename ContextT>
UniqueObjectPointerBase(ObjT * obj,const ContextT * context)1074 UniqueObjectPointerBase(ObjT *obj, const ContextT *context) : mObject(obj), mDeleter(context)
1075 {}
1076
~UniqueObjectPointerBase()1077 ~UniqueObjectPointerBase()
1078 {
1079 if (mObject)
1080 {
1081 mDeleter(mObject);
1082 }
1083 }
1084
1085 ObjT *operator->() const { return mObject; }
1086
release()1087 ObjT *release()
1088 {
1089 auto obj = mObject;
1090 mObject = nullptr;
1091 return obj;
1092 }
1093
get()1094 ObjT *get() const { return mObject; }
1095
reset(ObjT * obj)1096 void reset(ObjT *obj)
1097 {
1098 if (mObject)
1099 {
1100 mDeleter(mObject);
1101 }
1102 mObject = obj;
1103 }
1104
1105 private:
1106 ObjT *mObject;
1107 DeleterT mDeleter;
1108 };
1109
1110 template <typename ObjT, typename ContextT>
1111 using UniqueObjectPointer = UniqueObjectPointerBase<ObjT, DestroyThenDelete<ObjT, ContextT>>;
1112
1113 } // namespace angle
1114
1115 namespace gl
1116 {
1117 class State;
1118 } // namespace gl
1119
1120 #endif // LIBANGLE_ANGLETYPES_H_
1121