"Fossies" - the Fresh Open Source Software Archive

Member "mesa-20.1.8/src/gallium/drivers/freedreno/a5xx/fd5_gmem.c" (16 Sep 2020, 25822 Bytes) of package /linux/misc/mesa-20.1.8.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "fd5_gmem.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 20.1.5_vs_20.2.0-rc1.

    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/format/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, const struct fd_gmem_stateobj *gmem)
   48 {
   49     enum a5xx_tile_mode tile_mode;
   50     unsigned i;
   51 
   52     for (i = 0; i < A5XX_MAX_RENDER_TARGETS; i++) {
   53         enum a5xx_color_fmt format = 0;
   54         enum a3xx_color_swap swap = WZYX;
   55         bool srgb = false, sint = false, uint = false;
   56         struct fd_resource *rsc = NULL;
   57         struct fdl_slice *slice = NULL;
   58         uint32_t stride = 0;
   59         uint32_t size = 0;
   60         uint32_t base = 0;
   61         uint32_t offset = 0;
   62 
   63         if (gmem) {
   64             tile_mode = TILE5_2;
   65         } else {
   66             tile_mode = TILE5_LINEAR;
   67         }
   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             sint = util_format_is_pure_sint(pformat);
   80             uint = util_format_is_pure_uint(pformat);
   81 
   82             debug_assert(psurf->u.tex.first_layer == psurf->u.tex.last_layer);
   83 
   84             offset = fd_resource_offset(rsc, psurf->u.tex.level,
   85                     psurf->u.tex.first_layer);
   86 
   87             if (gmem) {
   88                 stride = gmem->bin_w * gmem->cbuf_cpp[i];
   89                 size = stride * gmem->bin_h;
   90                 base = gmem->cbuf_base[i];
   91             } else {
   92                 stride = slice->pitch;
   93                 size = slice->size0;
   94 
   95                 tile_mode = fd_resource_tile_mode(psurf->texture, psurf->u.tex.level);
   96             }
   97         }
   98 
   99         OUT_PKT4(ring, REG_A5XX_RB_MRT_BUF_INFO(i), 5);
  100         OUT_RING(ring, A5XX_RB_MRT_BUF_INFO_COLOR_FORMAT(format) |
  101                 A5XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE(tile_mode) |
  102                 A5XX_RB_MRT_BUF_INFO_COLOR_SWAP(swap) |
  103                 COND(gmem, 0x800) | /* XXX 0x1000 for RECTLIST clear, 0x0 for BLIT.. */
  104                 COND(srgb, A5XX_RB_MRT_BUF_INFO_COLOR_SRGB));
  105         OUT_RING(ring, A5XX_RB_MRT_PITCH(stride));
  106         OUT_RING(ring, A5XX_RB_MRT_ARRAY_PITCH(size));
  107         if (gmem || (i >= nr_bufs) || !bufs[i]) {
  108             OUT_RING(ring, base);           /* RB_MRT[i].BASE_LO */
  109             OUT_RING(ring, 0x00000000);     /* RB_MRT[i].BASE_HI */
  110         } else {
  111             debug_assert((offset + size) <= fd_bo_size(rsc->bo));
  112             OUT_RELOCW(ring, rsc->bo, offset, 0, 0);  /* BASE_LO/HI */
  113         }
  114 
  115         OUT_PKT4(ring, REG_A5XX_SP_FS_MRT_REG(i), 1);
  116         OUT_RING(ring, A5XX_SP_FS_MRT_REG_COLOR_FORMAT(format) |
  117                 COND(sint, A5XX_SP_FS_MRT_REG_COLOR_SINT) |
  118                 COND(uint, A5XX_SP_FS_MRT_REG_COLOR_UINT) |
  119                 COND(srgb, A5XX_SP_FS_MRT_REG_COLOR_SRGB));
  120 
  121         /* when we support UBWC, these would be the system memory
  122          * addr/pitch/etc:
  123          */
  124         OUT_PKT4(ring, REG_A5XX_RB_MRT_FLAG_BUFFER(i), 4);
  125         OUT_RING(ring, 0x00000000);    /* RB_MRT_FLAG_BUFFER[i].ADDR_LO */
  126         OUT_RING(ring, 0x00000000);    /* RB_MRT_FLAG_BUFFER[i].ADDR_HI */
  127         OUT_RING(ring, A5XX_RB_MRT_FLAG_BUFFER_PITCH(0));
  128         OUT_RING(ring, A5XX_RB_MRT_FLAG_BUFFER_ARRAY_PITCH(0));
  129     }
  130 }
  131 
  132 static void
  133 emit_zs(struct fd_ringbuffer *ring, struct pipe_surface *zsbuf,
  134         const struct fd_gmem_stateobj *gmem)
  135 {
  136     if (zsbuf) {
  137         struct fd_resource *rsc = fd_resource(zsbuf->texture);
  138         enum a5xx_depth_format fmt = fd5_pipe2depth(zsbuf->format);
  139         uint32_t cpp = rsc->layout.cpp;
  140         uint32_t stride = 0;
  141         uint32_t size = 0;
  142 
  143         if (gmem) {
  144             stride = cpp * gmem->bin_w;
  145             size = stride * gmem->bin_h;
  146         } else {
  147             struct fdl_slice *slice = fd_resource_slice(rsc, 0);
  148             stride = slice->pitch;
  149             size = slice->size0;
  150         }
  151 
  152         OUT_PKT4(ring, REG_A5XX_RB_DEPTH_BUFFER_INFO, 5);
  153         OUT_RING(ring, A5XX_RB_DEPTH_BUFFER_INFO_DEPTH_FORMAT(fmt));
  154         if (gmem) {
  155             OUT_RING(ring, gmem->zsbuf_base[0]); /* RB_DEPTH_BUFFER_BASE_LO */
  156             OUT_RING(ring, 0x00000000);          /* RB_DEPTH_BUFFER_BASE_HI */
  157         } else {
  158             OUT_RELOCW(ring, rsc->bo, 0, 0, 0);  /* RB_DEPTH_BUFFER_BASE_LO/HI */
  159         }
  160         OUT_RING(ring, A5XX_RB_DEPTH_BUFFER_PITCH(stride));
  161         OUT_RING(ring, A5XX_RB_DEPTH_BUFFER_ARRAY_PITCH(size));
  162 
  163         OUT_PKT4(ring, REG_A5XX_GRAS_SU_DEPTH_BUFFER_INFO, 1);
  164         OUT_RING(ring, A5XX_GRAS_SU_DEPTH_BUFFER_INFO_DEPTH_FORMAT(fmt));
  165 
  166         OUT_PKT4(ring, REG_A5XX_RB_DEPTH_FLAG_BUFFER_BASE_LO, 3);
  167         OUT_RING(ring, 0x00000000);    /* RB_DEPTH_FLAG_BUFFER_BASE_LO */
  168         OUT_RING(ring, 0x00000000);    /* RB_DEPTH_FLAG_BUFFER_BASE_HI */
  169         OUT_RING(ring, 0x00000000);    /* RB_DEPTH_FLAG_BUFFER_PITCH */
  170 
  171         if (rsc->lrz) {
  172             OUT_PKT4(ring, REG_A5XX_GRAS_LRZ_BUFFER_BASE_LO, 3);
  173             OUT_RELOCW(ring, rsc->lrz, 0x1000, 0, 0);
  174             OUT_RING(ring, A5XX_GRAS_LRZ_BUFFER_PITCH(rsc->lrz_pitch));
  175 
  176             OUT_PKT4(ring, REG_A5XX_GRAS_LRZ_FAST_CLEAR_BUFFER_BASE_LO, 2);
  177             OUT_RELOCW(ring, rsc->lrz, 0, 0, 0);
  178         } else {
  179             OUT_PKT4(ring, REG_A5XX_GRAS_LRZ_BUFFER_BASE_LO, 3);
  180             OUT_RING(ring, 0x00000000);
  181             OUT_RING(ring, 0x00000000);
  182             OUT_RING(ring, 0x00000000);     /* GRAS_LRZ_BUFFER_PITCH */
  183 
  184             OUT_PKT4(ring, REG_A5XX_GRAS_LRZ_FAST_CLEAR_BUFFER_BASE_LO, 2);
  185             OUT_RING(ring, 0x00000000);
  186             OUT_RING(ring, 0x00000000);
  187         }
  188 
  189         if (rsc->stencil) {
  190             if (gmem) {
  191                 stride = 1 * gmem->bin_w;
  192                 size = stride * gmem->bin_h;
  193             } else {
  194                 struct fdl_slice *slice = fd_resource_slice(rsc->stencil, 0);
  195                 stride = slice->pitch;
  196                 size = slice->size0;
  197             }
  198 
  199             OUT_PKT4(ring, REG_A5XX_RB_STENCIL_INFO, 5);
  200             OUT_RING(ring, A5XX_RB_STENCIL_INFO_SEPARATE_STENCIL);
  201             if (gmem) {
  202                 OUT_RING(ring, gmem->zsbuf_base[1]);  /* RB_STENCIL_BASE_LO */
  203                 OUT_RING(ring, 0x00000000);           /* RB_STENCIL_BASE_HI */
  204             } else {
  205                 OUT_RELOCW(ring, rsc->stencil->bo, 0, 0, 0);  /* RB_STENCIL_BASE_LO/HI */
  206             }
  207             OUT_RING(ring, A5XX_RB_STENCIL_PITCH(stride));
  208             OUT_RING(ring, A5XX_RB_STENCIL_ARRAY_PITCH(size));
  209         } else {
  210             OUT_PKT4(ring, REG_A5XX_RB_STENCIL_INFO, 1);
  211             OUT_RING(ring, 0x00000000);     /* RB_STENCIL_INFO */
  212         }
  213     } else {
  214         OUT_PKT4(ring, REG_A5XX_RB_DEPTH_BUFFER_INFO, 5);
  215         OUT_RING(ring, A5XX_RB_DEPTH_BUFFER_INFO_DEPTH_FORMAT(DEPTH5_NONE));
  216         OUT_RING(ring, 0x00000000);    /* RB_DEPTH_BUFFER_BASE_LO */
  217         OUT_RING(ring, 0x00000000);    /* RB_DEPTH_BUFFER_BASE_HI */
  218         OUT_RING(ring, 0x00000000);    /* RB_DEPTH_BUFFER_PITCH */
  219         OUT_RING(ring, 0x00000000);    /* RB_DEPTH_BUFFER_ARRAY_PITCH */
  220 
  221         OUT_PKT4(ring, REG_A5XX_GRAS_SU_DEPTH_BUFFER_INFO, 1);
  222         OUT_RING(ring, A5XX_GRAS_SU_DEPTH_BUFFER_INFO_DEPTH_FORMAT(DEPTH5_NONE));
  223 
  224         OUT_PKT4(ring, REG_A5XX_RB_DEPTH_FLAG_BUFFER_BASE_LO, 3);
  225         OUT_RING(ring, 0x00000000);    /* RB_DEPTH_FLAG_BUFFER_BASE_LO */
  226         OUT_RING(ring, 0x00000000);    /* RB_DEPTH_FLAG_BUFFER_BASE_HI */
  227         OUT_RING(ring, 0x00000000);    /* RB_DEPTH_FLAG_BUFFER_PITCH */
  228 
  229         OUT_PKT4(ring, REG_A5XX_RB_STENCIL_INFO, 1);
  230         OUT_RING(ring, 0x00000000);     /* RB_STENCIL_INFO */
  231     }
  232 }
  233 
  234 static bool
  235 use_hw_binning(struct fd_batch *batch)
  236 {
  237     const struct fd_gmem_stateobj *gmem = batch->gmem_state;
  238 
  239     if ((gmem->maxpw * gmem->maxph) > 32)
  240         return false;
  241 
  242     if ((gmem->maxpw > 15) || (gmem->maxph > 15))
  243         return false;
  244 
  245     return fd_binning_enabled && ((gmem->nbins_x * gmem->nbins_y) > 2) &&
  246             (batch->num_draws > 0);
  247 }
  248 
  249 static void
  250 patch_draws(struct fd_batch *batch, enum pc_di_vis_cull_mode vismode)
  251 {
  252     unsigned i;
  253     for (i = 0; i < fd_patch_num_elements(&batch->draw_patches); i++) {
  254         struct fd_cs_patch *patch = fd_patch_element(&batch->draw_patches, i);
  255         *patch->cs = patch->val | DRAW4(0, 0, 0, vismode);
  256     }
  257     util_dynarray_clear(&batch->draw_patches);
  258 }
  259 
  260 static void
  261 update_vsc_pipe(struct fd_batch *batch)
  262 {
  263     struct fd_context *ctx = batch->ctx;
  264     struct fd5_context *fd5_ctx = fd5_context(ctx);
  265     const struct fd_gmem_stateobj *gmem = batch->gmem_state;
  266     struct fd_ringbuffer *ring = batch->gmem;
  267     int i;
  268 
  269     OUT_PKT4(ring, REG_A5XX_VSC_BIN_SIZE, 3);
  270     OUT_RING(ring, A5XX_VSC_BIN_SIZE_WIDTH(gmem->bin_w) |
  271             A5XX_VSC_BIN_SIZE_HEIGHT(gmem->bin_h));
  272     OUT_RELOCW(ring, fd5_ctx->vsc_size_mem, 0, 0, 0); /* VSC_SIZE_ADDRESS_LO/HI */
  273 
  274     OUT_PKT4(ring, REG_A5XX_UNKNOWN_0BC5, 2);
  275     OUT_RING(ring, 0x00000000);   /* UNKNOWN_0BC5 */
  276     OUT_RING(ring, 0x00000000);   /* UNKNOWN_0BC6 */
  277 
  278     OUT_PKT4(ring, REG_A5XX_VSC_PIPE_CONFIG_REG(0), 16);
  279     for (i = 0; i < 16; i++) {
  280         const struct fd_vsc_pipe *pipe = &gmem->vsc_pipe[i];
  281         OUT_RING(ring, A5XX_VSC_PIPE_CONFIG_REG_X(pipe->x) |
  282                 A5XX_VSC_PIPE_CONFIG_REG_Y(pipe->y) |
  283                 A5XX_VSC_PIPE_CONFIG_REG_W(pipe->w) |
  284                 A5XX_VSC_PIPE_CONFIG_REG_H(pipe->h));
  285     }
  286 
  287     OUT_PKT4(ring, REG_A5XX_VSC_PIPE_DATA_ADDRESS_LO(0), 32);
  288     for (i = 0; i < 16; i++) {
  289         if (!ctx->vsc_pipe_bo[i]) {
  290             ctx->vsc_pipe_bo[i] = fd_bo_new(ctx->dev, 0x20000,
  291                     DRM_FREEDRENO_GEM_TYPE_KMEM, "vsc_pipe[%u]", i);
  292         }
  293         OUT_RELOCW(ring, ctx->vsc_pipe_bo[i], 0, 0, 0);     /* VSC_PIPE_DATA_ADDRESS[i].LO/HI */
  294     }
  295 
  296     OUT_PKT4(ring, REG_A5XX_VSC_PIPE_DATA_LENGTH_REG(0), 16);
  297     for (i = 0; i < 16; i++) {
  298         OUT_RING(ring, fd_bo_size(ctx->vsc_pipe_bo[i]) - 32); /* VSC_PIPE_DATA_LENGTH[i] */
  299     }
  300 }
  301 
  302 static void
  303 emit_binning_pass(struct fd_batch *batch)
  304 {
  305     struct fd_context *ctx = batch->ctx;
  306     struct fd_ringbuffer *ring = batch->gmem;
  307     const struct fd_gmem_stateobj *gmem = batch->gmem_state;
  308 
  309     uint32_t x1 = gmem->minx;
  310     uint32_t y1 = gmem->miny;
  311     uint32_t x2 = gmem->minx + gmem->width - 1;
  312     uint32_t y2 = gmem->miny + gmem->height - 1;
  313 
  314     fd5_set_render_mode(batch->ctx, ring, BINNING);
  315 
  316     OUT_PKT4(ring, REG_A5XX_RB_CNTL, 1);
  317     OUT_RING(ring, A5XX_RB_CNTL_WIDTH(gmem->bin_w) |
  318             A5XX_RB_CNTL_HEIGHT(gmem->bin_h));
  319 
  320     OUT_PKT4(ring, REG_A5XX_GRAS_SC_WINDOW_SCISSOR_TL, 2);
  321     OUT_RING(ring, A5XX_GRAS_SC_WINDOW_SCISSOR_TL_X(x1) |
  322             A5XX_GRAS_SC_WINDOW_SCISSOR_TL_Y(y1));
  323     OUT_RING(ring, A5XX_GRAS_SC_WINDOW_SCISSOR_BR_X(x2) |
  324             A5XX_GRAS_SC_WINDOW_SCISSOR_BR_Y(y2));
  325 
  326     OUT_PKT4(ring, REG_A5XX_RB_RESOLVE_CNTL_1, 2);
  327     OUT_RING(ring, A5XX_RB_RESOLVE_CNTL_1_X(x1) |
  328             A5XX_RB_RESOLVE_CNTL_1_Y(y1));
  329     OUT_RING(ring, A5XX_RB_RESOLVE_CNTL_2_X(x2) |
  330             A5XX_RB_RESOLVE_CNTL_2_Y(y2));
  331 
  332     update_vsc_pipe(batch);
  333 
  334     OUT_PKT4(ring, REG_A5XX_VPC_MODE_CNTL, 1);
  335     OUT_RING(ring, A5XX_VPC_MODE_CNTL_BINNING_PASS);
  336 
  337     OUT_PKT7(ring, CP_EVENT_WRITE, 1);
  338     OUT_RING(ring, UNK_2C);
  339 
  340     OUT_PKT4(ring, REG_A5XX_RB_WINDOW_OFFSET, 1);
  341     OUT_RING(ring, A5XX_RB_WINDOW_OFFSET_X(0) |
  342             A5XX_RB_WINDOW_OFFSET_Y(0));
  343 
  344     /* emit IB to binning drawcmds: */
  345     fd5_emit_ib(ring, batch->binning);
  346 
  347     fd_reset_wfi(batch);
  348 
  349     OUT_PKT7(ring, CP_EVENT_WRITE, 1);
  350     OUT_RING(ring, UNK_2D);
  351 
  352     OUT_PKT7(ring, CP_EVENT_WRITE, 4);
  353     OUT_RING(ring, CACHE_FLUSH_TS);
  354     OUT_RELOCW(ring, fd5_context(ctx)->blit_mem, 0, 0, 0);  /* ADDR_LO/HI */
  355     OUT_RING(ring, 0x00000000);
  356 
  357     // TODO CP_COND_WRITE's for all the vsc buffers (check for overflow??)
  358 
  359     fd_wfi(batch, ring);
  360 
  361     OUT_PKT4(ring, REG_A5XX_VPC_MODE_CNTL, 1);
  362     OUT_RING(ring, 0x0);
  363 }
  364 
  365 /* before first tile */
  366 static void
  367 fd5_emit_tile_init(struct fd_batch *batch)
  368 {
  369     struct fd_ringbuffer *ring = batch->gmem;
  370     struct pipe_framebuffer_state *pfb = &batch->framebuffer;
  371 
  372     fd5_emit_restore(batch, ring);
  373 
  374     if (batch->lrz_clear)
  375         fd5_emit_ib(ring, batch->lrz_clear);
  376 
  377     fd5_emit_lrz_flush(ring);
  378 
  379     OUT_PKT4(ring, REG_A5XX_GRAS_CL_CNTL, 1);
  380     OUT_RING(ring, 0x00000080);   /* GRAS_CL_CNTL */
  381 
  382     OUT_PKT7(ring, CP_SKIP_IB2_ENABLE_GLOBAL, 1);
  383     OUT_RING(ring, 0x0);
  384 
  385     OUT_PKT4(ring, REG_A5XX_PC_POWER_CNTL, 1);
  386     OUT_RING(ring, 0x00000003);   /* PC_POWER_CNTL */
  387 
  388     OUT_PKT4(ring, REG_A5XX_VFD_POWER_CNTL, 1);
  389     OUT_RING(ring, 0x00000003);   /* VFD_POWER_CNTL */
  390 
  391     /* 0x10000000 for BYPASS.. 0x7c13c080 for GMEM: */
  392     fd_wfi(batch, ring);
  393     OUT_PKT4(ring, REG_A5XX_RB_CCU_CNTL, 1);
  394     OUT_RING(ring, 0x7c13c080);   /* RB_CCU_CNTL */
  395 
  396     emit_zs(ring, pfb->zsbuf, batch->gmem_state);
  397     emit_mrt(ring, pfb->nr_cbufs, pfb->cbufs, batch->gmem_state);
  398 
  399     if (use_hw_binning(batch)) {
  400         emit_binning_pass(batch);
  401         fd5_emit_lrz_flush(ring);
  402         patch_draws(batch, USE_VISIBILITY);
  403     } else {
  404         patch_draws(batch, IGNORE_VISIBILITY);
  405     }
  406 
  407     fd5_set_render_mode(batch->ctx, ring, GMEM);
  408 }
  409 
  410 /* before mem2gmem */
  411 static void
  412 fd5_emit_tile_prep(struct fd_batch *batch, const struct fd_tile *tile)
  413 {
  414     struct fd_context *ctx = batch->ctx;
  415     const struct fd_gmem_stateobj *gmem = batch->gmem_state;
  416     struct fd5_context *fd5_ctx = fd5_context(ctx);
  417     struct fd_ringbuffer *ring = batch->gmem;
  418 
  419     uint32_t x1 = tile->xoff;
  420     uint32_t y1 = tile->yoff;
  421     uint32_t x2 = tile->xoff + tile->bin_w - 1;
  422     uint32_t y2 = tile->yoff + tile->bin_h - 1;
  423 
  424     OUT_PKT4(ring, REG_A5XX_GRAS_SC_WINDOW_SCISSOR_TL, 2);
  425     OUT_RING(ring, A5XX_GRAS_SC_WINDOW_SCISSOR_TL_X(x1) |
  426             A5XX_GRAS_SC_WINDOW_SCISSOR_TL_Y(y1));
  427     OUT_RING(ring, A5XX_GRAS_SC_WINDOW_SCISSOR_BR_X(x2) |
  428             A5XX_GRAS_SC_WINDOW_SCISSOR_BR_Y(y2));
  429 
  430     OUT_PKT4(ring, REG_A5XX_RB_RESOLVE_CNTL_1, 2);
  431     OUT_RING(ring, A5XX_RB_RESOLVE_CNTL_1_X(x1) |
  432             A5XX_RB_RESOLVE_CNTL_1_Y(y1));
  433     OUT_RING(ring, A5XX_RB_RESOLVE_CNTL_2_X(x2) |
  434             A5XX_RB_RESOLVE_CNTL_2_Y(y2));
  435 
  436     if (use_hw_binning(batch)) {
  437         const struct fd_vsc_pipe *pipe = &gmem->vsc_pipe[tile->p];
  438         struct fd_bo *pipe_bo = ctx->vsc_pipe_bo[tile->p];
  439 
  440         OUT_PKT7(ring, CP_WAIT_FOR_ME, 0);
  441 
  442         OUT_PKT7(ring, CP_SET_VISIBILITY_OVERRIDE, 1);
  443         OUT_RING(ring, 0x0);
  444 
  445         OUT_PKT7(ring, CP_SET_BIN_DATA5, 5);
  446         OUT_RING(ring, CP_SET_BIN_DATA5_0_VSC_SIZE(pipe->w * pipe->h) |
  447                 CP_SET_BIN_DATA5_0_VSC_N(tile->n));
  448         OUT_RELOC(ring, pipe_bo, 0, 0, 0);       /* VSC_PIPE[p].DATA_ADDRESS */
  449         OUT_RELOC(ring, fd5_ctx->vsc_size_mem,   /* VSC_SIZE_ADDRESS + (p * 4) */
  450                 (tile->p * 4), 0, 0);
  451     } else {
  452         OUT_PKT7(ring, CP_SET_VISIBILITY_OVERRIDE, 1);
  453         OUT_RING(ring, 0x1);
  454     }
  455 
  456     OUT_PKT4(ring, REG_A5XX_RB_WINDOW_OFFSET, 1);
  457     OUT_RING(ring, A5XX_RB_WINDOW_OFFSET_X(x1) |
  458             A5XX_RB_WINDOW_OFFSET_Y(y1));
  459 }
  460 
  461 
  462 /*
  463  * transfer from system memory to gmem
  464  */
  465 
  466 static void
  467 emit_mem2gmem_surf(struct fd_batch *batch, uint32_t base,
  468         struct pipe_surface *psurf, enum a5xx_blit_buf buf)
  469 {
  470     struct fd_ringbuffer *ring = batch->gmem;
  471     const struct fd_gmem_stateobj *gmem = batch->gmem_state;
  472     struct fd_resource *rsc = fd_resource(psurf->texture);
  473     uint32_t stride, size;
  474 
  475     debug_assert(psurf->u.tex.first_layer == psurf->u.tex.last_layer);
  476 
  477     if (buf == BLIT_S)
  478         rsc = rsc->stencil;
  479 
  480     if ((buf == BLIT_ZS) || (buf == BLIT_S)) {
  481         // XXX hack import via BLIT_MRT0 instead of BLIT_ZS, since I don't
  482         // know otherwise how to go from linear in sysmem to tiled in gmem.
  483         // possibly we want to flip this around gmem2mem and keep depth
  484         // tiled in sysmem (and fixup sampler state to assume tiled).. this
  485         // might be required for doing depth/stencil in bypass mode?
  486         struct fdl_slice *slice = fd_resource_slice(rsc, 0);
  487         enum a5xx_color_fmt format =
  488             fd5_pipe2color(fd_gmem_restore_format(rsc->base.format));
  489 
  490         OUT_PKT4(ring, REG_A5XX_RB_MRT_BUF_INFO(0), 5);
  491         OUT_RING(ring, A5XX_RB_MRT_BUF_INFO_COLOR_FORMAT(format) |
  492                 A5XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE(rsc->layout.tile_mode) |
  493                 A5XX_RB_MRT_BUF_INFO_COLOR_SWAP(WZYX));
  494         OUT_RING(ring, A5XX_RB_MRT_PITCH(slice->pitch));
  495         OUT_RING(ring, A5XX_RB_MRT_ARRAY_PITCH(slice->size0));
  496         OUT_RELOC(ring, rsc->bo, 0, 0, 0);  /* BASE_LO/HI */
  497 
  498         buf = BLIT_MRT0;
  499     }
  500 
  501     stride = gmem->bin_w << fdl_cpp_shift(&rsc->layout);
  502     size = stride * gmem->bin_h;
  503 
  504     OUT_PKT4(ring, REG_A5XX_RB_BLIT_FLAG_DST_LO, 4);
  505     OUT_RING(ring, 0x00000000);   /* RB_BLIT_FLAG_DST_LO */
  506     OUT_RING(ring, 0x00000000);   /* RB_BLIT_FLAG_DST_HI */
  507     OUT_RING(ring, 0x00000000);   /* RB_BLIT_FLAG_DST_PITCH */
  508     OUT_RING(ring, 0x00000000);   /* RB_BLIT_FLAG_DST_ARRAY_PITCH */
  509 
  510     OUT_PKT4(ring, REG_A5XX_RB_RESOLVE_CNTL_3, 5);
  511     OUT_RING(ring, 0x00000000);   /* RB_RESOLVE_CNTL_3 */
  512     OUT_RING(ring, base);         /* RB_BLIT_DST_LO */
  513     OUT_RING(ring, 0x00000000);   /* RB_BLIT_DST_HI */
  514     OUT_RING(ring, A5XX_RB_BLIT_DST_PITCH(stride));
  515     OUT_RING(ring, A5XX_RB_BLIT_DST_ARRAY_PITCH(size));
  516 
  517     OUT_PKT4(ring, REG_A5XX_RB_BLIT_CNTL, 1);
  518     OUT_RING(ring, A5XX_RB_BLIT_CNTL_BUF(buf));
  519 
  520     fd5_emit_blit(batch->ctx, ring);
  521 }
  522 
  523 static void
  524 fd5_emit_tile_mem2gmem(struct fd_batch *batch, const struct fd_tile *tile)
  525 {
  526     struct fd_ringbuffer *ring = batch->gmem;
  527     const struct fd_gmem_stateobj *gmem = batch->gmem_state;
  528     struct pipe_framebuffer_state *pfb = &batch->framebuffer;
  529 
  530     /*
  531      * setup mrt and zs with system memory base addresses:
  532      */
  533 
  534     emit_mrt(ring, pfb->nr_cbufs, pfb->cbufs, NULL);
  535 //  emit_zs(ring, pfb->zsbuf, NULL);
  536 
  537     OUT_PKT4(ring, REG_A5XX_RB_CNTL, 1);
  538     OUT_RING(ring, A5XX_RB_CNTL_WIDTH(gmem->bin_w) |
  539             A5XX_RB_CNTL_HEIGHT(gmem->bin_h) |
  540             A5XX_RB_CNTL_BYPASS);
  541 
  542     if (fd_gmem_needs_restore(batch, tile, FD_BUFFER_COLOR)) {
  543         unsigned i;
  544         for (i = 0; i < pfb->nr_cbufs; i++) {
  545             if (!pfb->cbufs[i])
  546                 continue;
  547             if (!(batch->restore & (PIPE_CLEAR_COLOR0 << i)))
  548                 continue;
  549             emit_mem2gmem_surf(batch, gmem->cbuf_base[i],
  550                     pfb->cbufs[i], BLIT_MRT0 + i);
  551         }
  552     }
  553 
  554     if (fd_gmem_needs_restore(batch, tile, FD_BUFFER_DEPTH | FD_BUFFER_STENCIL)) {
  555         struct fd_resource *rsc = fd_resource(pfb->zsbuf->texture);
  556 
  557         if (!rsc->stencil || fd_gmem_needs_restore(batch, tile, FD_BUFFER_DEPTH))
  558             emit_mem2gmem_surf(batch, gmem->zsbuf_base[0], pfb->zsbuf, BLIT_ZS);
  559         if (rsc->stencil && fd_gmem_needs_restore(batch, tile, FD_BUFFER_STENCIL))
  560             emit_mem2gmem_surf(batch, gmem->zsbuf_base[1], pfb->zsbuf, BLIT_S);
  561     }
  562 }
  563 
  564 
  565 /* before IB to rendering cmds: */
  566 static void
  567 fd5_emit_tile_renderprep(struct fd_batch *batch, const struct fd_tile *tile)
  568 {
  569     struct fd_ringbuffer *ring = batch->gmem;
  570     const struct fd_gmem_stateobj *gmem = batch->gmem_state;
  571     struct pipe_framebuffer_state *pfb = &batch->framebuffer;
  572 
  573     OUT_PKT4(ring, REG_A5XX_RB_CNTL, 1);
  574     OUT_RING(ring, A5XX_RB_CNTL_WIDTH(gmem->bin_w) |
  575             A5XX_RB_CNTL_HEIGHT(gmem->bin_h));
  576 
  577     emit_zs(ring, pfb->zsbuf, gmem);
  578     emit_mrt(ring, pfb->nr_cbufs, pfb->cbufs, gmem);
  579 
  580     enum a3xx_msaa_samples samples = fd_msaa_samples(pfb->samples);
  581 
  582     OUT_PKT4(ring, REG_A5XX_TPL1_TP_RAS_MSAA_CNTL, 2);
  583     OUT_RING(ring, A5XX_TPL1_TP_RAS_MSAA_CNTL_SAMPLES(samples));
  584     OUT_RING(ring, A5XX_TPL1_TP_DEST_MSAA_CNTL_SAMPLES(samples) |
  585             COND(samples == MSAA_ONE, A5XX_TPL1_TP_DEST_MSAA_CNTL_MSAA_DISABLE));
  586 
  587     OUT_PKT4(ring, REG_A5XX_RB_RAS_MSAA_CNTL, 2);
  588     OUT_RING(ring, A5XX_RB_RAS_MSAA_CNTL_SAMPLES(samples));
  589     OUT_RING(ring, A5XX_RB_DEST_MSAA_CNTL_SAMPLES(samples) |
  590             COND(samples == MSAA_ONE, A5XX_RB_DEST_MSAA_CNTL_MSAA_DISABLE));
  591 
  592 
  593     OUT_PKT4(ring, REG_A5XX_GRAS_SC_RAS_MSAA_CNTL, 2);
  594     OUT_RING(ring, A5XX_GRAS_SC_RAS_MSAA_CNTL_SAMPLES(samples));
  595     OUT_RING(ring, A5XX_GRAS_SC_DEST_MSAA_CNTL_SAMPLES(samples) |
  596             COND(samples == MSAA_ONE, A5XX_GRAS_SC_DEST_MSAA_CNTL_MSAA_DISABLE));
  597 }
  598 
  599 
  600 /*
  601  * transfer from gmem to system memory (ie. normal RAM)
  602  */
  603 
  604 static void
  605 emit_gmem2mem_surf(struct fd_batch *batch, uint32_t base,
  606         struct pipe_surface *psurf, enum a5xx_blit_buf buf)
  607 {
  608     struct fd_ringbuffer *ring = batch->gmem;
  609     struct fd_resource *rsc = fd_resource(psurf->texture);
  610     struct fdl_slice *slice;
  611     bool tiled;
  612     uint32_t offset;
  613 
  614     if (!rsc->valid)
  615         return;
  616 
  617     if (buf == BLIT_S)
  618         rsc = rsc->stencil;
  619 
  620     slice = fd_resource_slice(rsc, psurf->u.tex.level);
  621     offset = fd_resource_offset(rsc, psurf->u.tex.level,
  622             psurf->u.tex.first_layer);
  623 
  624     debug_assert(psurf->u.tex.first_layer == psurf->u.tex.last_layer);
  625 
  626     OUT_PKT4(ring, REG_A5XX_RB_BLIT_FLAG_DST_LO, 4);
  627     OUT_RING(ring, 0x00000000);   /* RB_BLIT_FLAG_DST_LO */
  628     OUT_RING(ring, 0x00000000);   /* RB_BLIT_FLAG_DST_HI */
  629     OUT_RING(ring, 0x00000000);   /* RB_BLIT_FLAG_DST_PITCH */
  630     OUT_RING(ring, 0x00000000);   /* RB_BLIT_FLAG_DST_ARRAY_PITCH */
  631 
  632     tiled = fd_resource_tile_mode(psurf->texture, psurf->u.tex.level);
  633 
  634     OUT_PKT4(ring, REG_A5XX_RB_RESOLVE_CNTL_3, 5);
  635     OUT_RING(ring, 0x00000004 |   /* XXX RB_RESOLVE_CNTL_3 */
  636             COND(tiled, A5XX_RB_RESOLVE_CNTL_3_TILED));
  637     OUT_RELOCW(ring, rsc->bo, offset, 0, 0);     /* RB_BLIT_DST_LO/HI */
  638     OUT_RING(ring, A5XX_RB_BLIT_DST_PITCH(slice->pitch));
  639     OUT_RING(ring, A5XX_RB_BLIT_DST_ARRAY_PITCH(slice->size0));
  640 
  641     OUT_PKT4(ring, REG_A5XX_RB_BLIT_CNTL, 1);
  642     OUT_RING(ring, A5XX_RB_BLIT_CNTL_BUF(buf));
  643 
  644 //  bool msaa_resolve = pfb->samples > 1;
  645     bool msaa_resolve = false;
  646     OUT_PKT4(ring, REG_A5XX_RB_CLEAR_CNTL, 1);
  647     OUT_RING(ring, COND(msaa_resolve, A5XX_RB_CLEAR_CNTL_MSAA_RESOLVE));
  648 
  649     fd5_emit_blit(batch->ctx, ring);
  650 }
  651 
  652 static void
  653 fd5_emit_tile_gmem2mem(struct fd_batch *batch, const struct fd_tile *tile)
  654 {
  655     const struct fd_gmem_stateobj *gmem = batch->gmem_state;
  656     struct pipe_framebuffer_state *pfb = &batch->framebuffer;
  657 
  658     if (batch->resolve & (FD_BUFFER_DEPTH | FD_BUFFER_STENCIL)) {
  659         struct fd_resource *rsc = fd_resource(pfb->zsbuf->texture);
  660 
  661         if (!rsc->stencil || (batch->resolve & FD_BUFFER_DEPTH))
  662             emit_gmem2mem_surf(batch, gmem->zsbuf_base[0], pfb->zsbuf, BLIT_ZS);
  663         if (rsc->stencil && (batch->resolve & FD_BUFFER_STENCIL))
  664             emit_gmem2mem_surf(batch, gmem->zsbuf_base[1], pfb->zsbuf, BLIT_S);
  665     }
  666 
  667     if (batch->resolve & FD_BUFFER_COLOR) {
  668         unsigned i;
  669         for (i = 0; i < pfb->nr_cbufs; i++) {
  670             if (!pfb->cbufs[i])
  671                 continue;
  672             if (!(batch->resolve & (PIPE_CLEAR_COLOR0 << i)))
  673                 continue;
  674             emit_gmem2mem_surf(batch, gmem->cbuf_base[i],
  675                     pfb->cbufs[i], BLIT_MRT0 + i);
  676         }
  677     }
  678 }
  679 
  680 static void
  681 fd5_emit_tile_fini(struct fd_batch *batch)
  682 {
  683     struct fd_ringbuffer *ring = batch->gmem;
  684 
  685     OUT_PKT7(ring, CP_SKIP_IB2_ENABLE_GLOBAL, 1);
  686     OUT_RING(ring, 0x0);
  687 
  688     fd5_emit_lrz_flush(ring);
  689 
  690     fd5_cache_flush(batch, ring);
  691     fd5_set_render_mode(batch->ctx, ring, BYPASS);
  692 }
  693 
  694 static void
  695 fd5_emit_sysmem_prep(struct fd_batch *batch)
  696 {
  697     struct pipe_framebuffer_state *pfb = &batch->framebuffer;
  698     struct fd_ringbuffer *ring = batch->gmem;
  699 
  700     fd5_emit_restore(batch, ring);
  701 
  702     fd5_emit_lrz_flush(ring);
  703 
  704     OUT_PKT7(ring, CP_SKIP_IB2_ENABLE_GLOBAL, 1);
  705     OUT_RING(ring, 0x0);
  706 
  707     OUT_PKT7(ring, CP_EVENT_WRITE, 1);
  708     OUT_RING(ring, PC_CCU_INVALIDATE_COLOR);
  709 
  710     OUT_PKT4(ring, REG_A5XX_PC_POWER_CNTL, 1);
  711     OUT_RING(ring, 0x00000003);   /* PC_POWER_CNTL */
  712 
  713     OUT_PKT4(ring, REG_A5XX_VFD_POWER_CNTL, 1);
  714     OUT_RING(ring, 0x00000003);   /* VFD_POWER_CNTL */
  715 
  716     /* 0x10000000 for BYPASS.. 0x7c13c080 for GMEM: */
  717     fd_wfi(batch, ring);
  718     OUT_PKT4(ring, REG_A5XX_RB_CCU_CNTL, 1);
  719     OUT_RING(ring, 0x10000000);   /* RB_CCU_CNTL */
  720 
  721     OUT_PKT4(ring, REG_A5XX_GRAS_SC_WINDOW_SCISSOR_TL, 2);
  722     OUT_RING(ring, A5XX_GRAS_SC_WINDOW_SCISSOR_TL_X(0) |
  723             A5XX_GRAS_SC_WINDOW_SCISSOR_TL_Y(0));
  724     OUT_RING(ring, A5XX_GRAS_SC_WINDOW_SCISSOR_BR_X(pfb->width - 1) |
  725             A5XX_GRAS_SC_WINDOW_SCISSOR_BR_Y(pfb->height - 1));
  726 
  727     OUT_PKT4(ring, REG_A5XX_RB_RESOLVE_CNTL_1, 2);
  728     OUT_RING(ring, A5XX_RB_RESOLVE_CNTL_1_X(0) |
  729             A5XX_RB_RESOLVE_CNTL_1_Y(0));
  730     OUT_RING(ring, A5XX_RB_RESOLVE_CNTL_2_X(pfb->width - 1) |
  731             A5XX_RB_RESOLVE_CNTL_2_Y(pfb->height - 1));
  732 
  733     OUT_PKT4(ring, REG_A5XX_RB_WINDOW_OFFSET, 1);
  734     OUT_RING(ring, A5XX_RB_WINDOW_OFFSET_X(0) |
  735             A5XX_RB_WINDOW_OFFSET_Y(0));
  736 
  737     OUT_PKT7(ring, CP_SET_VISIBILITY_OVERRIDE, 1);
  738     OUT_RING(ring, 0x1);
  739 
  740     OUT_PKT4(ring, REG_A5XX_RB_CNTL, 1);
  741     OUT_RING(ring, A5XX_RB_CNTL_WIDTH(0) |
  742             A5XX_RB_CNTL_HEIGHT(0) |
  743             A5XX_RB_CNTL_BYPASS);
  744 
  745     patch_draws(batch, IGNORE_VISIBILITY);
  746 
  747     emit_zs(ring, pfb->zsbuf, NULL);
  748     emit_mrt(ring, pfb->nr_cbufs, pfb->cbufs, NULL);
  749 
  750     OUT_PKT4(ring, REG_A5XX_TPL1_TP_RAS_MSAA_CNTL, 2);
  751     OUT_RING(ring, A5XX_TPL1_TP_RAS_MSAA_CNTL_SAMPLES(MSAA_ONE));
  752     OUT_RING(ring, A5XX_TPL1_TP_DEST_MSAA_CNTL_SAMPLES(MSAA_ONE) |
  753             A5XX_TPL1_TP_DEST_MSAA_CNTL_MSAA_DISABLE);
  754 
  755     OUT_PKT4(ring, REG_A5XX_RB_RAS_MSAA_CNTL, 2);
  756     OUT_RING(ring, A5XX_RB_RAS_MSAA_CNTL_SAMPLES(MSAA_ONE));
  757     OUT_RING(ring, A5XX_RB_DEST_MSAA_CNTL_SAMPLES(MSAA_ONE) |
  758             A5XX_RB_DEST_MSAA_CNTL_MSAA_DISABLE);
  759 
  760     OUT_PKT4(ring, REG_A5XX_GRAS_SC_RAS_MSAA_CNTL, 2);
  761     OUT_RING(ring, A5XX_GRAS_SC_RAS_MSAA_CNTL_SAMPLES(MSAA_ONE));
  762     OUT_RING(ring, A5XX_GRAS_SC_DEST_MSAA_CNTL_SAMPLES(MSAA_ONE) |
  763             A5XX_GRAS_SC_DEST_MSAA_CNTL_MSAA_DISABLE);
  764 }
  765 
  766 static void
  767 fd5_emit_sysmem_fini(struct fd_batch *batch)
  768 {
  769     struct fd5_context *fd5_ctx = fd5_context(batch->ctx);
  770     struct fd_ringbuffer *ring = batch->gmem;
  771 
  772     OUT_PKT7(ring, CP_SKIP_IB2_ENABLE_GLOBAL, 1);
  773     OUT_RING(ring, 0x0);
  774 
  775     fd5_emit_lrz_flush(ring);
  776 
  777     OUT_PKT7(ring, CP_EVENT_WRITE, 4);
  778     OUT_RING(ring, PC_CCU_FLUSH_COLOR_TS);
  779     OUT_RELOCW(ring, fd5_ctx->blit_mem, 0, 0, 0);  /* ADDR_LO/HI */
  780     OUT_RING(ring, 0x00000000);
  781 }
  782 
  783 void
  784 fd5_gmem_init(struct pipe_context *pctx)
  785 {
  786     struct fd_context *ctx = fd_context(pctx);
  787 
  788     ctx->emit_tile_init = fd5_emit_tile_init;
  789     ctx->emit_tile_prep = fd5_emit_tile_prep;
  790     ctx->emit_tile_mem2gmem = fd5_emit_tile_mem2gmem;
  791     ctx->emit_tile_renderprep = fd5_emit_tile_renderprep;
  792     ctx->emit_tile_gmem2mem = fd5_emit_tile_gmem2mem;
  793     ctx->emit_tile_fini = fd5_emit_tile_fini;
  794     ctx->emit_sysmem_prep = fd5_emit_sysmem_prep;
  795     ctx->emit_sysmem_fini = fd5_emit_sysmem_fini;
  796 }