1/*
2 * Copyright 2021 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef skgpu_EnumBitMask_DEFINED
9#define skgpu_EnumBitMask_DEFINED
10
11#include "experimental/graphite/include/GraphiteTypes.h"
12
13namespace skgpu {
14
15/**
16 * Wraps an enum that is used for flags, and enables masking with type safety. Example:
17 *
18 *   enum class MyFlags {
19 *       kNone = 0,
20 *       kA = 1,
21 *       kB = 2,
22 *       kC = 4,
23 *   };
24 *
25 *   SKGPU_MAKE_MASK_OPS(MyFlags)
26 *
27 *   ...
28 *
29 *       Mask<MyFlags> flags = MyFlags::kA | MyFlags::kB;
30 *
31 *       if (flags & MyFlags::kB) {}
32 *
33 *   ...
34 */
35template<typename E>
36class Mask {
37public:
38    SK_ALWAYS_INLINE constexpr Mask(E e) : Mask((int)e) {}
39
40    SK_ALWAYS_INLINE constexpr operator bool() const { return fValue; }
41
42    SK_ALWAYS_INLINE bool operator==(Mask m) const { return fValue == m.fValue; }
43    SK_ALWAYS_INLINE bool operator!=(Mask m) const { return fValue != m.fValue; }
44
45    SK_ALWAYS_INLINE constexpr Mask operator|(Mask m) const { return Mask(fValue | m.fValue); }
46    SK_ALWAYS_INLINE constexpr Mask operator&(Mask m) const { return Mask(fValue & m.fValue); }
47    SK_ALWAYS_INLINE constexpr Mask operator^(Mask m) const { return Mask(fValue ^ m.fValue); }
48    SK_ALWAYS_INLINE constexpr Mask operator~() const { return Mask(~fValue); }
49
50    SK_ALWAYS_INLINE Mask& operator|=(Mask m) { return *this = *this | m; }
51    SK_ALWAYS_INLINE Mask& operator&=(Mask m) { return *this = *this & m; }
52    SK_ALWAYS_INLINE Mask& operator^=(Mask m) { return *this = *this ^ m; }
53
54private:
55    SK_ALWAYS_INLINE constexpr explicit Mask(int value) : fValue(value) {}
56
57    int fValue;
58};
59
60/**
61 * Defines functions that make it possible to use bitwise operators on an enum.
62 */
63#define SKGPU_MAKE_MASK_OPS(E) \
64    SK_MAYBE_UNUSED constexpr skgpu::Mask<E> operator|(E a, E b) { return skgpu::Mask<E>(a) | b; } \
65    SK_MAYBE_UNUSED constexpr skgpu::Mask<E> operator&(E a, E b) { return skgpu::Mask<E>(a) & b; } \
66    SK_MAYBE_UNUSED constexpr skgpu::Mask<E> operator^(E a, E b) { return skgpu::Mask<E>(a) ^ b; } \
67    SK_MAYBE_UNUSED constexpr skgpu::Mask<E> operator~(E e) { return ~skgpu::Mask<E>(e); } \
68
69#define SKGPU_DECL_MASK_OPS_FRIENDS(E) \
70    friend constexpr skgpu::Mask<E> operator|(E, E); \
71    friend constexpr skgpu::Mask<E> operator&(E, E); \
72    friend constexpr skgpu::Mask<E> operator^(E, E); \
73    friend constexpr skgpu::Mask<E> operator~(E); \
74
75};  // namespace skgpu
76
77#endif // skgpu_EnumBitMask_DEFINED
78
79
80