From 3e43adef95ee24dd218279d2de56939b90edcb4c Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 13 May 2011 12:13:40 -0700 Subject: [PATCH] i965: Add support for rendering to depthbuffer mipmap levels > 0. Fixes GL_ARB_depth_texture/fbo-clear-formats GL_EXT_packed_depth_stencil/fbo-clear-formats --- src/mesa/drivers/dri/i965/brw_misc_state.c | 10 +++-- .../drivers/dri/i965/brw_wm_surface_state.c | 41 ++++++------------- src/mesa/drivers/dri/intel/intel_regions.c | 35 ++++++++++++++++ src/mesa/drivers/dri/intel/intel_regions.h | 4 ++ 4 files changed, 58 insertions(+), 32 deletions(-) diff --git a/src/mesa/drivers/dri/i965/brw_misc_state.c b/src/mesa/drivers/dri/i965/brw_misc_state.c index 938f6cf070d..3ec90096212 100644 --- a/src/mesa/drivers/dri/i965/brw_misc_state.c +++ b/src/mesa/drivers/dri/i965/brw_misc_state.c @@ -247,6 +247,7 @@ static void emit_depthbuffer(struct brw_context *brw) } else { struct intel_region *region = irb->region; unsigned int format; + uint32_t tile_x, tile_y, offset; switch (region->cpp) { case 2: @@ -263,7 +264,8 @@ static void emit_depthbuffer(struct brw_context *brw) return; } - assert(region->tiling != I915_TILING_X); + offset = intel_region_tile_offsets(region, &tile_x, &tile_y); + assert(intel->gen < 6 || region->tiling == I915_TILING_Y); BEGIN_BATCH(len); @@ -275,14 +277,16 @@ static void emit_depthbuffer(struct brw_context *brw) (BRW_SURFACE_2D << 29)); OUT_RELOC(region->buffer, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, - 0); + offset); OUT_BATCH((BRW_SURFACE_MIPMAPLAYOUT_BELOW << 1) | ((region->width - 1) << 6) | ((region->height - 1) << 19)); OUT_BATCH(0); if (intel->is_g4x || intel->gen >= 5) - OUT_BATCH(0); + OUT_BATCH(tile_x | (tile_y << 16)); + else + assert(tile_x == 0 && tile_y == 0); if (intel->gen >= 6) OUT_BATCH(0); diff --git a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c index cef0c65e478..de1953ed600 100644 --- a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c +++ b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c @@ -450,6 +450,7 @@ brw_update_renderbuffer_surface(struct brw_context *brw, struct intel_renderbuffer *irb = intel_renderbuffer(rb); struct intel_region *region = irb->region; struct brw_surface_state *surf; + uint32_t tile_x, tile_y; surf = brw_state_batch(brw, sizeof(*surf), 32, &brw->wm.surf_offset[unit]); @@ -488,37 +489,19 @@ brw_update_renderbuffer_surface(struct brw_context *brw, } surf->ss0.surface_type = BRW_SURFACE_2D; - if (region->tiling == I915_TILING_NONE) { - surf->ss1.base_addr = (region->draw_x + - region->draw_y * region->pitch) * region->cpp; - } else { - uint32_t tile_base, tile_x, tile_y; - uint32_t pitch = region->pitch * region->cpp; - - if (region->tiling == I915_TILING_X) { - tile_x = region->draw_x % (512 / region->cpp); - tile_y = region->draw_y % 8; - tile_base = ((region->draw_y / 8) * (8 * pitch)); - tile_base += (region->draw_x - tile_x) / (512 / region->cpp) * 4096; - } else { - /* Y */ - tile_x = region->draw_x % (128 / region->cpp); - tile_y = region->draw_y % 32; - tile_base = ((region->draw_y / 32) * (32 * pitch)); - tile_base += (region->draw_x - tile_x) / (128 / region->cpp) * 4096; - } - assert(brw->has_surface_tile_offset || (tile_x == 0 && tile_y == 0)); - assert(tile_x % 4 == 0); - assert(tile_y % 2 == 0); - /* Note that the low bits of these fields are missing, so - * there's the possibility of getting in trouble. - */ - surf->ss1.base_addr = tile_base; - surf->ss5.x_offset = tile_x / 4; - surf->ss5.y_offset = tile_y / 2; - } + /* reloc */ + surf->ss1.base_addr = intel_region_tile_offsets(region, &tile_x, &tile_y); surf->ss1.base_addr += region->buffer->offset; /* reloc */ + assert(brw->has_surface_tile_offset || (tile_x == 0 && tile_y == 0)); + /* 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 = rb->Width - 1; surf->ss2.height = rb->Height - 1; brw_set_surface_tiling(surf, region->tiling); diff --git a/src/mesa/drivers/dri/intel/intel_regions.c b/src/mesa/drivers/dri/intel/intel_regions.c index a4da1ce4fa5..0253bbc2aa0 100644 --- a/src/mesa/drivers/dri/intel/intel_regions.c +++ b/src/mesa/drivers/dri/intel/intel_regions.c @@ -524,3 +524,38 @@ intel_region_buffer(struct intel_context *intel, return region->buffer; } + +/** + * Rendering to tiled buffers requires that the base address of the + * buffer be aligned to a page boundary. We generally render to + * textures by pointing the surface at the mipmap image level, which + * may not be aligned to a tile boundary. + * + * This function returns an appropriately-aligned base offset + * according to the tiling restrictions, plus any required x/y offset + * from there. + */ +uint32_t +intel_region_tile_offsets(struct intel_region *region, + uint32_t *tile_x, + uint32_t *tile_y) +{ + uint32_t pitch = region->pitch * region->cpp; + + if (region->tiling == I915_TILING_NONE) { + *tile_x = 0; + *tile_y = 0; + return region->draw_x * region->cpp + region->draw_y * pitch; + } else if (region->tiling == I915_TILING_X) { + *tile_x = region->draw_x % (512 / region->cpp); + *tile_y = region->draw_y % 8; + return ((region->draw_y / 8) * (8 * pitch) + + (region->draw_x - *tile_x) / (512 / region->cpp) * 4096); + } else { + assert(region->tiling == I915_TILING_Y); + *tile_x = region->draw_x % (128 / region->cpp); + *tile_y = region->draw_y % 32; + return ((region->draw_y / 32) * (32 * pitch) + + (region->draw_x - *tile_x) / (128 / region->cpp) * 4096); + } +} diff --git a/src/mesa/drivers/dri/intel/intel_regions.h b/src/mesa/drivers/dri/intel/intel_regions.h index 8464a5e937d..a8a300d863c 100644 --- a/src/mesa/drivers/dri/intel/intel_regions.h +++ b/src/mesa/drivers/dri/intel/intel_regions.h @@ -142,6 +142,10 @@ drm_intel_bo *intel_region_buffer(struct intel_context *intel, struct intel_region *region, GLuint flag); +uint32_t intel_region_tile_offsets(struct intel_region *region, + uint32_t *tile_x, + uint32_t *tile_y); + void _mesa_copy_rect(GLubyte * dst, GLuint cpp, GLuint dst_pitch,