ok_format(enum pipe_format pfmt)
{
enum a6xx_color_fmt fmt = fd6_pipe2color(pfmt);
+
+ switch (pfmt) {
+ case PIPE_FORMAT_Z24_UNORM_S8_UINT:
+ case PIPE_FORMAT_Z24X8_UNORM:
+ case PIPE_FORMAT_Z16_UNORM:
+ case PIPE_FORMAT_Z32_UNORM:
+ case PIPE_FORMAT_Z32_FLOAT:
+ case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
+ case PIPE_FORMAT_S8_UINT:
+ return true;
+ default:
+ break;
+ }
+
if (fmt == ~0)
return false;
fail_if(util_format_is_compressed(info->src.format) &&
info->src.format != info->dst.format);
- /* src box can be inverted, which we don't support.. dst box cannot: */
- fail_if((info->src.box.width < 0) || (info->src.box.height < 0));
-
fail_if(!ok_dims(info->src.resource, &info->src.box, info->src.level));
fail_if(!ok_dims(info->dst.resource, &info->dst.box, info->dst.level));
debug_assert(info->dst.box.height >= 0);
debug_assert(info->dst.box.depth >= 0);
- /* non-multisampled could either have nr_samples == 0 or == 1 */
+ /* We could probably blit between resources with equal sample count.. */
fail_if(info->dst.resource->nr_samples > 1);
- fail_if(info->src.resource->nr_samples > 1);
+
+ /* CP_BLIT supports resolving, but seems to pick one only of the samples
+ * (no blending). This doesn't work for RGBA resolves, so we fall back in
+ * that case. However, GL/GLES spec says:
+ *
+ * "If the source formats are integer types or stencil values, a single
+ * sample’s value is selected for each pixel. If the source formats are
+ * floating-point or normalized types, the sample values for each pixel
+ * are resolved in an implementationdependent manner. If the source
+ * formats are depth values, sample values are resolved in an
+ * implementation-dependent manner where the result will be between the
+ * minimum and maximum depth values in the pixel."
+ *
+ * so do those with CP_BLIT.
+ */
+ fail_if((info->mask & PIPE_MASK_RGBA) &&
+ info->src.resource->nr_samples > 1);
fail_if(info->window_rectangle_include);
/*
* Emit source:
*/
- OUT_PKT4(ring, REG_A6XX_SP_PS_2D_SRC_INFO, 13);
+ OUT_PKT4(ring, REG_A6XX_SP_PS_2D_SRC_INFO, 10);
OUT_RING(ring, A6XX_SP_PS_2D_SRC_INFO_COLOR_FORMAT(RB6_R8_UNORM) |
- A6XX_SP_PS_2D_SRC_INFO_TILE_MODE(TILE6_LINEAR) |
- A6XX_SP_PS_2D_SRC_INFO_COLOR_SWAP(WZYX) | 0x500000);
+ A6XX_SP_PS_2D_SRC_INFO_TILE_MODE(src->tile_mode) |
+ A6XX_SP_PS_2D_SRC_INFO_COLOR_SWAP(WZYX) |
+ COND(fd6_ubwc_enabled(src, src->tile_mode), A6XX_SP_PS_2D_SRC_INFO_FLAGS) |
+ 0x500000);
OUT_RING(ring, A6XX_SP_PS_2D_SRC_SIZE_WIDTH(sshift + w) |
A6XX_SP_PS_2D_SRC_SIZE_HEIGHT(1)); /* SP_PS_2D_SRC_SIZE */
- OUT_RELOC(ring, src->bo, soff, 0, 0); /* SP_PS_2D_SRC_LO/HI */
+ OUT_RELOC(ring, src->bo, soff + src->offset, 0, 0); /* SP_PS_2D_SRC_LO/HI */
OUT_RING(ring, A6XX_SP_PS_2D_SRC_PITCH_PITCH(p));
OUT_RING(ring, 0x00000000);
OUT_RING(ring, 0x00000000);
OUT_RING(ring, 0x00000000);
- OUT_RING(ring, 0x00000000);
- OUT_RING(ring, 0x00000000);
- OUT_RING(ring, 0x00000000);
+ if (fd6_ubwc_enabled(src, src->tile_mode)) {
+ OUT_PKT4(ring, REG_A6XX_SP_PS_2D_SRC_FLAGS_LO, 6);
+ OUT_RELOC(ring, src->bo, soff + src->ubwc_offset, 0, 0);
+ OUT_RING(ring, A6XX_RB_MRT_FLAG_BUFFER_PITCH_PITCH(src->ubwc_pitch) |
+ A6XX_RB_MRT_FLAG_BUFFER_PITCH_ARRAY_PITCH(src->ubwc_size));
+ OUT_RING(ring, 0x00000000);
+ OUT_RING(ring, 0x00000000);
+ OUT_RING(ring, 0x00000000);
+ }
/*
* Emit destination:
*/
OUT_PKT4(ring, REG_A6XX_RB_2D_DST_INFO, 9);
OUT_RING(ring, A6XX_RB_2D_DST_INFO_COLOR_FORMAT(RB6_R8_UNORM) |
- A6XX_RB_2D_DST_INFO_TILE_MODE(TILE6_LINEAR) |
- A6XX_RB_2D_DST_INFO_COLOR_SWAP(WZYX));
- OUT_RELOC(ring, dst->bo, doff, 0, 0); /* RB_2D_DST_LO/HI */
+ A6XX_RB_2D_DST_INFO_TILE_MODE(dst->tile_mode) |
+ A6XX_RB_2D_DST_INFO_COLOR_SWAP(WZYX) |
+ COND(fd6_ubwc_enabled(dst, dst->tile_mode), A6XX_RB_2D_DST_INFO_FLAGS));
+ OUT_RELOC(ring, dst->bo, doff + dst->offset, 0, 0); /* RB_2D_DST_LO/HI */
OUT_RING(ring, A6XX_RB_2D_DST_SIZE_PITCH(p));
OUT_RING(ring, 0x00000000);
OUT_RING(ring, 0x00000000);
OUT_RING(ring, 0x00000000);
OUT_RING(ring, 0x00000000);
+ if (fd6_ubwc_enabled(dst, dst->tile_mode)) {
+ OUT_PKT4(ring, REG_A6XX_RB_2D_DST_FLAGS_LO, 6);
+ OUT_RELOC(ring, dst->bo, doff + dst->ubwc_offset, 0, 0);
+ OUT_RING(ring, A6XX_RB_MRT_FLAG_BUFFER_PITCH_PITCH(dst->ubwc_pitch) |
+ A6XX_RB_MRT_FLAG_BUFFER_PITCH_ARRAY_PITCH(dst->ubwc_size));
+ OUT_RING(ring, 0x00000000);
+ OUT_RING(ring, 0x00000000);
+ OUT_RING(ring, 0x00000000);
+ }
/*
* Blit command:
*/
enum a6xx_tile_mode stile, dtile;
enum a3xx_color_swap sswap, dswap;
unsigned spitch, dpitch;
- unsigned sx1, sy1, sx2, sy2;
- unsigned dx1, dy1, dx2, dy2;
+ int sx1, sy1, sx2, sy2;
+ int dx1, dy1, dx2, dy2;
if (DEBUG_BLIT_FALLBACK) {
fprintf(stderr, "texture blit: ");
if (info->filter == PIPE_TEX_FILTER_LINEAR)
filter = A6XX_SP_PS_2D_SRC_INFO_FILTER;
- OUT_PKT4(ring, REG_A6XX_SP_PS_2D_SRC_INFO, 13);
+ enum a3xx_msaa_samples samples = fd_msaa_samples(src->base.nr_samples);
+
+ OUT_PKT4(ring, REG_A6XX_SP_PS_2D_SRC_INFO, 10);
OUT_RING(ring, A6XX_SP_PS_2D_SRC_INFO_COLOR_FORMAT(sfmt) |
A6XX_SP_PS_2D_SRC_INFO_TILE_MODE(stile) |
- A6XX_SP_PS_2D_SRC_INFO_COLOR_SWAP(sswap) | 0x500000 | filter);
+ A6XX_SP_PS_2D_SRC_INFO_COLOR_SWAP(sswap) |
+ A6XX_SP_PS_2D_SRC_INFO_SAMPLES(samples) |
+ COND(fd6_ubwc_enabled(src, stile), A6XX_SP_PS_2D_SRC_INFO_FLAGS) |
+ 0x500000 | filter);
OUT_RING(ring, A6XX_SP_PS_2D_SRC_SIZE_WIDTH(width) |
A6XX_SP_PS_2D_SRC_SIZE_HEIGHT(height)); /* SP_PS_2D_SRC_SIZE */
- OUT_RELOC(ring, src->bo, soff, 0, 0); /* SP_PS_2D_SRC_LO/HI */
+ OUT_RELOC(ring, src->bo, soff + src->offset, 0, 0); /* SP_PS_2D_SRC_LO/HI */
OUT_RING(ring, A6XX_SP_PS_2D_SRC_PITCH_PITCH(spitch));
+
OUT_RING(ring, 0x00000000);
OUT_RING(ring, 0x00000000);
OUT_RING(ring, 0x00000000);
OUT_RING(ring, 0x00000000);
OUT_RING(ring, 0x00000000);
- OUT_RING(ring, 0x00000000);
- OUT_RING(ring, 0x00000000);
- OUT_RING(ring, 0x00000000);
+ if (fd6_ubwc_enabled(src, stile)) {
+ OUT_PKT4(ring, REG_A6XX_SP_PS_2D_SRC_FLAGS_LO, 6);
+ OUT_RELOC(ring, src->bo, soff + src->ubwc_offset, 0, 0);
+ OUT_RING(ring, A6XX_RB_MRT_FLAG_BUFFER_PITCH_PITCH(src->ubwc_pitch) |
+ A6XX_RB_MRT_FLAG_BUFFER_PITCH_ARRAY_PITCH(src->ubwc_size));
+ OUT_RING(ring, 0x00000000);
+ OUT_RING(ring, 0x00000000);
+ OUT_RING(ring, 0x00000000);
+ }
/*
* Emit destination:
OUT_PKT4(ring, REG_A6XX_RB_2D_DST_INFO, 9);
OUT_RING(ring, A6XX_RB_2D_DST_INFO_COLOR_FORMAT(dfmt) |
A6XX_RB_2D_DST_INFO_TILE_MODE(dtile) |
- A6XX_RB_2D_DST_INFO_COLOR_SWAP(dswap));
- OUT_RELOCW(ring, dst->bo, doff, 0, 0); /* RB_2D_DST_LO/HI */
+ A6XX_RB_2D_DST_INFO_COLOR_SWAP(dswap) |
+ COND(fd6_ubwc_enabled(dst, dtile), A6XX_RB_2D_DST_INFO_FLAGS));
+ OUT_RELOCW(ring, dst->bo, doff + dst->offset, 0, 0); /* RB_2D_DST_LO/HI */
OUT_RING(ring, A6XX_RB_2D_DST_SIZE_PITCH(dpitch));
OUT_RING(ring, 0x00000000);
OUT_RING(ring, 0x00000000);
OUT_RING(ring, 0x00000000);
OUT_RING(ring, 0x00000000);
+ if (fd6_ubwc_enabled(dst, dtile)) {
+ OUT_PKT4(ring, REG_A6XX_RB_2D_DST_FLAGS_LO, 6);
+ OUT_RELOC(ring, dst->bo, doff + dst->ubwc_offset, 0, 0);
+ OUT_RING(ring, A6XX_RB_MRT_FLAG_BUFFER_PITCH_PITCH(dst->ubwc_pitch) |
+ A6XX_RB_MRT_FLAG_BUFFER_PITCH_ARRAY_PITCH(dst->ubwc_size));
+ OUT_RING(ring, 0x00000000);
+ OUT_RING(ring, 0x00000000);
+ OUT_RING(ring, 0x00000000);
+ }
/*
* Blit command:
*/
}
}
+static void
+rewrite_zs_blit(struct fd_ringbuffer *ring, const struct pipe_blit_info *info)
+{
+ struct pipe_blit_info separate = *info;
+
+ if (DEBUG_BLIT_FALLBACK) {
+ fprintf(stderr, "---- rewrite_separate_zs_blit: ");
+ util_dump_blit_info(stderr, info);
+ fprintf(stderr, "\ndst resource: ");
+ util_dump_resource(stderr, info->dst.resource);
+ fprintf(stderr, "\nsrc resource: ");
+ util_dump_resource(stderr, info->src.resource);
+ fprintf(stderr, "\n\n");
+ }
+
+ switch (info->src.format) {
+ case PIPE_FORMAT_S8_UINT:
+ debug_assert(info->mask == PIPE_MASK_S);
+ separate.mask = PIPE_MASK_R;
+ separate.src.format = PIPE_FORMAT_R8_UINT;
+ separate.dst.format = PIPE_FORMAT_R8_UINT;
+ emit_blit_texture(ring, &separate);
+ break;
+
+ case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
+ if (info->mask & PIPE_MASK_Z) {
+ separate.mask = PIPE_MASK_R;
+ separate.src.format = PIPE_FORMAT_R32_FLOAT;
+ separate.dst.format = PIPE_FORMAT_R32_FLOAT;
+ emit_blit_texture(ring, &separate);
+ }
+ if (info->mask & PIPE_MASK_S) {
+ separate.mask = PIPE_MASK_R;
+ separate.src.format = PIPE_FORMAT_R8_UINT;
+ separate.dst.format = PIPE_FORMAT_R8_UINT;
+ separate.src.resource = &fd_resource(info->src.resource)->stencil->base;
+ separate.dst.resource = &fd_resource(info->dst.resource)->stencil->base;
+ emit_blit_texture(ring, &separate);
+ }
+ break;
+
+ case PIPE_FORMAT_Z16_UNORM:
+ separate.mask = PIPE_MASK_R;
+ separate.src.format = PIPE_FORMAT_R16_UNORM;
+ separate.dst.format = PIPE_FORMAT_R16_UNORM;
+ emit_blit_texture(ring, &separate);
+ break;
+
+ case PIPE_FORMAT_Z32_UNORM:
+ case PIPE_FORMAT_Z32_FLOAT:
+ debug_assert(info->mask == PIPE_MASK_Z);
+ separate.mask = PIPE_MASK_R;
+ separate.src.format = PIPE_FORMAT_R32_UINT;
+ separate.dst.format = PIPE_FORMAT_R32_UINT;
+ emit_blit_texture(ring, &separate);
+ break;
+
+ case PIPE_FORMAT_Z24_UNORM_S8_UINT:
+ debug_assert(info->mask == PIPE_MASK_ZS);
+ case PIPE_FORMAT_Z24X8_UNORM:
+ case PIPE_FORMAT_X8Z24_UNORM:
+ separate.mask = PIPE_MASK_R;
+ separate.src.format = PIPE_FORMAT_R32_UINT;
+ separate.dst.format = PIPE_FORMAT_R32_UINT;
+ emit_blit_texture(ring, &separate);
+ break;
+
+ default:
+ unreachable("");
+ }
+}
+
+static void
+rewrite_combined_zs_blit(struct fd_context *ctx, const struct pipe_blit_info *info)
+{
+ struct pipe_blit_info separate = *info;
+
+ if (DEBUG_BLIT_FALLBACK) {
+ fprintf(stderr, "---- rewrite_combined_zs_blit: ");
+ util_dump_blit_info(stderr, info);
+ fprintf(stderr, "\ndst resource: ");
+ util_dump_resource(stderr, info->dst.resource);
+ fprintf(stderr, "\nsrc resource: ");
+ util_dump_resource(stderr, info->src.resource);
+ fprintf(stderr, "\n");
+ }
+
+ switch (info->mask) {
+ case PIPE_MASK_Z:
+ separate.mask = PIPE_MASK_R | PIPE_MASK_G | PIPE_MASK_B;
+ separate.src.format = PIPE_FORMAT_R8G8B8A8_UNORM;
+ separate.dst.format = PIPE_FORMAT_R8G8B8A8_UNORM;
+
+ fd_blitter_blit(ctx, &separate);
+ break;
+
+ case PIPE_MASK_S:
+ separate.mask = PIPE_MASK_A;
+ separate.src.format = PIPE_FORMAT_R8G8B8A8_UNORM;
+ separate.dst.format = PIPE_FORMAT_R8G8B8A8_UNORM;
+
+ fd_blitter_blit(ctx, &separate);
+ break;
+
+ default:
+ unreachable("");
+ }
+}
+
static bool
fd6_blit(struct fd_context *ctx, const struct pipe_blit_info *info)
{
struct fd_batch *batch;
+ if (info->dst.format == PIPE_FORMAT_Z24_UNORM_S8_UINT &&
+ info->mask != PIPE_MASK_ZS) {
+ rewrite_combined_zs_blit(ctx, info);
+ return true;
+ }
+
if (!can_do_blit(info))
return false;
/* I don't *think* we need to handle blits between buffer <-> !buffer */
debug_assert(info->src.resource->target != PIPE_BUFFER);
debug_assert(info->dst.resource->target != PIPE_BUFFER);
- emit_blit_texture(batch->draw, info);
+
+ if (info->mask & (PIPE_MASK_ZS)) {
+ rewrite_zs_blit(batch->draw, info);
+ } else {
+ emit_blit_texture(batch->draw, info);
+ }
}
fd6_event_write(batch, batch->draw, 0x1d, true);