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