[Mesa-dev] [PATCH 4/8] i965: Update the shadow miptree from the main to fake the ETC2 compression

Eleni Maria Stea estea at igalia.com
Mon Nov 19 08:54:08 UTC 2018


On GPUs gen < 8 that don't support ETC2 sampling/rendering we now fake
the support using 2 mipmap trees: one (the main) that stores the
compressed data for the Get* functions to work and one (the shadow) that
stores the same data decompressed for the render/sampling to work.

Added the intel_update_decompressed_shadow function to update the shadow
tree with the decompressed data whenever the main miptree with the
compressed is changing.
---
 .../drivers/dri/i965/brw_wm_surface_state.c   |  1 +
 src/mesa/drivers/dri/i965/intel_mipmap_tree.c | 70 ++++++++++++++++++-
 src/mesa/drivers/dri/i965/intel_mipmap_tree.h |  3 +
 3 files changed, 71 insertions(+), 3 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
index 4d1eafac91..2e6d85e1fe 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
@@ -579,6 +579,7 @@ static void brw_update_texture_surface(struct gl_context *ctx,
 
       if (obj->StencilSampling && firstImage->_BaseFormat == GL_DEPTH_STENCIL) {
          if (devinfo->gen <= 7) {
+            assert(!intel_obj->mt->needs_fake_etc);
             assert(mt->shadow_mt && !mt->stencil_mt->shadow_needs_update);
             mt = mt->shadow_mt;
          } else {
diff --git a/src/mesa/drivers/dri/i965/intel_mipmap_tree.c b/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
index b24332ff67..ef3e2c33d3 100644
--- a/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
+++ b/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
@@ -3740,12 +3740,15 @@ intel_miptree_map(struct brw_context *brw,
    assert(mt->surf.samples == 1);
 
    if (mt->needs_fake_etc) {
-      if (!(mode & BRW_MAP_ETC_BIT)) {
+      if (!(mode & BRW_MAP_ETC_BIT) && !(mode & GL_MAP_READ_BIT)) {
          assert(mt->shadow_mt);
 
-         mt->is_shadow_mapped = true;
+         if (mt->shadow_needs_update) {
+            intel_update_decompressed_shadow(brw, mt);
+            mt->shadow_needs_update = false;
+         }
 
-         mt->shadow_needs_update = false;
+         mt->is_shadow_mapped = true;
          mt = miptree->shadow_mt;
       } else {
          mt->is_shadow_mapped = false;
@@ -3762,6 +3765,8 @@ intel_miptree_map(struct brw_context *brw,
 
    map = intel_miptree_attach_map(mt, level, slice, x, y, w, h, mode);
    if (!map){
+      miptree->is_shadow_mapped = false;
+
       *out_ptr = NULL;
       *out_stride = 0;
       return;
@@ -3942,3 +3947,62 @@ intel_miptree_get_clear_color(const struct gen_device_info *devinfo,
       return mt->fast_clear_color;
    }
 }
+
+void
+intel_update_decompressed_shadow(struct brw_context *brw,
+                                 struct intel_mipmap_tree *mt)
+{
+   struct intel_mipmap_tree *smt = mt->shadow_mt;
+
+   assert(smt);
+   assert(mt->needs_fake_etc);
+   assert(mt->surf.size_B > 0);
+
+   int img_w = smt->surf.logical_level0_px.width;
+   int img_h = smt->surf.logical_level0_px.height;
+   int img_d = smt->surf.logical_level0_px.depth;
+
+   ptrdiff_t shadow_stride = _mesa_format_row_stride(smt->format, img_w);
+
+   for (int level = smt->first_level; level <= smt->last_level; level++) {
+      struct compressed_pixelstore store;
+      _mesa_compute_compressed_pixelstore(mt->surf.dim,
+                                          mt->format,
+                                          img_w, img_h, img_d,
+                                          &brw->ctx.Unpack,
+                                          &store);
+      for (unsigned int slice = 0; slice < img_d; slice++) {
+         GLbitfield mmode = GL_MAP_READ_BIT | BRW_MAP_DIRECT_BIT |
+                            BRW_MAP_ETC_BIT;
+         GLbitfield smode = GL_MAP_WRITE_BIT |
+                            GL_MAP_INVALIDATE_RANGE_BIT |
+                            BRW_MAP_DIRECT_BIT;
+
+         uint32_t img_x, img_y;
+         intel_miptree_get_image_offset(smt, level, slice, &img_x, &img_y);
+
+         void *mptr = intel_miptree_map_raw(brw, mt, mmode) + mt->offset
+                    + img_y * store.TotalBytesPerRow
+                    + img_x * store.TotalBytesPerRow / img_w;
+
+         void *sptr;
+         intel_miptree_map(brw, smt, level, slice, img_x, img_y, img_w, img_h,
+                           smode, &sptr, &shadow_stride);
+
+         if (mt->format == MESA_FORMAT_ETC1_RGB8) {
+            _mesa_etc1_unpack_rgba8888(sptr, shadow_stride,
+                                       mptr, store.TotalBytesPerRow,
+                                       img_w, img_h);
+         } else {
+            _mesa_unpack_etc2_format(sptr, shadow_stride,
+                                     mptr, store.TotalBytesPerRow,
+                                     img_w, img_h, mt->format, true);
+         }
+
+         intel_miptree_unmap_raw(mt);
+         intel_miptree_unmap(brw, smt, level, slice);
+      }
+   }
+
+   mt->shadow_needs_update = false;
+}
diff --git a/src/mesa/drivers/dri/i965/intel_mipmap_tree.h b/src/mesa/drivers/dri/i965/intel_mipmap_tree.h
index aca45cfaa4..02c98c80ca 100644
--- a/src/mesa/drivers/dri/i965/intel_mipmap_tree.h
+++ b/src/mesa/drivers/dri/i965/intel_mipmap_tree.h
@@ -733,6 +733,9 @@ intel_miptree_get_clear_color(const struct gen_device_info *devinfo,
                               struct brw_bo **clear_color_bo,
                               uint32_t *clear_color_offset);
 
+void
+intel_update_decompressed_shadow(struct brw_context *brw,
+                                 struct intel_mipmap_tree *mt);
 
 static inline int
 intel_miptree_blt_pitch(struct intel_mipmap_tree *mt)
-- 
2.19.0



More information about the mesa-dev mailing list