<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Jan 13, 2015 at 11:37 PM, Ben Widawsky <span dir="ltr"><<a href="mailto:benjamin.widawsky@intel.com" target="_blank">benjamin.widawsky@intel.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">The blit engine is limited to 32Kx32K transfer. In cases where we have to fall<br>
back to the blitter, and when trying to blit a slice of a 2d texture array, or<br>
face of a cube map, we don't need to transfer the entire texture.<br>
<br>
I doubt this patch will get exercised at this point since we'll always allocate<br>
a linear BO for huge buffers. The next patch changes that.<br>
<br>
v2: Fix NDEBUG warning<br>
<br>
Signed-off-by: Ben Widawsky <<a href="mailto:ben@bwidawsk.net">ben@bwidawsk.net</a>><br>
---<br>
 src/mesa/drivers/dri/i965/intel_blit.c | 107 ++++++++++++++++++++++++++++++++-<br>
 1 file changed, 105 insertions(+), 2 deletions(-)<br>
<br>
diff --git a/src/mesa/drivers/dri/i965/intel_blit.c b/src/mesa/drivers/dri/i965/intel_blit.c<br>
index 9500bd7..a56e394 100644<br>
--- a/src/mesa/drivers/dri/i965/intel_blit.c<br>
+++ b/src/mesa/drivers/dri/i965/intel_blit.c<br>
@@ -130,6 +130,104 @@ set_blitter_tiling(struct brw_context *brw,<br>
       ADVANCE_BATCH();                                                  \<br>
    } while (0)<br>
<br>
+<br>
+/* Returns the height of the tiling format. This would be measured in scanlines<br>
+ * (of pitch bytes) */<br>
+static int<br>
+tile_height(uint32_t tiling)<br>
+{<br>
+   const long PAGE_SIZE = sysconf(_SC_PAGE_SIZE);<br>
+   switch (tiling) {<br>
+   case I915_TILING_X:<br>
+      return PAGE_SIZE / 512;<br>
+   case I915_TILING_Y:<br>
+      return PAGE_SIZE / 128;<br>
+   case I915_TILING_NONE:<br>
+   default:<br>
+      unreachable("Helper function is only used for tiled surfaces\n");<br>
+   }<br>
+}<br>
+<br>
+/* This function returns the offset to be used by the blit operation. It may<br>
+ * modify the y if the texture would otherwise fail to be able to perform a<br>
+ * blit. The x offset will not need to change based on the computations made by<br>
+ * this function.<br>
+ *<br>
+ * By the time we get to this function, the miptree creation code should have<br>
+ * already determined it's possible to blit the texture, so there should never<br>
+ * be a case where this function fails.<br>
+ */<br>
+static GLuint<br>
+intel_miptree_get_adjusted_y_offset(struct intel_mipmap_tree *mt, int slice,<br>
+                                    uint32_t *y)<br>
+{<br>
+   GLuint offset = mt->offset;<br>
+<br>
+   /* Convert an input number of rows: y into 2 values: an offset (page aligned<br>
+    * in byte units), and the remaining rows of y. The resulting 2 values will<br>
+    * be used as parameters for a blit operation [using the HW blit engine].<br>
+    * They will therefore conform to whatever restrictions are needed.<br>
+    *<br>
+    * XXX: This code assumes that LOD0 is always guaranteed to be properly<br>
+    * aligned for the blit operation. The round down only mutates y if the LOD<br>
+    * being adjusted isn't tile aligned. In other words, if input y is pointing<br>
+    * to LOD0 of a slice, the adjusted y should always be 0. Similarly if input<br>
+    * y is pointing to another LOD, and the offset happens to be tile aligned, y<br>
+    * will again be 0.<br>
+    *<br>
+    * The following diagram shows how the blit parameters are modified. In the<br>
+    * example, is is trying to blit with LOD1 from slice[x] as a surface, and<br>
+    * LOD1 is not properly tile aligned.  "TA" means tile aligned. The rectangle<br>
+    * is the BO that contains the mipmaps. There may be an offset from the start<br>
+    * of the BO to the first slice.<br>
+    *<br>
+    *                   INPUT                               OUTPUT<br>
+    *   0    +---------------------------+<br>
+    *        |                           |        +---------------------------+<br>
+    * offset |  slice[0]...slice[x-2]    | offset |  +----------+             |<br>
+    *        |                           |        |  |  lod0    | slice[x]    |<br>
+    *   TA   |  +----------+             |        |  |          |             |<br>
+    *        |  |  lod0    | slice[x-1]  |        |  +----------+             |<br>
+    *        |  |          |             |  y---> |  +---+ +-+                |<br>
+    *        |  +----------+             |        |  |   | +-+                |<br>
+    *        |  +---+ +-+                |        |  +---+ *                  |<br>
+    *        |  |   | +-+                |        |                           |<br>
+    *        |  +---+ *                  |        |  slice[x+1]...            |<br>
+    *        |                           |        +---------------------------+<br>
+    *        |  // qpitch padding        |<br>
+    *        |                           |<br>
+    *   TA   |  +----------+             |<br>
+    *        |  |  lod0    | slice[x]    |<br>
+    *        |  |          |             |<br>
+    *        |  +----------+             |<br>
+    *  y---> |  +---+ +-+                |<br>
+    *        |  |   | +-+                |<br>
+    *        |  +---+ *                  |<br>
+    *        |                           |<br>
+    *        |  slice[x+1]...            |<br>
+    *        +---------------------------+<br>
+    */<br>
+   if (slice > 0 && *y >= 32768) {<br></blockquote><div><br></div><div>Why are we going through all these hoops to avoid the adjustment?  Does setting an offset cost us something we want to avoid?  Also, I think the check above needs to check y2 not y1 because y2 is larger and will actually be the determining factor on whether or not we can blit.<br></div><div>--Jason<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+      const long PAGE_MASK = sysconf(_SC_PAGE_SIZE) - 1;<br>
+      (void) PAGE_MASK;<br>
+<br>
+      /* Since we need to output a page aligned offset, the original offset must<br>
+       * also be page aligned. For tiled buffers, it always should be. */<br>
+      assert((offset & PAGE_MASK) == 0);<br>
+<br>
+      /* Adjust the y value to pick the nearest tile aligned mipmap row */<br>
+      unsigned tile_aligned_row = ROUND_DOWN_TO(*y, tile_height(mt->tiling));<br>
+      *y -= tile_aligned_row;<br>
+<br>
+      /* Convert tiled aligned row to a byte offset for use by the blitter */<br>
+      tile_aligned_row *= mt->pitch;<br>
+      assert((tile_aligned_row & PAGE_MASK) == 0);<br>
+      offset += tile_aligned_row;<br>
+   }<br>
+<br>
+   return offset;<br>
+}<br>
+<br>
 /**<br>
  * Implements a rectangular block transfer (blit) of pixels between two<br>
  * miptrees.<br>
@@ -236,6 +334,11 @@ intel_miptree_blit(struct brw_context *brw,<br>
    dst_x += dst_image_x;<br>
    dst_y += dst_image_y;<br>
<br>
+   GLuint src_offset = intel_miptree_get_adjusted_y_offset(src_mt, src_slice,<br>
+                                                           &src_y);<br>
+   GLuint dst_offset = intel_miptree_get_adjusted_y_offset(dst_mt, dst_slice,<br>
+                                                           &dst_y);<br>
+<br>
    /* The blitter interprets the 16-bit destination x/y as a signed 16-bit<br>
     * value. The values we're working with are unsigned, so make sure we don't<br>
     * overflow.<br>
@@ -249,10 +352,10 @@ intel_miptree_blit(struct brw_context *brw,<br>
    if (!intelEmitCopyBlit(brw,<br>
                           src_mt->cpp,<br>
                           src_pitch,<br>
-                          src_mt->bo, src_mt->offset,<br>
+                          src_mt->bo, src_offset,<br>
                           src_mt->tiling,<br>
                           dst_mt->pitch,<br>
-                          dst_mt->bo, dst_mt->offset,<br>
+                          dst_mt->bo, dst_offset,<br>
                           dst_mt->tiling,<br>
                           src_x, src_y,<br>
                           dst_x, dst_y,<br>
<span class="HOEnZb"><font color="#888888">--<br>
2.2.1<br>
<br>
_______________________________________________<br>
mesa-dev mailing list<br>
<a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
<a href="http://lists.freedesktop.org/mailman/listinfo/mesa-dev" target="_blank">http://lists.freedesktop.org/mailman/listinfo/mesa-dev</a><br>
</font></span></blockquote></div><br></div></div>