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