1 /*
2 * Copyright © 2022 Google, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24 #ifndef FREEDRENO_COMMON_H_
25 #define FREEDRENO_COMMON_H_
26
27 #include "util/u_atomic.h"
28
29 #ifdef __cplusplus
30 template<typename E>
31 struct BitmaskEnum {
32 E value;
33
34 using underlying = typename std::underlying_type_t<E>;
35
36 #define FOREACH_TYPE(M, ...) \
37 M(E, ##__VA_ARGS__) \
38 M(bool, ##__VA_ARGS__) \
39 M(uint8_t, ##__VA_ARGS__) \
40 M(int8_t, ##__VA_ARGS__) \
41 M(uint16_t, ##__VA_ARGS__) \
42 M(int16_t, ##__VA_ARGS__) \
43 M(uint32_t, ##__VA_ARGS__) \
44 M(int32_t, ##__VA_ARGS__)
45
46 #define CONSTRUCTOR(T) BitmaskEnum(T value) : value(static_cast<E>(value)) {}
47 FOREACH_TYPE(CONSTRUCTOR)
48 #undef CONSTRUCTOR
49
50 #define CAST(T) inline operator T() const { return static_cast<T>(value); }
51 FOREACH_TYPE(CAST)
52 #undef CAST
53
54 #define BOP(T, OP) \
55 inline E operator OP(T rhs) const { \
56 return static_cast<E> ( \
57 static_cast<underlying>(value) OP \
58 static_cast<underlying>(rhs) \
59 ); \
60 }
61 FOREACH_TYPE(BOP, |)
62 FOREACH_TYPE(BOP, &)
63 #undef BOP
64
65 #define BOP(OP) \
66 inline BitmaskEnum<E> operator OP(BitmaskEnum<E> rhs) const { \
67 return static_cast<E> ( \
68 static_cast<underlying>(value) OP \
69 static_cast<underlying>(rhs.value) \
70 ); \
71 }
72 BOP(|)
73 BOP(&)
74 #undef BOP
75
76 #if defined(__GNUC__) && !defined(__clang)
77 /*
78 * Silence:
79 *
80 * ../src/freedreno/common/freedreno_common.h: In instantiation of 'E& BitmaskEnum<E>::operator|=(BitmaskEnum<E>::underlying) [with E = fd_dirty_3d_state; BitmaskEnum<E>::underlying = unsigned int]':
81 * ../src/gallium/drivers/freedreno/freedreno_context.h:620:16: required from here
82 * ../src/freedreno/common/freedreno_common.h:68:39: error: dereferencing type-punned pointer will break strict-aliasing rules [-Werror=strict-aliasing]
83 * 68 | reinterpret_cast<underlying&>(value) OP static_cast<underlying>(rhs) ); \
84 * | ^~~~~
85 *
86 * I cannot reproduce on gcc 12.2.1 or with clang 14.0.5 so I'm going to assume
87 * this is a bug with gcc 10.x
88 */
89 #pragma GCC diagnostic push
90 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
91 #endif
92
93 #define UOP(T, OP) \
94 inline E& operator OP(T rhs) { \
95 return reinterpret_cast<E&>( \
96 reinterpret_cast<underlying&>(value) OP static_cast<underlying>(rhs) ); \
97 }
98 UOP(underlying, |=)
99 UOP(underlying, &=)
100 #undef UOP
101
102 #if defined(__GNUC__) && !defined(__clang) && (__GNUC__ < 7)
103 #pragma GCC diagnostic pop
104 #endif
105
106 inline E operator ~() const {
107 static_assert(sizeof(E) == sizeof(BitmaskEnum<E>));
108 return static_cast<E> (
109 ~static_cast<underlying>(value)
110 );
111 }
112 #undef FOREACH_TYPE
113 };
114 #define BITMASK_ENUM(E) BitmaskEnum<E>
115 #else
116 #define BITMASK_ENUM(E) enum E
117 #endif
118
119 #ifdef __cplusplus
120 # define EXTERNC extern "C"
121 # define BEGINC EXTERNC {
122 # define ENDC }
123 #else
124 # define EXTERNC
125 # define BEGINC
126 # define ENDC
127 #endif
128
129 /*
130 * SWAP - swap value of @a and @b
131 */
132 #define SWAP(a, b) \
133 do { \
134 __typeof(a) __tmp = (a); \
135 (a) = (b); \
136 (b) = __tmp; \
137 } while (0)
138
139 /* for conditionally setting boolean flag(s): */
140 #define COND(bool, val) ((bool) ? (val) : 0)
141
142 #define BIT(bit) BITFIELD64_BIT(bit)
143
144 /**
145 * Helper for allocating sequence #s where zero is a non-valid seqno
146 */
147 typedef struct {
148 uint32_t counter;
149 } seqno_t;
150
151 static inline uint32_t
seqno_next(seqno_t * seq)152 seqno_next(seqno_t *seq)
153 {
154 uint32_t n;
155 do {
156 n = p_atomic_inc_return(&seq->counter);
157 } while (n == 0);
158 return n;
159 }
160
161 static inline uint16_t
seqno_next_u16(seqno_t * seq)162 seqno_next_u16(seqno_t *seq)
163 {
164 uint16_t n;
165 do {
166 n = p_atomic_inc_return(&seq->counter);
167 } while (n == 0);
168 return n;
169 }
170
171 #endif /* FREEDRENO_COMMON_H_ */
172