<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>