blob: 566876883431f4a600bd8ee103b265fd3e0e96f2 [file] [log] [blame]
/*
* Copyright © 2022 Google, Inc.
* SPDX-License-Identifier: MIT
*/
#ifndef FREEDRENO_COMMON_H_
#define FREEDRENO_COMMON_H_
#include "util/u_atomic.h"
#ifdef __cplusplus
#include <tuple>
#define __FD_GPU_GENS A6XX, A7XX
#define FD_GENX(FUNC_NAME) \
template <chip... CHIPs> constexpr auto FUNC_NAME##instantiate() \
{ \
return std::tuple_cat(std::make_tuple(FUNC_NAME<CHIPs>)...); \
} \
static constexpr auto FUNC_NAME##tmpl __attribute__((used)) = \
FUNC_NAME##instantiate<__FD_GPU_GENS>();
#define FD_CALLX(info, thing) \
({ \
decltype(&thing<A6XX>) genX_thing; \
switch (info->chip) { \
case 6: \
genX_thing = &thing<A6XX>; \
break; \
case 7: \
genX_thing = &thing<A7XX>; \
break; \
default: \
unreachable("Unknown hardware generation"); \
} \
genX_thing; \
})
template<typename E>
struct BitmaskEnum {
E value;
using underlying = typename std::underlying_type_t<E>;
#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<E>(value)) {}
FOREACH_TYPE(CONSTRUCTOR)
#undef CONSTRUCTOR
#define CAST(T) inline operator T() const { return static_cast<T>(value); }
FOREACH_TYPE(CAST)
#undef CAST
#define BOP(T, OP) \
inline E operator OP(T rhs) const { \
return static_cast<E> ( \
static_cast<underlying>(value) OP \
static_cast<underlying>(rhs) \
); \
}
FOREACH_TYPE(BOP, |)
FOREACH_TYPE(BOP, &)
#undef BOP
#define BOP(OP) \
inline BitmaskEnum<E> operator OP(BitmaskEnum<E> rhs) const { \
return static_cast<E> ( \
static_cast<underlying>(value) OP \
static_cast<underlying>(rhs.value) \
); \
}
BOP(|)
BOP(&)
#undef BOP
#if defined(__GNUC__) && !defined(__clang)
/*
* Silence:
*
* ../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]':
* ../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<underlying&>(value) OP static_cast<underlying>(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<E&>( \
reinterpret_cast<underlying&>(value) OP static_cast<underlying>(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<E>));
return static_cast<E> (
~static_cast<underlying>(value)
);
}
#undef FOREACH_TYPE
};
#define BITMASK_ENUM(E) BitmaskEnum<E>
#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_ */