diff mbox

[2/2] i965: Add support for rendering to depthbuffer mipmap levels > 0.

Message ID 1305407744-30992-2-git-send-email-eric@anholt.net
State New, archived
Headers show

Commit Message

Eric Anholt May 14, 2011, 9:15 p.m. UTC
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 ++++--
 src/mesa/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 mbox

Patch

diff --git a/src/mesa/drivers/dri/i965/brw_misc_state.c b/src/mesa/drivers/dri/i965/brw_misc_state.c
index e8c8b81..0d2f5da 100644
--- a/src/mesa/drivers/dri/i965/brw_misc_state.c
+++ b/src/mesa/drivers/dri/i965/brw_misc_state.c
@@ -241,6 +241,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:
@@ -257,7 +258,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);
@@ -269,14 +271,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 9b2072a..650e261 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
@@ -442,6 +442,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]);
@@ -480,37 +481,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 a4da1ce..0253bbc 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 8464a5e..a8a300d 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,