i965: Add support for rendering to depthbuffer mipmap levels > 0.
authorEric Anholt <eric@anholt.net>
Fri, 13 May 2011 19:13:40 +0000 (12:13 -0700)
committerEric Anholt <eric@anholt.net>
Wed, 18 May 2011 20:57:18 +0000 (13:57 -0700)
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
src/mesa/drivers/dri/i965/brw_wm_surface_state.c
src/mesa/drivers/dri/intel/intel_regions.c
src/mesa/drivers/dri/intel/intel_regions.h

index 938f6cf..3ec9009 100644 (file)
@@ -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);
index cef0c65..de1953e 100644 (file)
@@ -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);
index a4da1ce..0253bbc 100644 (file)
@@ -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);
+   }
+}
index 8464a5e..a8a300d 100644 (file)
@@ -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,