[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