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 struct Rectangle
34 {
RectangleRectangle35 Rectangle() : x(0), y(0), width(0), height(0) {}
RectangleRectangle36 constexpr Rectangle(int x_in, int y_in, int width_in, int height_in)
37 : x(x_in), y(y_in), width(width_in), height(height_in)
38 {}
39
x0Rectangle40 int x0() const { return x; }
y0Rectangle41 int y0() const { return y; }
x1Rectangle42 int x1() const { return x + width; }
y1Rectangle43 int y1() const { return y + height; }
44
isReversedXRectangle45 bool isReversedX() const { return width < 0; }
isReversedYRectangle46 bool isReversedY() const { return height < 0; }
47
48 // Returns a rectangle with the same area but flipped in X, Y, neither or both.
49 Rectangle flip(bool flipX, bool flipY) const;
50
51 // Returns a rectangle with the same area but with height and width guaranteed to be positive.
52 Rectangle removeReversal() const;
53
54 bool encloses(const gl::Rectangle &inside) const;
55
56 int x;
57 int y;
58 int width;
59 int height;
60 };
61
62 bool operator==(const Rectangle &a, const Rectangle &b);
63 bool operator!=(const Rectangle &a, const Rectangle &b);
64
65 bool ClipRectangle(const Rectangle &source, const Rectangle &clip, Rectangle *intersection);
66
67 struct Offset
68 {
OffsetOffset69 constexpr Offset() : x(0), y(0), z(0) {}
OffsetOffset70 constexpr Offset(int x_in, int y_in, int z_in) : x(x_in), y(y_in), z(z_in) {}
71
72 int x;
73 int y;
74 int z;
75 };
76
77 constexpr Offset kOffsetZero(0, 0, 0);
78
79 bool operator==(const Offset &a, const Offset &b);
80 bool operator!=(const Offset &a, const Offset &b);
81
82 struct Extents
83 {
ExtentsExtents84 Extents() : width(0), height(0), depth(0) {}
ExtentsExtents85 Extents(int width_, int height_, int depth_) : width(width_), height(height_), depth(depth_) {}
86
87 Extents(const Extents &other) = default;
88 Extents &operator=(const Extents &other) = default;
89
emptyExtents90 bool empty() const { return (width * height * depth) == 0; }
91
92 int width;
93 int height;
94 int depth;
95 };
96
97 bool operator==(const Extents &lhs, const Extents &rhs);
98 bool operator!=(const Extents &lhs, const Extents &rhs);
99
100 struct Box
101 {
BoxBox102 Box() : x(0), y(0), z(0), width(0), height(0), depth(0) {}
BoxBox103 Box(int x_in, int y_in, int z_in, int width_in, int height_in, int depth_in)
104 : x(x_in), y(y_in), z(z_in), width(width_in), height(height_in), depth(depth_in)
105 {}
BoxBox106 Box(const Offset &offset, const Extents &size)
107 : x(offset.x),
108 y(offset.y),
109 z(offset.z),
110 width(size.width),
111 height(size.height),
112 depth(size.depth)
113 {}
114 bool operator==(const Box &other) const;
115 bool operator!=(const Box &other) const;
116 Rectangle toRect() const;
117
118 int x;
119 int y;
120 int z;
121 int width;
122 int height;
123 int depth;
124 };
125
126 struct RasterizerState final
127 {
128 // This will zero-initialize the struct, including padding.
129 RasterizerState();
130
131 bool cullFace;
132 CullFaceMode cullMode;
133 GLenum frontFace;
134
135 bool polygonOffsetFill;
136 GLfloat polygonOffsetFactor;
137 GLfloat polygonOffsetUnits;
138
139 bool pointDrawMode;
140 bool multiSample;
141
142 bool rasterizerDiscard;
143 };
144
145 bool operator==(const RasterizerState &a, const RasterizerState &b);
146 bool operator!=(const RasterizerState &a, const RasterizerState &b);
147
148 struct BlendState final
149 {
150 // This will zero-initialize the struct, including padding.
151 BlendState();
152 BlendState(const BlendState &other);
153
154 bool allChannelsMasked() const;
155
156 bool blend;
157 GLenum sourceBlendRGB;
158 GLenum destBlendRGB;
159 GLenum sourceBlendAlpha;
160 GLenum destBlendAlpha;
161 GLenum blendEquationRGB;
162 GLenum blendEquationAlpha;
163
164 bool colorMaskRed;
165 bool colorMaskGreen;
166 bool colorMaskBlue;
167 bool colorMaskAlpha;
168
169 bool sampleAlphaToCoverage;
170
171 bool dither;
172 };
173
174 bool operator==(const BlendState &a, const BlendState &b);
175 bool operator!=(const BlendState &a, const BlendState &b);
176
177 struct DepthStencilState final
178 {
179 // This will zero-initialize the struct, including padding.
180 DepthStencilState();
181 DepthStencilState(const DepthStencilState &other);
182
183 bool depthTest;
184 GLenum depthFunc;
185 bool depthMask;
186
187 bool stencilTest;
188 GLenum stencilFunc;
189 GLuint stencilMask;
190 GLenum stencilFail;
191 GLenum stencilPassDepthFail;
192 GLenum stencilPassDepthPass;
193 GLuint stencilWritemask;
194 GLenum stencilBackFunc;
195 GLuint stencilBackMask;
196 GLenum stencilBackFail;
197 GLenum stencilBackPassDepthFail;
198 GLenum stencilBackPassDepthPass;
199 GLuint stencilBackWritemask;
200 };
201
202 bool operator==(const DepthStencilState &a, const DepthStencilState &b);
203 bool operator!=(const DepthStencilState &a, const DepthStencilState &b);
204
205 // Packs a sampler state for completeness checks:
206 // * minFilter: 5 values (3 bits)
207 // * magFilter: 2 values (1 bit)
208 // * wrapS: 3 values (2 bits)
209 // * wrapT: 3 values (2 bits)
210 // * compareMode: 1 bit (for == GL_NONE).
211 // This makes a total of 9 bits. We can pack this easily into 32 bits:
212 // * minFilter: 8 bits
213 // * magFilter: 8 bits
214 // * wrapS: 8 bits
215 // * wrapT: 4 bits
216 // * compareMode: 4 bits
217
218 struct PackedSamplerCompleteness
219 {
220 uint8_t minFilter;
221 uint8_t magFilter;
222 uint8_t wrapS;
223 uint8_t wrapTCompareMode;
224 };
225
226 static_assert(sizeof(PackedSamplerCompleteness) == sizeof(uint32_t), "Unexpected size");
227
228 // State from Table 6.10 (state per sampler object)
229 class SamplerState final
230 {
231 public:
232 // This will zero-initialize the struct, including padding.
233 SamplerState();
234 SamplerState(const SamplerState &other);
235
236 static SamplerState CreateDefaultForTarget(TextureType type);
237
getMinFilter()238 GLenum getMinFilter() const { return mMinFilter; }
239
240 void setMinFilter(GLenum minFilter);
241
getMagFilter()242 GLenum getMagFilter() const { return mMagFilter; }
243
244 void setMagFilter(GLenum magFilter);
245
getWrapS()246 GLenum getWrapS() const { return mWrapS; }
247
248 void setWrapS(GLenum wrapS);
249
getWrapT()250 GLenum getWrapT() const { return mWrapT; }
251
252 void setWrapT(GLenum wrapT);
253
getWrapR()254 GLenum getWrapR() const { return mWrapR; }
255
256 void setWrapR(GLenum wrapR);
257
getMaxAnisotropy()258 float getMaxAnisotropy() const { return mMaxAnisotropy; }
259
260 void setMaxAnisotropy(float maxAnisotropy);
261
getMinLod()262 GLfloat getMinLod() const { return mMinLod; }
263
264 void setMinLod(GLfloat minLod);
265
getMaxLod()266 GLfloat getMaxLod() const { return mMaxLod; }
267
268 void setMaxLod(GLfloat maxLod);
269
getCompareMode()270 GLenum getCompareMode() const { return mCompareMode; }
271
272 void setCompareMode(GLenum compareMode);
273
getCompareFunc()274 GLenum getCompareFunc() const { return mCompareFunc; }
275
276 void setCompareFunc(GLenum compareFunc);
277
getSRGBDecode()278 GLenum getSRGBDecode() const { return mSRGBDecode; }
279
280 void setSRGBDecode(GLenum sRGBDecode);
281
282 void setBorderColor(const ColorGeneric &color);
283
getBorderColor()284 const ColorGeneric &getBorderColor() const { return mBorderColor; }
285
sameCompleteness(const SamplerState & samplerState)286 bool sameCompleteness(const SamplerState &samplerState) const
287 {
288 return mCompleteness.packed == samplerState.mCompleteness.packed;
289 }
290
291 private:
292 void updateWrapTCompareMode();
293
294 GLenum mMinFilter;
295 GLenum mMagFilter;
296
297 GLenum mWrapS;
298 GLenum mWrapT;
299 GLenum mWrapR;
300
301 // From EXT_texture_filter_anisotropic
302 float mMaxAnisotropy;
303
304 GLfloat mMinLod;
305 GLfloat mMaxLod;
306
307 GLenum mCompareMode;
308 GLenum mCompareFunc;
309
310 GLenum mSRGBDecode;
311
312 ColorGeneric mBorderColor;
313
314 union Completeness
315 {
316 uint32_t packed;
317 PackedSamplerCompleteness typed;
318 };
319
320 Completeness mCompleteness;
321 };
322
323 bool operator==(const SamplerState &a, const SamplerState &b);
324 bool operator!=(const SamplerState &a, const SamplerState &b);
325
326 struct DrawArraysIndirectCommand
327 {
328 GLuint count;
329 GLuint instanceCount;
330 GLuint first;
331 GLuint baseInstance;
332 };
333 static_assert(sizeof(DrawArraysIndirectCommand) == 16,
334 "Unexpected size of DrawArraysIndirectCommand");
335
336 struct DrawElementsIndirectCommand
337 {
338 GLuint count;
339 GLuint primCount;
340 GLuint firstIndex;
341 GLint baseVertex;
342 GLuint baseInstance;
343 };
344 static_assert(sizeof(DrawElementsIndirectCommand) == 20,
345 "Unexpected size of DrawElementsIndirectCommand");
346
347 struct ImageUnit
348 {
349 ImageUnit();
350 ImageUnit(const ImageUnit &other);
351 ~ImageUnit();
352
353 BindingPointer<Texture> texture;
354 GLint level;
355 GLboolean layered;
356 GLint layer;
357 GLenum access;
358 GLenum format;
359 };
360
361 using ImageUnitTextureTypeMap = std::map<unsigned int, gl::TextureType>;
362
363 struct PixelStoreStateBase
364 {
365 GLint alignment = 4;
366 GLint rowLength = 0;
367 GLint skipRows = 0;
368 GLint skipPixels = 0;
369 GLint imageHeight = 0;
370 GLint skipImages = 0;
371 };
372
373 struct PixelUnpackState : PixelStoreStateBase
374 {};
375
376 struct PixelPackState : PixelStoreStateBase
377 {
378 bool reverseRowOrder = false;
379 };
380
381 // Used in Program and VertexArray.
382 using AttributesMask = angle::BitSet<MAX_VERTEX_ATTRIBS>;
383
384 // Used in Program
385 using UniformBlockBindingMask = angle::BitSet<IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS>;
386
387 // Used in Framebuffer / Program
388 using DrawBufferMask = angle::BitSet<IMPLEMENTATION_MAX_DRAW_BUFFERS>;
389
390 // Used in StateCache
391 using StorageBuffersMask = angle::BitSet<IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS>;
392
393 template <typename T>
394 using TexLevelArray = std::array<T, IMPLEMENTATION_MAX_TEXTURE_LEVELS>;
395
396 enum class ComponentType
397 {
398 Float = 0,
399 Int = 1,
400 UnsignedInt = 2,
401 NoType = 3,
402 EnumCount = 4,
403 InvalidEnum = 4,
404 };
405
GLenumToComponentType(GLenum componentType)406 constexpr ComponentType GLenumToComponentType(GLenum componentType)
407 {
408 switch (componentType)
409 {
410 case GL_FLOAT:
411 return ComponentType::Float;
412 case GL_INT:
413 return ComponentType::Int;
414 case GL_UNSIGNED_INT:
415 return ComponentType::UnsignedInt;
416 case GL_NONE:
417 return ComponentType::NoType;
418 default:
419 return ComponentType::InvalidEnum;
420 }
421 }
422
423 constexpr angle::PackedEnumMap<ComponentType, uint32_t> kComponentMasks = {{
424 {ComponentType::Float, 0x10001},
425 {ComponentType::Int, 0x00001},
426 {ComponentType::UnsignedInt, 0x10000},
427 }};
428
429 constexpr size_t kMaxComponentTypeMaskIndex = 16;
430 using ComponentTypeMask = angle::BitSet<kMaxComponentTypeMaskIndex * 2>;
431
SetComponentTypeMask(ComponentType type,size_t index,ComponentTypeMask * mask)432 ANGLE_INLINE void SetComponentTypeMask(ComponentType type, size_t index, ComponentTypeMask *mask)
433 {
434 ASSERT(index <= kMaxComponentTypeMaskIndex);
435 *mask &= ~(0x10001 << index);
436 *mask |= kComponentMasks[type] << index;
437 }
438
GetComponentTypeMask(const ComponentTypeMask & mask,size_t index)439 ANGLE_INLINE ComponentType GetComponentTypeMask(const ComponentTypeMask &mask, size_t index)
440 {
441 ASSERT(index <= kMaxComponentTypeMaskIndex);
442 uint32_t mask_bits = static_cast<uint32_t>((mask.to_ulong() >> index) & 0x10001);
443 switch (mask_bits)
444 {
445 case 0x10001:
446 return ComponentType::Float;
447 case 0x00001:
448 return ComponentType::Int;
449 case 0x10000:
450 return ComponentType::UnsignedInt;
451 default:
452 return ComponentType::InvalidEnum;
453 }
454 }
455
456 bool ValidateComponentTypeMasks(unsigned long outputTypes,
457 unsigned long inputTypes,
458 unsigned long outputMask,
459 unsigned long inputMask);
460
461 using ContextID = uintptr_t;
462
463 constexpr size_t kCubeFaceCount = 6;
464
465 using TextureMap = angle::PackedEnumMap<TextureType, BindingPointer<Texture>>;
466
467 // ShaderVector can contain one item per shader. It differs from ShaderMap in that the values are
468 // not indexed by ShaderType.
469 template <typename T>
470 using ShaderVector = angle::FixedVector<T, static_cast<size_t>(ShaderType::EnumCount)>;
471
472 template <typename T>
473 using AttachmentArray = std::array<T, IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS>;
474
475 template <typename T>
476 using DrawBuffersArray = std::array<T, IMPLEMENTATION_MAX_DRAW_BUFFERS>;
477
478 template <typename T>
479 using DrawBuffersVector = angle::FixedVector<T, IMPLEMENTATION_MAX_DRAW_BUFFERS>;
480
481 template <typename T>
482 using AttribArray = std::array<T, MAX_VERTEX_ATTRIBS>;
483
484 using ActiveTextureMask = angle::BitSet<IMPLEMENTATION_MAX_ACTIVE_TEXTURES>;
485
486 template <typename T>
487 using ActiveTextureArray = std::array<T, IMPLEMENTATION_MAX_ACTIVE_TEXTURES>;
488
489 using ActiveTexturePointerArray = ActiveTextureArray<Texture *>;
490 using ActiveTextureTypeArray = ActiveTextureArray<TextureType>;
491
492 template <typename T>
493 using UniformBuffersArray = std::array<T, IMPLEMENTATION_MAX_UNIFORM_BUFFER_BINDINGS>;
494 template <typename T>
495 using StorageBuffersArray = std::array<T, IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS>;
496 template <typename T>
497 using AtomicCounterBuffersArray = std::array<T, IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS>;
498 using AtomicCounterBufferMask = angle::BitSet<IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS>;
499
500 using ImageUnitMask = angle::BitSet<IMPLEMENTATION_MAX_IMAGE_UNITS>;
501
502 using SupportedSampleSet = std::set<GLuint>;
503
504 template <typename T>
505 using TransformFeedbackBuffersArray =
506 std::array<T, gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS>;
507
508 constexpr size_t kBarrierVectorDefaultSize = 16;
509
510 template <typename T>
511 using BarrierVector = angle::FastVector<T, kBarrierVectorDefaultSize>;
512
513 using BufferBarrierVector = BarrierVector<Buffer *>;
514
515 struct TextureAndLayout
516 {
517 Texture *texture;
518 GLenum layout;
519 };
520 using TextureBarrierVector = BarrierVector<TextureAndLayout>;
521
522 // OffsetBindingPointer.getSize() returns the size specified by the user, which may be larger than
523 // the size of the bound buffer. This function reduces the returned size to fit the bound buffer if
524 // necessary. Returns 0 if no buffer is bound or if integer overflow occurs.
525 GLsizeiptr GetBoundBufferAvailableSize(const OffsetBindingPointer<Buffer> &binding);
526
527 } // namespace gl
528
529 namespace rx
530 {
531 // A macro that determines whether an object has a given runtime type.
532 #if defined(__clang__)
533 # if __has_feature(cxx_rtti)
534 # define ANGLE_HAS_DYNAMIC_CAST 1
535 # endif
536 #elif !defined(NDEBUG) && (!defined(_MSC_VER) || defined(_CPPRTTI)) && \
537 (!defined(__GNUC__) || __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 3) || \
538 defined(__GXX_RTTI))
539 # define ANGLE_HAS_DYNAMIC_CAST 1
540 #endif
541
542 #ifdef ANGLE_HAS_DYNAMIC_CAST
543 # define ANGLE_HAS_DYNAMIC_TYPE(type, obj) (dynamic_cast<type>(obj) != nullptr)
544 # undef ANGLE_HAS_DYNAMIC_CAST
545 #else
546 # define ANGLE_HAS_DYNAMIC_TYPE(type, obj) (obj != nullptr)
547 #endif
548
549 // Downcast a base implementation object (EG TextureImpl to TextureD3D)
550 template <typename DestT, typename SrcT>
GetAs(SrcT * src)551 inline DestT *GetAs(SrcT *src)
552 {
553 ASSERT(ANGLE_HAS_DYNAMIC_TYPE(DestT *, src));
554 return static_cast<DestT *>(src);
555 }
556
557 template <typename DestT, typename SrcT>
GetAs(const SrcT * src)558 inline const DestT *GetAs(const SrcT *src)
559 {
560 ASSERT(ANGLE_HAS_DYNAMIC_TYPE(const DestT *, src));
561 return static_cast<const DestT *>(src);
562 }
563
564 #undef ANGLE_HAS_DYNAMIC_TYPE
565
566 // Downcast a GL object to an Impl (EG gl::Texture to rx::TextureD3D)
567 template <typename DestT, typename SrcT>
GetImplAs(SrcT * src)568 inline DestT *GetImplAs(SrcT *src)
569 {
570 return GetAs<DestT>(src->getImplementation());
571 }
572
573 template <typename DestT, typename SrcT>
SafeGetImplAs(SrcT * src)574 inline DestT *SafeGetImplAs(SrcT *src)
575 {
576 return src != nullptr ? GetAs<DestT>(src->getImplementation()) : nullptr;
577 }
578
579 } // namespace rx
580
581 #include "angletypes.inc"
582
583 namespace angle
584 {
585 // Zero-based for better array indexing
586 enum FramebufferBinding
587 {
588 FramebufferBindingRead = 0,
589 FramebufferBindingDraw,
590 FramebufferBindingSingletonMax,
591 FramebufferBindingBoth = FramebufferBindingSingletonMax,
592 FramebufferBindingMax,
593 FramebufferBindingUnknown = FramebufferBindingMax,
594 };
595
EnumToFramebufferBinding(GLenum enumValue)596 inline FramebufferBinding EnumToFramebufferBinding(GLenum enumValue)
597 {
598 switch (enumValue)
599 {
600 case GL_READ_FRAMEBUFFER:
601 return FramebufferBindingRead;
602 case GL_DRAW_FRAMEBUFFER:
603 return FramebufferBindingDraw;
604 case GL_FRAMEBUFFER:
605 return FramebufferBindingBoth;
606 default:
607 UNREACHABLE();
608 return FramebufferBindingUnknown;
609 }
610 }
611
FramebufferBindingToEnum(FramebufferBinding binding)612 inline GLenum FramebufferBindingToEnum(FramebufferBinding binding)
613 {
614 switch (binding)
615 {
616 case FramebufferBindingRead:
617 return GL_READ_FRAMEBUFFER;
618 case FramebufferBindingDraw:
619 return GL_DRAW_FRAMEBUFFER;
620 case FramebufferBindingBoth:
621 return GL_FRAMEBUFFER;
622 default:
623 UNREACHABLE();
624 return GL_NONE;
625 }
626 }
627
628 template <typename ObjT, typename ContextT>
629 class DestroyThenDelete
630 {
631 public:
DestroyThenDelete(const ContextT * context)632 DestroyThenDelete(const ContextT *context) : mContext(context) {}
633
operator()634 void operator()(ObjT *obj)
635 {
636 (void)(obj->onDestroy(mContext));
637 delete obj;
638 }
639
640 private:
641 const ContextT *mContext;
642 };
643
644 // Helper class for wrapping an onDestroy function.
645 template <typename ObjT, typename DeleterT>
646 class UniqueObjectPointerBase : angle::NonCopyable
647 {
648 public:
649 template <typename ContextT>
UniqueObjectPointerBase(const ContextT * context)650 UniqueObjectPointerBase(const ContextT *context) : mObject(nullptr), mDeleter(context)
651 {}
652
653 template <typename ContextT>
UniqueObjectPointerBase(ObjT * obj,const ContextT * context)654 UniqueObjectPointerBase(ObjT *obj, const ContextT *context) : mObject(obj), mDeleter(context)
655 {}
656
~UniqueObjectPointerBase()657 ~UniqueObjectPointerBase()
658 {
659 if (mObject)
660 {
661 mDeleter(mObject);
662 }
663 }
664
665 ObjT *operator->() const { return mObject; }
666
release()667 ObjT *release()
668 {
669 auto obj = mObject;
670 mObject = nullptr;
671 return obj;
672 }
673
get()674 ObjT *get() const { return mObject; }
675
reset(ObjT * obj)676 void reset(ObjT *obj)
677 {
678 if (mObject)
679 {
680 mDeleter(mObject);
681 }
682 mObject = obj;
683 }
684
685 private:
686 ObjT *mObject;
687 DeleterT mDeleter;
688 };
689
690 template <typename ObjT, typename ContextT>
691 using UniqueObjectPointer = UniqueObjectPointerBase<ObjT, DestroyThenDelete<ObjT, ContextT>>;
692
693 } // namespace angle
694
695 namespace gl
696 {
697 class State;
698 } // namespace gl
699
700 #endif // LIBANGLE_ANGLETYPES_H_
701