/* * Copyright © 2022 Google, Inc. * SPDX-License-Identifier: MIT */ #ifndef FREEDRENO_COMMON_H_ #define FREEDRENO_COMMON_H_ #include "util/u_atomic.h" #ifdef __cplusplus #include #define __FD_GPU_GENS A6XX, A7XX #define FD_GENX(FUNC_NAME) \ template constexpr auto FUNC_NAME##instantiate() \ { \ return std::tuple_cat(std::make_tuple(FUNC_NAME)...); \ } \ static constexpr auto FUNC_NAME##tmpl __attribute__((used)) = \ FUNC_NAME##instantiate<__FD_GPU_GENS>(); #define FD_CALLX(info, thing) \ ({ \ decltype(&thing) genX_thing; \ switch (info->chip) { \ case 6: \ genX_thing = &thing; \ break; \ case 7: \ genX_thing = &thing; \ break; \ default: \ unreachable("Unknown hardware generation"); \ } \ genX_thing; \ }) template struct BitmaskEnum { E value; using underlying = typename std::underlying_type_t; #define FOREACH_TYPE(M, ...) \ M(E, ##__VA_ARGS__) \ M(bool, ##__VA_ARGS__) \ M(uint8_t, ##__VA_ARGS__) \ M(int8_t, ##__VA_ARGS__) \ M(uint16_t, ##__VA_ARGS__) \ M(int16_t, ##__VA_ARGS__) \ M(uint32_t, ##__VA_ARGS__) \ M(int32_t, ##__VA_ARGS__) #define CONSTRUCTOR(T) BitmaskEnum(T value) : value(static_cast(value)) {} FOREACH_TYPE(CONSTRUCTOR) #undef CONSTRUCTOR #define CAST(T) inline operator T() const { return static_cast(value); } FOREACH_TYPE(CAST) #undef CAST #define BOP(T, OP) \ inline E operator OP(T rhs) const { \ return static_cast ( \ static_cast(value) OP \ static_cast(rhs) \ ); \ } FOREACH_TYPE(BOP, |) FOREACH_TYPE(BOP, &) #undef BOP #define BOP(OP) \ inline BitmaskEnum operator OP(BitmaskEnum rhs) const { \ return static_cast ( \ static_cast(value) OP \ static_cast(rhs.value) \ ); \ } BOP(|) BOP(&) #undef BOP #if defined(__GNUC__) && !defined(__clang) /* * Silence: * * ../src/freedreno/common/freedreno_common.h: In instantiation of 'E& BitmaskEnum::operator|=(BitmaskEnum::underlying) [with E = fd_dirty_3d_state; BitmaskEnum::underlying = unsigned int]': * ../src/gallium/drivers/freedreno/freedreno_context.h:620:16: required from here * ../src/freedreno/common/freedreno_common.h:68:39: error: dereferencing type-punned pointer will break strict-aliasing rules [-Werror=strict-aliasing] * 68 | reinterpret_cast(value) OP static_cast(rhs) ); \ * | ^~~~~ * * I cannot reproduce on gcc 12.2.1 or with clang 14.0.5 so I'm going to assume * this is a bug with gcc 10.x */ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wstrict-aliasing" #endif #define UOP(T, OP) \ inline E& operator OP(T rhs) { \ return reinterpret_cast( \ reinterpret_cast(value) OP static_cast(rhs) ); \ } UOP(underlying, |=) UOP(underlying, &=) #undef UOP #if defined(__GNUC__) && !defined(__clang) && (__GNUC__ < 7) #pragma GCC diagnostic pop #endif inline E operator ~() const { static_assert(sizeof(E) == sizeof(BitmaskEnum)); return static_cast ( ~static_cast(value) ); } #undef FOREACH_TYPE }; #define BITMASK_ENUM(E) BitmaskEnum #else #define BITMASK_ENUM(E) enum E #endif #ifdef __cplusplus # define EXTERNC extern "C" # define BEGINC EXTERNC { # define ENDC } #else # define EXTERNC # define BEGINC # define ENDC #endif /* * SWAP - swap value of @a and @b */ #define SWAP(a, b) \ do { \ __typeof(a) __tmp = (a); \ (a) = (b); \ (b) = __tmp; \ } while (0) /* for conditionally setting boolean flag(s): */ #define COND(bool, val) ((bool) ? (val) : 0) #define BIT(bit) BITFIELD64_BIT(bit) /** * Helper for allocating sequence #s where zero is a non-valid seqno */ typedef struct { uint32_t counter; } seqno_t; static inline uint32_t seqno_next(seqno_t *seq) { uint32_t n; do { n = p_atomic_inc_return(&seq->counter); } while (n == 0); return n; } static inline uint16_t seqno_next_u16(seqno_t *seq) { uint16_t n; do { n = p_atomic_inc_return(&seq->counter); } while (n == 0); return n; } #endif /* FREEDRENO_COMMON_H_ */