Some weird formats are omitted: ETC1. This patch will raise an assertion if intel_miptree_copy_slice is called on an ETC1 texture and intelEmitCopyBlit fails. However, I'm not certain if copy_slice can even be called on ETC1.
Other than the ETC1 problem, the patch looks good. I have a few nit requests that you can ignore if you wish. I'm withholding review until I'm convinced that copy_slice will not be called on ETC1 or I can think of a fix. On 11/05/2012 04:48 PM, Eric Anholt wrote: > Now that we have W-tiled S8, we can't just region_map and poke at bits -- > there has to be some swizzling. Rely on intel_miptree_map to get that job > done. This should also get the highest performance path we know of for the > mapping. > --- > src/mesa/drivers/dri/intel/intel_mipmap_tree.c | 101 > +++++++++++++++++++----- > src/mesa/drivers/dri/intel/intel_regions.c | 35 -------- > src/mesa/drivers/dri/intel/intel_regions.h | 10 --- > 3 files changed, 83 insertions(+), 63 deletions(-) > > diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c > b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c > index c70c1de..db0bac5 100644 > --- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c > +++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c > @@ -671,6 +671,68 @@ intel_miptree_get_image_offset(struct intel_mipmap_tree > *mt, > } > > static void > +intel_miptree_copy_slice_sw(struct intel_context *intel, > + struct intel_mipmap_tree *dst_mt, > + struct intel_mipmap_tree *src_mt, > + int level, > + int slice, > + int width, > + int height) > +{ > + void *src, *dst; > + int src_stride, dst_stride; > + int cpp = dst_mt->cpp; Below in intel_miptree_copy_slice, you add assert(src_mt->format == dst_mt->format); I'd like to see that assertion repeated here for documentation. > + > + /* If we're mapping separate stencil, the format we get mapped is not > + * mt->format! > + */ > + if (dst_mt->stencil_mt) { I would like a little comment here saying that, at time of miptree creation, the originally requested format was MESA_FORMAT_Z32_FLOAT_X24S8. Without such a comment, the `cpp = 8` is difficult to grok. It may seem obvious to you, the patch author, but I wasted a minute untying the if-tree's assumptions and the reason for `cpp = 8`. But I won't hold that comment nit against the patch. > + if (dst_mt->format == MESA_FORMAT_Z32_FLOAT) > + cpp = 8; > + else { Ditto for MESA_FORMAT_S8_Z24. > + assert(dst_mt->format == MESA_FORMAT_X8_Z24); > + assert(cpp == 4); > + } > + } > + > + intel_miptree_map(intel, src_mt, > + level, slice, > + 0, 0, > + width, height, > + GL_MAP_READ_BIT, > + &src, &src_stride); > + > + intel_miptree_map(intel, dst_mt, > + level, slice, > + 0, 0, > + width, height, > + GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT, > + &dst, &dst_stride); > + > + DBG("sw blit %s mt %p %p/%d -> %s mt %p %p/%d (%dx%d)\n", > + _mesa_get_format_name(src_mt->format), > + src_mt, src, src_stride, > + _mesa_get_format_name(dst_mt->format), > + dst_mt, dst, dst_stride, > + width, height); > + > + int row_size = cpp * width; > + if (src_stride == row_size && > + dst_stride == row_size) { > + memcpy(dst, src, row_size * height); > + } else { > + for (int i = 0; i < height; i++) { > + memcpy(dst, src, row_size); > + dst += dst_stride; > + src += src_stride; > + } > + } > + > + intel_miptree_unmap(intel, dst_mt, level, slice); > + intel_miptree_unmap(intel, src_mt, level, slice); > +} > + > +static void > intel_miptree_copy_slice(struct intel_context *intel, > struct intel_mipmap_tree *dst_mt, > struct intel_mipmap_tree *src_mt, > @@ -682,14 +744,33 @@ intel_miptree_copy_slice(struct intel_context *intel, > gl_format format = src_mt->format; > uint32_t width = src_mt->level[level].width; > uint32_t height = src_mt->level[level].height; > + int slice; > + > + if (face > 0) > + slice = face; > + else > + slice = depth; > > assert(depth < src_mt->level[level].depth); > + assert(src_mt->format == dst_mt->format); > > if (dst_mt->compressed) { > height = ALIGN(height, dst_mt->align_h) / dst_mt->align_h; > width = ALIGN(width, dst_mt->align_w); > } > > + /* If it's a packed depth/stencil buffer with separate stencil, we want to > + * just map the depth/stencil miptree and copy both depth and stencil > + * across in one go. > + */ > + if (src_mt->stencil_mt) { > + intel_miptree_copy_slice_sw(intel, > + dst_mt, src_mt, > + level, slice, > + width, height); > + return; > + } > + > uint32_t dst_x, dst_y, src_x, src_y; > intel_miptree_get_image_offset(dst_mt, level, face, depth, > &dst_x, &dst_y); > @@ -716,25 +797,9 @@ intel_miptree_copy_slice(struct intel_context *intel, > > fallback_debug("miptree validate blit for %s failed\n", > _mesa_get_format_name(format)); > - void *dst = intel_region_map(intel, dst_mt->region, GL_MAP_WRITE_BIT); > - void *src = intel_region_map(intel, src_mt->region, GL_MAP_READ_BIT); > - > - _mesa_copy_rect(dst, > - dst_mt->cpp, > - dst_mt->region->pitch, > - dst_x, dst_y, > - width, height, > - src, src_mt->region->pitch, > - src_x, src_y); > - > - intel_region_unmap(intel, dst_mt->region); > - intel_region_unmap(intel, src_mt->region); > - } > > - if (src_mt->stencil_mt) { > - intel_miptree_copy_slice(intel, > - dst_mt->stencil_mt, src_mt->stencil_mt, > - level, face, depth); > + intel_miptree_copy_slice_sw(intel, dst_mt, src_mt, level, slice, > + width, height); > } > } > > diff --git a/src/mesa/drivers/dri/intel/intel_regions.c > b/src/mesa/drivers/dri/intel/intel_regions.c > index 7cb008c..15c8ab9 100644 > --- a/src/mesa/drivers/dri/intel/intel_regions.c > +++ b/src/mesa/drivers/dri/intel/intel_regions.c > @@ -328,41 +328,6 @@ intel_region_release(struct intel_region **region_handle) > *region_handle = NULL; > } > > -/* > - * XXX Move this into core Mesa? > - */ > -void > -_mesa_copy_rect(GLubyte * dst, > - GLuint cpp, > - GLuint dst_pitch, > - GLuint dst_x, > - GLuint dst_y, > - GLuint width, > - GLuint height, > - const GLubyte * src, > - GLuint src_pitch, GLuint src_x, GLuint src_y) > -{ > - GLuint i; > - > - dst_pitch *= cpp; > - src_pitch *= cpp; > - dst += dst_x * cpp; > - src += src_x * cpp; > - dst += dst_y * dst_pitch; > - src += src_y * src_pitch; > - width *= cpp; > - > - if (width == dst_pitch && width == src_pitch) > - memcpy(dst, src, height * width); > - else { > - for (i = 0; i < height; i++) { > - memcpy(dst, src, width); > - dst += dst_pitch; > - src += src_pitch; > - } > - } > -} > - > /* Copy rectangular sub-regions. Need better logic about when to > * push buffers into AGP - will currently do so whenever possible. > */ > diff --git a/src/mesa/drivers/dri/intel/intel_regions.h > b/src/mesa/drivers/dri/intel/intel_regions.h > index 8737a6d..a463b04 100644 > --- a/src/mesa/drivers/dri/intel/intel_regions.h > +++ b/src/mesa/drivers/dri/intel/intel_regions.h > @@ -123,16 +123,6 @@ intel_region_copy(struct intel_context *intel, > bool flip, > GLenum logicop); > > -void _mesa_copy_rect(GLubyte * dst, > - GLuint cpp, > - GLuint dst_pitch, > - GLuint dst_x, > - GLuint dst_y, > - GLuint width, > - GLuint height, > - const GLubyte * src, > - GLuint src_pitch, GLuint src_x, GLuint src_y); > - > void > intel_region_get_tile_masks(struct intel_region *region, > uint32_t *mask_x, uint32_t *mask_y, > _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev