diff options
author | Eric Anholt <eric@anholt.net> | 2011-01-10 15:45:28 -0800 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2011-01-10 17:21:54 -0800 |
commit | c0cdae03685056e170c25da7d46aed959176d652 (patch) | |
tree | da0fd3d59d757a7c605a38289e5567af13ef2a48 /src/mesa/drivers | |
parent | 6bdc31942138f4dff5a701f26fe186a6e2e92275 (diff) |
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.
Diffstat (limited to 'src/mesa/drivers')
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_fallback.c | 29 | ||||
-rw-r--r-- | 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 7262cf6958..82356a5bc0 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 88934eb812..cbb6275e9c 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); } |