freedreno/a6xx: scissor fixes
[mesa.git] / src / gallium / drivers / freedreno / a6xx / fd6_gmem.c
1 /*
2 * Copyright (C) 2016 Rob Clark <robclark@freedesktop.org>
3 * Copyright © 2018 Google, Inc.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 *
24 * Authors:
25 * Rob Clark <robclark@freedesktop.org>
26 */
27
28 #include <stdio.h>
29
30 #include "pipe/p_state.h"
31 #include "util/u_string.h"
32 #include "util/u_memory.h"
33 #include "util/u_inlines.h"
34 #include "util/u_format.h"
35
36 #include "freedreno_draw.h"
37 #include "freedreno_state.h"
38 #include "freedreno_resource.h"
39
40 #include "fd6_gmem.h"
41 #include "fd6_context.h"
42 #include "fd6_draw.h"
43 #include "fd6_emit.h"
44 #include "fd6_program.h"
45 #include "fd6_format.h"
46 #include "fd6_zsa.h"
47
48 static void
49 emit_mrt(struct fd_ringbuffer *ring, unsigned nr_bufs,
50 struct pipe_surface **bufs, struct fd_gmem_stateobj *gmem)
51 {
52 enum a6xx_tile_mode tile_mode;
53 unsigned srgb_cntl = 0;
54 unsigned i;
55
56 for (i = 0; i < nr_bufs; i++) {
57 enum a6xx_color_fmt format = 0;
58 enum a3xx_color_swap swap = WZYX;
59 bool sint = false, uint = false;
60 struct fd_resource *rsc = NULL;
61 struct fd_resource_slice *slice = NULL;
62 uint32_t stride = 0;
63 uint32_t offset = 0;
64
65 if (gmem) {
66 tile_mode = TILE6_2;
67 } else {
68 tile_mode = TILE6_LINEAR;
69 }
70
71 if (!bufs[i])
72 continue;
73
74 struct pipe_surface *psurf = bufs[i];
75 enum pipe_format pformat = psurf->format;
76 rsc = fd_resource(psurf->texture);
77 if (!rsc->bo)
78 continue;
79
80 uint32_t base = gmem ? gmem->cbuf_base[i] : 0;
81 slice = fd_resource_slice(rsc, psurf->u.tex.level);
82 format = fd6_pipe2color(pformat);
83 swap = fd6_pipe2swap(pformat);
84 sint = util_format_is_pure_sint(pformat);
85 uint = util_format_is_pure_uint(pformat);
86
87 if (util_format_is_srgb(pformat))
88 srgb_cntl |= (1 << i);
89
90 offset = fd_resource_offset(rsc, psurf->u.tex.level,
91 psurf->u.tex.first_layer);
92
93 stride = slice->pitch * rsc->cpp;
94
95 debug_assert(psurf->u.tex.first_layer == psurf->u.tex.last_layer);
96 debug_assert((offset + slice->size0) <= fd_bo_size(rsc->bo));
97
98 OUT_PKT4(ring, REG_A6XX_RB_MRT_BUF_INFO(i), 6);
99 OUT_RING(ring, A6XX_RB_MRT_BUF_INFO_COLOR_FORMAT(format) |
100 A6XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE(rsc->tile_mode) |
101 A6XX_RB_MRT_BUF_INFO_COLOR_SWAP(swap));
102 OUT_RING(ring, A6XX_RB_MRT_PITCH(stride));
103 OUT_RING(ring, A6XX_RB_MRT_ARRAY_PITCH(slice->size0));
104 OUT_RELOCW(ring, rsc->bo, offset, 0, 0); /* BASE_LO/HI */
105 OUT_RING(ring, base); /* RB_MRT[i].BASE_GMEM */
106 OUT_PKT4(ring, REG_A6XX_SP_FS_MRT_REG(i), 1);
107 OUT_RING(ring, A6XX_SP_FS_MRT_REG_COLOR_FORMAT(format) |
108 COND(sint, A6XX_SP_FS_MRT_REG_COLOR_SINT) |
109 COND(uint, A6XX_SP_FS_MRT_REG_COLOR_UINT));
110
111 #if 0
112 /* when we support UBWC, these would be the system memory
113 * addr/pitch/etc:
114 */
115 OUT_PKT4(ring, REG_A6XX_RB_MRT_FLAG_BUFFER(i), 4);
116 OUT_RING(ring, 0x00000000); /* RB_MRT_FLAG_BUFFER[i].ADDR_LO */
117 OUT_RING(ring, 0x00000000); /* RB_MRT_FLAG_BUFFER[i].ADDR_HI */
118 OUT_RING(ring, A6XX_RB_MRT_FLAG_BUFFER_PITCH(0));
119 OUT_RING(ring, A6XX_RB_MRT_FLAG_BUFFER_ARRAY_PITCH(0));
120 #endif
121 }
122
123 OUT_PKT4(ring, REG_A6XX_RB_SRGB_CNTL, 1);
124 OUT_RING(ring, srgb_cntl);
125
126 OUT_PKT4(ring, REG_A6XX_SP_SRGB_CNTL, 1);
127 OUT_RING(ring, srgb_cntl);
128 }
129
130 static void
131 emit_zs(struct fd_ringbuffer *ring, struct pipe_surface *zsbuf,
132 struct fd_gmem_stateobj *gmem)
133 {
134 if (zsbuf) {
135 struct fd_resource *rsc = fd_resource(zsbuf->texture);
136 enum a6xx_depth_format fmt = fd6_pipe2depth(zsbuf->format);
137 struct fd_resource_slice *slice = fd_resource_slice(rsc, 0);
138 uint32_t stride = slice->pitch * rsc->cpp;
139 uint32_t size = slice->size0;
140 uint32_t base = gmem ? gmem->zsbuf_base[0] : 0;
141
142 OUT_PKT4(ring, REG_A6XX_RB_DEPTH_BUFFER_INFO, 6);
143 OUT_RING(ring, A6XX_RB_DEPTH_BUFFER_INFO_DEPTH_FORMAT(fmt));
144 OUT_RING(ring, A6XX_RB_DEPTH_BUFFER_PITCH(stride));
145 OUT_RING(ring, A6XX_RB_DEPTH_BUFFER_ARRAY_PITCH(size));
146 OUT_RELOCW(ring, rsc->bo, 0, 0, 0); /* RB_DEPTH_BUFFER_BASE_LO/HI */
147 OUT_RING(ring, base); /* RB_DEPTH_BUFFER_BASE_GMEM */
148
149 OUT_PKT4(ring, REG_A6XX_GRAS_SU_DEPTH_BUFFER_INFO, 1);
150 OUT_RING(ring, A6XX_GRAS_SU_DEPTH_BUFFER_INFO_DEPTH_FORMAT(fmt));
151
152 OUT_PKT4(ring, REG_A6XX_RB_DEPTH_FLAG_BUFFER_BASE_LO, 3);
153 OUT_RING(ring, 0x00000000); /* RB_DEPTH_FLAG_BUFFER_BASE_LO */
154 OUT_RING(ring, 0x00000000); /* RB_DEPTH_FLAG_BUFFER_BASE_HI */
155 OUT_RING(ring, 0x00000000); /* RB_DEPTH_FLAG_BUFFER_PITCH */
156
157 if (rsc->lrz) {
158 OUT_PKT4(ring, REG_A6XX_GRAS_LRZ_BUFFER_BASE_LO, 5);
159 OUT_RELOCW(ring, rsc->lrz, 0x1000, 0, 0);
160 OUT_RING(ring, A6XX_GRAS_LRZ_BUFFER_PITCH_PITCH(rsc->lrz_pitch));
161 OUT_RELOCW(ring, rsc->lrz, 0, 0, 0); /* GRAS_LRZ_FAST_CLEAR_BUFFER_BASE_LO/HI */
162 } else {
163 OUT_PKT4(ring, REG_A6XX_GRAS_LRZ_BUFFER_BASE_LO, 5);
164 OUT_RING(ring, 0x00000000);
165 OUT_RING(ring, 0x00000000);
166 OUT_RING(ring, 0x00000000); /* GRAS_LRZ_BUFFER_PITCH */
167 OUT_RING(ring, 0x00000000); /* GRAS_LRZ_FAST_CLEAR_BUFFER_BASE_LO */
168 OUT_RING(ring, 0x00000000);
169 }
170
171 if (rsc->stencil) {
172 struct fd_resource_slice *slice = fd_resource_slice(rsc->stencil, 0);
173 stride = slice->pitch * rsc->cpp;
174 size = slice->size0;
175 uint32_t base = gmem ? gmem->zsbuf_base[1] : 0;
176
177 OUT_PKT4(ring, REG_A6XX_RB_STENCIL_INFO, 5);
178 OUT_RING(ring, A6XX_RB_STENCIL_INFO_SEPARATE_STENCIL);
179 OUT_RING(ring, A6XX_RB_STENCIL_BUFFER_PITCH(stride));
180 OUT_RING(ring, A6XX_RB_STENCIL_BUFFER_ARRAY_PITCH(size));
181 OUT_RELOCW(ring, rsc->stencil->bo, 0, 0, 0); /* RB_STENCIL_BASE_LO/HI */
182 OUT_RING(ring, base); /* RB_STENCIL_BASE_LO */
183 }
184 } else {
185 OUT_PKT4(ring, REG_A6XX_RB_DEPTH_BUFFER_INFO, 6);
186 OUT_RING(ring, A6XX_RB_DEPTH_BUFFER_INFO_DEPTH_FORMAT(DEPTH6_NONE));
187 OUT_RING(ring, 0x00000000); /* RB_DEPTH_BUFFER_PITCH */
188 OUT_RING(ring, 0x00000000); /* RB_DEPTH_BUFFER_ARRAY_PITCH */
189 OUT_RING(ring, 0x00000000); /* RB_DEPTH_BUFFER_BASE_LO */
190 OUT_RING(ring, 0x00000000); /* RB_DEPTH_BUFFER_BASE_HI */
191 OUT_RING(ring, 0x00000000); /* RB_DEPTH_BUFFER_BASE_GMEM */
192
193 OUT_PKT4(ring, REG_A6XX_GRAS_SU_DEPTH_BUFFER_INFO, 1);
194 OUT_RING(ring, A6XX_GRAS_SU_DEPTH_BUFFER_INFO_DEPTH_FORMAT(DEPTH6_NONE));
195
196 OUT_PKT4(ring, REG_A6XX_GRAS_LRZ_BUFFER_BASE_LO, 5);
197 OUT_RING(ring, 0x00000000); /* RB_DEPTH_FLAG_BUFFER_BASE_LO */
198 OUT_RING(ring, 0x00000000); /* RB_DEPTH_FLAG_BUFFER_BASE_HI */
199 OUT_RING(ring, 0x00000000); /* GRAS_LRZ_BUFFER_PITCH */
200 OUT_RING(ring, 0x00000000); /* GRAS_LRZ_FAST_CLEAR_BUFFER_BASE_LO */
201 OUT_RING(ring, 0x00000000); /* GRAS_LRZ_FAST_CLEAR_BUFFER_BASE_HI */
202
203 OUT_PKT4(ring, REG_A6XX_RB_STENCIL_INFO, 1);
204 OUT_RING(ring, 0x00000000); /* RB_STENCIL_INFO */
205 }
206 }
207
208 static bool
209 use_hw_binning(struct fd_batch *batch)
210 {
211 return false;
212 }
213
214 static void
215 patch_draws(struct fd_batch *batch, enum pc_di_vis_cull_mode vismode)
216 {
217 unsigned i;
218 for (i = 0; i < fd_patch_num_elements(&batch->draw_patches); i++) {
219 struct fd_cs_patch *patch = fd_patch_element(&batch->draw_patches, i);
220 *patch->cs = patch->val | DRAW4(0, 0, 0, vismode);
221 }
222 util_dynarray_resize(&batch->draw_patches, 0);
223 }
224
225 static void
226 patch_gmem_bases(struct fd_batch *batch)
227 {
228 struct fd_gmem_stateobj *gmem = &batch->ctx->gmem;
229 unsigned i;
230
231 for (i = 0; i < fd_patch_num_elements(&batch->gmem_patches); i++) {
232 struct fd_cs_patch *patch = fd_patch_element(&batch->gmem_patches, i);
233 if (patch->val < MAX_RENDER_TARGETS)
234 *patch->cs = gmem->cbuf_base[patch->val];
235 else
236 *patch->cs = gmem->zsbuf_base[0];
237 }
238 util_dynarray_resize(&batch->gmem_patches, 0);
239 }
240
241 static void
242 update_vsc_pipe(struct fd_batch *batch)
243 {
244 struct fd_context *ctx = batch->ctx;
245 struct fd6_context *fd6_ctx = fd6_context(ctx);
246 struct fd_gmem_stateobj *gmem = &batch->ctx->gmem;
247 struct fd_ringbuffer *ring = batch->gmem;
248 int i;
249
250 OUT_PKT4(ring, REG_A6XX_VSC_BIN_SIZE, 3);
251 OUT_RING(ring, A6XX_VSC_BIN_SIZE_WIDTH(gmem->bin_w) |
252 A6XX_VSC_BIN_SIZE_HEIGHT(gmem->bin_h));
253 OUT_RELOCW(ring, fd6_ctx->vsc_size_mem, 0, 0, 0); /* VSC_SIZE_ADDRESS_LO/HI */
254
255 #if 0
256 OUT_PKT4(ring, REG_A6XX_UNKNOWN_0BC5, 2);
257 OUT_RING(ring, 0x00000000); /* UNKNOWN_0BC5 */
258 OUT_RING(ring, 0x00000000); /* UNKNOWN_0BC6 */
259 #endif
260
261 OUT_PKT4(ring, REG_A6XX_VSC_PIPE_CONFIG_REG(0), 16);
262 for (i = 0; i < 16; i++) {
263 struct fd_vsc_pipe *pipe = &ctx->vsc_pipe[i];
264 OUT_RING(ring, A6XX_VSC_PIPE_CONFIG_REG_X(pipe->x) |
265 A6XX_VSC_PIPE_CONFIG_REG_Y(pipe->y) |
266 A6XX_VSC_PIPE_CONFIG_REG_W(pipe->w) |
267 A6XX_VSC_PIPE_CONFIG_REG_H(pipe->h));
268 }
269
270 #if 0
271 OUT_PKT4(ring, REG_A6XX_VSC_PIPE_DATA_ADDRESS_LO(0), 32);
272 for (i = 0; i < 16; i++) {
273 struct fd_vsc_pipe *pipe = &ctx->vsc_pipe[i];
274 if (!pipe->bo) {
275 pipe->bo = fd_bo_new(ctx->dev, 0x20000,
276 DRM_FREEDRENO_GEM_TYPE_KMEM);
277 }
278 OUT_RELOCW(ring, pipe->bo, 0, 0, 0); /* VSC_PIPE_DATA_ADDRESS[i].LO/HI */
279 }
280 #endif
281
282 #if 0
283 OUT_PKT4(ring, REG_A6XX_VSC_PIPE_DATA_LENGTH_REG(0), 16);
284 for (i = 0; i < 16; i++) {
285 struct fd_vsc_pipe *pipe = &ctx->vsc_pipe[i];
286 OUT_RING(ring, fd_bo_size(pipe->bo) - 32); /* VSC_PIPE_DATA_LENGTH[i] */
287 }
288 #endif
289 }
290
291 static void
292 set_scissor(struct fd_ringbuffer *ring, uint32_t x1, uint32_t y1, uint32_t x2, uint32_t y2)
293 {
294 OUT_PKT4(ring, REG_A6XX_GRAS_SC_WINDOW_SCISSOR_TL, 2);
295 OUT_RING(ring, A6XX_GRAS_SC_WINDOW_SCISSOR_TL_X(x1) |
296 A6XX_GRAS_SC_WINDOW_SCISSOR_TL_Y(y1));
297 OUT_RING(ring, A6XX_GRAS_SC_WINDOW_SCISSOR_BR_X(x2) |
298 A6XX_GRAS_SC_WINDOW_SCISSOR_BR_Y(y2));
299
300 OUT_PKT4(ring, REG_A6XX_GRAS_RESOLVE_CNTL_1, 2);
301 OUT_RING(ring, A6XX_GRAS_RESOLVE_CNTL_1_X(x1) |
302 A6XX_GRAS_RESOLVE_CNTL_1_Y(y1));
303 OUT_RING(ring, A6XX_GRAS_RESOLVE_CNTL_2_X(x2) |
304 A6XX_GRAS_RESOLVE_CNTL_2_Y(y2));
305 }
306
307 static void
308 emit_binning_pass(struct fd_batch *batch)
309 {
310 struct fd_context *ctx = batch->ctx;
311 struct fd_ringbuffer *ring = batch->gmem;
312 struct fd_gmem_stateobj *gmem = &batch->ctx->gmem;
313
314 uint32_t x1 = gmem->minx;
315 uint32_t y1 = gmem->miny;
316 uint32_t x2 = gmem->minx + gmem->width - 1;
317 uint32_t y2 = gmem->miny + gmem->height - 1;
318
319 emit_marker6(ring, 7);
320 OUT_PKT7(ring, CP_SET_MARKER, 1);
321 OUT_RING(ring, A2XX_CP_SET_MARKER_0_MODE(RM6_BINNING) | 0x10); /* | 0x10 ? */
322 emit_marker6(ring, 7);
323
324 #if 0
325 OUT_PKT4(ring, REG_A6XX_RB_CNTL, 1);
326 OUT_RING(ring, A6XX_RB_CNTL_WIDTH(gmem->bin_w) |
327 A6XX_RB_CNTL_HEIGHT(gmem->bin_h));
328 #endif
329
330 set_scissor(ring, x1, y1, x2, y2);
331
332 update_vsc_pipe(batch);
333
334 #if 0
335 OUT_PKT4(ring, REG_A6XX_VPC_MODE_CNTL, 1);
336 OUT_RING(ring, A6XX_VPC_MODE_CNTL_BINNING_PASS);
337 #endif
338
339 OUT_PKT7(ring, CP_EVENT_WRITE, 1);
340 OUT_RING(ring, UNK_2C);
341
342 OUT_PKT4(ring, REG_A6XX_RB_WINDOW_OFFSET, 1);
343 OUT_RING(ring, A6XX_RB_WINDOW_OFFSET_X(0) |
344 A6XX_RB_WINDOW_OFFSET_Y(0));
345
346 /* emit IB to binning drawcmds: */
347 ctx->emit_ib(ring, batch->binning);
348
349 fd_reset_wfi(batch);
350
351 OUT_PKT7(ring, CP_EVENT_WRITE, 1);
352 OUT_RING(ring, UNK_2D);
353
354 OUT_PKT7(ring, CP_EVENT_WRITE, 4);
355 OUT_RING(ring, CACHE_FLUSH_TS);
356 OUT_RELOCW(ring, fd6_context(ctx)->blit_mem, 0, 0, 0); /* ADDR_LO/HI */
357 OUT_RING(ring, 0x00000000);
358
359 // TODO CP_COND_WRITE's for all the vsc buffers (check for overflow??)
360
361 fd_wfi(batch, ring);
362
363 #if 0
364 OUT_PKT4(ring, REG_A6XX_VPC_MODE_CNTL, 1);
365 OUT_RING(ring, 0x0);
366 #endif
367 }
368
369 static void
370 disable_msaa(struct fd_ringbuffer *ring)
371 {
372 // TODO MSAA
373 OUT_PKT4(ring, REG_A6XX_SP_TP_RAS_MSAA_CNTL, 2);
374 OUT_RING(ring, A6XX_SP_TP_RAS_MSAA_CNTL_SAMPLES(MSAA_ONE));
375 OUT_RING(ring, A6XX_SP_TP_DEST_MSAA_CNTL_SAMPLES(MSAA_ONE) |
376 A6XX_SP_TP_DEST_MSAA_CNTL_MSAA_DISABLE);
377
378 OUT_PKT4(ring, REG_A6XX_GRAS_RAS_MSAA_CNTL, 2);
379 OUT_RING(ring, A6XX_GRAS_RAS_MSAA_CNTL_SAMPLES(MSAA_ONE));
380 OUT_RING(ring, A6XX_GRAS_DEST_MSAA_CNTL_SAMPLES(MSAA_ONE) |
381 A6XX_GRAS_DEST_MSAA_CNTL_MSAA_DISABLE);
382
383 OUT_PKT4(ring, REG_A6XX_RB_RAS_MSAA_CNTL, 2);
384 OUT_RING(ring, A6XX_RB_RAS_MSAA_CNTL_SAMPLES(MSAA_ONE));
385 OUT_RING(ring, A6XX_RB_DEST_MSAA_CNTL_SAMPLES(MSAA_ONE) |
386 A6XX_RB_DEST_MSAA_CNTL_MSAA_DISABLE);
387 }
388
389 static void
390 set_bin_size(struct fd_ringbuffer *ring, uint32_t w, uint32_t h, uint32_t flag)
391 {
392 OUT_PKT4(ring, REG_A6XX_X1_BIN_SIZE, 1);
393 OUT_RING(ring, A6XX_X1_BIN_SIZE_WIDTH(w) |
394 A6XX_X1_BIN_SIZE_HEIGHT(h) | flag);
395 OUT_PKT4(ring, REG_A6XX_X2_BIN_SIZE, 1);
396 OUT_RING(ring, A6XX_X2_BIN_SIZE_WIDTH(w) |
397 A6XX_X2_BIN_SIZE_HEIGHT(h) | flag);
398
399 /* no flag for X3_BIN_SIZE... */
400 OUT_PKT4(ring, REG_A6XX_X3_BIN_SIZE, 1);
401 OUT_RING(ring, A6XX_X3_BIN_SIZE_WIDTH(w) |
402 A6XX_X3_BIN_SIZE_HEIGHT(h));
403 }
404
405 /* before first tile */
406 static void
407 fd6_emit_tile_init(struct fd_batch *batch)
408 {
409 struct fd_context *ctx = batch->ctx;
410 struct fd_ringbuffer *ring = batch->gmem;
411 struct pipe_framebuffer_state *pfb = &batch->framebuffer;
412 struct fd_gmem_stateobj *gmem = &batch->ctx->gmem;
413
414 fd6_emit_restore(batch, ring);
415
416 if (batch->lrz_clear)
417 ctx->emit_ib(ring, batch->lrz_clear);
418
419 fd6_emit_lrz_flush(ring);
420
421 OUT_PKT7(ring, CP_EVENT_WRITE, 1);
422 OUT_RING(ring, 0x31); /* vertex cache invalidate? */
423
424 #if 0
425 OUT_PKT4(ring, REG_A6XX_GRAS_CL_CNTL, 1);
426 OUT_RING(ring, 0x00000080); /* GRAS_CL_CNTL */
427 #endif
428
429 OUT_PKT7(ring, CP_SKIP_IB2_ENABLE_GLOBAL, 1);
430 OUT_RING(ring, 0x0);
431
432 #if 0
433 OUT_PKT4(ring, REG_A6XX_PC_POWER_CNTL, 1);
434 OUT_RING(ring, 0x00000003); /* PC_POWER_CNTL */
435 #endif
436
437 #if 0
438 OUT_PKT4(ring, REG_A6XX_VFD_POWER_CNTL, 1);
439 OUT_RING(ring, 0x00000003); /* VFD_POWER_CNTL */
440 #endif
441
442 /* 0x10000000 for BYPASS.. 0x7c13c080 for GMEM: */
443 fd_wfi(batch, ring);
444 OUT_PKT4(ring, REG_A6XX_RB_CCU_CNTL, 1);
445 OUT_RING(ring, 0x7c400004); /* RB_CCU_CNTL */
446
447 DBG("emit_mrt");
448 emit_zs(ring, pfb->zsbuf, &ctx->gmem);
449 emit_mrt(ring, pfb->nr_cbufs, pfb->cbufs, &ctx->gmem);
450
451 patch_gmem_bases(batch);
452
453 set_bin_size(ring, gmem->bin_w, gmem->bin_h, 0x6000000);
454
455 disable_msaa(ring);
456
457 if (use_hw_binning(batch)) {
458 emit_binning_pass(batch);
459 fd6_emit_lrz_flush(ring);
460 patch_draws(batch, USE_VISIBILITY);
461 } else {
462 patch_draws(batch, IGNORE_VISIBILITY);
463 }
464 }
465
466 static void
467 set_window_offset(struct fd_ringbuffer *ring, uint32_t x1, uint32_t y1)
468 {
469 OUT_PKT4(ring, REG_A6XX_RB_WINDOW_OFFSET, 1);
470 OUT_RING(ring, A6XX_RB_WINDOW_OFFSET_X(x1) |
471 A6XX_RB_WINDOW_OFFSET_Y(y1));
472
473 OUT_PKT4(ring, REG_A6XX_X1_WINDOW_OFFSET, 1);
474 OUT_RING(ring, A6XX_X1_WINDOW_OFFSET_X(x1) |
475 A6XX_X1_WINDOW_OFFSET_Y(y1));
476
477 OUT_PKT4(ring, REG_A6XX_X2_WINDOW_OFFSET, 1);
478 OUT_RING(ring, A6XX_X2_WINDOW_OFFSET_X(x1) |
479 A6XX_X2_WINDOW_OFFSET_Y(y1));
480
481 OUT_PKT4(ring, REG_A6XX_X3_WINDOW_OFFSET, 1);
482 OUT_RING(ring, A6XX_X3_WINDOW_OFFSET_X(x1) |
483 A6XX_X3_WINDOW_OFFSET_Y(y1));
484 }
485
486 /* before mem2gmem */
487 static void
488 fd6_emit_tile_prep(struct fd_batch *batch, struct fd_tile *tile)
489 {
490 struct fd_context *ctx = batch->ctx;
491 struct fd6_context *fd6_ctx = fd6_context(ctx);
492 struct fd_ringbuffer *ring = batch->gmem;
493
494 emit_marker6(ring, 7);
495 OUT_PKT7(ring, CP_SET_MARKER, 1);
496 OUT_RING(ring, A2XX_CP_SET_MARKER_0_MODE(RM6_GMEM) | 0x10); /* | 0x10 ? */
497 emit_marker6(ring, 7);
498
499 uint32_t x1 = tile->xoff;
500 uint32_t y1 = tile->yoff;
501 uint32_t x2 = tile->xoff + tile->bin_w - 1;
502 uint32_t y2 = tile->yoff + tile->bin_h - 1;
503
504 set_scissor(ring, x1, y1, x2, y2);
505
506 set_window_offset(ring, x1, y1);
507
508 OUT_PKT4(ring, REG_A6XX_VPC_SO_OVERRIDE, 1);
509 OUT_RING(ring, A6XX_VPC_SO_OVERRIDE_SO_DISABLE);
510
511 if (use_hw_binning(batch)) {
512 struct fd_vsc_pipe *pipe = &ctx->vsc_pipe[tile->p];
513
514 OUT_PKT7(ring, CP_WAIT_FOR_ME, 0);
515
516 OUT_PKT7(ring, CP_SET_VISIBILITY_OVERRIDE, 1);
517 OUT_RING(ring, 0x0);
518
519 OUT_PKT7(ring, CP_SET_BIN_DATA5, 5);
520 OUT_RING(ring, CP_SET_BIN_DATA5_0_VSC_SIZE(pipe->w * pipe->h) |
521 CP_SET_BIN_DATA5_0_VSC_N(tile->n));
522 OUT_RELOC(ring, pipe->bo, 0, 0, 0); /* VSC_PIPE[p].DATA_ADDRESS */
523 OUT_RELOC(ring, fd6_ctx->vsc_size_mem, /* VSC_SIZE_ADDRESS + (p * 4) */
524 (tile->p * 4), 0, 0);
525 } else {
526 OUT_PKT7(ring, CP_SET_VISIBILITY_OVERRIDE, 1);
527 OUT_RING(ring, 0x1);
528 }
529
530 OUT_PKT7(ring, CP_SET_MODE, 1);
531 OUT_RING(ring, 0x0);
532 }
533
534 static void
535 set_blit_scissor(struct fd_batch *batch)
536 {
537 struct fd_ringbuffer *ring = batch->gmem;
538 struct pipe_scissor_state blit_scissor;
539 struct pipe_framebuffer_state *pfb = &batch->framebuffer;
540
541 blit_scissor.minx = batch->max_scissor.minx;
542 blit_scissor.miny = batch->max_scissor.miny;
543 blit_scissor.maxx = MIN2(pfb->width - 1, batch->max_scissor.maxx);
544 blit_scissor.maxy = MIN2(pfb->height - 1, batch->max_scissor.maxy);
545
546 OUT_PKT4(ring, REG_A6XX_RB_BLIT_SCISSOR_TL, 2);
547 OUT_RING(ring,
548 A6XX_RB_BLIT_SCISSOR_TL_X(blit_scissor.minx) |
549 A6XX_RB_BLIT_SCISSOR_TL_Y(blit_scissor.miny));
550 OUT_RING(ring,
551 A6XX_RB_BLIT_SCISSOR_BR_X(blit_scissor.maxx - 1) |
552 A6XX_RB_BLIT_SCISSOR_BR_Y(blit_scissor.maxy - 1));
553 }
554
555 static void
556 emit_blit(struct fd_batch *batch, uint32_t base,
557 struct pipe_surface *psurf,
558 struct fd_resource *rsc)
559 {
560 struct fd_ringbuffer *ring = batch->gmem;
561 struct fd_resource_slice *slice;
562 uint32_t offset;
563
564 slice = fd_resource_slice(rsc, psurf->u.tex.level);
565 offset = fd_resource_offset(rsc, psurf->u.tex.level,
566 psurf->u.tex.first_layer);
567
568 debug_assert(psurf->u.tex.first_layer == psurf->u.tex.last_layer);
569
570 enum pipe_format pfmt = psurf->format;
571 enum a6xx_color_fmt format = fd6_pipe2color(pfmt);
572 uint32_t stride = slice->pitch * rsc->cpp;
573 uint32_t size = slice->size0;
574 enum a3xx_color_swap swap = fd6_pipe2swap(pfmt);
575
576 // TODO: tile mode
577 // bool tiled;
578 // tiled = rsc->tile_mode &&
579 // !fd_resource_level_linear(psurf->texture, psurf->u.tex.level);
580
581 OUT_PKT4(ring, REG_A6XX_RB_BLIT_DST_INFO, 5);
582 OUT_RING(ring,
583 A6XX_RB_BLIT_DST_INFO_TILE_MODE(TILE6_LINEAR) |
584 A6XX_RB_BLIT_DST_INFO_COLOR_FORMAT(format) |
585 A6XX_RB_BLIT_DST_INFO_COLOR_SWAP(swap));
586 OUT_RELOCW(ring, rsc->bo, offset, 0, 0); /* RB_BLIT_DST_LO/HI */
587 OUT_RING(ring, A6XX_RB_BLIT_DST_PITCH(stride));
588 OUT_RING(ring, A6XX_RB_BLIT_DST_ARRAY_PITCH(size));
589
590 OUT_PKT4(ring, REG_A6XX_RB_BLIT_BASE_GMEM, 1);
591 OUT_RING(ring, base);
592
593 fd6_emit_blit(batch->ctx, ring);
594 }
595
596 static void
597 emit_restore_blit(struct fd_batch *batch, uint32_t base,
598 struct pipe_surface *psurf,
599 struct fd_resource *rsc,
600 unsigned buffer)
601 {
602 struct fd_ringbuffer *ring = batch->gmem;
603 uint32_t info = 0;
604
605 switch (buffer) {
606 case FD_BUFFER_COLOR:
607 info |= A6XX_RB_BLIT_INFO_UNK0;
608 break;
609 case FD_BUFFER_STENCIL:
610 info |= A6XX_RB_BLIT_INFO_UNK0;
611 break;
612 case FD_BUFFER_DEPTH:
613 info |= A6XX_RB_BLIT_INFO_DEPTH;
614 break;
615 }
616
617 if (util_format_is_pure_integer(psurf->format))
618 info |= A6XX_RB_BLIT_INFO_INTEGER;
619
620 OUT_PKT4(ring, REG_A6XX_RB_BLIT_INFO, 1);
621 OUT_RING(ring, info | A6XX_RB_BLIT_INFO_GMEM);
622
623 emit_blit(batch, base, psurf, rsc);
624 }
625
626 /*
627 * transfer from system memory to gmem
628 */
629 static void
630 fd6_emit_tile_mem2gmem(struct fd_batch *batch, struct fd_tile *tile)
631 {
632 struct fd_context *ctx = batch->ctx;
633 struct fd_gmem_stateobj *gmem = &ctx->gmem;
634 struct pipe_framebuffer_state *pfb = &batch->framebuffer;
635
636 set_blit_scissor(batch);
637
638 if (fd_gmem_needs_restore(batch, tile, FD_BUFFER_COLOR)) {
639 unsigned i;
640 for (i = 0; i < pfb->nr_cbufs; i++) {
641 if (!pfb->cbufs[i])
642 continue;
643 if (!(batch->restore & (PIPE_CLEAR_COLOR0 << i)))
644 continue;
645 emit_restore_blit(batch, gmem->cbuf_base[i], pfb->cbufs[i],
646 fd_resource(pfb->cbufs[i]->texture),
647 FD_BUFFER_COLOR);
648 }
649 }
650
651 if (fd_gmem_needs_restore(batch, tile, FD_BUFFER_DEPTH | FD_BUFFER_STENCIL)) {
652 struct fd_resource *rsc = fd_resource(pfb->zsbuf->texture);
653
654 if (!rsc->stencil || fd_gmem_needs_restore(batch, tile, FD_BUFFER_DEPTH)) {
655 emit_restore_blit(batch, gmem->zsbuf_base[0], pfb->zsbuf, rsc,
656 FD_BUFFER_DEPTH);
657 }
658 if (rsc->stencil && fd_gmem_needs_restore(batch, tile, FD_BUFFER_STENCIL)) {
659 emit_restore_blit(batch, gmem->zsbuf_base[1], pfb->zsbuf, rsc->stencil,
660 FD_BUFFER_STENCIL);
661 }
662 }
663 }
664
665 /* before IB to rendering cmds: */
666 static void
667 fd6_emit_tile_renderprep(struct fd_batch *batch, struct fd_tile *tile)
668 {
669 }
670
671 static void
672 emit_resolve_blit(struct fd_batch *batch, uint32_t base,
673 struct pipe_surface *psurf,
674 struct fd_resource *rsc,
675 unsigned buffer)
676 {
677 struct fd_ringbuffer *ring = batch->gmem;
678 uint32_t info = 0;
679
680 switch (buffer) {
681 case FD_BUFFER_COLOR:
682 break;
683 case FD_BUFFER_STENCIL:
684 info |= A6XX_RB_BLIT_INFO_UNK0;
685 break;
686 case FD_BUFFER_DEPTH:
687 info |= A6XX_RB_BLIT_INFO_DEPTH;
688 break;
689 }
690
691 if (util_format_is_pure_integer(psurf->format))
692 info |= A6XX_RB_BLIT_INFO_INTEGER;
693
694 OUT_PKT4(ring, REG_A6XX_RB_BLIT_INFO, 1);
695 OUT_RING(ring, info);
696
697 emit_blit(batch, base, psurf, rsc);
698 }
699
700 /*
701 * transfer from gmem to system memory (ie. normal RAM)
702 */
703
704 static void
705 fd6_emit_tile_gmem2mem(struct fd_batch *batch, struct fd_tile *tile)
706 {
707 struct fd_context *ctx = batch->ctx;
708 struct fd_gmem_stateobj *gmem = &ctx->gmem;
709 struct pipe_framebuffer_state *pfb = &batch->framebuffer;
710 struct fd_ringbuffer *ring = batch->gmem;
711
712 OUT_PKT7(ring, CP_SKIP_IB2_ENABLE_GLOBAL, 1);
713 OUT_RING(ring, 0x0);
714
715 emit_marker6(ring, 7);
716 OUT_PKT7(ring, CP_SET_MARKER, 1);
717 OUT_RING(ring, A2XX_CP_SET_MARKER_0_MODE(RM6_RESOLVE)); /* | 0x10 ? */
718 emit_marker6(ring, 7);
719
720 set_blit_scissor(batch);
721
722 if (batch->resolve & (FD_BUFFER_DEPTH | FD_BUFFER_STENCIL)) {
723 struct fd_resource *rsc = fd_resource(pfb->zsbuf->texture);
724
725 if (!rsc->stencil || (batch->resolve & FD_BUFFER_DEPTH)) {
726 emit_resolve_blit(batch, gmem->zsbuf_base[0], pfb->zsbuf, rsc,
727 FD_BUFFER_DEPTH);
728 }
729 if (rsc->stencil && (batch->resolve & FD_BUFFER_STENCIL)) {
730 emit_resolve_blit(batch, gmem->zsbuf_base[1], pfb->zsbuf, rsc->stencil,
731 FD_BUFFER_STENCIL);
732 }
733 }
734
735 if (batch->resolve & FD_BUFFER_COLOR) {
736 unsigned i;
737 for (i = 0; i < pfb->nr_cbufs; i++) {
738 if (!pfb->cbufs[i])
739 continue;
740 if (!(batch->resolve & (PIPE_CLEAR_COLOR0 << i)))
741 continue;
742 emit_resolve_blit(batch, gmem->cbuf_base[i], pfb->cbufs[i],
743 fd_resource(pfb->cbufs[i]->texture),
744 FD_BUFFER_COLOR);
745 }
746 }
747 }
748
749 static void
750 fd6_emit_tile_fini(struct fd_batch *batch)
751 {
752 struct fd_ringbuffer *ring = batch->gmem;
753
754 fd6_emit_lrz_flush(ring);
755
756 fd6_cache_flush(batch, ring);
757 }
758
759 static void
760 fd6_emit_sysmem_prep(struct fd_batch *batch)
761 {
762 struct pipe_framebuffer_state *pfb = &batch->framebuffer;
763 struct fd_ringbuffer *ring = batch->gmem;
764
765 fd6_emit_restore(batch, ring);
766
767 fd6_emit_lrz_flush(ring);
768
769 emit_marker6(ring, 7);
770 OUT_PKT7(ring, CP_SET_MARKER, 1);
771 OUT_RING(ring, A2XX_CP_SET_MARKER_0_MODE(RM6_BYPASS) | 0x10); /* | 0x10 ? */
772 emit_marker6(ring, 7);
773
774 OUT_PKT7(ring, CP_SKIP_IB2_ENABLE_GLOBAL, 1);
775 OUT_RING(ring, 0x0);
776
777 OUT_PKT7(ring, CP_EVENT_WRITE, 1);
778 OUT_RING(ring, PC_CCU_INVALIDATE_COLOR);
779
780 OUT_PKT7(ring, CP_EVENT_WRITE, 1);
781 OUT_RING(ring, 0x31); /* vertex cache invalidate? */
782
783 #if 0
784 OUT_PKT4(ring, REG_A6XX_PC_POWER_CNTL, 1);
785 OUT_RING(ring, 0x00000003); /* PC_POWER_CNTL */
786 #endif
787
788 #if 0
789 OUT_PKT4(ring, REG_A6XX_VFD_POWER_CNTL, 1);
790 OUT_RING(ring, 0x00000003); /* VFD_POWER_CNTL */
791 #endif
792
793 /* 0x10000000 for BYPASS.. 0x7c13c080 for GMEM: */
794 fd_wfi(batch, ring);
795 OUT_PKT4(ring, REG_A6XX_RB_CCU_CNTL, 1);
796 OUT_RING(ring, 0x10000000); /* RB_CCU_CNTL */
797
798 set_scissor(ring, 0, 0, pfb->width - 1, pfb->height - 1);
799
800 set_window_offset(ring, 0, 0);
801
802 set_bin_size(ring, 0, 0, 0xc00000); /* 0xc00000 = BYPASS? */
803
804 OUT_PKT7(ring, CP_SET_VISIBILITY_OVERRIDE, 1);
805 OUT_RING(ring, 0x1);
806
807 patch_draws(batch, IGNORE_VISIBILITY);
808
809 emit_zs(ring, pfb->zsbuf, NULL);
810 emit_mrt(ring, pfb->nr_cbufs, pfb->cbufs, NULL);
811
812 disable_msaa(ring);
813 }
814
815 static void
816 fd6_emit_sysmem_fini(struct fd_batch *batch)
817 {
818 struct fd6_context *fd6_ctx = fd6_context(batch->ctx);
819 struct fd_ringbuffer *ring = batch->gmem;
820
821 OUT_PKT7(ring, CP_SKIP_IB2_ENABLE_GLOBAL, 1);
822 OUT_RING(ring, 0x0);
823
824 fd6_emit_lrz_flush(ring);
825
826 OUT_PKT7(ring, CP_EVENT_WRITE, 4);
827 OUT_RING(ring, UNK_1D);
828 OUT_RELOCW(ring, fd6_ctx->blit_mem, 0, 0, 0); /* ADDR_LO/HI */
829 OUT_RING(ring, 0x00000000);
830 }
831
832 void
833 fd6_gmem_init(struct pipe_context *pctx)
834 {
835 struct fd_context *ctx = fd_context(pctx);
836
837 ctx->emit_tile_init = fd6_emit_tile_init;
838 ctx->emit_tile_prep = fd6_emit_tile_prep;
839 ctx->emit_tile_mem2gmem = fd6_emit_tile_mem2gmem;
840 ctx->emit_tile_renderprep = fd6_emit_tile_renderprep;
841 ctx->emit_tile_gmem2mem = fd6_emit_tile_gmem2mem;
842 ctx->emit_tile_fini = fd6_emit_tile_fini;
843 ctx->emit_sysmem_prep = fd6_emit_sysmem_prep;
844 ctx->emit_sysmem_fini = fd6_emit_sysmem_fini;
845 }