[Mesa-dev] [PATCH 5/6] i965/blit: Let _intratile_offset_el() resolve image offset

Topi Pohjolainen topi.pohjolainen at gmail.com
Wed Jul 26 19:28:37 UTC 2017


Image offset is really a triple: aligned byte offset, intra-tile
x and intra-tile y. Taking intra-tile offsets into account in the
caller side of emit_miptree_blit() and then applying tile-aligned
byte offset in emit_miptree_blit() is confusing. Now both are
handled in single location: get_blit_intratile_offset_el().

Signed-off-by: Topi Pohjolainen <topi.pohjolainen at intel.com>
---
 src/mesa/drivers/dri/i965/intel_blit.c | 106 ++++++++++++++++++++++-----------
 1 file changed, 71 insertions(+), 35 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/intel_blit.c b/src/mesa/drivers/dri/i965/intel_blit.c
index e7338bdf46..d308cfb416 100644
--- a/src/mesa/drivers/dri/i965/intel_blit.c
+++ b/src/mesa/drivers/dri/i965/intel_blit.c
@@ -42,6 +42,7 @@
 static void
 intel_miptree_set_alpha_to_one(struct brw_context *brw,
                                struct intel_mipmap_tree *mt,
+                               unsigned level, unsigned layer,
                                int x, int y, int width, int height);
 
 static GLuint translate_raster_op(GLenum logicop)
@@ -164,15 +165,68 @@ intel_miptree_blit_compatible_formats(mesa_format src, mesa_format dst)
 
 static void
 get_blit_intratile_offset_el(const struct brw_context *brw,
-                             struct intel_mipmap_tree *mt,
+                             const struct intel_mipmap_tree *mt,
+                             unsigned level, unsigned layer, 
                              uint32_t total_x_offset_el,
                              uint32_t total_y_offset_el,
                              struct isl_image_offset *image_offset)
 {
+   struct isl_image_offset base_offset;
+   intel_miptree_get_tile_offsets(mt, level, layer, &base_offset);
+   
+   /* Given offsets are relative to the start of the slice and we need the
+    * offset that is relative to the beginning of the buffer.
+    *
+    * Image offset is really a triple: aligned byte offset, intra-tile
+    * x and intra-tile y. In order to simply add the page aligned offset of
+    * the start of the image and the page aligned offset of the given position
+    * (total_x_offset_el, total_y_offset_el) within the image, we need to
+    * first augment the position within the image with the intra-tile start
+    * position (x,y) of the image itself. Otherwise we might get intra-tile
+    * offsets that don't actually fit into one page:
+    *
+    *             +-------------------------------------+ page N
+    *        / \  |                                     |
+    *   d_1   |   |                                     |
+    *        \ /  |                                     |
+    *             +                                     + start of the image
+    *             |                                     |
+    *             |                                     |
+    *             +-------------------------------------+ page N + 1
+    *             |                                     |
+    *             .                                     .
+    *             .                                     .
+    *             +-------------------------------------+ page N + M
+    *        / \  |                                     |
+    *   d_2   |   |                                     |
+    *        \ /  |                                     |
+    *             +                                     + (total_x_offset_el,
+    *             |                                     |  total_y_offset_el)
+    *             |                                     |
+    *             +-------------------------------------+ page N + M + 1
+    *
+    * Consider a case where d_1 + d_2 > sizeof(page). If one calculates the
+    * triple separately for the start of the image and for the position
+    * within the image, one gets page aligned of N + M and d_1 + d_2. If in
+    * turn one takes d_1 into account as offsetting the position _within_ the
+    * image, one gets page aligned of N + M + 1 and d_1 + d_2 - sizeof(page)
+    * where 0 <= d_1 + d_2 - sizeof(page) < sizeof(page).
+    */
+   total_x_offset_el += base_offset.intra_tile_x;
+   total_y_offset_el += base_offset.intra_tile_y;
+
    isl_tiling_get_intratile_offset_el(mt->surf.tiling,
                                       mt->cpp * 8, mt->surf.row_pitch,
                                       total_x_offset_el, total_y_offset_el,
                                       image_offset);
+ 
+   /* Finally add the byte offset of the page aligned start of the image to
+    * the page aligned offset with the image giving page aligned offset
+    * relative to the beginning of the buffer.
+    */
+   image_offset->tile_aligned_byte_offset +=
+      base_offset.tile_aligned_byte_offset;
+
    if (mt->surf.tiling == ISL_TILING_LINEAR) {
       /* From the Broadwell PRM docs for XY_SRC_COPY_BLT::SourceBaseAddress:
        *
@@ -197,8 +251,10 @@ get_blit_intratile_offset_el(const struct brw_context *brw,
 static bool
 emit_miptree_blit(struct brw_context *brw,
                   struct intel_mipmap_tree *src_mt,
+                  unsigned src_level, unsigned src_layer,
                   uint32_t src_x, uint32_t src_y,
                   struct intel_mipmap_tree *dst_mt,
+                  unsigned dst_level, unsigned dst_layer,
                   uint32_t dst_x, uint32_t dst_y,
                   uint32_t width, uint32_t height,
                   bool reverse, GLenum logicop)
@@ -237,12 +293,12 @@ emit_miptree_blit(struct brw_context *brw,
          const uint32_t chunk_h = MIN2(max_chunk_size, height - chunk_y);
 
          struct isl_image_offset src_offset;
-         get_blit_intratile_offset_el(brw, src_mt,
+         get_blit_intratile_offset_el(brw, src_mt, src_level, src_layer,
                                       src_x + chunk_x, src_y + chunk_y,
                                       &src_offset);
 
          struct isl_image_offset dst_offset;
-         get_blit_intratile_offset_el(brw, dst_mt,
+         get_blit_intratile_offset_el(brw, dst_mt, dst_level, dst_layer,
                                       dst_x + chunk_x, dst_y + chunk_y,
                                       &dst_offset);
 
@@ -251,13 +307,11 @@ emit_miptree_blit(struct brw_context *brw,
                                 reverse ? -src_mt->surf.row_pitch :
                                            src_mt->surf.row_pitch,
                                 src_mt->bo,
-                                src_mt->offset +
-                                   src_offset.tile_aligned_byte_offset,
+                                src_offset.tile_aligned_byte_offset,
                                 src_mt->surf.tiling,
                                 dst_mt->surf.row_pitch,
                                 dst_mt->bo,
-                                dst_mt->offset +
-                                   dst_offset.tile_aligned_byte_offset,
+                                dst_offset.tile_aligned_byte_offset,
                                 dst_mt->surf.tiling,
                                 src_offset.intra_tile_x,
                                 src_offset.intra_tile_y,
@@ -341,18 +395,11 @@ intel_miptree_blit(struct brw_context *brw,
       dst_y = minify(h0, dst_level - dst_mt->first_level) - dst_y - height;
    }
 
-   uint32_t src_image_x, src_image_y, dst_image_x, dst_image_y;
-   intel_miptree_get_image_offset(src_mt, src_level, src_slice,
-                                  &src_image_x, &src_image_y);
-   intel_miptree_get_image_offset(dst_mt, dst_level, dst_slice,
-                                  &dst_image_x, &dst_image_y);
-   src_x += src_image_x;
-   src_y += src_image_y;
-   dst_x += dst_image_x;
-   dst_y += dst_image_y;
-
-   if (!emit_miptree_blit(brw, src_mt, src_x, src_y,
-                          dst_mt, dst_x, dst_y, width, height,
+   if (!emit_miptree_blit(brw, src_mt, src_level, src_slice,
+                          src_x, src_y,
+                          dst_mt, dst_level, dst_slice,
+                          dst_x, dst_y,
+                          width, height,
                           src_flip != dst_flip, logicop)) {
       return false;
    }
@@ -360,7 +407,7 @@ intel_miptree_blit(struct brw_context *brw,
    /* XXX This could be done in a single pass using XY_FULL_MONO_PATTERN_BLT */
    if (_mesa_get_format_bits(src_format, GL_ALPHA_BITS) == 0 &&
        _mesa_get_format_bits(dst_format, GL_ALPHA_BITS) > 0) {
-      intel_miptree_set_alpha_to_one(brw, dst_mt,
+      intel_miptree_set_alpha_to_one(brw, dst_mt, dst_level, dst_slice,
                                      dst_x, dst_y,
                                      width, height);
    }
@@ -391,10 +438,6 @@ intel_miptree_copy(struct brw_context *brw,
    intel_miptree_access_raw(brw, src_mt, src_level, src_slice, false);
    intel_miptree_access_raw(brw, dst_mt, dst_level, dst_slice, true);
 
-   uint32_t src_image_x, src_image_y;
-   intel_miptree_get_image_offset(src_mt, src_level, src_slice,
-                                  &src_image_x, &src_image_y);
-
    if (_mesa_is_format_compressed(src_mt->format)) {
       GLuint bw, bh;
       _mesa_get_format_block_size(src_mt->format, &bw, &bh);
@@ -420,12 +463,6 @@ intel_miptree_copy(struct brw_context *brw,
       src_width = DIV_ROUND_UP(src_width, (int)bw);
       src_height = DIV_ROUND_UP(src_height, (int)bh);
    }
-   src_x += src_image_x;
-   src_y += src_image_y;
-
-   uint32_t dst_image_x, dst_image_y;
-   intel_miptree_get_image_offset(dst_mt, dst_level, dst_slice,
-                                  &dst_image_x, &dst_image_y);
 
    if (_mesa_is_format_compressed(dst_mt->format)) {
       GLuint bw, bh;
@@ -437,11 +474,9 @@ intel_miptree_copy(struct brw_context *brw,
       dst_x /= (int)bw;
       dst_y /= (int)bh;
    }
-   dst_x += dst_image_x;
-   dst_y += dst_image_y;
 
-   return emit_miptree_blit(brw, src_mt, src_x, src_y,
-                            dst_mt, dst_x, dst_y,
+   return emit_miptree_blit(brw, src_mt, src_level, src_slice, src_x, src_y,
+                            dst_mt, dst_level, dst_slice, dst_x, dst_y,
                             src_width, src_height, false, GL_COPY);
 }
 
@@ -778,6 +813,7 @@ intel_emit_linear_blit(struct brw_context *brw,
 static void
 intel_miptree_set_alpha_to_one(struct brw_context *brw,
                               struct intel_mipmap_tree *mt,
+                              unsigned level, unsigned layer,
                               int x, int y, int width, int height)
 {
    uint32_t BR13, CMD;
@@ -820,7 +856,7 @@ intel_miptree_set_alpha_to_one(struct brw_context *brw,
          const uint32_t chunk_h = MIN2(max_chunk_size, height - chunk_y);
 
          struct isl_image_offset image_offset;
-         get_blit_intratile_offset_el(brw, mt,
+         get_blit_intratile_offset_el(brw, mt, level, layer,
                                       x + chunk_x, y + chunk_y,
                                       &image_offset);
 
-- 
2.11.0



More information about the mesa-dev mailing list