summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2011-05-13 12:13:40 -0700
committerEric Anholt <eric@anholt.net>2011-05-18 13:57:18 -0700
commit3e43adef95ee24dd218279d2de56939b90edcb4c (patch)
treebab3d389ad1df2baa29223b6dd7d0ecb0f5855f4
parenta98dd64af750fb6dae54b2dc02e0c5a3711156af (diff)
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
-rw-r--r--src/mesa/drivers/dri/i965/brw_misc_state.c10
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm_surface_state.c41
-rw-r--r--src/mesa/drivers/dri/intel/intel_regions.c35
-rw-r--r--src/mesa/drivers/dri/intel/intel_regions.h4
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 938f6cf070..3ec9009621 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 cef0c65e47..de1953ed60 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 a4da1ce4fa..0253bbc2aa 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 8464a5e937..a8a300d863 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,