X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Ffreedreno%2Ffreedreno_util.h;h=b3076b9f5c64a9b74540df6d571eb6e56ebfd54a;hb=f370e95421f553ace931a02743c96be80fd62dc8;hp=fb1e392bc1e3459db8999aecabdf64ee18a1bf73;hpb=6173cc19c45d92ef0b7bc6aa008aa89bb29abbda;p=mesa.git diff --git a/src/gallium/drivers/freedreno/freedreno_util.h b/src/gallium/drivers/freedreno/freedreno_util.h index fb1e392bc1e..b3076b9f5c6 100644 --- a/src/gallium/drivers/freedreno/freedreno_util.h +++ b/src/gallium/drivers/freedreno/freedreno_util.h @@ -33,38 +33,86 @@ #include #include "pipe/p_format.h" +#include "pipe/p_state.h" #include "util/u_debug.h" +#include "util/u_math.h" +#include "util/u_half.h" +#include "util/u_dynarray.h" +#include "util/u_pack_color.h" -#include "freedreno_pm4.h" -#include "freedreno_a2xx_reg.h" +#include "adreno_common.xml.h" +#include "adreno_pm4.xml.h" -enum sq_surfaceformat fd_pipe2surface(enum pipe_format format); -enum rb_colorformatx fd_pipe2color(enum pipe_format format); -enum rb_depth_format fd_pipe2depth(enum pipe_format format); +enum adreno_rb_depth_format fd_pipe2depth(enum pipe_format format); enum pc_di_index_size fd_pipe2index(enum pipe_format format); -uint32_t fd_tex_swiz(enum pipe_format format, unsigned swizzle_r, - unsigned swizzle_g, unsigned swizzle_b, unsigned swizzle_a); +enum adreno_rb_blend_factor fd_blend_factor(unsigned factor); +enum adreno_pa_su_sc_draw fd_polygon_mode(unsigned mode); +enum adreno_stencil_op fd_stencil_op(unsigned op); +#define A3XX_MAX_MIP_LEVELS 14 +/* TBD if it is same on a2xx, but for now: */ +#define MAX_MIP_LEVELS A3XX_MAX_MIP_LEVELS + +#define FD_DBG_MSGS 0x0001 +#define FD_DBG_DISASM 0x0002 +#define FD_DBG_DCLEAR 0x0004 +#define FD_DBG_FLUSH 0x0008 +#define FD_DBG_NOSCIS 0x0010 +#define FD_DBG_DIRECT 0x0020 +#define FD_DBG_NOBYPASS 0x0040 +#define FD_DBG_FRAGHALF 0x0080 +#define FD_DBG_NOBIN 0x0100 +#define FD_DBG_OPTMSGS 0x0400 +#define FD_DBG_OPTDUMP 0x0800 +#define FD_DBG_GLSL120 0x1000 +#define FD_DBG_NOCP 0x2000 -#define FD_DBG_MSGS 0x1 -#define FD_DBG_DISASM 0x2 extern int fd_mesa_debug; +extern bool fd_binning_enabled; #define DBG(fmt, ...) \ do { if (fd_mesa_debug & FD_DBG_MSGS) \ debug_printf("%s:%d: "fmt "\n", \ __FUNCTION__, __LINE__, ##__VA_ARGS__); } while (0) -#define ALIGN(v,a) (((v) + (a) - 1) & ~((a) - 1)) -#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) +/* for conditionally setting boolean flag(s): */ +#define COND(bool, val) ((bool) ? (val) : 0) +#define CP_REG(reg) ((0x4 << 16) | ((unsigned int)((reg) - (0x2000)))) -#define min(a, b) (((a) < (b)) ? (a) : (b)) -#define max(a, b) (((a) > (b)) ? (a) : (b)) +static inline uint32_t DRAW(enum pc_di_primtype prim_type, + enum pc_di_src_sel source_select, enum pc_di_index_size index_size, + enum pc_di_vis_cull_mode vis_cull_mode, + uint8_t instances) +{ + return (prim_type << 0) | + (source_select << 6) | + ((index_size & 1) << 11) | + ((index_size >> 1) << 13) | + (vis_cull_mode << 9) | + (1 << 14) | + (instances << 24); +} +/* for tracking cmdstream positions that need to be patched: */ +struct fd_cs_patch { + uint32_t *cs; + uint32_t val; +}; +#define fd_patch_num_elements(buf) ((buf)->size / sizeof(struct fd_cs_patch)) +#define fd_patch_element(buf, i) util_dynarray_element(buf, struct fd_cs_patch, i) + +static inline enum pipe_format +pipe_surface_format(struct pipe_surface *psurf) +{ + if (!psurf) + return PIPE_FORMAT_NONE; + return psurf->format; +} #define LOG_DWORDS 0 +static inline void emit_marker(struct fd_ringbuffer *ring, int scratch_idx); static inline void OUT_RING(struct fd_ringbuffer *ring, uint32_t data) @@ -76,15 +124,53 @@ OUT_RING(struct fd_ringbuffer *ring, uint32_t data) *(ring->cur++) = data; } +/* like OUT_RING() but appends a cmdstream patch point to 'buf' */ +static inline void +OUT_RINGP(struct fd_ringbuffer *ring, uint32_t data, + struct util_dynarray *buf) +{ + if (LOG_DWORDS) { + DBG("ring[%p]: OUT_RINGP %04x: %08x", ring, + (uint32_t)(ring->cur - ring->last_start), data); + } + util_dynarray_append(buf, struct fd_cs_patch, ((struct fd_cs_patch){ + .cs = ring->cur++, + .val = data, + })); +} + static inline void OUT_RELOC(struct fd_ringbuffer *ring, struct fd_bo *bo, - uint32_t offset, uint32_t or) + uint32_t offset, uint32_t or, int32_t shift) +{ + if (LOG_DWORDS) { + DBG("ring[%p]: OUT_RELOC %04x: %p+%u << %d", ring, + (uint32_t)(ring->cur - ring->last_start), bo, offset, shift); + } + fd_ringbuffer_reloc(ring, &(struct fd_reloc){ + .bo = bo, + .flags = FD_RELOC_READ, + .offset = offset, + .or = or, + .shift = shift, + }); +} + +static inline void +OUT_RELOCW(struct fd_ringbuffer *ring, struct fd_bo *bo, + uint32_t offset, uint32_t or, int32_t shift) { if (LOG_DWORDS) { - DBG("ring[%p]: OUT_RELOC %04x: %p+%u", ring, - (uint32_t)(ring->cur - ring->last_start), bo, offset); + DBG("ring[%p]: OUT_RELOCW %04x: %p+%u << %d", ring, + (uint32_t)(ring->cur - ring->last_start), bo, offset, shift); } - fd_ringbuffer_emit_reloc(ring, bo, offset, or); + fd_ringbuffer_reloc(ring, &(struct fd_reloc){ + .bo = bo, + .flags = FD_RELOC_READ | FD_RELOC_WRITE, + .offset = offset, + .or = or, + .shift = shift, + }); } static inline void BEGIN_RING(struct fd_ringbuffer *ring, uint32_t ndwords) @@ -112,13 +198,69 @@ OUT_PKT3(struct fd_ringbuffer *ring, uint8_t opcode, uint16_t cnt) OUT_RING(ring, CP_TYPE3_PKT | ((cnt-1) << 16) | ((opcode & 0xFF) << 8)); } +static inline void +OUT_WFI(struct fd_ringbuffer *ring) +{ + OUT_PKT3(ring, CP_WAIT_FOR_IDLE, 1); + OUT_RING(ring, 0x00000000); +} + static inline void OUT_IB(struct fd_ringbuffer *ring, struct fd_ringmarker *start, struct fd_ringmarker *end) { + uint32_t dwords = fd_ringmarker_dwords(start, end); + + assert(dwords > 0); + + /* for debug after a lock up, write a unique counter value + * to scratch6 for each IB, to make it easier to match up + * register dumps to cmdstream. The combination of IB and + * DRAW (scratch7) is enough to "triangulate" the particular + * draw that caused lockup. + */ + emit_marker(ring, 6); + OUT_PKT3(ring, CP_INDIRECT_BUFFER_PFD, 2); - fd_ringbuffer_emit_reloc_ring(ring, start); - OUT_RING(ring, fd_ringmarker_dwords(start, end)); + fd_ringbuffer_emit_reloc_ring(ring, start, end); + OUT_RING(ring, dwords); + + emit_marker(ring, 6); +} + +/* CP_SCRATCH_REG4 is used to hold base address for query results: */ +#define HW_QUERY_BASE_REG REG_AXXX_CP_SCRATCH_REG4 + +static inline void +emit_marker(struct fd_ringbuffer *ring, int scratch_idx) +{ + extern unsigned marker_cnt; + unsigned reg = REG_AXXX_CP_SCRATCH_REG0 + scratch_idx; + assert(reg != HW_QUERY_BASE_REG); + if (reg == HW_QUERY_BASE_REG) + return; + OUT_PKT0(ring, reg, 1); + OUT_RING(ring, ++marker_cnt); +} + +/* helper to get numeric value from environment variable.. mostly + * just leaving this here because it is helpful to brute-force figure + * out unknown formats, etc, which blob driver does not support: + */ +static inline uint32_t env2u(const char *envvar) +{ + char *str = getenv(envvar); + if (str) + return strtoul(str, NULL, 0); + return 0; +} + +static inline uint32_t +pack_rgba(enum pipe_format format, const float *rgba) +{ + union util_color uc; + util_pack_color(rgba, format, &uc); + return uc.ui[0]; } #endif /* FREEDRENO_UTIL_H_ */