Home | History | Annotate | Download | only in a5xx
      1 /*
      2  * Copyright (C) 2016 Rob Clark <robclark (at) 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 (at) 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 }
    604