blob: e98c8c5da066c8dfd6c5430aaa109e6ae8f71e6d [file] [log] [blame]
Austin Engcc2516a2023-10-17 20:57:54 +00001// Copyright 2017 The Dawn & Tint Authors
Ben Clayton9fb7a512022-02-04 18:18:18 +00002//
Austin Engcc2516a2023-10-17 20:57:54 +00003// Redistribution and use in source and binary forms, with or without
4// modification, are permitted provided that the following conditions are met:
Ben Clayton9fb7a512022-02-04 18:18:18 +00005//
Austin Engcc2516a2023-10-17 20:57:54 +00006// 1. Redistributions of source code must retain the above copyright notice, this
7// list of conditions and the following disclaimer.
Ben Clayton9fb7a512022-02-04 18:18:18 +00008//
Austin Engcc2516a2023-10-17 20:57:54 +00009// 2. Redistributions in binary form must reproduce the above copyright notice,
10// this list of conditions and the following disclaimer in the documentation
11// and/or other materials provided with the distribution.
12//
13// 3. Neither the name of the copyright holder nor the names of its
14// contributors may be used to endorse or promote products derived from
15// this software without specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
21// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Ben Clayton9fb7a512022-02-04 18:18:18 +000027
Kai Ninomiya68892272024-01-04 10:02:49 +000028#ifndef WEBGPU_ENUM_CLASS_BITMASKS_H_
29#define WEBGPU_ENUM_CLASS_BITMASKS_H_
Ben Clayton9fb7a512022-02-04 18:18:18 +000030
31#include <type_traits>
32
Kai Ninomiya68892272024-01-04 10:02:49 +000033// The operators in wgpu:: namespace need be introduced into other namespaces with
Ben Clayton9fb7a512022-02-04 18:18:18 +000034// using-declarations for C++ Argument Dependent Lookup to work.
Kai Ninomiya68892272024-01-04 10:02:49 +000035#define WGPU_IMPORT_BITMASK_OPERATORS \
36 using wgpu::operator|; \
37 using wgpu::operator&; \
38 using wgpu::operator^; \
39 using wgpu::operator~; \
40 using wgpu::operator&=; \
41 using wgpu::operator|=; \
42 using wgpu::operator^=; \
43 using wgpu::HasZeroOrOneBits;
Ben Clayton9fb7a512022-02-04 18:18:18 +000044
Kai Ninomiya68892272024-01-04 10:02:49 +000045namespace wgpu {
Ben Clayton9fb7a512022-02-04 18:18:18 +000046
dan sinclair41e4d9a2022-05-01 14:40:55 +000047template <typename T>
Kai Ninomiya68892272024-01-04 10:02:49 +000048struct IsWGPUBitmask {
dan sinclair41e4d9a2022-05-01 14:40:55 +000049 static constexpr bool enable = false;
50};
Ben Clayton9fb7a512022-02-04 18:18:18 +000051
dan sinclair41e4d9a2022-05-01 14:40:55 +000052template <typename T, typename Enable = void>
53struct LowerBitmask {
54 static constexpr bool enable = false;
55};
Ben Clayton9fb7a512022-02-04 18:18:18 +000056
dan sinclair41e4d9a2022-05-01 14:40:55 +000057template <typename T>
Kai Ninomiya68892272024-01-04 10:02:49 +000058struct LowerBitmask<T, typename std::enable_if<IsWGPUBitmask<T>::enable>::type> {
dan sinclair41e4d9a2022-05-01 14:40:55 +000059 static constexpr bool enable = true;
60 using type = T;
61 constexpr static T Lower(T t) { return t; }
62};
Ben Clayton9fb7a512022-02-04 18:18:18 +000063
dan sinclair41e4d9a2022-05-01 14:40:55 +000064template <typename T>
65struct BoolConvertible {
66 using Integral = typename std::underlying_type<T>::type;
Ben Clayton9fb7a512022-02-04 18:18:18 +000067
dan sinclair41e4d9a2022-05-01 14:40:55 +000068 // NOLINTNEXTLINE(runtime/explicit)
Corentin Wallez40358fd2023-01-30 13:51:32 +000069 explicit constexpr BoolConvertible(Integral value) : value(value) {}
dan sinclair41e4d9a2022-05-01 14:40:55 +000070 constexpr operator bool() const { return value != 0; }
71 constexpr operator T() const { return static_cast<T>(value); }
Ben Clayton9fb7a512022-02-04 18:18:18 +000072
dan sinclair41e4d9a2022-05-01 14:40:55 +000073 Integral value;
74};
Ben Clayton9fb7a512022-02-04 18:18:18 +000075
dan sinclair41e4d9a2022-05-01 14:40:55 +000076template <typename T>
77struct LowerBitmask<BoolConvertible<T>> {
78 static constexpr bool enable = true;
79 using type = T;
80 static constexpr type Lower(BoolConvertible<T> t) { return t; }
81};
Ben Clayton9fb7a512022-02-04 18:18:18 +000082
dan sinclair41e4d9a2022-05-01 14:40:55 +000083template <
84 typename T1,
85 typename T2,
86 typename = typename std::enable_if<LowerBitmask<T1>::enable && LowerBitmask<T2>::enable>::type>
87constexpr BoolConvertible<typename LowerBitmask<T1>::type> operator|(T1 left, T2 right) {
88 using T = typename LowerBitmask<T1>::type;
89 using Integral = typename std::underlying_type<T>::type;
Corentin Wallez40358fd2023-01-30 13:51:32 +000090 return BoolConvertible<T>(static_cast<Integral>(LowerBitmask<T1>::Lower(left)) |
91 static_cast<Integral>(LowerBitmask<T2>::Lower(right)));
dan sinclair41e4d9a2022-05-01 14:40:55 +000092}
Ben Clayton9fb7a512022-02-04 18:18:18 +000093
dan sinclair41e4d9a2022-05-01 14:40:55 +000094template <
95 typename T1,
96 typename T2,
97 typename = typename std::enable_if<LowerBitmask<T1>::enable && LowerBitmask<T2>::enable>::type>
98constexpr BoolConvertible<typename LowerBitmask<T1>::type> operator&(T1 left, T2 right) {
99 using T = typename LowerBitmask<T1>::type;
100 using Integral = typename std::underlying_type<T>::type;
Corentin Wallez40358fd2023-01-30 13:51:32 +0000101 return BoolConvertible<T>(static_cast<Integral>(LowerBitmask<T1>::Lower(left)) &
102 static_cast<Integral>(LowerBitmask<T2>::Lower(right)));
dan sinclair41e4d9a2022-05-01 14:40:55 +0000103}
Ben Clayton9fb7a512022-02-04 18:18:18 +0000104
dan sinclair41e4d9a2022-05-01 14:40:55 +0000105template <
106 typename T1,
107 typename T2,
108 typename = typename std::enable_if<LowerBitmask<T1>::enable && LowerBitmask<T2>::enable>::type>
109constexpr BoolConvertible<typename LowerBitmask<T1>::type> operator^(T1 left, T2 right) {
110 using T = typename LowerBitmask<T1>::type;
111 using Integral = typename std::underlying_type<T>::type;
Corentin Wallez40358fd2023-01-30 13:51:32 +0000112 return BoolConvertible<T>(static_cast<Integral>(LowerBitmask<T1>::Lower(left)) ^
113 static_cast<Integral>(LowerBitmask<T2>::Lower(right)));
dan sinclair41e4d9a2022-05-01 14:40:55 +0000114}
Ben Clayton9fb7a512022-02-04 18:18:18 +0000115
dan sinclair41e4d9a2022-05-01 14:40:55 +0000116template <typename T1>
117constexpr BoolConvertible<typename LowerBitmask<T1>::type> operator~(T1 t) {
118 using T = typename LowerBitmask<T1>::type;
119 using Integral = typename std::underlying_type<T>::type;
Corentin Wallez40358fd2023-01-30 13:51:32 +0000120 return BoolConvertible<T>(~static_cast<Integral>(LowerBitmask<T1>::Lower(t)));
dan sinclair41e4d9a2022-05-01 14:40:55 +0000121}
Ben Clayton9fb7a512022-02-04 18:18:18 +0000122
dan sinclair41e4d9a2022-05-01 14:40:55 +0000123template <
124 typename T,
125 typename T2,
Kai Ninomiya68892272024-01-04 10:02:49 +0000126 typename = typename std::enable_if<IsWGPUBitmask<T>::enable && LowerBitmask<T2>::enable>::type>
dan sinclair41e4d9a2022-05-01 14:40:55 +0000127constexpr T& operator&=(T& l, T2 right) {
128 T r = LowerBitmask<T2>::Lower(right);
129 l = l & r;
130 return l;
131}
Ben Clayton9fb7a512022-02-04 18:18:18 +0000132
dan sinclair41e4d9a2022-05-01 14:40:55 +0000133template <
134 typename T,
135 typename T2,
Kai Ninomiya68892272024-01-04 10:02:49 +0000136 typename = typename std::enable_if<IsWGPUBitmask<T>::enable && LowerBitmask<T2>::enable>::type>
dan sinclair41e4d9a2022-05-01 14:40:55 +0000137constexpr T& operator|=(T& l, T2 right) {
138 T r = LowerBitmask<T2>::Lower(right);
139 l = l | r;
140 return l;
141}
Ben Clayton9fb7a512022-02-04 18:18:18 +0000142
dan sinclair41e4d9a2022-05-01 14:40:55 +0000143template <
144 typename T,
145 typename T2,
Kai Ninomiya68892272024-01-04 10:02:49 +0000146 typename = typename std::enable_if<IsWGPUBitmask<T>::enable && LowerBitmask<T2>::enable>::type>
dan sinclair41e4d9a2022-05-01 14:40:55 +0000147constexpr T& operator^=(T& l, T2 right) {
148 T r = LowerBitmask<T2>::Lower(right);
149 l = l ^ r;
150 return l;
151}
Ben Clayton9fb7a512022-02-04 18:18:18 +0000152
dan sinclair41e4d9a2022-05-01 14:40:55 +0000153template <typename T>
154constexpr bool HasZeroOrOneBits(T value) {
155 using Integral = typename std::underlying_type<T>::type;
156 return (static_cast<Integral>(value) & (static_cast<Integral>(value) - 1)) == 0;
157}
Ben Clayton9fb7a512022-02-04 18:18:18 +0000158
Kai Ninomiya68892272024-01-04 10:02:49 +0000159} // namespace wgpu
Ben Clayton9fb7a512022-02-04 18:18:18 +0000160
Kai Ninomiya68892272024-01-04 10:02:49 +0000161#endif // WEBGPU_ENUM_CLASS_BITMASKS_H_