From f04f219906e40a6647a10fd9c1928509fe25fb84 Mon Sep 17 00:00:00 2001 From: Paul Berry Date: Wed, 29 Aug 2012 16:04:15 -0700 Subject: [PATCH] i965/blorp: Account for offsets when emitting SURFACE_STATE. Fixes piglit tests "framebuffer-blit-levels {read,draw} depth". NOTE: This is a candidate for stable release branches. Reviewed-by: Eric Anholt --- src/mesa/drivers/dri/i965/brw_blorp.cpp | 25 ++++++++++++++++++++++++ src/mesa/drivers/dri/i965/brw_blorp.h | 2 ++ src/mesa/drivers/dri/i965/gen6_blorp.cpp | 13 +++++++++--- src/mesa/drivers/dri/i965/gen7_blorp.cpp | 12 +++++++++++- 4 files changed, 48 insertions(+), 4 deletions(-) diff --git a/src/mesa/drivers/dri/i965/brw_blorp.cpp b/src/mesa/drivers/dri/i965/brw_blorp.cpp index af1156c39b1..3368907e1b8 100644 --- a/src/mesa/drivers/dri/i965/brw_blorp.cpp +++ b/src/mesa/drivers/dri/i965/brw_blorp.cpp @@ -107,6 +107,31 @@ brw_blorp_surface_info::set(struct brw_context *brw, } } + +/** + * Split x_offset and y_offset into a base offset (in bytes) and a remaining + * x/y offset (in pixels). Note: we can't do this by calling + * intel_renderbuffer_tile_offsets(), because the offsets may have been + * adjusted to account for Y vs. W tiling differences. So we compute it + * directly from the adjusted offsets. + */ +uint32_t +brw_blorp_surface_info::compute_tile_offsets(uint32_t *tile_x, + uint32_t *tile_y) const +{ + struct intel_region *region = mt->region; + uint32_t mask_x, mask_y; + + intel_region_get_tile_masks(region, &mask_x, &mask_y); + + *tile_x = x_offset & mask_x; + *tile_y = y_offset & mask_y; + + return intel_region_get_aligned_offset(region, x_offset & ~mask_x, + y_offset & ~mask_y); +} + + brw_blorp_params::brw_blorp_params() : x0(0), y0(0), diff --git a/src/mesa/drivers/dri/i965/brw_blorp.h b/src/mesa/drivers/dri/i965/brw_blorp.h index ef0c27491e1..0ad7c1b61cf 100644 --- a/src/mesa/drivers/dri/i965/brw_blorp.h +++ b/src/mesa/drivers/dri/i965/brw_blorp.h @@ -104,6 +104,8 @@ public: struct intel_mipmap_tree *mt, unsigned int level, unsigned int layer); + uint32_t compute_tile_offsets(uint32_t *tile_x, uint32_t *tile_y) const; + /* Setting this flag indicates that the buffer's contents are W-tiled * stencil data, but the surface state should be set up for Y tiled * MESA_FORMAT_R8 data (this is necessary because surface states don't diff --git a/src/mesa/drivers/dri/i965/gen6_blorp.cpp b/src/mesa/drivers/dri/i965/gen6_blorp.cpp index d5d65c635f2..baf3fa4531c 100644 --- a/src/mesa/drivers/dri/i965/gen6_blorp.cpp +++ b/src/mesa/drivers/dri/i965/gen6_blorp.cpp @@ -424,6 +424,7 @@ gen6_blorp_emit_surface_state(struct brw_context *brw, height /= 2; } struct intel_region *region = surface->mt->region; + uint32_t tile_x, tile_y; uint32_t *surf = (uint32_t *) brw_state_batch(brw, AUB_TRACE_SURFACE_STATE, 6 * 4, 32, @@ -435,7 +436,8 @@ gen6_blorp_emit_surface_state(struct brw_context *brw, surface->brw_surfaceformat << BRW_SURFACE_FORMAT_SHIFT); /* reloc */ - surf[1] = region->bo->offset; /* No tile offsets needed */ + surf[1] = (surface->compute_tile_offsets(&tile_x, &tile_y) + + region->bo->offset); surf[2] = (0 << BRW_SURFACE_LOD_SHIFT | (width - 1) << BRW_SURFACE_WIDTH_SHIFT | @@ -453,8 +455,13 @@ gen6_blorp_emit_surface_state(struct brw_context *brw, surf[4] = brw_get_surface_num_multisamples(surface->num_samples); - surf[5] = (0 << BRW_SURFACE_X_OFFSET_SHIFT | - 0 << BRW_SURFACE_Y_OFFSET_SHIFT | + /* Note that the low bits of these fields are missing, so + * there's the possibility of getting in trouble. + */ + assert(tile_x % 4 == 0); + assert(tile_y % 2 == 0); + surf[5] = ((tile_x / 4) << BRW_SURFACE_X_OFFSET_SHIFT | + (tile_y / 2) << BRW_SURFACE_Y_OFFSET_SHIFT | (surface->mt->align_h == 4 ? BRW_SURFACE_VERTICAL_ALIGN_ENABLE : 0)); diff --git a/src/mesa/drivers/dri/i965/gen7_blorp.cpp b/src/mesa/drivers/dri/i965/gen7_blorp.cpp index 3520ff60265..00f13a53212 100644 --- a/src/mesa/drivers/dri/i965/gen7_blorp.cpp +++ b/src/mesa/drivers/dri/i965/gen7_blorp.cpp @@ -150,6 +150,7 @@ gen7_blorp_emit_surface_state(struct brw_context *brw, * gen6_blorp_emit_surface_state). */ struct intel_region *region = surface->mt->region; + uint32_t tile_x, tile_y; struct gen7_surface_state *surf = (struct gen7_surface_state *) brw_state_batch(brw, AUB_TRACE_SURFACE_STATE, sizeof(*surf), 32, @@ -167,7 +168,16 @@ gen7_blorp_emit_surface_state(struct brw_context *brw, GEN7_SURFACE_ARYSPC_LOD0 : GEN7_SURFACE_ARYSPC_FULL; /* reloc */ - surf->ss1.base_addr = region->bo->offset; /* No tile offsets needed */ + surf->ss1.base_addr = surface->compute_tile_offsets(&tile_x, &tile_y); + surf->ss1.base_addr += region->bo->offset; + + /* Note that the low bits of these fields are missing, so + * there's the possibility of getting in trouble. + */ + assert(tile_x % 4 == 0); + assert(tile_y % 2 == 0); + surf->ss5.x_offset = tile_x / 4; + surf->ss5.y_offset = tile_y / 2; surf->ss2.width = width - 1; surf->ss2.height = height - 1; -- 2.30.2