etnaviv: enable texture upload memory throttling
[mesa.git] / src / gallium / drivers / etnaviv / etnaviv_blt.c
index 1f13bbc31cdbc82bfff8b4510ef5a63a3ac24b6d..81217918d3b271490a872b5ae2b430295bf7a478 100644 (file)
 
 #include <assert.h>
 
-/* Currently, used BLT formats overlap 100% with RS formats */
-#define translate_blt_format translate_rs_format
+static uint32_t
+etna_compatible_blt_format(enum pipe_format fmt)
+{
+   /* YUYV and UYVY are blocksize 4, but 2 bytes per pixel */
+   if (fmt == PIPE_FORMAT_YUYV || fmt == PIPE_FORMAT_UYVY)
+      return BLT_FORMAT_R8G8;
+
+   switch (util_format_get_blocksize(fmt)) {
+   case 1: return BLT_FORMAT_R8;
+   case 2: return BLT_FORMAT_R8G8;
+   case 4: return BLT_FORMAT_A8R8G8B8;
+   case 8: return BLT_FORMAT_A16R16G16B16;
+   default: return ETNA_NO_MATCH;
+   }
+}
 
 static inline uint32_t
 blt_compute_stride_bits(const struct blt_imginfo *img)
@@ -68,10 +81,10 @@ blt_compute_img_config_bits(const struct blt_imginfo *img, bool for_dest)
       tiling_bits |= for_dest ? BLT_IMAGE_CONFIG_TO_SUPER_TILED : BLT_IMAGE_CONFIG_FROM_SUPER_TILED;
    }
 
-   return BLT_IMAGE_CONFIG_CACHE_MODE(img->cache_mode) |
+   return BLT_IMAGE_CONFIG_TS_MODE(img->ts_mode) |
           COND(img->use_ts, BLT_IMAGE_CONFIG_TS) |
-          COND(img->compressed, BLT_IMAGE_CONFIG_COMPRESSION) |
-          BLT_IMAGE_CONFIG_COMPRESSION_FORMAT(img->compress_fmt) |
+          COND(img->use_ts && img->ts_compress_fmt >= 0, BLT_IMAGE_CONFIG_COMPRESSION) |
+          BLT_IMAGE_CONFIG_COMPRESSION_FORMAT(img->ts_compress_fmt) |
           COND(for_dest, BLT_IMAGE_CONFIG_UNK22) |
           BLT_IMAGE_CONFIG_SWIZ_R(0) | /* not used? */
           BLT_IMAGE_CONFIG_SWIZ_G(1) |
@@ -182,7 +195,7 @@ emit_blt_inplace(struct etna_cmd_stream *stream, const struct blt_inplace_op *op
    etna_cmd_stream_reserve(stream, 64*2); /* Never allow BLT sequences to be broken up */
    etna_set_state(stream, VIVS_BLT_ENABLE, 0x00000001);
    etna_set_state(stream, VIVS_BLT_CONFIG,
-         VIVS_BLT_CONFIG_INPLACE_CACHE_MODE(op->cache_mode) |
+         VIVS_BLT_CONFIG_INPLACE_TS_MODE(op->ts_mode) |
          VIVS_BLT_CONFIG_INPLACE_BOTH |
          (util_logbase2(op->bpp) << VIVS_BLT_CONFIG_INPLACE_BPP__SHIFT));
    etna_set_state(stream, VIVS_BLT_DEST_TS_CLEAR_VALUE0, op->ts_clear_value[0]);
@@ -202,7 +215,7 @@ etna_blit_clear_color_blt(struct pipe_context *pctx, struct pipe_surface *dst,
 {
    struct etna_context *ctx = etna_context(pctx);
    struct etna_surface *surf = etna_surface(dst);
-   uint32_t new_clear_value = etna_clear_blit_pack_rgba(surf->base.format, color->f);
+   uint64_t new_clear_value = etna_clear_blit_pack_rgba(surf->base.format, color);
 
    struct etna_resource *res = etna_resource(surf->base.texture);
    struct blt_clear_op clr = {};
@@ -211,12 +224,7 @@ etna_blit_clear_color_blt(struct pipe_context *pctx, struct pipe_surface *dst,
    clr.dest.addr.flags = ETNA_RELOC_WRITE;
    clr.dest.bpp = util_format_get_blocksize(surf->base.format);
    clr.dest.stride = surf->surf.stride;
-   /* TODO: color compression
-   clr.dest.compressed = 1;
-   clr.dest.compress_fmt = 3;
-   */
    clr.dest.tiling = res->layout;
-   clr.dest.cache_mode = TS_CACHE_MODE_128; /* TODO: cache modes */
 
    if (surf->surf.ts_size) {
       clr.dest.use_ts = 1;
@@ -224,11 +232,13 @@ etna_blit_clear_color_blt(struct pipe_context *pctx, struct pipe_surface *dst,
       clr.dest.ts_addr.offset = 0;
       clr.dest.ts_addr.flags = ETNA_RELOC_WRITE;
       clr.dest.ts_clear_value[0] = new_clear_value;
-      clr.dest.ts_clear_value[1] = new_clear_value;
+      clr.dest.ts_clear_value[1] = new_clear_value >> 32;
+      clr.dest.ts_mode = surf->level->ts_mode;
+      clr.dest.ts_compress_fmt = surf->level->ts_compress_fmt;
    }
 
    clr.clear_value[0] = new_clear_value;
-   clr.clear_value[1] = new_clear_value;
+   clr.clear_value[1] = new_clear_value >> 32;
    clr.clear_bits[0] = 0xffffffff; /* TODO: Might want to clear only specific channels? */
    clr.clear_bits[1] = 0xffffffff;
    clr.rect_x = 0; /* What about scissors? */
@@ -241,7 +251,9 @@ etna_blit_clear_color_blt(struct pipe_context *pctx, struct pipe_surface *dst,
    /* This made the TS valid */
    if (surf->surf.ts_size) {
       ctx->framebuffer.TS_COLOR_CLEAR_VALUE = new_clear_value;
+      ctx->framebuffer.TS_COLOR_CLEAR_VALUE_EXT = new_clear_value >> 32;
       surf->level->ts_valid = true;
+      ctx->dirty |= ETNA_DIRTY_TS | ETNA_DIRTY_DERIVE_TS;
    }
 
    surf->level->clear_value = new_clear_value;
@@ -279,6 +291,10 @@ etna_blit_clear_zs_blt(struct pipe_context *pctx, struct pipe_surface *dst,
    if (buffers & PIPE_CLEAR_STENCIL)
       new_clear_bits |= clear_bits_stencil;
 
+   /* if all bits are cleared, update TS clear value */
+   if (new_clear_bits == 0xffffffff)
+      surf->level->clear_value = new_clear_value;
+
    /* TODO unduplicate this */
    struct etna_resource *res = etna_resource(surf->base.texture);
    struct blt_clear_op clr = {};
@@ -287,20 +303,17 @@ etna_blit_clear_zs_blt(struct pipe_context *pctx, struct pipe_surface *dst,
    clr.dest.addr.flags = ETNA_RELOC_WRITE;
    clr.dest.bpp = util_format_get_blocksize(surf->base.format);
    clr.dest.stride = surf->surf.stride;
-#if 0 /* TODO depth compression */
-   clr.dest.compressed = 1;
-   clr.dest.compress_fmt = COLOR_COMPRESSION_FORMAT_D24S8;
-#endif
    clr.dest.tiling = res->layout;
-   clr.dest.cache_mode = TS_CACHE_MODE_128; /* TODO: cache modes */
 
    if (surf->surf.ts_size) {
       clr.dest.use_ts = 1;
       clr.dest.ts_addr.bo = res->ts_bo;
       clr.dest.ts_addr.offset = 0;
       clr.dest.ts_addr.flags = ETNA_RELOC_WRITE;
-      clr.dest.ts_clear_value[0] = new_clear_value;
-      clr.dest.ts_clear_value[1] = new_clear_value;
+      clr.dest.ts_clear_value[0] = surf->level->clear_value;
+      clr.dest.ts_clear_value[1] = surf->level->clear_value;
+      clr.dest.ts_mode = surf->level->ts_mode;
+      clr.dest.ts_compress_fmt = surf->level->ts_compress_fmt;
    }
 
    clr.clear_value[0] = new_clear_value;
@@ -316,11 +329,11 @@ etna_blit_clear_zs_blt(struct pipe_context *pctx, struct pipe_surface *dst,
 
    /* This made the TS valid */
    if (surf->surf.ts_size) {
-      ctx->framebuffer.TS_DEPTH_CLEAR_VALUE = new_clear_value;
+      ctx->framebuffer.TS_DEPTH_CLEAR_VALUE = surf->level->clear_value;
       surf->level->ts_valid = true;
+      ctx->dirty |= ETNA_DIRTY_TS | ETNA_DIRTY_DERIVE_TS;
    }
 
-   surf->level->clear_value = new_clear_value;
    resource_written(ctx, surf->base.texture);
    etna_resource(surf->base.texture)->seqno++;
 }
@@ -330,6 +343,7 @@ etna_clear_blt(struct pipe_context *pctx, unsigned buffers,
            const union pipe_color_union *color, double depth, unsigned stencil)
 {
    struct etna_context *ctx = etna_context(pctx);
+   mtx_lock(&ctx->lock);
 
    etna_set_state(ctx->stream, VIVS_GL_FLUSH_CACHE, 0x00000c23);
    etna_set_state(ctx->stream, VIVS_TS_FLUSH_CACHE, VIVS_TS_FLUSH_CACHE_FLUSH);
@@ -350,9 +364,9 @@ etna_clear_blt(struct pipe_context *pctx, unsigned buffers,
       etna_set_state(ctx->stream, VIVS_GL_FLUSH_CACHE, 0x00000c23);
    else
       etna_set_state(ctx->stream, VIVS_GL_FLUSH_CACHE, 0x00000002);
+   mtx_unlock(&ctx->lock);
 }
 
-
 static bool
 etna_try_blt_blit(struct pipe_context *pctx,
                  const struct pipe_blit_info *blit_info)
@@ -366,7 +380,7 @@ etna_try_blt_blit(struct pipe_context *pctx,
    assert(blit_info->src.level <= src->base.last_level);
    assert(blit_info->dst.level <= dst->base.last_level);
 
-   if (!translate_samples_to_xyscale(src->base.nr_samples, &msaa_xscale, &msaa_yscale, NULL))
+   if (!translate_samples_to_xyscale(src->base.nr_samples, &msaa_xscale, &msaa_yscale))
       return false;
 
    /* The width/height are in pixels; they do not change as a result of
@@ -389,37 +403,42 @@ etna_try_blt_blit(struct pipe_context *pctx,
       return false;
    }
 
-   /* TODO: 1 byte per pixel formats aren't handled by etna_compatible_rs_format nor
-    * translate_rs_format.
-    * Also this should be smarter about format conversions; etna_compatible_rs_format
-    * assumes all 2-byte pixel format are laid out as 4444, all 4-byte pixel formats
-    * are 8888.
+   /* Only support same format (used tiling/detiling) blits for now.
+    * TODO: figure out which different-format blits are possible and test them
+    *  - need to use correct swizzle
+    *  - set sRGB bits correctly
+    *  - avoid trying to convert between float/int formats?
     */
-   unsigned src_format = etna_compatible_rs_format(blit_info->src.format);
-   unsigned dst_format = etna_compatible_rs_format(blit_info->dst.format);
-   if (translate_blt_format(src_format) == ETNA_NO_MATCH ||
-       translate_blt_format(dst_format) == ETNA_NO_MATCH ||
-       blit_info->scissor_enable ||
+   if (blit_info->src.format != blit_info->dst.format)
+      return false;
+
+   uint32_t format = etna_compatible_blt_format(blit_info->dst.format);
+   if (format == ETNA_NO_MATCH)
+      return false;
+
+   if (blit_info->scissor_enable ||
        blit_info->dst.box.depth != blit_info->src.box.depth ||
        blit_info->dst.box.depth != 1) {
       return false;
    }
 
-   /* Ensure that the Z coordinate is sane */
-   assert(dst->base.target == PIPE_TEXTURE_CUBE || blit_info->dst.box.z == 0);
-   assert(src->base.target == PIPE_TEXTURE_CUBE || blit_info->src.box.z == 0);
-   assert(blit_info->src.box.z < src->base.array_size);
-   assert(blit_info->dst.box.z < dst->base.array_size);
-
    struct etna_resource_level *src_lev = &src->levels[blit_info->src.level];
    struct etna_resource_level *dst_lev = &dst->levels[blit_info->dst.level];
 
-   /* Kick off BLT here */
+   /* if we asked for in-place resolve, return immediately if ts isn't valid
+    * do this check separately because it applies when compression is used, but
+    * we can't use inplace resolve path with compression
+    */
    if (src == dst) {
-      /* Resolve-in-place */
       assert(!memcmp(&blit_info->src, &blit_info->dst, sizeof(blit_info->src)));
       if (!src_lev->ts_size || !src_lev->ts_valid) /* No TS, no worries */
          return true;
+   }
+
+   mtx_lock(&ctx->lock);
+   /* Kick off BLT here */
+   if (src == dst && src_lev->ts_compress_fmt < 0) {
+      /* Resolve-in-place */
       struct blt_inplace_op op = {};
 
       op.addr.bo = src->bo;
@@ -430,8 +449,8 @@ etna_try_blt_blit(struct pipe_context *pctx,
       op.ts_addr.flags = ETNA_RELOC_READ;
       op.ts_clear_value[0] = src_lev->clear_value;
       op.ts_clear_value[1] = src_lev->clear_value;
-      op.cache_mode = TS_CACHE_MODE_128; /* TODO: cache modes */
-      op.num_tiles = src_lev->size / 128; /* TODO: cache modes */
+      op.ts_mode = src_lev->ts_mode;
+      op.num_tiles = DIV_ROUND_UP(src_lev->size, src_lev->ts_mode ? 256 : 128);
       op.bpp = util_format_get_blocksize(src->base.format);
 
       etna_set_state(ctx->stream, VIVS_GL_FLUSH_CACHE, 0x00000c23);
@@ -444,14 +463,11 @@ etna_try_blt_blit(struct pipe_context *pctx,
       op.src.addr.bo = src->bo;
       op.src.addr.offset = src_lev->offset + blit_info->src.box.z * src_lev->layer_stride;
       op.src.addr.flags = ETNA_RELOC_READ;
-      op.src.format = translate_blt_format(src_format);
+      op.src.format = format;
       op.src.stride = src_lev->stride;
       op.src.tiling = src->layout;
-      op.src.cache_mode = TS_CACHE_MODE_128; /* TODO: cache modes */
-      const struct util_format_description *src_format_desc =
-         util_format_description(blit_info->src.format);
       for (unsigned x=0; x<4; ++x)
-         op.src.swizzle[x] = src_format_desc->swizzle[x];
+         op.src.swizzle[x] = x;
 
       if (src_lev->ts_size && src_lev->ts_valid) {
          op.src.use_ts = 1;
@@ -460,23 +476,18 @@ etna_try_blt_blit(struct pipe_context *pctx,
          op.src.ts_addr.flags = ETNA_RELOC_READ;
          op.src.ts_clear_value[0] = src_lev->clear_value;
          op.src.ts_clear_value[1] = src_lev->clear_value;
+         op.src.ts_mode = src_lev->ts_mode;
+         op.src.ts_compress_fmt = src_lev->ts_compress_fmt;
       }
 
       op.dest.addr.bo = dst->bo;
       op.dest.addr.offset = dst_lev->offset + blit_info->dst.box.z * dst_lev->layer_stride;
       op.dest.addr.flags = ETNA_RELOC_WRITE;
-      op.dest.format = translate_blt_format(dst_format);
+      op.dest.format = format;
       op.dest.stride = dst_lev->stride;
-      /* TODO color compression
-      op.dest.compressed = 1;
-      op.dest.compress_fmt = 3;
-      */
       op.dest.tiling = dst->layout;
-      op.dest.cache_mode = TS_CACHE_MODE_128; /* TODO cache modes */
-      const struct util_format_description *dst_format_desc =
-         util_format_description(blit_info->dst.format);
       for (unsigned x=0; x<4; ++x)
-         op.dest.swizzle[x] = dst_format_desc->swizzle[x];
+         op.dest.swizzle[x] = x;
 
       op.dest_x = blit_info->dst.box.x;
       op.dest_y = blit_info->dst.box.y;
@@ -515,6 +526,7 @@ etna_try_blt_blit(struct pipe_context *pctx,
 
    dst->seqno++;
    dst_lev->ts_valid = false;
+   mtx_unlock(&ctx->lock);
 
    return true;
 }