1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21bf215546Sopenharmony_ci * SOFTWARE.
22bf215546Sopenharmony_ci *
23bf215546Sopenharmony_ci * Authors:
24bf215546Sopenharmony_ci *    Rob Clark <robclark@freedesktop.org>
25bf215546Sopenharmony_ci */
26bf215546Sopenharmony_ci
27bf215546Sopenharmony_ci#ifndef FREEDRENO_UTIL_H_
28bf215546Sopenharmony_ci#define FREEDRENO_UTIL_H_
29bf215546Sopenharmony_ci
30bf215546Sopenharmony_ci#include "common/freedreno_common.h"
31bf215546Sopenharmony_ci
32bf215546Sopenharmony_ci#include "drm/freedreno_drmif.h"
33bf215546Sopenharmony_ci#include "drm/freedreno_ringbuffer.h"
34bf215546Sopenharmony_ci
35bf215546Sopenharmony_ci#include "pipe/p_format.h"
36bf215546Sopenharmony_ci#include "pipe/p_state.h"
37bf215546Sopenharmony_ci#include "util/compiler.h"
38bf215546Sopenharmony_ci#include "util/half_float.h"
39bf215546Sopenharmony_ci#include "util/log.h"
40bf215546Sopenharmony_ci#include "util/u_debug.h"
41bf215546Sopenharmony_ci#include "util/u_dynarray.h"
42bf215546Sopenharmony_ci#include "util/u_math.h"
43bf215546Sopenharmony_ci#include "util/u_pack_color.h"
44bf215546Sopenharmony_ci
45bf215546Sopenharmony_ci#include "adreno_common.xml.h"
46bf215546Sopenharmony_ci#include "adreno_pm4.xml.h"
47bf215546Sopenharmony_ci#include "disasm.h"
48bf215546Sopenharmony_ci
49bf215546Sopenharmony_ci#ifdef __cplusplus
50bf215546Sopenharmony_ciextern "C" {
51bf215546Sopenharmony_ci#endif
52bf215546Sopenharmony_ci
53bf215546Sopenharmony_cienum adreno_rb_depth_format fd_pipe2depth(enum pipe_format format);
54bf215546Sopenharmony_cienum pc_di_index_size fd_pipe2index(enum pipe_format format);
55bf215546Sopenharmony_cienum pipe_format fd_gmem_restore_format(enum pipe_format format);
56bf215546Sopenharmony_cienum adreno_rb_blend_factor fd_blend_factor(unsigned factor);
57bf215546Sopenharmony_cienum adreno_pa_su_sc_draw fd_polygon_mode(unsigned mode);
58bf215546Sopenharmony_cienum adreno_stencil_op fd_stencil_op(unsigned op);
59bf215546Sopenharmony_ci
60bf215546Sopenharmony_ci#define A3XX_MAX_MIP_LEVELS 14
61bf215546Sopenharmony_ci
62bf215546Sopenharmony_ci#define A2XX_MAX_RENDER_TARGETS 1
63bf215546Sopenharmony_ci#define A3XX_MAX_RENDER_TARGETS 4
64bf215546Sopenharmony_ci#define A4XX_MAX_RENDER_TARGETS 8
65bf215546Sopenharmony_ci#define A5XX_MAX_RENDER_TARGETS 8
66bf215546Sopenharmony_ci#define A6XX_MAX_RENDER_TARGETS 8
67bf215546Sopenharmony_ci
68bf215546Sopenharmony_ci#define MAX_RENDER_TARGETS A6XX_MAX_RENDER_TARGETS
69bf215546Sopenharmony_ci
70bf215546Sopenharmony_ci/* clang-format off */
71bf215546Sopenharmony_cienum fd_debug_flag {
72bf215546Sopenharmony_ci   FD_DBG_MSGS         = BITFIELD_BIT(0),
73bf215546Sopenharmony_ci   FD_DBG_DISASM       = BITFIELD_BIT(1),
74bf215546Sopenharmony_ci   FD_DBG_DCLEAR       = BITFIELD_BIT(2),
75bf215546Sopenharmony_ci   FD_DBG_DDRAW        = BITFIELD_BIT(3),
76bf215546Sopenharmony_ci   FD_DBG_NOSCIS       = BITFIELD_BIT(4),
77bf215546Sopenharmony_ci   FD_DBG_DIRECT       = BITFIELD_BIT(5),
78bf215546Sopenharmony_ci   FD_DBG_GMEM         = BITFIELD_BIT(6),
79bf215546Sopenharmony_ci   FD_DBG_PERF         = BITFIELD_BIT(7),
80bf215546Sopenharmony_ci   FD_DBG_NOBIN        = BITFIELD_BIT(8),
81bf215546Sopenharmony_ci   FD_DBG_SYSMEM       = BITFIELD_BIT(9),
82bf215546Sopenharmony_ci   FD_DBG_SERIALC      = BITFIELD_BIT(10),
83bf215546Sopenharmony_ci   FD_DBG_SHADERDB     = BITFIELD_BIT(11),
84bf215546Sopenharmony_ci   FD_DBG_FLUSH        = BITFIELD_BIT(12),
85bf215546Sopenharmony_ci   FD_DBG_DEQP         = BITFIELD_BIT(13),
86bf215546Sopenharmony_ci   FD_DBG_INORDER      = BITFIELD_BIT(14),
87bf215546Sopenharmony_ci   FD_DBG_BSTAT        = BITFIELD_BIT(15),
88bf215546Sopenharmony_ci   FD_DBG_NOGROW       = BITFIELD_BIT(16),
89bf215546Sopenharmony_ci   FD_DBG_LRZ          = BITFIELD_BIT(17),
90bf215546Sopenharmony_ci   FD_DBG_NOINDR       = BITFIELD_BIT(18),
91bf215546Sopenharmony_ci   FD_DBG_NOBLIT       = BITFIELD_BIT(19),
92bf215546Sopenharmony_ci   FD_DBG_HIPRIO       = BITFIELD_BIT(20),
93bf215546Sopenharmony_ci   FD_DBG_TTILE        = BITFIELD_BIT(21),
94bf215546Sopenharmony_ci   FD_DBG_PERFC        = BITFIELD_BIT(22),
95bf215546Sopenharmony_ci   FD_DBG_NOUBWC       = BITFIELD_BIT(23),
96bf215546Sopenharmony_ci   FD_DBG_NOLRZ        = BITFIELD_BIT(24),
97bf215546Sopenharmony_ci   FD_DBG_NOTILE       = BITFIELD_BIT(25),
98bf215546Sopenharmony_ci   FD_DBG_LAYOUT       = BITFIELD_BIT(26),
99bf215546Sopenharmony_ci   FD_DBG_NOFP16       = BITFIELD_BIT(27),
100bf215546Sopenharmony_ci   FD_DBG_NOHW         = BITFIELD_BIT(28),
101bf215546Sopenharmony_ci   FD_DBG_NOSBIN       = BITFIELD_BIT(29),
102bf215546Sopenharmony_ci};
103bf215546Sopenharmony_ci/* clang-format on */
104bf215546Sopenharmony_ci
105bf215546Sopenharmony_ciextern int fd_mesa_debug;
106bf215546Sopenharmony_ciextern bool fd_binning_enabled;
107bf215546Sopenharmony_ci
108bf215546Sopenharmony_ci#define FD_DBG(category) unlikely(fd_mesa_debug &FD_DBG_##category)
109bf215546Sopenharmony_ci
110bf215546Sopenharmony_ci#include <unistd.h>
111bf215546Sopenharmony_ci#include <sys/types.h>
112bf215546Sopenharmony_ci#include <sys/syscall.h>
113bf215546Sopenharmony_ci
114bf215546Sopenharmony_ci#define DBG(fmt, ...)                                                          \
115bf215546Sopenharmony_ci   do {                                                                        \
116bf215546Sopenharmony_ci      if (FD_DBG(MSGS))                                                        \
117bf215546Sopenharmony_ci         mesa_logi("%5d: %s:%d: " fmt, ((pid_t)syscall(SYS_gettid)),           \
118bf215546Sopenharmony_ci                                        __FUNCTION__, __LINE__,                \
119bf215546Sopenharmony_ci                                        ##__VA_ARGS__);                        \
120bf215546Sopenharmony_ci   } while (0)
121bf215546Sopenharmony_ci
122bf215546Sopenharmony_ci#define perf_debug_message(debug, type, ...)                                   \
123bf215546Sopenharmony_ci   do {                                                                        \
124bf215546Sopenharmony_ci      if (FD_DBG(PERF))                                                        \
125bf215546Sopenharmony_ci         mesa_logw(__VA_ARGS__);                                               \
126bf215546Sopenharmony_ci      struct util_debug_callback *__d = (debug);                               \
127bf215546Sopenharmony_ci      if (__d)                                                                 \
128bf215546Sopenharmony_ci         util_debug_message(__d, type, __VA_ARGS__);                           \
129bf215546Sopenharmony_ci   } while (0)
130bf215546Sopenharmony_ci
131bf215546Sopenharmony_ci#define perf_debug_ctx(ctx, ...)                                               \
132bf215546Sopenharmony_ci   do {                                                                        \
133bf215546Sopenharmony_ci      struct fd_context *__c = (ctx);                                          \
134bf215546Sopenharmony_ci      perf_debug_message(__c ? &__c->debug : NULL, PERF_INFO, __VA_ARGS__);    \
135bf215546Sopenharmony_ci   } while (0)
136bf215546Sopenharmony_ci
137bf215546Sopenharmony_ci#define perf_debug(...) perf_debug_ctx(NULL, __VA_ARGS__)
138bf215546Sopenharmony_ci
139bf215546Sopenharmony_ci#define perf_time_ctx(ctx, limit_ns, fmt, ...)                                 \
140bf215546Sopenharmony_ci   for (struct __perf_time_state __s =                                         \
141bf215546Sopenharmony_ci           {                                                                   \
142bf215546Sopenharmony_ci              .t = -__perf_get_time(ctx),                                      \
143bf215546Sopenharmony_ci           };                                                                  \
144bf215546Sopenharmony_ci        !__s.done; ({                                                          \
145bf215546Sopenharmony_ci           __s.t += __perf_get_time(ctx);                                      \
146bf215546Sopenharmony_ci           __s.done = true;                                                    \
147bf215546Sopenharmony_ci           if (__s.t > (limit_ns)) {                                           \
148bf215546Sopenharmony_ci              perf_debug_ctx(ctx, fmt " (%.03f ms)", ##__VA_ARGS__,            \
149bf215546Sopenharmony_ci                             (double)__s.t / 1000000.0);                       \
150bf215546Sopenharmony_ci           }                                                                   \
151bf215546Sopenharmony_ci        }))
152bf215546Sopenharmony_ci
153bf215546Sopenharmony_ci#define perf_time(limit_ns, fmt, ...)                                          \
154bf215546Sopenharmony_ci   perf_time_ctx(NULL, limit_ns, fmt, ##__VA_ARGS__)
155bf215546Sopenharmony_ci
156bf215546Sopenharmony_cistruct __perf_time_state {
157bf215546Sopenharmony_ci   int64_t t;
158bf215546Sopenharmony_ci   bool done;
159bf215546Sopenharmony_ci};
160bf215546Sopenharmony_ci
161bf215546Sopenharmony_ci/* static inline would be nice here, except 'struct fd_context' is not
162bf215546Sopenharmony_ci * defined yet:
163bf215546Sopenharmony_ci */
164bf215546Sopenharmony_ci#define __perf_get_time(ctx)                                                   \
165bf215546Sopenharmony_ci   ((FD_DBG(PERF) || ({                                                        \
166bf215546Sopenharmony_ci        struct fd_context *__c = (ctx);                                        \
167bf215546Sopenharmony_ci        unlikely(__c && __c->debug.debug_message);                             \
168bf215546Sopenharmony_ci     }))                                                                       \
169bf215546Sopenharmony_ci       ? os_time_get_nano()                                                    \
170bf215546Sopenharmony_ci       : 0)
171bf215546Sopenharmony_ci
172bf215546Sopenharmony_cistruct fd_context;
173bf215546Sopenharmony_ci
174bf215546Sopenharmony_ci/**
175bf215546Sopenharmony_ci * A psuedo-variable for defining where various parts of the fd_context
176bf215546Sopenharmony_ci * can be safely accessed.
177bf215546Sopenharmony_ci *
178bf215546Sopenharmony_ci * With threaded_context, certain pctx funcs are called from gallium
179bf215546Sopenharmony_ci * front-end/state-tracker (eg. CSO creation), while others are called
180bf215546Sopenharmony_ci * from the driver thread.  Things called from driver thread can safely
181bf215546Sopenharmony_ci * access anything in the ctx, while things called from the fe/st thread
182bf215546Sopenharmony_ci * must limit themselves to "safe" things (ie. ctx->screen is safe as it
183bf215546Sopenharmony_ci * is immutable, but the blitter_context is not).
184bf215546Sopenharmony_ci */
185bf215546Sopenharmony_ciextern lock_cap_t fd_context_access_cap;
186bf215546Sopenharmony_ci
187bf215546Sopenharmony_ci/**
188bf215546Sopenharmony_ci * Make the annotation a bit less verbose.. mark fields which should only
189bf215546Sopenharmony_ci * be accessed by driver-thread with 'dt'
190bf215546Sopenharmony_ci */
191bf215546Sopenharmony_ci#define dt guarded_by(fd_context_access_cap)
192bf215546Sopenharmony_ci
193bf215546Sopenharmony_ci/**
194bf215546Sopenharmony_ci * Annotation for entry-point functions only called in driver thread.
195bf215546Sopenharmony_ci *
196bf215546Sopenharmony_ci * For static functions, apply the annotation to the function declaration.
197bf215546Sopenharmony_ci * Otherwise apply to the function prototype.
198bf215546Sopenharmony_ci */
199bf215546Sopenharmony_ci#define in_dt assert_cap(fd_context_access_cap)
200bf215546Sopenharmony_ci
201bf215546Sopenharmony_ci/**
202bf215546Sopenharmony_ci * Annotation for internal functions which are only called from entry-
203bf215546Sopenharmony_ci * point functions (with 'in_dt' annotation) or other internal functions
204bf215546Sopenharmony_ci * with the 'assert_dt' annotation.
205bf215546Sopenharmony_ci *
206bf215546Sopenharmony_ci * For static functions, apply the annotation to the function declaration.
207bf215546Sopenharmony_ci * Otherwise apply to the function prototype.
208bf215546Sopenharmony_ci */
209bf215546Sopenharmony_ci#define assert_dt requires_cap(fd_context_access_cap)
210bf215546Sopenharmony_ci
211bf215546Sopenharmony_ci/**
212bf215546Sopenharmony_ci * Special helpers for context access outside of driver thread.  For ex,
213bf215546Sopenharmony_ci * pctx->get_query_result() is not called on driver thread, but the
214bf215546Sopenharmony_ci * query is guaranteed to be flushed, or the driver thread queue is
215bf215546Sopenharmony_ci * guaranteed to be flushed.
216bf215546Sopenharmony_ci *
217bf215546Sopenharmony_ci * Use with caution!
218bf215546Sopenharmony_ci */
219bf215546Sopenharmony_cistatic inline void
220bf215546Sopenharmony_cifd_context_access_begin(struct fd_context *ctx)
221bf215546Sopenharmony_ci   acquire_cap(fd_context_access_cap)
222bf215546Sopenharmony_ci{
223bf215546Sopenharmony_ci}
224bf215546Sopenharmony_ci
225bf215546Sopenharmony_cistatic inline void
226bf215546Sopenharmony_cifd_context_access_end(struct fd_context *ctx) release_cap(fd_context_access_cap)
227bf215546Sopenharmony_ci{
228bf215546Sopenharmony_ci}
229bf215546Sopenharmony_ci
230bf215546Sopenharmony_ci#define CP_REG(reg) ((0x4 << 16) | ((unsigned int)((reg) - (0x2000))))
231bf215546Sopenharmony_ci
232bf215546Sopenharmony_cistatic inline uint32_t
233bf215546Sopenharmony_ciDRAW(enum pc_di_primtype prim_type, enum pc_di_src_sel source_select,
234bf215546Sopenharmony_ci     enum pc_di_index_size index_size, enum pc_di_vis_cull_mode vis_cull_mode,
235bf215546Sopenharmony_ci     uint8_t instances)
236bf215546Sopenharmony_ci{
237bf215546Sopenharmony_ci   return (prim_type << 0) | (source_select << 6) | ((index_size & 1) << 11) |
238bf215546Sopenharmony_ci          ((index_size >> 1) << 13) | (vis_cull_mode << 9) | (1 << 14) |
239bf215546Sopenharmony_ci          (instances << 24);
240bf215546Sopenharmony_ci}
241bf215546Sopenharmony_ci
242bf215546Sopenharmony_cistatic inline uint32_t
243bf215546Sopenharmony_ciDRAW_A20X(enum pc_di_primtype prim_type,
244bf215546Sopenharmony_ci          enum pc_di_face_cull_sel faceness_cull_select,
245bf215546Sopenharmony_ci          enum pc_di_src_sel source_select, enum pc_di_index_size index_size,
246bf215546Sopenharmony_ci          bool pre_fetch_cull_enable, bool grp_cull_enable, uint16_t count)
247bf215546Sopenharmony_ci{
248bf215546Sopenharmony_ci   return (prim_type << 0) | (source_select << 6) |
249bf215546Sopenharmony_ci          (faceness_cull_select << 8) | ((index_size & 1) << 11) |
250bf215546Sopenharmony_ci          ((index_size >> 1) << 13) | (pre_fetch_cull_enable << 14) |
251bf215546Sopenharmony_ci          (grp_cull_enable << 15) | (count << 16);
252bf215546Sopenharmony_ci}
253bf215546Sopenharmony_ci
254bf215546Sopenharmony_ci/* for tracking cmdstream positions that need to be patched: */
255bf215546Sopenharmony_cistruct fd_cs_patch {
256bf215546Sopenharmony_ci   uint32_t *cs;
257bf215546Sopenharmony_ci   uint32_t val;
258bf215546Sopenharmony_ci};
259bf215546Sopenharmony_ci#define fd_patch_num_elements(buf) ((buf)->size / sizeof(struct fd_cs_patch))
260bf215546Sopenharmony_ci#define fd_patch_element(buf, i)                                               \
261bf215546Sopenharmony_ci   util_dynarray_element(buf, struct fd_cs_patch, i)
262bf215546Sopenharmony_ci
263bf215546Sopenharmony_cistatic inline enum pipe_format
264bf215546Sopenharmony_cipipe_surface_format(struct pipe_surface *psurf)
265bf215546Sopenharmony_ci{
266bf215546Sopenharmony_ci   if (!psurf)
267bf215546Sopenharmony_ci      return PIPE_FORMAT_NONE;
268bf215546Sopenharmony_ci   return psurf->format;
269bf215546Sopenharmony_ci}
270bf215546Sopenharmony_ci
271bf215546Sopenharmony_cistatic inline bool
272bf215546Sopenharmony_cifd_surface_half_precision(const struct pipe_surface *psurf)
273bf215546Sopenharmony_ci{
274bf215546Sopenharmony_ci   enum pipe_format format;
275bf215546Sopenharmony_ci
276bf215546Sopenharmony_ci   if (!psurf)
277bf215546Sopenharmony_ci      return true;
278bf215546Sopenharmony_ci
279bf215546Sopenharmony_ci   format = psurf->format;
280bf215546Sopenharmony_ci
281bf215546Sopenharmony_ci   /* colors are provided in consts, which go through cov.f32f16, which will
282bf215546Sopenharmony_ci    * break these values
283bf215546Sopenharmony_ci    */
284bf215546Sopenharmony_ci   if (util_format_is_pure_integer(format))
285bf215546Sopenharmony_ci      return false;
286bf215546Sopenharmony_ci
287bf215546Sopenharmony_ci   /* avoid losing precision on 32-bit float formats */
288bf215546Sopenharmony_ci   if (util_format_is_float(format) &&
289bf215546Sopenharmony_ci       util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 0) ==
290bf215546Sopenharmony_ci          32)
291bf215546Sopenharmony_ci      return false;
292bf215546Sopenharmony_ci
293bf215546Sopenharmony_ci   return true;
294bf215546Sopenharmony_ci}
295bf215546Sopenharmony_ci
296bf215546Sopenharmony_cistatic inline unsigned
297bf215546Sopenharmony_cifd_sampler_first_level(const struct pipe_sampler_view *view)
298bf215546Sopenharmony_ci{
299bf215546Sopenharmony_ci   if (view->target == PIPE_BUFFER)
300bf215546Sopenharmony_ci      return 0;
301bf215546Sopenharmony_ci   return view->u.tex.first_level;
302bf215546Sopenharmony_ci}
303bf215546Sopenharmony_ci
304bf215546Sopenharmony_cistatic inline unsigned
305bf215546Sopenharmony_cifd_sampler_last_level(const struct pipe_sampler_view *view)
306bf215546Sopenharmony_ci{
307bf215546Sopenharmony_ci   if (view->target == PIPE_BUFFER)
308bf215546Sopenharmony_ci      return 0;
309bf215546Sopenharmony_ci   return view->u.tex.last_level;
310bf215546Sopenharmony_ci}
311bf215546Sopenharmony_ci
312bf215546Sopenharmony_cistatic inline bool
313bf215546Sopenharmony_cifd_half_precision(struct pipe_framebuffer_state *pfb)
314bf215546Sopenharmony_ci{
315bf215546Sopenharmony_ci   unsigned i;
316bf215546Sopenharmony_ci
317bf215546Sopenharmony_ci   for (i = 0; i < pfb->nr_cbufs; i++)
318bf215546Sopenharmony_ci      if (!fd_surface_half_precision(pfb->cbufs[i]))
319bf215546Sopenharmony_ci         return false;
320bf215546Sopenharmony_ci
321bf215546Sopenharmony_ci   return true;
322bf215546Sopenharmony_ci}
323bf215546Sopenharmony_ci
324bf215546Sopenharmony_cistatic inline void emit_marker(struct fd_ringbuffer *ring, int scratch_idx);
325bf215546Sopenharmony_ci
326bf215546Sopenharmony_ci/* like OUT_RING() but appends a cmdstream patch point to 'buf' */
327bf215546Sopenharmony_cistatic inline void
328bf215546Sopenharmony_ciOUT_RINGP(struct fd_ringbuffer *ring, uint32_t data, struct util_dynarray *buf)
329bf215546Sopenharmony_ci{
330bf215546Sopenharmony_ci   if (LOG_DWORDS) {
331bf215546Sopenharmony_ci      DBG("ring[%p]: OUT_RINGP  %04x:  %08x", ring,
332bf215546Sopenharmony_ci          (uint32_t)(ring->cur - ring->start), data);
333bf215546Sopenharmony_ci   }
334bf215546Sopenharmony_ci   util_dynarray_append(buf, struct fd_cs_patch,
335bf215546Sopenharmony_ci                        ((struct fd_cs_patch){
336bf215546Sopenharmony_ci                           .cs = ring->cur++,
337bf215546Sopenharmony_ci                           .val = data,
338bf215546Sopenharmony_ci                        }));
339bf215546Sopenharmony_ci}
340bf215546Sopenharmony_ci
341bf215546Sopenharmony_cistatic inline void
342bf215546Sopenharmony_ci__OUT_IB(struct fd_ringbuffer *ring, bool prefetch,
343bf215546Sopenharmony_ci         struct fd_ringbuffer *target)
344bf215546Sopenharmony_ci{
345bf215546Sopenharmony_ci   if (target->cur == target->start)
346bf215546Sopenharmony_ci      return;
347bf215546Sopenharmony_ci
348bf215546Sopenharmony_ci   unsigned count = fd_ringbuffer_cmd_count(target);
349bf215546Sopenharmony_ci
350bf215546Sopenharmony_ci   /* for debug after a lock up, write a unique counter value
351bf215546Sopenharmony_ci    * to scratch6 for each IB, to make it easier to match up
352bf215546Sopenharmony_ci    * register dumps to cmdstream.  The combination of IB and
353bf215546Sopenharmony_ci    * DRAW (scratch7) is enough to "triangulate" the particular
354bf215546Sopenharmony_ci    * draw that caused lockup.
355bf215546Sopenharmony_ci    */
356bf215546Sopenharmony_ci   emit_marker(ring, 6);
357bf215546Sopenharmony_ci
358bf215546Sopenharmony_ci   for (unsigned i = 0; i < count; i++) {
359bf215546Sopenharmony_ci      uint32_t dwords;
360bf215546Sopenharmony_ci      OUT_PKT3(ring, prefetch ? CP_INDIRECT_BUFFER_PFE : CP_INDIRECT_BUFFER_PFD,
361bf215546Sopenharmony_ci               2);
362bf215546Sopenharmony_ci      dwords = fd_ringbuffer_emit_reloc_ring_full(ring, target, i) / 4;
363bf215546Sopenharmony_ci      assert(dwords > 0);
364bf215546Sopenharmony_ci      OUT_RING(ring, dwords);
365bf215546Sopenharmony_ci      OUT_PKT2(ring);
366bf215546Sopenharmony_ci   }
367bf215546Sopenharmony_ci
368bf215546Sopenharmony_ci   emit_marker(ring, 6);
369bf215546Sopenharmony_ci}
370bf215546Sopenharmony_ci
371bf215546Sopenharmony_cistatic inline void
372bf215546Sopenharmony_ci__OUT_IB5(struct fd_ringbuffer *ring, struct fd_ringbuffer *target)
373bf215546Sopenharmony_ci{
374bf215546Sopenharmony_ci   if (target->cur == target->start)
375bf215546Sopenharmony_ci      return;
376bf215546Sopenharmony_ci
377bf215546Sopenharmony_ci   unsigned count = fd_ringbuffer_cmd_count(target);
378bf215546Sopenharmony_ci
379bf215546Sopenharmony_ci   for (unsigned i = 0; i < count; i++) {
380bf215546Sopenharmony_ci      uint32_t dwords;
381bf215546Sopenharmony_ci      OUT_PKT7(ring, CP_INDIRECT_BUFFER, 3);
382bf215546Sopenharmony_ci      dwords = fd_ringbuffer_emit_reloc_ring_full(ring, target, i) / 4;
383bf215546Sopenharmony_ci      assert(dwords > 0);
384bf215546Sopenharmony_ci      OUT_RING(ring, dwords);
385bf215546Sopenharmony_ci   }
386bf215546Sopenharmony_ci}
387bf215546Sopenharmony_ci
388bf215546Sopenharmony_ci/* CP_SCRATCH_REG4 is used to hold base address for query results: */
389bf215546Sopenharmony_ci// XXX annoyingly scratch regs move on a5xx.. and additionally different
390bf215546Sopenharmony_ci// packet types.. so freedreno_query_hw is going to need a bit of
391bf215546Sopenharmony_ci// rework..
392bf215546Sopenharmony_ci#define HW_QUERY_BASE_REG REG_AXXX_CP_SCRATCH_REG4
393bf215546Sopenharmony_ci
394bf215546Sopenharmony_ci#ifdef DEBUG
395bf215546Sopenharmony_ci#define __EMIT_MARKER 1
396bf215546Sopenharmony_ci#else
397bf215546Sopenharmony_ci#define __EMIT_MARKER 0
398bf215546Sopenharmony_ci#endif
399bf215546Sopenharmony_ci
400bf215546Sopenharmony_cistatic inline void
401bf215546Sopenharmony_ciemit_marker(struct fd_ringbuffer *ring, int scratch_idx)
402bf215546Sopenharmony_ci{
403bf215546Sopenharmony_ci   extern int32_t marker_cnt;
404bf215546Sopenharmony_ci   unsigned reg = REG_AXXX_CP_SCRATCH_REG0 + scratch_idx;
405bf215546Sopenharmony_ci   assert(reg != HW_QUERY_BASE_REG);
406bf215546Sopenharmony_ci   if (reg == HW_QUERY_BASE_REG)
407bf215546Sopenharmony_ci      return;
408bf215546Sopenharmony_ci   if (__EMIT_MARKER) {
409bf215546Sopenharmony_ci      OUT_WFI(ring);
410bf215546Sopenharmony_ci      OUT_PKT0(ring, reg, 1);
411bf215546Sopenharmony_ci      OUT_RING(ring, p_atomic_inc_return(&marker_cnt));
412bf215546Sopenharmony_ci   }
413bf215546Sopenharmony_ci}
414bf215546Sopenharmony_ci
415bf215546Sopenharmony_cistatic inline uint32_t
416bf215546Sopenharmony_cipack_rgba(enum pipe_format format, const float *rgba)
417bf215546Sopenharmony_ci{
418bf215546Sopenharmony_ci   union util_color uc;
419bf215546Sopenharmony_ci   util_pack_color(rgba, format, &uc);
420bf215546Sopenharmony_ci   return uc.ui[0];
421bf215546Sopenharmony_ci}
422bf215546Sopenharmony_ci
423bf215546Sopenharmony_ci/*
424bf215546Sopenharmony_ci * a3xx+ helpers:
425bf215546Sopenharmony_ci */
426bf215546Sopenharmony_ci
427bf215546Sopenharmony_cistatic inline enum a3xx_msaa_samples
428bf215546Sopenharmony_cifd_msaa_samples(unsigned samples)
429bf215546Sopenharmony_ci{
430bf215546Sopenharmony_ci   switch (samples) {
431bf215546Sopenharmony_ci   default:
432bf215546Sopenharmony_ci      assert(0);
433bf215546Sopenharmony_ci   case 0:
434bf215546Sopenharmony_ci   case 1:
435bf215546Sopenharmony_ci      return MSAA_ONE;
436bf215546Sopenharmony_ci   case 2:
437bf215546Sopenharmony_ci      return MSAA_TWO;
438bf215546Sopenharmony_ci   case 4:
439bf215546Sopenharmony_ci      return MSAA_FOUR;
440bf215546Sopenharmony_ci   case 8:
441bf215546Sopenharmony_ci      return MSAA_EIGHT;
442bf215546Sopenharmony_ci   }
443bf215546Sopenharmony_ci}
444bf215546Sopenharmony_ci
445bf215546Sopenharmony_ci/*
446bf215546Sopenharmony_ci * a4xx+ helpers:
447bf215546Sopenharmony_ci */
448bf215546Sopenharmony_ci
449bf215546Sopenharmony_cistatic inline enum a4xx_state_block
450bf215546Sopenharmony_cifd4_stage2shadersb(gl_shader_stage type)
451bf215546Sopenharmony_ci{
452bf215546Sopenharmony_ci   switch (type) {
453bf215546Sopenharmony_ci   case MESA_SHADER_VERTEX:
454bf215546Sopenharmony_ci      return SB4_VS_SHADER;
455bf215546Sopenharmony_ci   case MESA_SHADER_FRAGMENT:
456bf215546Sopenharmony_ci      return SB4_FS_SHADER;
457bf215546Sopenharmony_ci   case MESA_SHADER_COMPUTE:
458bf215546Sopenharmony_ci   case MESA_SHADER_KERNEL:
459bf215546Sopenharmony_ci      return SB4_CS_SHADER;
460bf215546Sopenharmony_ci   default:
461bf215546Sopenharmony_ci      unreachable("bad shader type");
462bf215546Sopenharmony_ci      return (enum a4xx_state_block) ~0;
463bf215546Sopenharmony_ci   }
464bf215546Sopenharmony_ci}
465bf215546Sopenharmony_ci
466bf215546Sopenharmony_cistatic inline enum a4xx_index_size
467bf215546Sopenharmony_cifd4_size2indextype(unsigned index_size)
468bf215546Sopenharmony_ci{
469bf215546Sopenharmony_ci   switch (index_size) {
470bf215546Sopenharmony_ci   case 1:
471bf215546Sopenharmony_ci      return INDEX4_SIZE_8_BIT;
472bf215546Sopenharmony_ci   case 2:
473bf215546Sopenharmony_ci      return INDEX4_SIZE_16_BIT;
474bf215546Sopenharmony_ci   case 4:
475bf215546Sopenharmony_ci      return INDEX4_SIZE_32_BIT;
476bf215546Sopenharmony_ci   }
477bf215546Sopenharmony_ci   DBG("unsupported index size: %d", index_size);
478bf215546Sopenharmony_ci   assert(0);
479bf215546Sopenharmony_ci   return INDEX4_SIZE_32_BIT;
480bf215546Sopenharmony_ci}
481bf215546Sopenharmony_ci
482bf215546Sopenharmony_ci#ifdef __cplusplus
483bf215546Sopenharmony_ci}
484bf215546Sopenharmony_ci#endif
485bf215546Sopenharmony_ci
486bf215546Sopenharmony_ci#endif /* FREEDRENO_UTIL_H_ */
487