xref: /aosp_15_r20/external/mesa3d/src/freedreno/common/freedreno_common.h (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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