freedreno/a5xx: srgb fix
[mesa.git] / src / gallium / drivers / freedreno / a5xx / fd5_gmem.c
1 /*
2 * Copyright (C) 2016 Rob Clark <robclark@freedesktop.org>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *
23 * Authors:
24 * Rob Clark <robclark@freedesktop.org>
25 */
26
27 #include "pipe/p_state.h"
28 #include "util/u_string.h"
29 #include "util/u_memory.h"
30 #include "util/u_inlines.h"
31 #include "util/u_format.h"
32
33 #include "freedreno_draw.h"
34 #include "freedreno_state.h"
35 #include "freedreno_resource.h"
36
37 #include "fd5_gmem.h"
38 #include "fd5_context.h"
39 #include "fd5_draw.h"
40 #include "fd5_emit.h"
41 #include "fd5_program.h"
42 #include "fd5_format.h"
43 #include "fd5_zsa.h"
44
45 static void
46 emit_mrt(struct fd_ringbuffer *ring, unsigned nr_bufs,
47 struct pipe_surface **bufs, struct fd_gmem_stateobj *gmem)
48 {
49 enum a5xx_tile_mode tile_mode;
50 unsigned i;
51
52 if (gmem) {
53 tile_mode = TILE5_2;
54 } else {
55 tile_mode = TILE5_LINEAR;
56 }
57
58 for (i = 0; i < A5XX_MAX_RENDER_TARGETS; i++) {
59 enum a5xx_color_fmt format = 0;
60 enum a3xx_color_swap swap = WZYX;
61 bool srgb = false;
62 struct fd_resource *rsc = NULL;
63 struct fd_resource_slice *slice = NULL;
64 uint32_t stride = 0;
65 uint32_t size = 0;
66 uint32_t base = 0;
67 uint32_t offset = 0;
68
69 if ((i < nr_bufs) && bufs[i]) {
70 struct pipe_surface *psurf = bufs[i];
71 enum pipe_format pformat = psurf->format;
72
73 rsc = fd_resource(psurf->texture);
74
75 slice = fd_resource_slice(rsc, psurf->u.tex.level);
76 format = fd5_pipe2color(pformat);
77 swap = fd5_pipe2swap(pformat);
78 srgb = util_format_is_srgb(pformat);
79
80 debug_assert(psurf->u.tex.first_layer == psurf->u.tex.last_layer);
81
82 offset = fd_resource_offset(rsc, psurf->u.tex.level,
83 psurf->u.tex.first_layer);
84
85 if (gmem) {
86 stride = gmem->bin_w * rsc->cpp;
87 size = stride * gmem->bin_h;
88 base = gmem->cbuf_base[i];
89 } else {
90 stride = slice->pitch * rsc->cpp;
91 size = slice->size0;
92 }
93 }
94
95 OUT_PKT4(ring, REG_A5XX_RB_MRT_BUF_INFO(i), 5);
96 OUT_RING(ring, A5XX_RB_MRT_BUF_INFO_COLOR_FORMAT(format) |
97 A5XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE(tile_mode) |
98 A5XX_RB_MRT_BUF_INFO_COLOR_SWAP(swap) |
99 COND(gmem, 0x800) | /* XXX 0x1000 for RECTLIST clear, 0x0 for BLIT.. */
100 COND(srgb, A5XX_RB_MRT_BUF_INFO_COLOR_SRGB));
101 OUT_RING(ring, A5XX_RB_MRT_PITCH(stride));
102 OUT_RING(ring, A5XX_RB_MRT_ARRAY_PITCH(size));
103 if (gmem || (i >= nr_bufs) || !bufs[i]) {
104 OUT_RING(ring, base); /* RB_MRT[i].BASE_LO */
105 OUT_RING(ring, 0x00000000); /* RB_MRT[i].BASE_HI */
106 } else {
107 debug_assert((offset + size) <= fd_bo_size(rsc->bo));
108 OUT_RELOCW(ring, rsc->bo, offset, 0, 0); /* BASE_LO/HI */
109 }
110
111 OUT_PKT4(ring, REG_A5XX_SP_FS_MRT_REG(i), 1);
112 OUT_RING(ring, A5XX_SP_FS_MRT_REG_COLOR_FORMAT(format) |
113 COND(srgb, A5XX_SP_FS_MRT_REG_COLOR_SRGB));
114
115 /* when we support UBWC, these would be the system memory
116 * addr/pitch/etc:
117 */
118 OUT_PKT4(ring, REG_A5XX_RB_MRT_FLAG_BUFFER(i), 4);
119 OUT_RING(ring, 0x00000000); /* RB_MRT_FLAG_BUFFER[i].ADDR_LO */
120 OUT_RING(ring, 0x00000000); /* RB_MRT_FLAG_BUFFER[i].ADDR_HI */
121 OUT_RING(ring, A5XX_RB_MRT_FLAG_BUFFER_PITCH(0));
122 OUT_RING(ring, A5XX_RB_MRT_FLAG_BUFFER_ARRAY_PITCH(0));
123 }
124 }
125
126 static void
127 emit_zs(struct fd_ringbuffer *ring, struct pipe_surface *zsbuf,
128 struct fd_gmem_stateobj *gmem)
129 {
130 if (zsbuf) {
131 struct fd_resource *rsc = fd_resource(zsbuf->texture);
132 enum a5xx_depth_format fmt = fd5_pipe2depth(zsbuf->format);
133 uint32_t cpp = rsc->cpp;
134 uint32_t stride = 0;
135 uint32_t size = 0;
136
137 if (gmem) {
138 stride = cpp * gmem->bin_w;
139 size = stride * gmem->bin_h;
140 } else {
141 struct fd_resource_slice *slice = fd_resource_slice(rsc, 0);
142 stride = slice->pitch * rsc->cpp;
143 size = slice->size0;
144 }
145
146 OUT_PKT4(ring, REG_A5XX_RB_DEPTH_BUFFER_INFO, 5);
147 OUT_RING(ring, A5XX_RB_DEPTH_BUFFER_INFO_DEPTH_FORMAT(fmt));
148 if (gmem) {
149 OUT_RING(ring, gmem->zsbuf_base[0]); /* RB_DEPTH_BUFFER_BASE_LO */
150 OUT_RING(ring, 0x00000000); /* RB_DEPTH_BUFFER_BASE_HI */
151 } else {
152 OUT_RELOCW(ring, rsc->bo, 0, 0, 0); /* RB_DEPTH_BUFFER_BASE_LO/HI */
153 }
154 OUT_RING(ring, A5XX_RB_DEPTH_BUFFER_PITCH(stride));
155 OUT_RING(ring, A5XX_RB_DEPTH_BUFFER_ARRAY_PITCH(size));
156
157 OUT_PKT4(ring, REG_A5XX_GRAS_SU_DEPTH_BUFFER_INFO, 1);
158 OUT_RING(ring, A5XX_GRAS_SU_DEPTH_BUFFER_INFO_DEPTH_FORMAT(fmt));
159
160 OUT_PKT4(ring, REG_A5XX_RB_DEPTH_FLAG_BUFFER_BASE_LO, 3);
161 OUT_RING(ring, 0x00000000); /* RB_DEPTH_FLAG_BUFFER_BASE_LO */
162 OUT_RING(ring, 0x00000000); /* RB_DEPTH_FLAG_BUFFER_BASE_HI */
163 OUT_RING(ring, 0x00000000); /* RB_DEPTH_FLAG_BUFFER_PITCH */
164
165 if (rsc->stencil) {
166 if (gmem) {
167 stride = 1 * gmem->bin_w;
168 size = stride * gmem->bin_h;
169 } else {
170 struct fd_resource_slice *slice = fd_resource_slice(rsc->stencil, 0);
171 stride = slice->pitch * rsc->cpp;
172 size = slice->size0;
173 }
174
175 OUT_PKT4(ring, REG_A5XX_RB_STENCIL_INFO, 5);
176 OUT_RING(ring, A5XX_RB_STENCIL_INFO_SEPARATE_STENCIL);
177 if (gmem) {
178 OUT_RING(ring, gmem->zsbuf_base[1]); /* RB_STENCIL_BASE_LO */
179 OUT_RING(ring, 0x00000000); /* RB_STENCIL_BASE_HI */
180 } else {
181 OUT_RELOCW(ring, rsc->stencil->bo, 0, 0, 0); /* RB_STENCIL_BASE_LO/HI */
182 }
183 OUT_RING(ring, A5XX_RB_STENCIL_PITCH(stride));
184 OUT_RING(ring, A5XX_RB_STENCIL_ARRAY_PITCH(size));
185 } else {
186 OUT_PKT4(ring, REG_A5XX_RB_STENCIL_INFO, 1);
187 OUT_RING(ring, 0x00000000); /* RB_STENCIL_INFO */
188 }
189 } else {
190 OUT_PKT4(ring, REG_A5XX_RB_DEPTH_BUFFER_INFO, 5);
191 OUT_RING(ring, A5XX_RB_DEPTH_BUFFER_INFO_DEPTH_FORMAT(DEPTH5_NONE));
192 OUT_RING(ring, 0x00000000); /* RB_DEPTH_BUFFER_BASE_LO */
193 OUT_RING(ring, 0x00000000); /* RB_DEPTH_BUFFER_BASE_HI */
194 OUT_RING(ring, 0x00000000); /* RB_DEPTH_BUFFER_PITCH */
195 OUT_RING(ring, 0x00000000); /* RB_DEPTH_BUFFER_ARRAY_PITCH */
196
197 OUT_PKT4(ring, REG_A5XX_GRAS_SU_DEPTH_BUFFER_INFO, 1);
198 OUT_RING(ring, A5XX_GRAS_SU_DEPTH_BUFFER_INFO_DEPTH_FORMAT(DEPTH5_NONE));
199
200 OUT_PKT4(ring, REG_A5XX_RB_DEPTH_FLAG_BUFFER_BASE_LO, 3);
201 OUT_RING(ring, 0x00000000); /* RB_DEPTH_FLAG_BUFFER_BASE_LO */
202 OUT_RING(ring, 0x00000000); /* RB_DEPTH_FLAG_BUFFER_BASE_HI */
203 OUT_RING(ring, 0x00000000); /* RB_DEPTH_FLAG_BUFFER_PITCH */
204
205 OUT_PKT4(ring, REG_A5XX_RB_STENCIL_INFO, 1);
206 OUT_RING(ring, 0x00000000); /* RB_STENCIL_INFO */
207 }
208 }
209
210 static void
211 patch_draws(struct fd_batch *batch, enum pc_di_vis_cull_mode vismode)
212 {
213 unsigned i;
214 for (i = 0; i < fd_patch_num_elements(&batch->draw_patches); i++) {
215 struct fd_cs_patch *patch = fd_patch_element(&batch->draw_patches, i);
216 *patch->cs = patch->val | DRAW4(0, 0, 0, vismode);
217 }
218 util_dynarray_resize(&batch->draw_patches, 0);
219 }
220
221 /* before first tile */
222 static void
223 fd5_emit_tile_init(struct fd_batch *batch)
224 {
225 struct fd_ringbuffer *ring = batch->gmem;
226
227 fd5_emit_restore(batch, ring);
228
229 OUT_PKT7(ring, CP_EVENT_WRITE, 1);
230 OUT_RING(ring, UNK_26);
231
232 OUT_PKT7(ring, CP_SKIP_IB2_ENABLE_GLOBAL, 1);
233 OUT_RING(ring, 0x0);
234
235 OUT_PKT4(ring, REG_A5XX_PC_POWER_CNTL, 1);
236 OUT_RING(ring, 0x00000003); /* PC_POWER_CNTL */
237
238 OUT_PKT4(ring, REG_A5XX_VFD_POWER_CNTL, 1);
239 OUT_RING(ring, 0x00000003); /* VFD_POWER_CNTL */
240
241 /* 0x10000000 for BYPASS.. 0x7c13c080 for GMEM: */
242 fd_wfi(batch, ring);
243 OUT_PKT4(ring, REG_A5XX_RB_CCU_CNTL, 1);
244 OUT_RING(ring, 0x7c13c080); /* RB_CCU_CNTL */
245
246 /*
247 opcode: CP_PREEMPT_ENABLE_LOCAL (6a) (2 dwords)
248 */
249
250 fd5_set_render_mode(batch->ctx, ring, GMEM);
251 }
252
253 /* before mem2gmem */
254 static void
255 fd5_emit_tile_prep(struct fd_batch *batch, struct fd_tile *tile)
256 {
257 struct fd_ringbuffer *ring = batch->gmem;
258
259 uint32_t x1 = tile->xoff;
260 uint32_t y1 = tile->yoff;
261 uint32_t x2 = tile->xoff + tile->bin_w - 1;
262 uint32_t y2 = tile->yoff + tile->bin_h - 1;
263
264 OUT_PKT4(ring, REG_A5XX_GRAS_SC_WINDOW_SCISSOR_TL, 2);
265 OUT_RING(ring, A5XX_GRAS_SC_WINDOW_SCISSOR_TL_X(x1) |
266 A5XX_GRAS_SC_WINDOW_SCISSOR_TL_Y(y1));
267 OUT_RING(ring, A5XX_GRAS_SC_WINDOW_SCISSOR_BR_X(x2) |
268 A5XX_GRAS_SC_WINDOW_SCISSOR_BR_Y(y2));
269
270 OUT_PKT4(ring, REG_A5XX_RB_RESOLVE_CNTL_1, 2);
271 OUT_RING(ring, A5XX_RB_RESOLVE_CNTL_1_X(x1) |
272 A5XX_RB_RESOLVE_CNTL_1_Y(y1));
273 OUT_RING(ring, A5XX_RB_RESOLVE_CNTL_2_X(x2) |
274 A5XX_RB_RESOLVE_CNTL_2_Y(y2));
275
276 OUT_PKT4(ring, REG_A5XX_RB_WINDOW_OFFSET, 1);
277 OUT_RING(ring, A5XX_RB_WINDOW_OFFSET_X(x1) |
278 A5XX_RB_WINDOW_OFFSET_Y(y1));
279 }
280
281
282 /*
283 * transfer from system memory to gmem
284 */
285
286 static void
287 emit_mem2gmem_surf(struct fd_batch *batch, uint32_t base,
288 struct pipe_surface *psurf, enum a5xx_blit_buf buf)
289 {
290 struct fd_ringbuffer *ring = batch->gmem;
291 struct fd_gmem_stateobj *gmem = &batch->ctx->gmem;
292 struct fd_resource *rsc = fd_resource(psurf->texture);
293 uint32_t stride, size;
294
295 debug_assert(psurf->u.tex.first_layer == psurf->u.tex.last_layer);
296
297 stride = gmem->bin_w * rsc->cpp;
298 size = stride * gmem->bin_h;
299
300 OUT_PKT4(ring, REG_A5XX_RB_BLIT_FLAG_DST_LO, 4);
301 OUT_RING(ring, 0x00000000); /* RB_BLIT_FLAG_DST_LO */
302 OUT_RING(ring, 0x00000000); /* RB_BLIT_FLAG_DST_HI */
303 OUT_RING(ring, 0x00000000); /* RB_BLIT_FLAG_DST_PITCH */
304 OUT_RING(ring, 0x00000000); /* RB_BLIT_FLAG_DST_ARRAY_PITCH */
305
306 OUT_PKT4(ring, REG_A5XX_RB_RESOLVE_CNTL_3, 5);
307 OUT_RING(ring, 0x00000000); /* RB_RESOLVE_CNTL_3 */
308 OUT_RING(ring, base); /* RB_BLIT_DST_LO */
309 OUT_RING(ring, 0x00000000); /* RB_BLIT_DST_HI */
310 OUT_RING(ring, A5XX_RB_BLIT_DST_PITCH(stride));
311 OUT_RING(ring, A5XX_RB_BLIT_DST_ARRAY_PITCH(size));
312
313 OUT_PKT4(ring, REG_A5XX_RB_BLIT_CNTL, 1);
314 OUT_RING(ring, A5XX_RB_BLIT_CNTL_BUF(buf));
315
316 fd5_emit_blit(batch->ctx, ring);
317 }
318
319 static void
320 fd5_emit_tile_mem2gmem(struct fd_batch *batch, struct fd_tile *tile)
321 {
322 struct fd_ringbuffer *ring = batch->gmem;
323 struct fd_context *ctx = batch->ctx;
324 struct fd_gmem_stateobj *gmem = &ctx->gmem;
325 struct pipe_framebuffer_state *pfb = &batch->framebuffer;
326
327 /*
328 * setup mrt and zs with system memory base addresses:
329 */
330
331 emit_mrt(ring, pfb->nr_cbufs, pfb->cbufs, NULL);
332 // emit_zs(ring, pfb->zsbuf, NULL);
333
334 OUT_PKT4(ring, REG_A5XX_RB_CNTL, 1);
335 OUT_RING(ring, A5XX_RB_CNTL_WIDTH(gmem->bin_w) |
336 A5XX_RB_CNTL_HEIGHT(gmem->bin_h) |
337 A5XX_RB_CNTL_BYPASS);
338
339 if (fd_gmem_needs_restore(batch, tile, FD_BUFFER_COLOR)) {
340 unsigned i;
341 for (i = 0; i < pfb->nr_cbufs; i++) {
342 if (!pfb->cbufs[i])
343 continue;
344 if (!(batch->restore & (PIPE_CLEAR_COLOR0 << i)))
345 continue;
346 emit_mem2gmem_surf(batch, gmem->cbuf_base[i],
347 pfb->cbufs[i], BLIT_MRT0 + i);
348 }
349 }
350
351 if (fd_gmem_needs_restore(batch, tile, FD_BUFFER_DEPTH | FD_BUFFER_STENCIL)) {
352 struct fd_resource *rsc = fd_resource(pfb->zsbuf->texture);
353 // XXX BLIT_ZS vs BLIT_Z32 .. need some more cmdstream traces
354 // with z32_x24s8..
355
356 // XXX hack import via BLIT_MRT0 instead of BLIT_ZS, since I don't
357 // know otherwise how to go from linear in sysmem to tiled in gmem.
358 // possibly we want to flip this around gmem2mem and keep depth
359 // tiled in sysmem (and fixup sampler state to assume tiled).. this
360 // might be required for doing depth/stencil in bypass mode?
361 struct fd_resource_slice *slice = fd_resource_slice(rsc, 0);
362 enum a5xx_color_fmt format =
363 fd5_pipe2color(fd_gmem_restore_format(pfb->zsbuf->format));
364
365 OUT_PKT4(ring, REG_A5XX_RB_MRT_BUF_INFO(0), 5);
366 OUT_RING(ring, A5XX_RB_MRT_BUF_INFO_COLOR_FORMAT(format) |
367 A5XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE(TILE5_LINEAR) |
368 A5XX_RB_MRT_BUF_INFO_COLOR_SWAP(WZYX));
369 OUT_RING(ring, A5XX_RB_MRT_PITCH(slice->pitch * rsc->cpp));
370 OUT_RING(ring, A5XX_RB_MRT_ARRAY_PITCH(slice->size0));
371 OUT_RELOCW(ring, rsc->bo, 0, 0, 0); /* BASE_LO/HI */
372
373 emit_mem2gmem_surf(batch, ctx->gmem.zsbuf_base[0], pfb->zsbuf, BLIT_MRT0);
374 }
375 }
376
377
378 /* before IB to rendering cmds: */
379 static void
380 fd5_emit_tile_renderprep(struct fd_batch *batch, struct fd_tile *tile)
381 {
382 struct fd_ringbuffer *ring = batch->gmem;
383 struct fd_gmem_stateobj *gmem = &batch->ctx->gmem;
384 struct pipe_framebuffer_state *pfb = &batch->framebuffer;
385
386 OUT_PKT7(ring, CP_SET_VISIBILITY_OVERRIDE, 1);
387 OUT_RING(ring, 0x1);
388
389 OUT_PKT4(ring, REG_A5XX_RB_CNTL, 1);
390 OUT_RING(ring, A5XX_RB_CNTL_WIDTH(gmem->bin_w) |
391 A5XX_RB_CNTL_HEIGHT(gmem->bin_h));
392
393 patch_draws(batch, IGNORE_VISIBILITY);
394
395 emit_zs(ring, pfb->zsbuf, gmem);
396 emit_mrt(ring, pfb->nr_cbufs, pfb->cbufs, gmem);
397
398 // TODO MSAA
399 OUT_PKT4(ring, REG_A5XX_TPL1_TP_RAS_MSAA_CNTL, 2);
400 OUT_RING(ring, A5XX_TPL1_TP_RAS_MSAA_CNTL_SAMPLES(MSAA_ONE));
401 OUT_RING(ring, A5XX_TPL1_TP_DEST_MSAA_CNTL_SAMPLES(MSAA_ONE) |
402 A5XX_TPL1_TP_DEST_MSAA_CNTL_MSAA_DISABLE);
403
404 OUT_PKT4(ring, REG_A5XX_RB_RAS_MSAA_CNTL, 2);
405 OUT_RING(ring, A5XX_RB_RAS_MSAA_CNTL_SAMPLES(MSAA_ONE));
406 OUT_RING(ring, A5XX_RB_DEST_MSAA_CNTL_SAMPLES(MSAA_ONE) |
407 A5XX_RB_DEST_MSAA_CNTL_MSAA_DISABLE);
408
409 OUT_PKT4(ring, REG_A5XX_GRAS_SC_RAS_MSAA_CNTL, 2);
410 OUT_RING(ring, A5XX_GRAS_SC_RAS_MSAA_CNTL_SAMPLES(MSAA_ONE));
411 OUT_RING(ring, A5XX_GRAS_SC_DEST_MSAA_CNTL_SAMPLES(MSAA_ONE) |
412 A5XX_GRAS_SC_DEST_MSAA_CNTL_MSAA_DISABLE);
413 }
414
415
416 /*
417 * transfer from gmem to system memory (ie. normal RAM)
418 */
419
420 static void
421 emit_gmem2mem_surf(struct fd_batch *batch, uint32_t base,
422 struct pipe_surface *psurf, enum a5xx_blit_buf buf)
423 {
424 struct fd_ringbuffer *ring = batch->gmem;
425 struct fd_resource *rsc = fd_resource(psurf->texture);
426 struct fd_resource_slice *slice;
427 uint32_t offset;
428
429 slice = fd_resource_slice(rsc, psurf->u.tex.level);
430 offset = fd_resource_offset(rsc, psurf->u.tex.level,
431 psurf->u.tex.first_layer);
432
433 debug_assert(psurf->u.tex.first_layer == psurf->u.tex.last_layer);
434
435 OUT_PKT4(ring, REG_A5XX_RB_BLIT_FLAG_DST_LO, 4);
436 OUT_RING(ring, 0x00000000); /* RB_BLIT_FLAG_DST_LO */
437 OUT_RING(ring, 0x00000000); /* RB_BLIT_FLAG_DST_HI */
438 OUT_RING(ring, 0x00000000); /* RB_BLIT_FLAG_DST_PITCH */
439 OUT_RING(ring, 0x00000000); /* RB_BLIT_FLAG_DST_ARRAY_PITCH */
440
441 OUT_PKT4(ring, REG_A5XX_RB_RESOLVE_CNTL_3, 5);
442 OUT_RING(ring, 0x00000004); /* XXX RB_RESOLVE_CNTL_3 */
443 OUT_RELOCW(ring, rsc->bo, offset, 0, 0); /* RB_BLIT_DST_LO/HI */
444 OUT_RING(ring, A5XX_RB_BLIT_DST_PITCH(slice->pitch * rsc->cpp));
445 OUT_RING(ring, A5XX_RB_BLIT_DST_ARRAY_PITCH(slice->size0));
446
447 OUT_PKT4(ring, REG_A5XX_RB_BLIT_CNTL, 1);
448 OUT_RING(ring, A5XX_RB_BLIT_CNTL_BUF(buf));
449
450 fd5_emit_blit(batch->ctx, ring);
451 }
452
453 static void
454 fd5_emit_tile_gmem2mem(struct fd_batch *batch, struct fd_tile *tile)
455 {
456 struct fd_context *ctx = batch->ctx;
457 struct fd_gmem_stateobj *gmem = &ctx->gmem;
458 struct pipe_framebuffer_state *pfb = &batch->framebuffer;
459
460 if (batch->resolve & (FD_BUFFER_DEPTH | FD_BUFFER_STENCIL)) {
461 struct fd_resource *rsc = fd_resource(pfb->zsbuf->texture);
462 // XXX BLIT_ZS vs BLIT_Z32 .. need some more cmdstream traces
463 // with z32_x24s8..
464 if (!rsc->stencil || (batch->resolve & FD_BUFFER_DEPTH))
465 emit_gmem2mem_surf(batch, gmem->zsbuf_base[0], pfb->zsbuf, BLIT_ZS);
466 if (rsc->stencil && (batch->resolve & FD_BUFFER_STENCIL))
467 emit_gmem2mem_surf(batch, gmem->zsbuf_base[1], pfb->zsbuf, BLIT_ZS);
468 }
469
470 if (batch->resolve & FD_BUFFER_COLOR) {
471 unsigned i;
472 for (i = 0; i < pfb->nr_cbufs; i++) {
473 if (!pfb->cbufs[i])
474 continue;
475 if (!(batch->resolve & (PIPE_CLEAR_COLOR0 << i)))
476 continue;
477 emit_gmem2mem_surf(batch, gmem->cbuf_base[i],
478 pfb->cbufs[i], BLIT_MRT0 + i);
479 }
480 }
481 }
482
483 static void
484 fd5_emit_tile_fini(struct fd_batch *batch)
485 {
486 struct fd_ringbuffer *ring = batch->gmem;
487
488 OUT_PKT7(ring, CP_SKIP_IB2_ENABLE_GLOBAL, 1);
489 OUT_RING(ring, 0x0);
490
491 OUT_PKT7(ring, CP_EVENT_WRITE, 1);
492 OUT_RING(ring, UNK_26);
493
494 fd5_cache_flush(batch, ring);
495 fd5_set_render_mode(batch->ctx, ring, BYPASS);
496 }
497
498 static void
499 fd5_emit_sysmem_prep(struct fd_batch *batch)
500 {
501 struct pipe_framebuffer_state *pfb = &batch->framebuffer;
502 struct fd_ringbuffer *ring = batch->gmem;
503
504 fd5_emit_restore(batch, ring);
505
506 OUT_PKT7(ring, CP_EVENT_WRITE, 1);
507 OUT_RING(ring, UNK_26);
508
509 OUT_PKT7(ring, CP_SKIP_IB2_ENABLE_GLOBAL, 1);
510 OUT_RING(ring, 0x0);
511
512 OUT_PKT7(ring, CP_EVENT_WRITE, 1);
513 OUT_RING(ring, UNK_19);
514
515 OUT_PKT4(ring, REG_A5XX_PC_POWER_CNTL, 1);
516 OUT_RING(ring, 0x00000003); /* PC_POWER_CNTL */
517
518 OUT_PKT4(ring, REG_A5XX_VFD_POWER_CNTL, 1);
519 OUT_RING(ring, 0x00000003); /* VFD_POWER_CNTL */
520
521 /* 0x10000000 for BYPASS.. 0x7c13c080 for GMEM: */
522 fd_wfi(batch, ring);
523 OUT_PKT4(ring, REG_A5XX_RB_CCU_CNTL, 1);
524 OUT_RING(ring, 0x10000000); /* RB_CCU_CNTL */
525
526 OUT_PKT4(ring, REG_A5XX_GRAS_SC_WINDOW_SCISSOR_TL, 2);
527 OUT_RING(ring, A5XX_GRAS_SC_WINDOW_SCISSOR_TL_X(0) |
528 A5XX_GRAS_SC_WINDOW_SCISSOR_TL_Y(0));
529 OUT_RING(ring, A5XX_GRAS_SC_WINDOW_SCISSOR_BR_X(pfb->width - 1) |
530 A5XX_GRAS_SC_WINDOW_SCISSOR_BR_Y(pfb->height - 1));
531
532 OUT_PKT4(ring, REG_A5XX_RB_RESOLVE_CNTL_1, 2);
533 OUT_RING(ring, A5XX_RB_RESOLVE_CNTL_1_X(0) |
534 A5XX_RB_RESOLVE_CNTL_1_Y(0));
535 OUT_RING(ring, A5XX_RB_RESOLVE_CNTL_2_X(pfb->width - 1) |
536 A5XX_RB_RESOLVE_CNTL_2_Y(pfb->height - 1));
537
538 OUT_PKT4(ring, REG_A5XX_RB_WINDOW_OFFSET, 1);
539 OUT_RING(ring, A5XX_RB_WINDOW_OFFSET_X(0) |
540 A5XX_RB_WINDOW_OFFSET_Y(0));
541
542 OUT_PKT7(ring, CP_SET_VISIBILITY_OVERRIDE, 1);
543 OUT_RING(ring, 0x1);
544
545 OUT_PKT4(ring, REG_A5XX_RB_CNTL, 1);
546 OUT_RING(ring, A5XX_RB_CNTL_WIDTH(0) |
547 A5XX_RB_CNTL_HEIGHT(0) |
548 A5XX_RB_CNTL_BYPASS);
549
550 patch_draws(batch, IGNORE_VISIBILITY);
551
552 emit_zs(ring, pfb->zsbuf, NULL);
553 emit_mrt(ring, pfb->nr_cbufs, pfb->cbufs, NULL);
554
555 // TODO MSAA
556 OUT_PKT4(ring, REG_A5XX_TPL1_TP_RAS_MSAA_CNTL, 2);
557 OUT_RING(ring, A5XX_TPL1_TP_RAS_MSAA_CNTL_SAMPLES(MSAA_ONE));
558 OUT_RING(ring, A5XX_TPL1_TP_DEST_MSAA_CNTL_SAMPLES(MSAA_ONE) |
559 A5XX_TPL1_TP_DEST_MSAA_CNTL_MSAA_DISABLE);
560
561 OUT_PKT4(ring, REG_A5XX_RB_RAS_MSAA_CNTL, 2);
562 OUT_RING(ring, A5XX_RB_RAS_MSAA_CNTL_SAMPLES(MSAA_ONE));
563 OUT_RING(ring, A5XX_RB_DEST_MSAA_CNTL_SAMPLES(MSAA_ONE) |
564 A5XX_RB_DEST_MSAA_CNTL_MSAA_DISABLE);
565
566 OUT_PKT4(ring, REG_A5XX_GRAS_SC_RAS_MSAA_CNTL, 2);
567 OUT_RING(ring, A5XX_GRAS_SC_RAS_MSAA_CNTL_SAMPLES(MSAA_ONE));
568 OUT_RING(ring, A5XX_GRAS_SC_DEST_MSAA_CNTL_SAMPLES(MSAA_ONE) |
569 A5XX_GRAS_SC_DEST_MSAA_CNTL_MSAA_DISABLE);
570 }
571
572 static void
573 fd5_emit_sysmem_fini(struct fd_batch *batch)
574 {
575 struct fd5_context *fd5_ctx = fd5_context(batch->ctx);
576 struct fd_ringbuffer *ring = batch->gmem;
577
578 OUT_PKT7(ring, CP_SKIP_IB2_ENABLE_GLOBAL, 1);
579 OUT_RING(ring, 0x0);
580
581 OUT_PKT7(ring, CP_EVENT_WRITE, 1);
582 OUT_RING(ring, UNK_26);
583
584 OUT_PKT7(ring, CP_EVENT_WRITE, 4);
585 OUT_RING(ring, UNK_1D);
586 OUT_RELOCW(ring, fd5_ctx->blit_mem, 0, 0, 0); /* ADDR_LO/HI */
587 OUT_RING(ring, 0x00000000);
588 }
589
590 void
591 fd5_gmem_init(struct pipe_context *pctx)
592 {
593 struct fd_context *ctx = fd_context(pctx);
594
595 ctx->emit_tile_init = fd5_emit_tile_init;
596 ctx->emit_tile_prep = fd5_emit_tile_prep;
597 ctx->emit_tile_mem2gmem = fd5_emit_tile_mem2gmem;
598 ctx->emit_tile_renderprep = fd5_emit_tile_renderprep;
599 ctx->emit_tile_gmem2mem = fd5_emit_tile_gmem2mem;
600 ctx->emit_tile_fini = fd5_emit_tile_fini;
601 ctx->emit_sysmem_prep = fd5_emit_sysmem_prep;
602 ctx->emit_sysmem_fini = fd5_emit_sysmem_fini;
603 }