X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Ffreedreno%2Fa5xx%2Ffd5_blitter.c;h=0cfe92ac22f5e9e979f769a11eb8e78c10377603;hb=228eddd7eefbe6ac78a284fe7fc1d5c4b23b0f37;hp=5769b7eb8f37531a226827b0e72de0afeaa2f60d;hpb=e095b1347ec0765e45ee9dd4c22c510a3c746b22;p=mesa.git diff --git a/src/gallium/drivers/freedreno/a5xx/fd5_blitter.c b/src/gallium/drivers/freedreno/a5xx/fd5_blitter.c index 5769b7eb8f3..0cfe92ac22f 100644 --- a/src/gallium/drivers/freedreno/a5xx/fd5_blitter.c +++ b/src/gallium/drivers/freedreno/a5xx/fd5_blitter.c @@ -52,6 +52,9 @@ ok_dims(const struct pipe_resource *r, const struct pipe_box *b, int lvl) static bool ok_format(enum pipe_format fmt) { + if (util_format_is_compressed(fmt)) + return false; + switch (fmt) { case PIPE_FORMAT_R10G10B10A2_SSCALED: case PIPE_FORMAT_R10G10B10A2_SNORM: @@ -66,8 +69,13 @@ ok_format(enum pipe_format fmt) case PIPE_FORMAT_R10G10B10A2_UINT: return false; default: - return true; + break; } + + if (fd5_pipe2color(fmt) == ~0) + return false; + + return true; } static bool @@ -85,6 +93,16 @@ can_do_blit(const struct pipe_blit_info *info) if (!ok_format(info->src.format)) return false; + /* hw ignores {SRC,DST}_INFO.COLOR_SWAP if {SRC,DST}_INFO.TILE_MODE + * is set (not linear). We can kind of get around that when tiling/ + * untiling by setting both src and dst COLOR_SWAP=WZYX, but that + * means the formats must match: + */ + if ((fd_resource(info->dst.resource)->tile_mode || + fd_resource(info->src.resource)->tile_mode) && + info->dst.format != info->src.format) + return false; + /* until we figure out a few more registers: */ if ((info->dst.box.width != info->src.box.width) || (info->dst.box.height != info->src.box.height)) @@ -128,12 +146,6 @@ can_do_blit(const struct pipe_blit_info *info) if (info->mask != util_format_get_mask(info->dst.format)) return false; - if (util_format_is_compressed(info->dst.format)) - return false; - - if (util_format_is_compressed(info->src.format)) - return false; - return true; } @@ -254,6 +266,7 @@ emit_blit_buffer(struct fd_ringbuffer *ring, const struct pipe_blit_info *info) */ OUT_PKT4(ring, REG_A5XX_RB_2D_SRC_INFO, 9); OUT_RING(ring, A5XX_RB_2D_SRC_INFO_COLOR_FORMAT(RB5_R8_UNORM) | + A5XX_RB_2D_SRC_INFO_TILE_MODE(TILE5_LINEAR) | A5XX_RB_2D_SRC_INFO_COLOR_SWAP(WZYX)); OUT_RELOC(ring, src->bo, soff, 0, 0); /* RB_2D_SRC_LO/HI */ OUT_RING(ring, A5XX_RB_2D_SRC_SIZE_PITCH(p) | @@ -273,6 +286,7 @@ emit_blit_buffer(struct fd_ringbuffer *ring, const struct pipe_blit_info *info) */ OUT_PKT4(ring, REG_A5XX_RB_2D_DST_INFO, 9); OUT_RING(ring, A5XX_RB_2D_DST_INFO_COLOR_FORMAT(RB5_R8_UNORM) | + A5XX_RB_2D_DST_INFO_TILE_MODE(TILE5_LINEAR) | A5XX_RB_2D_DST_INFO_COLOR_SWAP(WZYX)); OUT_RELOCW(ring, dst->bo, doff, 0, 0); /* RB_2D_DST_LO/HI */ OUT_RING(ring, A5XX_RB_2D_DST_SIZE_PITCH(p) | @@ -312,6 +326,7 @@ emit_blit(struct fd_ringbuffer *ring, const struct pipe_blit_info *info) struct fd_resource *src, *dst; struct fd_resource_slice *sslice, *dslice; enum a5xx_color_fmt sfmt, dfmt; + enum a5xx_tile_mode stile, dtile; enum a3xx_color_swap sswap, dswap; unsigned ssize, dsize, spitch, dpitch; unsigned sx1, sy1, sx2, sy2; @@ -326,12 +341,27 @@ emit_blit(struct fd_ringbuffer *ring, const struct pipe_blit_info *info) sfmt = fd5_pipe2color(info->src.format); dfmt = fd5_pipe2color(info->dst.format); + stile = fd_resource_level_linear(info->src.resource, info->src.level) ? + TILE5_LINEAR : src->tile_mode; + dtile = fd_resource_level_linear(info->dst.resource, info->dst.level) ? + TILE5_LINEAR : dst->tile_mode; + sswap = fd5_pipe2swap(info->src.format); dswap = fd5_pipe2swap(info->dst.format); spitch = sslice->pitch * src->cpp; dpitch = dslice->pitch * dst->cpp; + /* if dtile, then dswap ignored by hw, and likewise if stile then sswap + * ignored by hw.. but in this case we have already rejected the blit + * if src and dst formats differ, so juse use WZYX for both src and + * dst swap mode (so we don't change component order) + */ + if (stile || dtile) { + debug_assert(info->src.format == info->dst.format); + sswap = dswap = WZYX; + } + sx1 = sbox->x; sy1 = sbox->y; sx2 = sbox->x + sbox->width - 1; @@ -367,6 +397,7 @@ emit_blit(struct fd_ringbuffer *ring, const struct pipe_blit_info *info) */ OUT_PKT4(ring, REG_A5XX_RB_2D_SRC_INFO, 9); OUT_RING(ring, A5XX_RB_2D_SRC_INFO_COLOR_FORMAT(sfmt) | + A5XX_RB_2D_SRC_INFO_TILE_MODE(stile) | A5XX_RB_2D_SRC_INFO_COLOR_SWAP(sswap)); OUT_RELOC(ring, src->bo, soff, 0, 0); /* RB_2D_SRC_LO/HI */ OUT_RING(ring, A5XX_RB_2D_SRC_SIZE_PITCH(spitch) | @@ -379,6 +410,7 @@ emit_blit(struct fd_ringbuffer *ring, const struct pipe_blit_info *info) OUT_PKT4(ring, REG_A5XX_GRAS_2D_SRC_INFO, 1); OUT_RING(ring, A5XX_GRAS_2D_SRC_INFO_COLOR_FORMAT(sfmt) | + A5XX_GRAS_2D_SRC_INFO_TILE_MODE(stile) | A5XX_GRAS_2D_SRC_INFO_COLOR_SWAP(sswap)); /* @@ -386,6 +418,7 @@ emit_blit(struct fd_ringbuffer *ring, const struct pipe_blit_info *info) */ OUT_PKT4(ring, REG_A5XX_RB_2D_DST_INFO, 9); OUT_RING(ring, A5XX_RB_2D_DST_INFO_COLOR_FORMAT(dfmt) | + A5XX_RB_2D_DST_INFO_TILE_MODE(dtile) | A5XX_RB_2D_DST_INFO_COLOR_SWAP(dswap)); OUT_RELOCW(ring, dst->bo, doff, 0, 0); /* RB_2D_DST_LO/HI */ OUT_RING(ring, A5XX_RB_2D_DST_SIZE_PITCH(dpitch) | @@ -398,6 +431,7 @@ emit_blit(struct fd_ringbuffer *ring, const struct pipe_blit_info *info) OUT_PKT4(ring, REG_A5XX_GRAS_2D_DST_INFO, 1); OUT_RING(ring, A5XX_GRAS_2D_DST_INFO_COLOR_FORMAT(dfmt) | + A5XX_GRAS_2D_DST_INFO_TILE_MODE(dtile) | A5XX_GRAS_2D_DST_INFO_COLOR_SWAP(dswap)); /* @@ -415,17 +449,16 @@ emit_blit(struct fd_ringbuffer *ring, const struct pipe_blit_info *info) } } -void +bool fd5_blitter_blit(struct fd_context *ctx, const struct pipe_blit_info *info) { struct fd_batch *batch; if (!can_do_blit(info)) { - fd_blitter_blit(ctx, info); - return; + return false; } - batch = fd_batch_create(ctx, true); + batch = fd_bc_alloc_batch(&ctx->screen->batch_cache, ctx, true); fd5_emit_restore(batch, batch->draw); fd5_emit_lrz_flush(batch->draw); @@ -434,6 +467,8 @@ fd5_blitter_blit(struct fd_context *ctx, const struct pipe_blit_info *info) if ((info->src.resource->target == PIPE_BUFFER) && (info->dst.resource->target == PIPE_BUFFER)) { + assert(fd_resource(info->src.resource)->tile_mode == TILE5_LINEAR); + assert(fd_resource(info->dst.resource)->tile_mode == TILE5_LINEAR); emit_blit_buffer(batch->draw, info); } else { /* I don't *think* we need to handle blits between buffer <-> !buffer */ @@ -441,8 +476,23 @@ fd5_blitter_blit(struct fd_context *ctx, const struct pipe_blit_info *info) debug_assert(info->dst.resource->target != PIPE_BUFFER); emit_blit(batch->draw, info); } + fd_resource(info->dst.resource)->valid = true; batch->needs_flush = true; fd_batch_flush(batch, false, false); + + return true; +} + +unsigned +fd5_tile_mode(const struct pipe_resource *tmpl) +{ + /* basically just has to be a format we can blit, so uploads/downloads + * via linear staging buffer works: + */ + if (ok_format(tmpl->format)) + return TILE5_3; + + return TILE5_LINEAR; }