Path: blob/21.2-virgl/src/gallium/drivers/freedreno/a4xx/fd4_gmem.c
4574 views
/*1* Copyright (C) 2014 Rob Clark <[email protected]>2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,19* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE20* SOFTWARE.21*22* Authors:23* Rob Clark <[email protected]>24*/2526#include "pipe/p_state.h"27#include "util/format/u_format.h"28#include "util/u_inlines.h"29#include "util/u_memory.h"30#include "util/u_string.h"3132#include "freedreno_draw.h"33#include "freedreno_resource.h"34#include "freedreno_state.h"3536#include "fd4_context.h"37#include "fd4_draw.h"38#include "fd4_emit.h"39#include "fd4_format.h"40#include "fd4_gmem.h"41#include "fd4_program.h"42#include "fd4_zsa.h"4344static void45fd4_gmem_emit_set_prog(struct fd_context *ctx, struct fd4_emit *emit,46struct fd_program_stateobj *prog)47{48emit->skip_consts = true;49emit->key.vs = prog->vs;50emit->key.fs = prog->fs;51emit->prog = fd4_program_state(52ir3_cache_lookup(ctx->shader_cache, &emit->key, &ctx->debug));53/* reset the fd4_emit_get_*p cache */54emit->vs = NULL;55emit->fs = NULL;56}5758static void59emit_mrt(struct fd_ringbuffer *ring, unsigned nr_bufs,60struct pipe_surface **bufs, const uint32_t *bases, uint32_t bin_w,61bool decode_srgb)62{63enum a4xx_tile_mode tile_mode;64unsigned i;6566if (bin_w) {67tile_mode = 2;68} else {69tile_mode = TILE4_LINEAR;70}7172for (i = 0; i < A4XX_MAX_RENDER_TARGETS; i++) {73enum a4xx_color_fmt format = 0;74enum a3xx_color_swap swap = WZYX;75bool srgb = false;76struct fd_resource *rsc = NULL;77uint32_t stride = 0;78uint32_t base = 0;79uint32_t offset = 0;8081if ((i < nr_bufs) && bufs[i]) {82struct pipe_surface *psurf = bufs[i];83enum pipe_format pformat = psurf->format;8485rsc = fd_resource(psurf->texture);8687/* In case we're drawing to Z32F_S8, the "color" actually goes to88* the stencil89*/90if (rsc->stencil) {91rsc = rsc->stencil;92pformat = rsc->b.b.format;93if (bases)94bases++;95}9697format = fd4_pipe2color(pformat);98swap = fd4_pipe2swap(pformat);99100if (decode_srgb)101srgb = util_format_is_srgb(pformat);102else103pformat = util_format_linear(pformat);104105debug_assert(psurf->u.tex.first_layer == psurf->u.tex.last_layer);106107offset = fd_resource_offset(rsc, psurf->u.tex.level,108psurf->u.tex.first_layer);109110if (bin_w) {111stride = bin_w << fdl_cpp_shift(&rsc->layout);112113if (bases) {114base = bases[i];115}116} else {117stride = fd_resource_pitch(rsc, psurf->u.tex.level);118}119} else if ((i < nr_bufs) && bases) {120base = bases[i];121}122123OUT_PKT0(ring, REG_A4XX_RB_MRT_BUF_INFO(i), 3);124OUT_RING(ring, A4XX_RB_MRT_BUF_INFO_COLOR_FORMAT(format) |125A4XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE(tile_mode) |126A4XX_RB_MRT_BUF_INFO_COLOR_BUF_PITCH(stride) |127A4XX_RB_MRT_BUF_INFO_COLOR_SWAP(swap) |128COND(srgb, A4XX_RB_MRT_BUF_INFO_COLOR_SRGB));129if (bin_w || (i >= nr_bufs) || !bufs[i]) {130OUT_RING(ring, base);131OUT_RING(ring, A4XX_RB_MRT_CONTROL3_STRIDE(stride));132} else {133OUT_RELOC(ring, rsc->bo, offset, 0, 0);134/* RB_MRT[i].CONTROL3.STRIDE not emitted by c2d..135* not sure if we need to skip it for bypass or136* not.137*/138OUT_RING(ring, A4XX_RB_MRT_CONTROL3_STRIDE(0));139}140}141}142143static bool144use_hw_binning(struct fd_batch *batch)145{146const struct fd_gmem_stateobj *gmem = batch->gmem_state;147148if ((gmem->maxpw * gmem->maxph) > 32)149return false;150151if ((gmem->maxpw > 15) || (gmem->maxph > 15))152return false;153154return fd_binning_enabled && ((gmem->nbins_x * gmem->nbins_y) > 2);155}156157/* transfer from gmem to system memory (ie. normal RAM) */158159static void160emit_gmem2mem_surf(struct fd_batch *batch, bool stencil, uint32_t base,161struct pipe_surface *psurf)162{163struct fd_ringbuffer *ring = batch->gmem;164struct fd_resource *rsc = fd_resource(psurf->texture);165enum pipe_format pformat = psurf->format;166uint32_t offset, pitch;167168if (!rsc->valid)169return;170171if (stencil) {172debug_assert(rsc->stencil);173rsc = rsc->stencil;174pformat = rsc->b.b.format;175}176177offset =178fd_resource_offset(rsc, psurf->u.tex.level, psurf->u.tex.first_layer);179pitch = fd_resource_pitch(rsc, psurf->u.tex.level);180181debug_assert(psurf->u.tex.first_layer == psurf->u.tex.last_layer);182183OUT_PKT0(ring, REG_A4XX_RB_COPY_CONTROL, 4);184OUT_RING(ring, A4XX_RB_COPY_CONTROL_MSAA_RESOLVE(MSAA_ONE) |185A4XX_RB_COPY_CONTROL_MODE(RB_COPY_RESOLVE) |186A4XX_RB_COPY_CONTROL_GMEM_BASE(base));187OUT_RELOC(ring, rsc->bo, offset, 0, 0); /* RB_COPY_DEST_BASE */188OUT_RING(ring, A4XX_RB_COPY_DEST_PITCH_PITCH(pitch));189OUT_RING(ring, A4XX_RB_COPY_DEST_INFO_TILE(TILE4_LINEAR) |190A4XX_RB_COPY_DEST_INFO_FORMAT(fd4_pipe2color(pformat)) |191A4XX_RB_COPY_DEST_INFO_COMPONENT_ENABLE(0xf) |192A4XX_RB_COPY_DEST_INFO_ENDIAN(ENDIAN_NONE) |193A4XX_RB_COPY_DEST_INFO_SWAP(fd4_pipe2swap(pformat)));194195fd4_draw(batch, ring, DI_PT_RECTLIST, IGNORE_VISIBILITY,196DI_SRC_SEL_AUTO_INDEX, 2, 1, INDEX4_SIZE_8_BIT, 0, 0, NULL);197}198199static void200fd4_emit_tile_gmem2mem(struct fd_batch *batch,201const struct fd_tile *tile) assert_dt202{203struct fd_context *ctx = batch->ctx;204const struct fd_gmem_stateobj *gmem = batch->gmem_state;205struct fd_ringbuffer *ring = batch->gmem;206struct pipe_framebuffer_state *pfb = &batch->framebuffer;207struct fd4_emit emit = {208.debug = &ctx->debug,209.vtx = &ctx->solid_vbuf_state,210};211fd4_gmem_emit_set_prog(ctx, &emit, &ctx->solid_prog);212213OUT_PKT0(ring, REG_A4XX_RB_DEPTH_CONTROL, 1);214OUT_RING(ring, A4XX_RB_DEPTH_CONTROL_ZFUNC(FUNC_NEVER));215216OUT_PKT0(ring, REG_A4XX_RB_STENCIL_CONTROL, 2);217OUT_RING(ring, A4XX_RB_STENCIL_CONTROL_FUNC(FUNC_NEVER) |218A4XX_RB_STENCIL_CONTROL_FAIL(STENCIL_KEEP) |219A4XX_RB_STENCIL_CONTROL_ZPASS(STENCIL_KEEP) |220A4XX_RB_STENCIL_CONTROL_ZFAIL(STENCIL_KEEP) |221A4XX_RB_STENCIL_CONTROL_FUNC_BF(FUNC_NEVER) |222A4XX_RB_STENCIL_CONTROL_FAIL_BF(STENCIL_KEEP) |223A4XX_RB_STENCIL_CONTROL_ZPASS_BF(STENCIL_KEEP) |224A4XX_RB_STENCIL_CONTROL_ZFAIL_BF(STENCIL_KEEP));225OUT_RING(ring, 0x00000000); /* RB_STENCIL_CONTROL2 */226227OUT_PKT0(ring, REG_A4XX_RB_STENCILREFMASK, 2);228OUT_RING(ring, 0xff000000 | A4XX_RB_STENCILREFMASK_STENCILREF(0) |229A4XX_RB_STENCILREFMASK_STENCILMASK(0) |230A4XX_RB_STENCILREFMASK_STENCILWRITEMASK(0xff));231OUT_RING(ring, 0xff000000 | A4XX_RB_STENCILREFMASK_BF_STENCILREF(0) |232A4XX_RB_STENCILREFMASK_BF_STENCILMASK(0) |233A4XX_RB_STENCILREFMASK_BF_STENCILWRITEMASK(0xff));234235OUT_PKT0(ring, REG_A4XX_GRAS_SU_MODE_CONTROL, 1);236OUT_RING(ring, A4XX_GRAS_SU_MODE_CONTROL_LINEHALFWIDTH(0));237238fd_wfi(batch, ring);239240OUT_PKT0(ring, REG_A4XX_GRAS_CL_CLIP_CNTL, 1);241OUT_RING(ring, 0x80000); /* GRAS_CL_CLIP_CNTL */242243OUT_PKT0(ring, REG_A4XX_GRAS_CL_VPORT_XOFFSET_0, 6);244OUT_RING(ring, A4XX_GRAS_CL_VPORT_XOFFSET_0((float)pfb->width / 2.0));245OUT_RING(ring, A4XX_GRAS_CL_VPORT_XSCALE_0((float)pfb->width / 2.0));246OUT_RING(ring, A4XX_GRAS_CL_VPORT_YOFFSET_0((float)pfb->height / 2.0));247OUT_RING(ring, A4XX_GRAS_CL_VPORT_YSCALE_0(-(float)pfb->height / 2.0));248OUT_RING(ring, A4XX_GRAS_CL_VPORT_ZOFFSET_0(0.0));249OUT_RING(ring, A4XX_GRAS_CL_VPORT_ZSCALE_0(1.0));250251OUT_PKT0(ring, REG_A4XX_RB_RENDER_CONTROL, 1);252OUT_RING(ring, A4XX_RB_RENDER_CONTROL_DISABLE_COLOR_PIPE | 0xa); /* XXX */253254OUT_PKT0(ring, REG_A4XX_GRAS_SC_CONTROL, 1);255OUT_RING(ring, A4XX_GRAS_SC_CONTROL_RENDER_MODE(RB_RESOLVE_PASS) |256A4XX_GRAS_SC_CONTROL_MSAA_DISABLE |257A4XX_GRAS_SC_CONTROL_MSAA_SAMPLES(MSAA_ONE) |258A4XX_GRAS_SC_CONTROL_RASTER_MODE(1));259260OUT_PKT0(ring, REG_A4XX_PC_PRIM_VTX_CNTL, 1);261OUT_RING(ring, A4XX_PC_PRIM_VTX_CNTL_PROVOKING_VTX_LAST);262263OUT_PKT0(ring, REG_A4XX_GRAS_ALPHA_CONTROL, 1);264OUT_RING(ring, 0x00000002);265266OUT_PKT0(ring, REG_A4XX_GRAS_SC_WINDOW_SCISSOR_BR, 2);267OUT_RING(ring, A4XX_GRAS_SC_WINDOW_SCISSOR_BR_X(pfb->width - 1) |268A4XX_GRAS_SC_WINDOW_SCISSOR_BR_Y(pfb->height - 1));269OUT_RING(ring, A4XX_GRAS_SC_WINDOW_SCISSOR_TL_X(0) |270A4XX_GRAS_SC_WINDOW_SCISSOR_TL_Y(0));271272OUT_PKT0(ring, REG_A4XX_VFD_INDEX_OFFSET, 2);273OUT_RING(ring, 0); /* VFD_INDEX_OFFSET */274OUT_RING(ring, 0); /* ??? UNKNOWN_2209 */275276fd4_program_emit(ring, &emit, 0, NULL);277fd4_emit_vertex_bufs(ring, &emit);278279if (batch->resolve & (FD_BUFFER_DEPTH | FD_BUFFER_STENCIL)) {280struct fd_resource *rsc = fd_resource(pfb->zsbuf->texture);281if (!rsc->stencil || (batch->resolve & FD_BUFFER_DEPTH))282emit_gmem2mem_surf(batch, false, gmem->zsbuf_base[0], pfb->zsbuf);283if (rsc->stencil && (batch->resolve & FD_BUFFER_STENCIL))284emit_gmem2mem_surf(batch, true, gmem->zsbuf_base[1], pfb->zsbuf);285}286287if (batch->resolve & FD_BUFFER_COLOR) {288unsigned i;289for (i = 0; i < pfb->nr_cbufs; i++) {290if (!pfb->cbufs[i])291continue;292if (!(batch->resolve & (PIPE_CLEAR_COLOR0 << i)))293continue;294emit_gmem2mem_surf(batch, false, gmem->cbuf_base[i], pfb->cbufs[i]);295}296}297298OUT_PKT0(ring, REG_A4XX_GRAS_SC_CONTROL, 1);299OUT_RING(ring, A4XX_GRAS_SC_CONTROL_RENDER_MODE(RB_RENDERING_PASS) |300A4XX_GRAS_SC_CONTROL_MSAA_DISABLE |301A4XX_GRAS_SC_CONTROL_MSAA_SAMPLES(MSAA_ONE) |302A4XX_GRAS_SC_CONTROL_RASTER_MODE(0));303}304305/* transfer from system memory to gmem */306307static void308emit_mem2gmem_surf(struct fd_batch *batch, const uint32_t *bases,309struct pipe_surface **bufs, uint32_t nr_bufs, uint32_t bin_w)310{311struct fd_ringbuffer *ring = batch->gmem;312struct pipe_surface *zsbufs[2];313314emit_mrt(ring, nr_bufs, bufs, bases, bin_w, false);315316if (bufs[0] && (bufs[0]->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT)) {317/* The gmem_restore_tex logic will put the first buffer's stencil318* as color. Supply it with the proper information to make that319* happen.320*/321zsbufs[0] = zsbufs[1] = bufs[0];322bufs = zsbufs;323nr_bufs = 2;324}325326fd4_emit_gmem_restore_tex(ring, nr_bufs, bufs);327328fd4_draw(batch, ring, DI_PT_RECTLIST, IGNORE_VISIBILITY,329DI_SRC_SEL_AUTO_INDEX, 2, 1, INDEX4_SIZE_8_BIT, 0, 0, NULL);330}331332static void333fd4_emit_tile_mem2gmem(struct fd_batch *batch,334const struct fd_tile *tile) assert_dt335{336struct fd_context *ctx = batch->ctx;337const struct fd_gmem_stateobj *gmem = batch->gmem_state;338struct fd_ringbuffer *ring = batch->gmem;339struct pipe_framebuffer_state *pfb = &batch->framebuffer;340struct fd4_emit emit = {341.debug = &ctx->debug,342.vtx = &ctx->blit_vbuf_state,343.sprite_coord_enable = 1,344.no_decode_srgb = true,345};346/* NOTE: They all use the same VP, this is for vtx bufs. */347fd4_gmem_emit_set_prog(ctx, &emit, &ctx->blit_prog[0]);348349unsigned char mrt_comp[A4XX_MAX_RENDER_TARGETS] = {0};350float x0, y0, x1, y1;351unsigned bin_w = tile->bin_w;352unsigned bin_h = tile->bin_h;353unsigned i;354355/* write texture coordinates to vertexbuf: */356x0 = ((float)tile->xoff) / ((float)pfb->width);357x1 = ((float)tile->xoff + bin_w) / ((float)pfb->width);358y0 = ((float)tile->yoff) / ((float)pfb->height);359y1 = ((float)tile->yoff + bin_h) / ((float)pfb->height);360361OUT_PKT3(ring, CP_MEM_WRITE, 5);362OUT_RELOC(ring, fd_resource(ctx->blit_texcoord_vbuf)->bo, 0, 0, 0);363OUT_RING(ring, fui(x0));364OUT_RING(ring, fui(y0));365OUT_RING(ring, fui(x1));366OUT_RING(ring, fui(y1));367368for (i = 0; i < A4XX_MAX_RENDER_TARGETS; i++) {369mrt_comp[i] = ((i < pfb->nr_cbufs) && pfb->cbufs[i]) ? 0xf : 0;370371OUT_PKT0(ring, REG_A4XX_RB_MRT_CONTROL(i), 1);372OUT_RING(ring, A4XX_RB_MRT_CONTROL_ROP_CODE(ROP_COPY) |373A4XX_RB_MRT_CONTROL_COMPONENT_ENABLE(0xf));374375OUT_PKT0(ring, REG_A4XX_RB_MRT_BLEND_CONTROL(i), 1);376OUT_RING(377ring,378A4XX_RB_MRT_BLEND_CONTROL_RGB_SRC_FACTOR(FACTOR_ONE) |379A4XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE(BLEND_DST_PLUS_SRC) |380A4XX_RB_MRT_BLEND_CONTROL_RGB_DEST_FACTOR(FACTOR_ZERO) |381A4XX_RB_MRT_BLEND_CONTROL_ALPHA_SRC_FACTOR(FACTOR_ONE) |382A4XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE(BLEND_DST_PLUS_SRC) |383A4XX_RB_MRT_BLEND_CONTROL_ALPHA_DEST_FACTOR(FACTOR_ZERO));384}385386OUT_PKT0(ring, REG_A4XX_RB_RENDER_COMPONENTS, 1);387OUT_RING(ring, A4XX_RB_RENDER_COMPONENTS_RT0(mrt_comp[0]) |388A4XX_RB_RENDER_COMPONENTS_RT1(mrt_comp[1]) |389A4XX_RB_RENDER_COMPONENTS_RT2(mrt_comp[2]) |390A4XX_RB_RENDER_COMPONENTS_RT3(mrt_comp[3]) |391A4XX_RB_RENDER_COMPONENTS_RT4(mrt_comp[4]) |392A4XX_RB_RENDER_COMPONENTS_RT5(mrt_comp[5]) |393A4XX_RB_RENDER_COMPONENTS_RT6(mrt_comp[6]) |394A4XX_RB_RENDER_COMPONENTS_RT7(mrt_comp[7]));395396OUT_PKT0(ring, REG_A4XX_RB_RENDER_CONTROL, 1);397OUT_RING(ring, 0x8); /* XXX RB_RENDER_CONTROL */398399OUT_PKT0(ring, REG_A4XX_RB_DEPTH_CONTROL, 1);400OUT_RING(ring, A4XX_RB_DEPTH_CONTROL_ZFUNC(FUNC_LESS));401402OUT_PKT0(ring, REG_A4XX_GRAS_CL_CLIP_CNTL, 1);403OUT_RING(ring, 0x280000); /* XXX GRAS_CL_CLIP_CNTL */404405OUT_PKT0(ring, REG_A4XX_GRAS_SU_MODE_CONTROL, 1);406OUT_RING(ring, A4XX_GRAS_SU_MODE_CONTROL_LINEHALFWIDTH(0) |407A4XX_GRAS_SU_MODE_CONTROL_RENDERING_PASS);408409OUT_PKT0(ring, REG_A4XX_GRAS_CL_VPORT_XOFFSET_0, 6);410OUT_RING(ring, A4XX_GRAS_CL_VPORT_XOFFSET_0((float)bin_w / 2.0));411OUT_RING(ring, A4XX_GRAS_CL_VPORT_XSCALE_0((float)bin_w / 2.0));412OUT_RING(ring, A4XX_GRAS_CL_VPORT_YOFFSET_0((float)bin_h / 2.0));413OUT_RING(ring, A4XX_GRAS_CL_VPORT_YSCALE_0(-(float)bin_h / 2.0));414OUT_RING(ring, A4XX_GRAS_CL_VPORT_ZOFFSET_0(0.0));415OUT_RING(ring, A4XX_GRAS_CL_VPORT_ZSCALE_0(1.0));416417OUT_PKT0(ring, REG_A4XX_GRAS_SC_WINDOW_SCISSOR_BR, 2);418OUT_RING(ring, A4XX_GRAS_SC_WINDOW_SCISSOR_BR_X(bin_w - 1) |419A4XX_GRAS_SC_WINDOW_SCISSOR_BR_Y(bin_h - 1));420OUT_RING(ring, A4XX_GRAS_SC_WINDOW_SCISSOR_TL_X(0) |421A4XX_GRAS_SC_WINDOW_SCISSOR_TL_Y(0));422423OUT_PKT0(ring, REG_A4XX_GRAS_SC_SCREEN_SCISSOR_TL, 2);424OUT_RING(ring, A4XX_GRAS_SC_SCREEN_SCISSOR_TL_X(0) |425A4XX_GRAS_SC_SCREEN_SCISSOR_TL_Y(0));426OUT_RING(ring, A4XX_GRAS_SC_SCREEN_SCISSOR_BR_X(bin_w - 1) |427A4XX_GRAS_SC_SCREEN_SCISSOR_BR_Y(bin_h - 1));428429OUT_PKT0(ring, REG_A4XX_RB_MODE_CONTROL, 1);430OUT_RING(ring, A4XX_RB_MODE_CONTROL_WIDTH(gmem->bin_w) |431A4XX_RB_MODE_CONTROL_HEIGHT(gmem->bin_h));432433OUT_PKT0(ring, REG_A4XX_RB_STENCIL_CONTROL, 2);434OUT_RING(ring, A4XX_RB_STENCIL_CONTROL_FUNC(FUNC_ALWAYS) |435A4XX_RB_STENCIL_CONTROL_FAIL(STENCIL_KEEP) |436A4XX_RB_STENCIL_CONTROL_ZPASS(STENCIL_KEEP) |437A4XX_RB_STENCIL_CONTROL_ZFAIL(STENCIL_KEEP) |438A4XX_RB_STENCIL_CONTROL_FUNC_BF(FUNC_ALWAYS) |439A4XX_RB_STENCIL_CONTROL_FAIL_BF(STENCIL_KEEP) |440A4XX_RB_STENCIL_CONTROL_ZPASS_BF(STENCIL_KEEP) |441A4XX_RB_STENCIL_CONTROL_ZFAIL_BF(STENCIL_KEEP));442OUT_RING(ring, 0x00000000); /* RB_STENCIL_CONTROL2 */443444OUT_PKT0(ring, REG_A4XX_GRAS_SC_CONTROL, 1);445OUT_RING(ring, A4XX_GRAS_SC_CONTROL_RENDER_MODE(RB_RENDERING_PASS) |446A4XX_GRAS_SC_CONTROL_MSAA_DISABLE |447A4XX_GRAS_SC_CONTROL_MSAA_SAMPLES(MSAA_ONE) |448A4XX_GRAS_SC_CONTROL_RASTER_MODE(1));449450OUT_PKT0(ring, REG_A4XX_PC_PRIM_VTX_CNTL, 1);451OUT_RING(ring, A4XX_PC_PRIM_VTX_CNTL_PROVOKING_VTX_LAST |452A4XX_PC_PRIM_VTX_CNTL_VAROUT(1));453454OUT_PKT0(ring, REG_A4XX_VFD_INDEX_OFFSET, 2);455OUT_RING(ring, 0); /* VFD_INDEX_OFFSET */456OUT_RING(ring, 0); /* ??? UNKNOWN_2209 */457458fd4_emit_vertex_bufs(ring, &emit);459460/* for gmem pitch/base calculations, we need to use the non-461* truncated tile sizes:462*/463bin_w = gmem->bin_w;464bin_h = gmem->bin_h;465466if (fd_gmem_needs_restore(batch, tile, FD_BUFFER_COLOR)) {467fd4_gmem_emit_set_prog(ctx, &emit, &ctx->blit_prog[pfb->nr_cbufs - 1]);468fd4_program_emit(ring, &emit, pfb->nr_cbufs, pfb->cbufs);469emit_mem2gmem_surf(batch, gmem->cbuf_base, pfb->cbufs, pfb->nr_cbufs,470bin_w);471}472473if (fd_gmem_needs_restore(batch, tile,474FD_BUFFER_DEPTH | FD_BUFFER_STENCIL)) {475switch (pfb->zsbuf->format) {476case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:477case PIPE_FORMAT_Z32_FLOAT:478if (pfb->zsbuf->format == PIPE_FORMAT_Z32_FLOAT)479fd4_gmem_emit_set_prog(ctx, &emit, &ctx->blit_z);480else481fd4_gmem_emit_set_prog(ctx, &emit, &ctx->blit_zs);482483OUT_PKT0(ring, REG_A4XX_RB_DEPTH_CONTROL, 1);484OUT_RING(ring, A4XX_RB_DEPTH_CONTROL_Z_ENABLE |485A4XX_RB_DEPTH_CONTROL_Z_WRITE_ENABLE |486A4XX_RB_DEPTH_CONTROL_ZFUNC(FUNC_ALWAYS) |487A4XX_RB_DEPTH_CONTROL_EARLY_Z_DISABLE);488489OUT_PKT0(ring, REG_A4XX_GRAS_ALPHA_CONTROL, 1);490OUT_RING(ring, A4XX_GRAS_ALPHA_CONTROL_ALPHA_TEST_ENABLE);491492OUT_PKT0(ring, REG_A4XX_GRAS_CL_CLIP_CNTL, 1);493OUT_RING(ring, 0x80000); /* GRAS_CL_CLIP_CNTL */494495break;496default:497/* Non-float can use a regular color write. It's split over 8-bit498* components, so half precision is always sufficient.499*/500fd4_gmem_emit_set_prog(ctx, &emit, &ctx->blit_prog[0]);501break;502}503fd4_program_emit(ring, &emit, 1, &pfb->zsbuf);504emit_mem2gmem_surf(batch, gmem->zsbuf_base, &pfb->zsbuf, 1, bin_w);505}506507OUT_PKT0(ring, REG_A4XX_GRAS_SC_CONTROL, 1);508OUT_RING(ring, A4XX_GRAS_SC_CONTROL_RENDER_MODE(RB_RENDERING_PASS) |509A4XX_GRAS_SC_CONTROL_MSAA_SAMPLES(MSAA_ONE) |510A4XX_GRAS_SC_CONTROL_RASTER_MODE(0));511512OUT_PKT0(ring, REG_A4XX_RB_MODE_CONTROL, 1);513OUT_RING(ring, A4XX_RB_MODE_CONTROL_WIDTH(gmem->bin_w) |514A4XX_RB_MODE_CONTROL_HEIGHT(gmem->bin_h) |5150x00010000); /* XXX */516}517518static void519patch_draws(struct fd_batch *batch, enum pc_di_vis_cull_mode vismode)520{521unsigned i;522for (i = 0; i < fd_patch_num_elements(&batch->draw_patches); i++) {523struct fd_cs_patch *patch = fd_patch_element(&batch->draw_patches, i);524*patch->cs = patch->val | DRAW4(0, 0, 0, vismode);525}526util_dynarray_clear(&batch->draw_patches);527}528529/* for rendering directly to system memory: */530static void531fd4_emit_sysmem_prep(struct fd_batch *batch) assert_dt532{533struct pipe_framebuffer_state *pfb = &batch->framebuffer;534struct fd_ringbuffer *ring = batch->gmem;535536fd4_emit_restore(batch, ring);537538OUT_PKT0(ring, REG_A4XX_RB_FRAME_BUFFER_DIMENSION, 1);539OUT_RING(ring, A4XX_RB_FRAME_BUFFER_DIMENSION_WIDTH(pfb->width) |540A4XX_RB_FRAME_BUFFER_DIMENSION_HEIGHT(pfb->height));541542emit_mrt(ring, pfb->nr_cbufs, pfb->cbufs, NULL, 0, true);543544/* setup scissor/offset for current tile: */545OUT_PKT0(ring, REG_A4XX_RB_BIN_OFFSET, 1);546OUT_RING(ring, A4XX_RB_BIN_OFFSET_X(0) | A4XX_RB_BIN_OFFSET_Y(0));547548OUT_PKT0(ring, REG_A4XX_GRAS_SC_SCREEN_SCISSOR_TL, 2);549OUT_RING(ring, A4XX_GRAS_SC_SCREEN_SCISSOR_TL_X(0) |550A4XX_GRAS_SC_SCREEN_SCISSOR_TL_Y(0));551OUT_RING(ring, A4XX_GRAS_SC_SCREEN_SCISSOR_BR_X(pfb->width - 1) |552A4XX_GRAS_SC_SCREEN_SCISSOR_BR_Y(pfb->height - 1));553554OUT_PKT0(ring, REG_A4XX_RB_MODE_CONTROL, 1);555OUT_RING(ring, A4XX_RB_MODE_CONTROL_WIDTH(0) |556A4XX_RB_MODE_CONTROL_HEIGHT(0) | 0x00c00000); /* XXX */557558OUT_PKT0(ring, REG_A4XX_RB_RENDER_CONTROL, 1);559OUT_RING(ring, 0x8);560561patch_draws(batch, IGNORE_VISIBILITY);562}563564static void565update_vsc_pipe(struct fd_batch *batch) assert_dt566{567struct fd_context *ctx = batch->ctx;568const struct fd_gmem_stateobj *gmem = batch->gmem_state;569struct fd4_context *fd4_ctx = fd4_context(ctx);570struct fd_ringbuffer *ring = batch->gmem;571int i;572573OUT_PKT0(ring, REG_A4XX_VSC_SIZE_ADDRESS, 1);574OUT_RELOC(ring, fd4_ctx->vsc_size_mem, 0, 0, 0); /* VSC_SIZE_ADDRESS */575576OUT_PKT0(ring, REG_A4XX_VSC_PIPE_CONFIG_REG(0), 8);577for (i = 0; i < 8; i++) {578const struct fd_vsc_pipe *pipe = &gmem->vsc_pipe[i];579OUT_RING(ring, A4XX_VSC_PIPE_CONFIG_REG_X(pipe->x) |580A4XX_VSC_PIPE_CONFIG_REG_Y(pipe->y) |581A4XX_VSC_PIPE_CONFIG_REG_W(pipe->w) |582A4XX_VSC_PIPE_CONFIG_REG_H(pipe->h));583}584585OUT_PKT0(ring, REG_A4XX_VSC_PIPE_DATA_ADDRESS_REG(0), 8);586for (i = 0; i < 8; i++) {587if (!ctx->vsc_pipe_bo[i]) {588ctx->vsc_pipe_bo[i] = fd_bo_new(589ctx->dev, 0x40000, 0, "vsc_pipe[%u]", i);590}591OUT_RELOC(ring, ctx->vsc_pipe_bo[i], 0, 0,5920); /* VSC_PIPE_DATA_ADDRESS[i] */593}594595OUT_PKT0(ring, REG_A4XX_VSC_PIPE_DATA_LENGTH_REG(0), 8);596for (i = 0; i < 8; i++) {597OUT_RING(ring, fd_bo_size(ctx->vsc_pipe_bo[i]) -59832); /* VSC_PIPE_DATA_LENGTH[i] */599}600}601602static void603emit_binning_pass(struct fd_batch *batch) assert_dt604{605const struct fd_gmem_stateobj *gmem = batch->gmem_state;606struct pipe_framebuffer_state *pfb = &batch->framebuffer;607struct fd_ringbuffer *ring = batch->gmem;608int i;609610uint32_t x1 = gmem->minx;611uint32_t y1 = gmem->miny;612uint32_t x2 = gmem->minx + gmem->width - 1;613uint32_t y2 = gmem->miny + gmem->height - 1;614615OUT_PKT0(ring, REG_A4XX_PC_BINNING_COMMAND, 1);616OUT_RING(ring, A4XX_PC_BINNING_COMMAND_BINNING_ENABLE);617618OUT_PKT0(ring, REG_A4XX_GRAS_SC_CONTROL, 1);619OUT_RING(ring, A4XX_GRAS_SC_CONTROL_RENDER_MODE(RB_TILING_PASS) |620A4XX_GRAS_SC_CONTROL_MSAA_DISABLE |621A4XX_GRAS_SC_CONTROL_MSAA_SAMPLES(MSAA_ONE) |622A4XX_GRAS_SC_CONTROL_RASTER_MODE(0));623624OUT_PKT0(ring, REG_A4XX_RB_FRAME_BUFFER_DIMENSION, 1);625OUT_RING(ring, A4XX_RB_FRAME_BUFFER_DIMENSION_WIDTH(pfb->width) |626A4XX_RB_FRAME_BUFFER_DIMENSION_HEIGHT(pfb->height));627628/* setup scissor/offset for whole screen: */629OUT_PKT0(ring, REG_A4XX_RB_BIN_OFFSET, 1);630OUT_RING(ring, A4XX_RB_BIN_OFFSET_X(x1) | A4XX_RB_BIN_OFFSET_Y(y1));631632OUT_PKT0(ring, REG_A4XX_GRAS_SC_SCREEN_SCISSOR_TL, 2);633OUT_RING(ring, A4XX_GRAS_SC_SCREEN_SCISSOR_TL_X(x1) |634A4XX_GRAS_SC_SCREEN_SCISSOR_TL_Y(y1));635OUT_RING(ring, A4XX_GRAS_SC_SCREEN_SCISSOR_BR_X(x2) |636A4XX_GRAS_SC_SCREEN_SCISSOR_BR_Y(y2));637638for (i = 0; i < A4XX_MAX_RENDER_TARGETS; i++) {639OUT_PKT0(ring, REG_A4XX_RB_MRT_CONTROL(i), 1);640OUT_RING(ring, A4XX_RB_MRT_CONTROL_ROP_CODE(ROP_CLEAR) |641A4XX_RB_MRT_CONTROL_COMPONENT_ENABLE(0xf));642}643644/* emit IB to binning drawcmds: */645fd4_emit_ib(ring, batch->binning);646647fd_reset_wfi(batch);648fd_wfi(batch, ring);649650/* and then put stuff back the way it was: */651652OUT_PKT0(ring, REG_A4XX_PC_BINNING_COMMAND, 1);653OUT_RING(ring, 0x00000000);654655OUT_PKT0(ring, REG_A4XX_GRAS_SC_CONTROL, 1);656OUT_RING(ring, A4XX_GRAS_SC_CONTROL_RENDER_MODE(RB_RENDERING_PASS) |657A4XX_GRAS_SC_CONTROL_MSAA_DISABLE |658A4XX_GRAS_SC_CONTROL_MSAA_SAMPLES(MSAA_ONE) |659A4XX_GRAS_SC_CONTROL_RASTER_MODE(0));660661fd_event_write(batch, ring, CACHE_FLUSH);662fd_wfi(batch, ring);663}664665/* before first tile */666static void667fd4_emit_tile_init(struct fd_batch *batch) assert_dt668{669struct fd_ringbuffer *ring = batch->gmem;670struct pipe_framebuffer_state *pfb = &batch->framebuffer;671const struct fd_gmem_stateobj *gmem = batch->gmem_state;672673fd4_emit_restore(batch, ring);674675OUT_PKT0(ring, REG_A4XX_VSC_BIN_SIZE, 1);676OUT_RING(ring, A4XX_VSC_BIN_SIZE_WIDTH(gmem->bin_w) |677A4XX_VSC_BIN_SIZE_HEIGHT(gmem->bin_h));678679update_vsc_pipe(batch);680681fd_wfi(batch, ring);682OUT_PKT0(ring, REG_A4XX_RB_FRAME_BUFFER_DIMENSION, 1);683OUT_RING(ring, A4XX_RB_FRAME_BUFFER_DIMENSION_WIDTH(pfb->width) |684A4XX_RB_FRAME_BUFFER_DIMENSION_HEIGHT(pfb->height));685686if (use_hw_binning(batch)) {687OUT_PKT0(ring, REG_A4XX_RB_MODE_CONTROL, 1);688OUT_RING(ring, A4XX_RB_MODE_CONTROL_WIDTH(gmem->bin_w) |689A4XX_RB_MODE_CONTROL_HEIGHT(gmem->bin_h));690691OUT_PKT0(ring, REG_A4XX_RB_RENDER_CONTROL, 1);692OUT_RING(ring, A4XX_RB_RENDER_CONTROL_BINNING_PASS |693A4XX_RB_RENDER_CONTROL_DISABLE_COLOR_PIPE | 0x8);694695/* emit hw binning pass: */696emit_binning_pass(batch);697698patch_draws(batch, USE_VISIBILITY);699} else {700patch_draws(batch, IGNORE_VISIBILITY);701}702703OUT_PKT0(ring, REG_A4XX_RB_MODE_CONTROL, 1);704OUT_RING(ring, A4XX_RB_MODE_CONTROL_WIDTH(gmem->bin_w) |705A4XX_RB_MODE_CONTROL_HEIGHT(gmem->bin_h) |706A4XX_RB_MODE_CONTROL_ENABLE_GMEM);707}708709/* before mem2gmem */710static void711fd4_emit_tile_prep(struct fd_batch *batch, const struct fd_tile *tile)712{713struct fd_ringbuffer *ring = batch->gmem;714struct pipe_framebuffer_state *pfb = &batch->framebuffer;715const struct fd_gmem_stateobj *gmem = batch->gmem_state;716717if (pfb->zsbuf) {718struct fd_resource *rsc = fd_resource(pfb->zsbuf->texture);719uint32_t cpp = rsc->layout.cpp;720721OUT_PKT0(ring, REG_A4XX_RB_DEPTH_INFO, 3);722OUT_RING(ring, A4XX_RB_DEPTH_INFO_DEPTH_BASE(gmem->zsbuf_base[0]) |723A4XX_RB_DEPTH_INFO_DEPTH_FORMAT(724fd4_pipe2depth(pfb->zsbuf->format)));725OUT_RING(ring, A4XX_RB_DEPTH_PITCH(cpp * gmem->bin_w));726OUT_RING(ring, A4XX_RB_DEPTH_PITCH2(cpp * gmem->bin_w));727728OUT_PKT0(ring, REG_A4XX_RB_STENCIL_INFO, 2);729if (rsc->stencil) {730OUT_RING(ring,731A4XX_RB_STENCIL_INFO_SEPARATE_STENCIL |732A4XX_RB_STENCIL_INFO_STENCIL_BASE(gmem->zsbuf_base[1]));733OUT_RING(ring, A4XX_RB_STENCIL_PITCH(rsc->stencil->layout.cpp *734gmem->bin_w));735} else {736OUT_RING(ring, 0x00000000);737OUT_RING(ring, 0x00000000);738}739} else {740OUT_PKT0(ring, REG_A4XX_RB_DEPTH_INFO, 3);741OUT_RING(ring, 0x00000000);742OUT_RING(ring, 0x00000000);743OUT_RING(ring, 0x00000000);744745OUT_PKT0(ring, REG_A4XX_RB_STENCIL_INFO, 2);746OUT_RING(ring, 0); /* RB_STENCIL_INFO */747OUT_RING(ring, 0); /* RB_STENCIL_PITCH */748}749750OUT_PKT0(ring, REG_A4XX_GRAS_DEPTH_CONTROL, 1);751if (pfb->zsbuf) {752OUT_RING(ring, A4XX_GRAS_DEPTH_CONTROL_FORMAT(753fd4_pipe2depth(pfb->zsbuf->format)));754} else {755OUT_RING(ring, A4XX_GRAS_DEPTH_CONTROL_FORMAT(DEPTH4_NONE));756}757}758759/* before IB to rendering cmds: */760static void761fd4_emit_tile_renderprep(struct fd_batch *batch,762const struct fd_tile *tile) assert_dt763{764struct fd_context *ctx = batch->ctx;765struct fd4_context *fd4_ctx = fd4_context(ctx);766struct fd_ringbuffer *ring = batch->gmem;767const struct fd_gmem_stateobj *gmem = batch->gmem_state;768struct pipe_framebuffer_state *pfb = &batch->framebuffer;769770uint32_t x1 = tile->xoff;771uint32_t y1 = tile->yoff;772uint32_t x2 = tile->xoff + tile->bin_w - 1;773uint32_t y2 = tile->yoff + tile->bin_h - 1;774775if (use_hw_binning(batch)) {776const struct fd_vsc_pipe *pipe = &gmem->vsc_pipe[tile->p];777struct fd_bo *pipe_bo = ctx->vsc_pipe_bo[tile->p];778779assert(pipe->w && pipe->h);780781fd_event_write(batch, ring, HLSQ_FLUSH);782fd_wfi(batch, ring);783784OUT_PKT0(ring, REG_A4XX_PC_VSTREAM_CONTROL, 1);785OUT_RING(ring, A4XX_PC_VSTREAM_CONTROL_SIZE(pipe->w * pipe->h) |786A4XX_PC_VSTREAM_CONTROL_N(tile->n));787788OUT_PKT3(ring, CP_SET_BIN_DATA, 2);789OUT_RELOC(ring, pipe_bo, 0, 0,7900); /* BIN_DATA_ADDR <- VSC_PIPE[p].DATA_ADDRESS */791OUT_RELOC(ring, fd4_ctx->vsc_size_mem, /* BIN_SIZE_ADDR <-792VSC_SIZE_ADDRESS + (p * 4) */793(tile->p * 4), 0, 0);794} else {795OUT_PKT0(ring, REG_A4XX_PC_VSTREAM_CONTROL, 1);796OUT_RING(ring, 0x00000000);797}798799OUT_PKT3(ring, CP_SET_BIN, 3);800OUT_RING(ring, 0x00000000);801OUT_RING(ring, CP_SET_BIN_1_X1(x1) | CP_SET_BIN_1_Y1(y1));802OUT_RING(ring, CP_SET_BIN_2_X2(x2) | CP_SET_BIN_2_Y2(y2));803804emit_mrt(ring, pfb->nr_cbufs, pfb->cbufs, gmem->cbuf_base, gmem->bin_w,805true);806807/* setup scissor/offset for current tile: */808OUT_PKT0(ring, REG_A4XX_RB_BIN_OFFSET, 1);809OUT_RING(ring, A4XX_RB_BIN_OFFSET_X(tile->xoff) |810A4XX_RB_BIN_OFFSET_Y(tile->yoff));811812OUT_PKT0(ring, REG_A4XX_GRAS_SC_SCREEN_SCISSOR_TL, 2);813OUT_RING(ring, A4XX_GRAS_SC_SCREEN_SCISSOR_TL_X(x1) |814A4XX_GRAS_SC_SCREEN_SCISSOR_TL_Y(y1));815OUT_RING(ring, A4XX_GRAS_SC_SCREEN_SCISSOR_BR_X(x2) |816A4XX_GRAS_SC_SCREEN_SCISSOR_BR_Y(y2));817818OUT_PKT0(ring, REG_A4XX_RB_RENDER_CONTROL, 1);819OUT_RING(ring, 0x8);820}821822void823fd4_gmem_init(struct pipe_context *pctx) disable_thread_safety_analysis824{825struct fd_context *ctx = fd_context(pctx);826827ctx->emit_sysmem_prep = fd4_emit_sysmem_prep;828ctx->emit_tile_init = fd4_emit_tile_init;829ctx->emit_tile_prep = fd4_emit_tile_prep;830ctx->emit_tile_mem2gmem = fd4_emit_tile_mem2gmem;831ctx->emit_tile_renderprep = fd4_emit_tile_renderprep;832ctx->emit_tile_gmem2mem = fd4_emit_tile_gmem2mem;833}834835836