1 /*
2 * Copyright © 2022 Google, Inc.
3 * SPDX-License-Identifier: MIT
4 */
5
6 #ifndef FREEDRENO_COMMON_H_
7 #define FREEDRENO_COMMON_H_
8
9 #include "util/u_atomic.h"
10
11 #ifdef __cplusplus
12
13 #include <tuple>
14
15 #define __FD_GPU_GENS A6XX, A7XX
16 #define FD_GENX(FUNC_NAME) \
17 template <chip... CHIPs> constexpr auto FUNC_NAME##instantiate() \
18 { \
19 return std::tuple_cat(std::make_tuple(FUNC_NAME<CHIPs>)...); \
20 } \
21 static constexpr auto FUNC_NAME##tmpl __attribute__((used)) = \
22 FUNC_NAME##instantiate<__FD_GPU_GENS>();
23
24 #define FD_CALLX(info, thing) \
25 ({ \
26 decltype(&thing<A6XX>) genX_thing; \
27 switch (info->chip) { \
28 case 6: \
29 genX_thing = &thing<A6XX>; \
30 break; \
31 case 7: \
32 genX_thing = &thing<A7XX>; \
33 break; \
34 default: \
35 unreachable("Unknown hardware generation"); \
36 } \
37 genX_thing; \
38 })
39
40
41 template<typename E>
42 struct BitmaskEnum {
43 E value;
44
45 using underlying = typename std::underlying_type_t<E>;
46
47 #define FOREACH_TYPE(M, ...) \
48 M(E, ##__VA_ARGS__) \
49 M(bool, ##__VA_ARGS__) \
50 M(uint8_t, ##__VA_ARGS__) \
51 M(int8_t, ##__VA_ARGS__) \
52 M(uint16_t, ##__VA_ARGS__) \
53 M(int16_t, ##__VA_ARGS__) \
54 M(uint32_t, ##__VA_ARGS__) \
55 M(int32_t, ##__VA_ARGS__)
56
57 #define CONSTRUCTOR(T) BitmaskEnum(T value) : value(static_cast<E>(value)) {}
58 FOREACH_TYPE(CONSTRUCTOR)
59 #undef CONSTRUCTOR
60
61 #define CAST(T) inline operator T() const { return static_cast<T>(value); }
62 FOREACH_TYPE(CAST)
63 #undef CAST
64
65 #define BOP(T, OP) \
66 inline E operator OP(T rhs) const { \
67 return static_cast<E> ( \
68 static_cast<underlying>(value) OP \
69 static_cast<underlying>(rhs) \
70 ); \
71 }
72 FOREACH_TYPE(BOP, |)
73 FOREACH_TYPE(BOP, &)
74 #undef BOP
75
76 #define BOP(OP) \
77 inline BitmaskEnum<E> operator OP(BitmaskEnum<E> rhs) const { \
78 return static_cast<E> ( \
79 static_cast<underlying>(value) OP \
80 static_cast<underlying>(rhs.value) \
81 ); \
82 }
83 BOP(|)
84 BOP(&)
85 #undef BOP
86
87 #if defined(__GNUC__) && !defined(__clang)
88 /*
89 * Silence:
90 *
91 * ../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]':
92 * ../src/gallium/drivers/freedreno/freedreno_context.h:620:16: required from here
93 * ../src/freedreno/common/freedreno_common.h:68:39: error: dereferencing type-punned pointer will break strict-aliasing rules [-Werror=strict-aliasing]
94 * 68 | reinterpret_cast<underlying&>(value) OP static_cast<underlying>(rhs) ); \
95 * | ^~~~~
96 *
97 * I cannot reproduce on gcc 12.2.1 or with clang 14.0.5 so I'm going to assume
98 * this is a bug with gcc 10.x
99 */
100 #pragma GCC diagnostic push
101 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
102 #endif
103
104 #define UOP(T, OP) \
105 inline E& operator OP(T rhs) { \
106 return reinterpret_cast<E&>( \
107 reinterpret_cast<underlying&>(value) OP static_cast<underlying>(rhs) ); \
108 }
109 UOP(underlying, |=)
110 UOP(underlying, &=)
111 #undef UOP
112
113 #if defined(__GNUC__) && !defined(__clang) && (__GNUC__ < 7)
114 #pragma GCC diagnostic pop
115 #endif
116
117 inline E operator ~() const {
118 static_assert(sizeof(E) == sizeof(BitmaskEnum<E>));
119 return static_cast<E> (
120 ~static_cast<underlying>(value)
121 );
122 }
123 #undef FOREACH_TYPE
124 };
125 #define BITMASK_ENUM(E) BitmaskEnum<E>
126 #else
127 #define BITMASK_ENUM(E) enum E
128 #endif
129
130 #ifdef __cplusplus
131 # define EXTERNC extern "C"
132 # define BEGINC EXTERNC {
133 # define ENDC }
134 #else
135 # define EXTERNC
136 # define BEGINC
137 # define ENDC
138 #endif
139
140 /*
141 * SWAP - swap value of @a and @b
142 */
143 #define SWAP(a, b) \
144 do { \
145 __typeof(a) __tmp = (a); \
146 (a) = (b); \
147 (b) = __tmp; \
148 } while (0)
149
150 /* for conditionally setting boolean flag(s): */
151 #define COND(bool, val) ((bool) ? (val) : 0)
152
153 #define BIT(bit) BITFIELD64_BIT(bit)
154
155 /**
156 * Helper for allocating sequence #s where zero is a non-valid seqno
157 */
158 typedef struct {
159 uint32_t counter;
160 } seqno_t;
161
162 static inline uint32_t
seqno_next(seqno_t * seq)163 seqno_next(seqno_t *seq)
164 {
165 uint32_t n;
166 do {
167 n = p_atomic_inc_return(&seq->counter);
168 } while (n == 0);
169 return n;
170 }
171
172 static inline uint16_t
seqno_next_u16(seqno_t * seq)173 seqno_next_u16(seqno_t *seq)
174 {
175 uint16_t n;
176 do {
177 n = p_atomic_inc_return(&seq->counter);
178 } while (n == 0);
179 return n;
180 }
181
182 #endif /* FREEDRENO_COMMON_H_ */
183