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