Mesa (master): i965: Use a new miptree to avoid software fallbacks due to drawing offset.

Eric Anholt anholt at kemper.freedesktop.org
Tue Jan 11 01:22:50 UTC 2011


Module: Mesa
Branch: master
Commit: c0cdae03685056e170c25da7d46aed959176d652
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=c0cdae03685056e170c25da7d46aed959176d652

Author: Eric Anholt <eric at anholt.net>
Date:   Mon Jan 10 15:45:28 2011 -0800

i965: Use a new miptree to avoid software fallbacks due to drawing offset.

When attaching a small mipmap level to an FBO, the original gen4
didn't have the bits to support rendering to it.  Instead of falling
back, just blit it to a new little miptree just for it, and let it get
revalidated into the stack later just like any other new teximage.

Bug #30365.

---

 src/mesa/drivers/dri/i965/brw_fallback.c |   29 +-----------
 src/mesa/drivers/dri/intel/intel_fbo.c   |   78 +++++++++++++++++++++++++-----
 2 files changed, 67 insertions(+), 40 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_fallback.c b/src/mesa/drivers/dri/i965/brw_fallback.c
index 7262cf6..82356a5 100644
--- a/src/mesa/drivers/dri/i965/brw_fallback.c
+++ b/src/mesa/drivers/dri/i965/brw_fallback.c
@@ -80,33 +80,6 @@ static GLboolean do_check_fallback(struct brw_context *brw)
       return GL_TRUE;
    }
 
-   /* _NEW_BUFFERS */
-   if (!brw->has_surface_tile_offset) {
-      for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
-	 struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[i];
-	 struct intel_renderbuffer *irb = intel_renderbuffer(rb);
-
-	 /* The original gen4 hardware couldn't set up WM surfaces pointing
-	  * at an offset within a tile, which can happen when rendering to
-	  * anything but the base level of a texture or the +X face/0 depth.
-	  * This was fixed with the 4 Series hardware.
-	  *
-	  * For these original chips, you would have to make the depth and
-	  * color destination surfaces include information on the texture
-	  * type, LOD, face, and various limits to use them as a destination.
-	  * I would have done this, but there's also a nasty requirement that
-	  * the depth and the color surfaces all be of the same LOD, which
-	  * may be a worse requirement than this alignment.  (Also, we may
-	  * want to just demote the texture to untiled, instead).
-	  */
-	 if (irb->region && irb->region->tiling != I915_TILING_NONE &&
-	     (irb->region->draw_offset & 4095)) {
-	    DBG("FALLBACK: non-tile-aligned destination for tiled FBO\n");
-	    return GL_TRUE;
-	 }
-      }
-   }
-
    return GL_FALSE;
 }
 
@@ -117,7 +90,7 @@ static void check_fallback(struct brw_context *brw)
 
 const struct brw_tracked_state brw_check_fallback = {
    .dirty = {
-      .mesa = _NEW_BUFFERS | _NEW_RENDERMODE | _NEW_TEXTURE | _NEW_STENCIL,
+      .mesa = _NEW_RENDERMODE | _NEW_TEXTURE | _NEW_STENCIL,
       .brw  = 0,
       .cache = 0
    },
diff --git a/src/mesa/drivers/dri/intel/intel_fbo.c b/src/mesa/drivers/dri/intel/intel_fbo.c
index 88934eb..cbb6275 100644
--- a/src/mesa/drivers/dri/intel/intel_fbo.c
+++ b/src/mesa/drivers/dri/intel/intel_fbo.c
@@ -45,6 +45,9 @@
 #include "intel_regions.h"
 #include "intel_tex.h"
 #include "intel_span.h"
+#ifndef I915
+#include "brw_context.h"
+#endif
 
 #define FILE_DEBUG_FLAG DEBUG_FBO
 
@@ -421,6 +424,24 @@ intel_wrap_texture(struct gl_context * ctx, struct gl_texture_image *texImage)
    return irb;
 }
 
+static void
+intel_set_draw_offset_for_image(struct intel_texture_image *intel_image,
+				int zoffset)
+{
+   struct intel_mipmap_tree *mt = intel_image->mt;
+   unsigned int dst_x, dst_y;
+
+   /* compute offset of the particular 2D image within the texture region */
+   intel_miptree_get_image_offset(intel_image->mt,
+				  intel_image->level,
+				  intel_image->face,
+				  zoffset,
+				  &dst_x, &dst_y);
+
+   mt->region->draw_offset = (dst_y * mt->region->pitch + dst_x) * mt->cpp;
+   mt->region->draw_x = dst_x;
+   mt->region->draw_y = dst_y;
+}
 
 /**
  * Called by glFramebufferTexture[123]DEXT() (and other places) to
@@ -433,11 +454,11 @@ intel_render_texture(struct gl_context * ctx,
                      struct gl_framebuffer *fb,
                      struct gl_renderbuffer_attachment *att)
 {
+   struct intel_context *intel = intel_context(ctx);
    struct gl_texture_image *newImage
       = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
    struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer);
    struct intel_texture_image *intel_image;
-   GLuint dst_x, dst_y;
 
    (void) fb;
 
@@ -483,19 +504,52 @@ intel_render_texture(struct gl_context * ctx,
       intel_region_reference(&irb->region, intel_image->mt->region);
    }
 
-   /* compute offset of the particular 2D image within the texture region */
-   intel_miptree_get_image_offset(intel_image->mt,
-				  att->TextureLevel,
-				  att->CubeMapFace,
-				  att->Zoffset,
-				  &dst_x, &dst_y);
-
-   intel_image->mt->region->draw_offset = (dst_y * intel_image->mt->region->pitch +
-					   dst_x) * intel_image->mt->cpp;
-   intel_image->mt->region->draw_x = dst_x;
-   intel_image->mt->region->draw_y = dst_y;
+   intel_set_draw_offset_for_image(intel_image, att->Zoffset);
    intel_image->used_as_render_target = GL_TRUE;
 
+#ifndef I915
+   if (!brw_context(ctx)->has_surface_tile_offset &&
+       (intel_image->mt->region->draw_offset & 4095) != 0) {
+      /* Original gen4 hardware couldn't draw to a non-tile-aligned
+       * destination in a miptree unless you actually setup your
+       * renderbuffer as a miptree and used the fragile
+       * lod/array_index/etc. controls to select the image.  So,
+       * instead, we just make a new single-level miptree and render
+       * into that.
+       */
+      struct intel_mipmap_tree *old_mt = intel_image->mt;
+      struct intel_mipmap_tree *new_mt;
+      int comp_byte = 0, texel_bytes;
+
+      if (_mesa_is_format_compressed(intel_image->base.TexFormat))
+	 comp_byte = intel_compressed_num_bytes(intel_image->base.TexFormat);
+
+      texel_bytes = _mesa_get_format_bytes(intel_image->base.TexFormat);
+
+      new_mt = intel_miptree_create(intel, newImage->TexObject->Target,
+				    intel_image->base._BaseFormat,
+				    intel_image->base.InternalFormat,
+				    intel_image->level,
+				    intel_image->level,
+				    intel_image->base.Width,
+				    intel_image->base.Height,
+				    intel_image->base.Depth,
+				    texel_bytes, comp_byte, GL_TRUE);
+
+      intel_miptree_image_copy(intel,
+                               new_mt,
+                               intel_image->face,
+			       intel_image->level,
+			       old_mt);
+
+      intel_miptree_release(intel, &intel_image->mt);
+      intel_image->mt = new_mt;
+      intel_set_draw_offset_for_image(intel_image, att->Zoffset);
+
+      intel_region_release(&irb->region);
+      intel_region_reference(&irb->region, intel_image->mt->region);
+   }
+#endif
    /* update drawing region, etc */
    intel_draw_buffer(ctx, fb);
 }




More information about the mesa-commit mailing list