[Mesa-dev] [PATCH] mesa: Convert _mesa_generate_mipmap to MapTexImage()-based access.

Chad Versace chad at chad-versace.us
Wed Sep 28 12:32:48 PDT 2011


This patch fixes many Piglit tests [failing due to assert(region->map_refcount == 0)]
on SNB when HiZ is enabled, and causes no regressions.

Tested-by: Chad Versace <chad at chad-versace.us>

On 09/27/2011 12:27 PM, Eric Anholt wrote:
> From: Brian Paul<brianp at vmware.com>
>
> Now that we can zero-copy generate the mipmaps into brand new
> glTexImage()-generated storage using MapTextureImage(), we no longer
> need to allocate image->Data in mipmap generate.  This requires
> deleting the drivers' old overrides of the miptree tracking after
> calling _mesa_generate_mipmap at the same time, or the drivers
> promptly lose our newly-generated data.
> ---
>   src/mesa/drivers/dri/intel/intel_tex.c         |   30 +---
>   src/mesa/drivers/dri/nouveau/nouveau_texture.c |   10 -
>   src/mesa/drivers/dri/radeon/radeon_texture.c   |   50 +-----
>   src/mesa/main/mipmap.c                         |  270 +++++++++++++-----------
>   src/mesa/main/mipmap.h                         |    4 +-
>   src/mesa/state_tracker/st_gen_mipmap.c         |  205 +------------------
>   6 files changed, 153 insertions(+), 416 deletions(-)
>
> diff --git a/src/mesa/drivers/dri/intel/intel_tex.c b/src/mesa/drivers/dri/intel/intel_tex.c
> index 55b3e34..bc7b1f6 100644
> --- a/src/mesa/drivers/dri/intel/intel_tex.c
> +++ b/src/mesa/drivers/dri/intel/intel_tex.c
> @@ -163,37 +163,9 @@ intelGenerateMipmap(struct gl_context *ctx, GLenum target,
>                       struct gl_texture_object *texObj)
>   {
>      if (_mesa_meta_check_generate_mipmap_fallback(ctx, target, texObj)) {
> -      /* sw path: need to map texture images */
> -      struct intel_context *intel = intel_context(ctx);
> -      struct intel_texture_object *intelObj = intel_texture_object(texObj);
> -      struct gl_texture_image *first_image = texObj->Image[0][texObj->BaseLevel];
> -
>         fallback_debug("%s - fallback to swrast\n", __FUNCTION__);
>
> -      if (_mesa_is_format_compressed(first_image->TexFormat)) {
> -         _mesa_generate_mipmap(ctx, target, texObj);
> -      } else {
> -         intel_tex_map_level_images(intel, intelObj, texObj->BaseLevel);
> -         _mesa_generate_mipmap(ctx, target, texObj);
> -         intel_tex_unmap_level_images(intel, intelObj, texObj->BaseLevel);
> -      }
> -
> -      if (!_mesa_is_format_compressed(first_image->TexFormat)) {
> -         GLuint nr_faces = (texObj->Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
> -         GLuint face, i;
> -         for (face = 0; face<  nr_faces; face++) {
> -            for (i = texObj->BaseLevel + 1; i<  texObj->MaxLevel; i++) {
> -               struct intel_texture_image *intelImage =
> -                  intel_texture_image(texObj->Image[face][i]);
> -               if (!intelImage)
> -                  break;
> -               /* Unreference the miptree to signal that the new Data is a
> -                * bare pointer from mesa.
> -                */
> -               intel_miptree_release(&intelImage->mt);
> -            }
> -         }
> -      }
> +      _mesa_generate_mipmap(ctx, target, texObj);
>      }
>      else {
>         _mesa_meta_GenerateMipmap(ctx, target, texObj);
> diff --git a/src/mesa/drivers/dri/nouveau/nouveau_texture.c b/src/mesa/drivers/dri/nouveau/nouveau_texture.c
> index 9dc2186..508c8a5 100644
> --- a/src/mesa/drivers/dri/nouveau/nouveau_texture.c
> +++ b/src/mesa/drivers/dri/nouveau/nouveau_texture.c
> @@ -739,17 +739,7 @@ nouveau_generate_mipmap(struct gl_context *ctx, GLenum target,
>   {
>   	if (_mesa_meta_check_generate_mipmap_fallback(ctx, target, t)) {
>   		struct gl_texture_image *base = t->Image[0][t->BaseLevel];
> -
> -		nouveau_teximage_map(ctx, base, GL_MAP_READ_BIT,
> -				     0, 0, base->Width, base->Height);
>   		_mesa_generate_mipmap(ctx, target, t);
> -		nouveau_teximage_unmap(ctx, base);
> -
> -		if (!_mesa_is_format_compressed(base->TexFormat)) {
> -			store_mipmap(ctx, target, t->BaseLevel + 1,
> -				     get_last_level(t), t);
> -		}
> -
>   	} else {
>   		_mesa_meta_GenerateMipmap(ctx, target, t);
>   	}
> diff --git a/src/mesa/drivers/dri/radeon/radeon_texture.c b/src/mesa/drivers/dri/radeon/radeon_texture.c
> index 7f824ce..6bd8967 100644
> --- a/src/mesa/drivers/dri/radeon/radeon_texture.c
> +++ b/src/mesa/drivers/dri/radeon/radeon_texture.c
> @@ -324,52 +324,6 @@ radeon_unmap_texture_image(struct gl_context *ctx,
>   		radeon_bo_unmap(image->mt->bo);
>   }
>
> -/**
> - * Wraps Mesa's implementation to ensure that the base level image is mapped.
> - *
> - * This relies on internal details of _mesa_generate_mipmap, in particular
> - * the fact that the memory for recreated texture images is always freed.
> - */
> -static void radeon_generate_mipmap(struct gl_context *ctx, GLenum target,
> -				   struct gl_texture_object *texObj)
> -{
> -	radeonTexObj* t = radeon_tex_obj(texObj);
> -	GLuint nr_faces = (t->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
> -	int i, face;
> -	struct gl_texture_image *first_image;
> -
> -	radeon_print(RADEON_TEXTURE, RADEON_VERBOSE,
> -			"%s(%p, tex %p) Target type %s.\n",
> -			__func__, ctx, texObj,
> -			_mesa_lookup_enum_by_nr(target));
> -
> -	_mesa_generate_mipmap(ctx, target, texObj);
> -
> -	/* For the compressed case, we don't need to do the
> -	 * non-TexImage recovery path below.
> -	 */
> -	first_image = texObj->Image[0][texObj->BaseLevel];
> -	if (_mesa_is_format_compressed(first_image->TexFormat))
> -		return;
> -
> -	for (face = 0; face<  nr_faces; face++) {
> -		for (i = texObj->BaseLevel + 1; i<  texObj->MaxLevel; i++) {
> -			radeon_texture_image *image;
> -
> -			image = get_radeon_texture_image(texObj->Image[face][i]);
> -
> -			if (image == NULL)
> -				break;
> -
> -			image->mtlevel = i;
> -			image->mtface = face;
> -
> -			radeon_miptree_unreference(&image->mt);
> -		}
> -	}
> -	
> -}
> -
>   void radeonGenerateMipmap(struct gl_context* ctx, GLenum target, struct gl_texture_object *texObj)
>   {
>   	radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
> @@ -392,9 +346,7 @@ void radeonGenerateMipmap(struct gl_context* ctx, GLenum target, struct gl_textu
>   	}
>
>   	if (_mesa_meta_check_generate_mipmap_fallback(ctx, target, texObj)) {
> -		radeon_teximage_map(baseimage, GL_FALSE);
> -		radeon_generate_mipmap(ctx, target, texObj);
> -		radeon_teximage_unmap(baseimage);
> +		_mesa_generate_mipmap(ctx, target, texObj);
>   	} else {
>   		_mesa_meta_GenerateMipmap(ctx, target, texObj);
>   	}
> diff --git a/src/mesa/main/mipmap.c b/src/mesa/main/mipmap.c
> index e0cc6a2..4c8ab23 100644
> --- a/src/mesa/main/mipmap.c
> +++ b/src/mesa/main/mipmap.c
> @@ -1414,8 +1414,6 @@ make_2d_mipmap(GLenum datatype, GLuint comps, GLint border,
>      const GLint srcWidthNB = srcWidth - 2 * border;  /* sizes w/out border */
>      const GLint dstWidthNB = dstWidth - 2 * border;
>      const GLint dstHeightNB = dstHeight - 2 * border;
> -   const GLint srcRowBytes = bpt * srcRowStride;
> -   const GLint dstRowBytes = bpt * dstRowStride;
>      const GLubyte *srcA, *srcB;
>      GLubyte *dst;
>      GLint row, srcRowStep;
> @@ -1424,7 +1422,7 @@ make_2d_mipmap(GLenum datatype, GLuint comps, GLint border,
>      srcA = srcPtr + border * ((srcWidth + 1) * bpt);
>      if (srcHeight>  1&&  srcHeight>  dstHeight) {
>         /* sample from two source rows */
> -      srcB = srcA + srcRowBytes;
> +      srcB = srcA + srcRowStride;
>         srcRowStep = 2;
>      }
>      else {
> @@ -1438,9 +1436,9 @@ make_2d_mipmap(GLenum datatype, GLuint comps, GLint border,
>      for (row = 0; row<  dstHeightNB; row++) {
>         do_row(datatype, comps, srcWidthNB, srcA, srcB,
>                dstWidthNB, dst);
> -      srcA += srcRowStep * srcRowBytes;
> -      srcB += srcRowStep * srcRowBytes;
> -      dst += dstRowBytes;
> +      srcA += srcRowStep * srcRowStride;
> +      srcB += srcRowStep * srcRowStride;
> +      dst += dstRowStride;
>      }
>
>      /* This is ugly but probably won't be used much */
> @@ -1500,9 +1498,9 @@ make_2d_mipmap(GLenum datatype, GLuint comps, GLint border,
>   static void
>   make_3d_mipmap(GLenum datatype, GLuint comps, GLint border,
>                  GLint srcWidth, GLint srcHeight, GLint srcDepth,
> -               const GLubyte *srcPtr, GLint srcRowStride,
> +               const GLubyte **srcPtr, GLint srcRowStride,
>                  GLint dstWidth, GLint dstHeight, GLint dstDepth,
> -               GLubyte *dstPtr, GLint dstRowStride)
> +               GLubyte **dstPtr, GLint dstRowStride)
>   {
>      const GLint bpt = bytes_per_pixel(datatype, comps);
>      const GLint srcWidthNB = srcWidth - 2 * border;  /* sizes w/out border */
> @@ -1525,7 +1523,7 @@ make_3d_mipmap(GLenum datatype, GLuint comps, GLint border,
>      bytesPerDstRow = dstWidth * bpt;
>
>      /* Offset between adjacent src images to be averaged together */
> -   srcImageOffset = (srcDepth == dstDepth) ? 0 : bytesPerSrcImage;
> +   srcImageOffset = (srcDepth == dstDepth) ? 0 : 1;
>
>      /* Offset between adjacent src rows to be averaged together */
>      srcRowOffset = (srcHeight == dstHeight) ? 0 : srcWidth * bpt;
> @@ -1545,15 +1543,15 @@ make_3d_mipmap(GLenum datatype, GLuint comps, GLint border,
>
>      for (img = 0; img<  dstDepthNB; img++) {
>         /* first source image pointer, skipping border */
> -      const GLubyte *imgSrcA = srcPtr
> -         + (bytesPerSrcImage + bytesPerSrcRow + border) * bpt * border
> -         + img * (bytesPerSrcImage + srcImageOffset);
> +      const GLubyte *imgSrcA = srcPtr[img * 2 + border]
> +         + bytesPerSrcRow * border + bpt * border;
>         /* second source image pointer, skipping border */
> -      const GLubyte *imgSrcB = imgSrcA + srcImageOffset;
> +      const GLubyte *imgSrcB = srcPtr[img * 2 + srcImageOffset + border]
> +         + bytesPerSrcRow * border + bpt * border;
> +
>         /* address of the dest image, skipping border */
> -      GLubyte *imgDst = dstPtr
> -         + (bytesPerDstImage + bytesPerDstRow + border) * bpt * border
> -         + img * bytesPerDstImage;
> +      GLubyte *imgDst = dstPtr[img + border]
> +         + bytesPerDstRow * border + bpt * border;
>
>         /* setup the four source row pointers and the dest row pointer */
>         const GLubyte *srcImgARowA = imgSrcA;
> @@ -1581,13 +1579,14 @@ make_3d_mipmap(GLenum datatype, GLuint comps, GLint border,
>      /* Luckily we can leverage the make_2d_mipmap() function here! */
>      if (border>  0) {
>         /* do front border image */
> -      make_2d_mipmap(datatype, comps, 1, srcWidth, srcHeight, srcPtr, srcRowStride,
> -                     dstWidth, dstHeight, dstPtr, dstRowStride);
> +      make_2d_mipmap(datatype, comps, 1,
> +                     srcWidth, srcHeight, srcPtr[0], srcRowStride,
> +                     dstWidth, dstHeight, dstPtr[0], dstRowStride);
>         /* do back border image */
> -      make_2d_mipmap(datatype, comps, 1, srcWidth, srcHeight,
> -                     srcPtr + bytesPerSrcImage * (srcDepth - 1), srcRowStride,
> -                     dstWidth, dstHeight,
> -                     dstPtr + bytesPerDstImage * (dstDepth - 1), dstRowStride);
> +      make_2d_mipmap(datatype, comps, 1,
> +                     srcWidth, srcHeight, srcPtr[srcDepth - 1], srcRowStride,
> +                     dstWidth, dstHeight, dstPtr[dstDepth - 1], dstRowStride);
> +
>         /* do four remaining border edges that span the image slices */
>         if (srcDepth == dstDepth) {
>            /* just copy border pixels from src to dst */
> @@ -1596,29 +1595,23 @@ make_3d_mipmap(GLenum datatype, GLuint comps, GLint border,
>               GLubyte *dst;
>
>               /* do border along [img][row=0][col=0] */
> -            src = srcPtr + (img + 1) * bytesPerSrcImage;
> -            dst = dstPtr + (img + 1) * bytesPerDstImage;
> +            src = srcPtr[img * 2];
> +            dst = dstPtr[img];
>               memcpy(dst, src, bpt);
>
>               /* do border along [img][row=dstHeight-1][col=0] */
> -            src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
> -                         + (srcHeight - 1) * bytesPerSrcRow;
> -            dst = dstPtr + (img + 1) * bytesPerDstImage
> -                         + (dstHeight - 1) * bytesPerDstRow;
> +            src = srcPtr[img * 2] + (srcHeight - 1) * bytesPerSrcRow;
> +            dst = dstPtr[img] + (dstHeight - 1) * bytesPerDstRow;
>               memcpy(dst, src, bpt);
>
>               /* do border along [img][row=0][col=dstWidth-1] */
> -            src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
> -                         + (srcWidth - 1) * bpt;
> -            dst = dstPtr + (img + 1) * bytesPerDstImage
> -                         + (dstWidth - 1) * bpt;
> +            src = srcPtr[img * 2] + (srcWidth - 1) * bpt;
> +            dst = dstPtr[img] + (dstWidth - 1) * bpt;
>               memcpy(dst, src, bpt);
>
>               /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
> -            src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
> -                         + (bytesPerSrcImage - bpt);
> -            dst = dstPtr + (img + 1) * bytesPerDstImage
> -                         + (bytesPerDstImage - bpt);
> +            src = srcPtr[img * 2] + (bytesPerSrcImage - bpt);
> +            dst = dstPtr[img] + (bytesPerDstImage - bpt);
>               memcpy(dst, src, bpt);
>            }
>         }
> @@ -1626,34 +1619,34 @@ make_3d_mipmap(GLenum datatype, GLuint comps, GLint border,
>            /* average border pixels from adjacent src image pairs */
>            ASSERT(srcDepthNB == 2 * dstDepthNB);
>            for (img = 0; img<  dstDepthNB; img++) {
> -            const GLubyte *src;
> +            const GLubyte *srcA, *srcB;
>               GLubyte *dst;
>
>               /* do border along [img][row=0][col=0] */
> -            src = srcPtr + (img * 2 + 1) * bytesPerSrcImage;
> -            dst = dstPtr + (img + 1) * bytesPerDstImage;
> -            do_row(datatype, comps, 1, src, src + srcImageOffset, 1, dst);
> +            srcA = srcPtr[img * 2 + 0];
> +            srcB = srcPtr[img * 2 + srcImageOffset];
> +            dst = dstPtr[img];
> +            do_row(datatype, comps, 1, srcA, srcB, 1, dst);
>
>               /* do border along [img][row=dstHeight-1][col=0] */
> -            src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
> -                         + (srcHeight - 1) * bytesPerSrcRow;
> -            dst = dstPtr + (img + 1) * bytesPerDstImage
> -                         + (dstHeight - 1) * bytesPerDstRow;
> -            do_row(datatype, comps, 1, src, src + srcImageOffset, 1, dst);
> +            srcA = srcPtr[img * 2 + 0]
> +               + (srcHeight - 1) * bytesPerSrcRow;
> +            srcB = srcPtr[img * 2 + srcImageOffset]
> +               + (srcHeight - 1) * bytesPerSrcRow;
> +            dst = dstPtr[img] + (dstHeight - 1) * bytesPerDstRow;
> +            do_row(datatype, comps, 1, srcA, srcB, 1, dst);
>
>               /* do border along [img][row=0][col=dstWidth-1] */
> -            src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
> -                         + (srcWidth - 1) * bpt;
> -            dst = dstPtr + (img + 1) * bytesPerDstImage
> -                         + (dstWidth - 1) * bpt;
> -            do_row(datatype, comps, 1, src, src + srcImageOffset, 1, dst);
> +            srcA = srcPtr[img * 2 + 0] + (srcWidth - 1) * bpt;
> +            srcB = srcPtr[img * 2 + srcImageOffset] + (srcWidth - 1) * bpt;
> +            dst = dstPtr[img] + (dstWidth - 1) * bpt;
> +            do_row(datatype, comps, 1, srcA, srcB, 1, dst);
>
>               /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
> -            src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
> -                         + (bytesPerSrcImage - bpt);
> -            dst = dstPtr + (img + 1) * bytesPerDstImage
> -                         + (bytesPerDstImage - bpt);
> -            do_row(datatype, comps, 1, src, src + srcImageOffset, 1, dst);
> +            srcA = srcPtr[img * 2 + 0] + (bytesPerSrcImage - bpt);
> +            srcB = srcPtr[img * 2 + srcImageOffset] + (bytesPerSrcImage - bpt);
> +            dst = dstPtr[img] + (bytesPerDstImage - bpt);
> +            do_row(datatype, comps, 1, srcA, srcB, 1, dst);
>            }
>         }
>      }
> @@ -1670,8 +1663,6 @@ make_1d_stack_mipmap(GLenum datatype, GLuint comps, GLint border,
>      const GLint srcWidthNB = srcWidth - 2 * border;  /* sizes w/out border */
>      const GLint dstWidthNB = dstWidth - 2 * border;
>      const GLint dstHeightNB = dstHeight - 2 * border;
> -   const GLint srcRowBytes = bpt * srcRowStride;
> -   const GLint dstRowBytes = bpt * dstRowStride;
>      const GLubyte *src;
>      GLubyte *dst;
>      GLint row;
> @@ -1683,8 +1674,8 @@ make_1d_stack_mipmap(GLenum datatype, GLuint comps, GLint border,
>      for (row = 0; row<  dstHeightNB; row++) {
>         do_row(datatype, comps, srcWidthNB, src, src,
>                dstWidthNB, dst);
> -      src += srcRowBytes;
> -      dst += dstRowBytes;
> +      src += srcRowStride;
> +      dst += dstRowStride;
>      }
>
>      if (border) {
> @@ -1708,87 +1699,86 @@ make_1d_stack_mipmap(GLenum datatype, GLuint comps, GLint border,
>   static void
>   make_2d_stack_mipmap(GLenum datatype, GLuint comps, GLint border,
>                        GLint srcWidth, GLint srcHeight,
> -		     const GLubyte *srcPtr, GLint srcRowStride,
> +		     const GLubyte **srcPtr, GLint srcRowStride,
>                        GLint dstWidth, GLint dstHeight, GLint dstDepth,
> -                     GLubyte *dstPtr, GLint dstRowStride)
> +                     GLubyte **dstPtr, GLint dstRowStride)
>   {
>      const GLint bpt = bytes_per_pixel(datatype, comps);
>      const GLint srcWidthNB = srcWidth - 2 * border;  /* sizes w/out border */
>      const GLint dstWidthNB = dstWidth - 2 * border;
>      const GLint dstHeightNB = dstHeight - 2 * border;
>      const GLint dstDepthNB = dstDepth - 2 * border;
> -   const GLint srcRowBytes = bpt * srcRowStride;
> -   const GLint dstRowBytes = bpt * dstRowStride;
>      const GLubyte *srcA, *srcB;
>      GLubyte *dst;
>      GLint layer;
>      GLint row;
>
> -   /* Compute src and dst pointers, skipping any border */
> -   srcA = srcPtr + border * ((srcWidth + 1) * bpt);
> -   if (srcHeight>  1)
> -      srcB = srcA + srcRowBytes;
> -   else
> -      srcB = srcA;
> -   dst = dstPtr + border * ((dstWidth + 1) * bpt);
> -
>      for (layer = 0; layer<  dstDepthNB; layer++) {
> +
> +      /* Compute src and dst pointers, skipping any border */
> +      srcA = srcPtr[layer] + border * (srcWidth + 1) * bpt;
> +      if (srcHeight>  1)
> +         srcB = srcA + srcRowStride;
> +      else
> +         srcB = srcA;
> +      dst = dstPtr[layer] + border * (dstWidth + 1) * bpt;
> +
>         for (row = 0; row<  dstHeightNB; row++) {
>            do_row(datatype, comps, srcWidthNB, srcA, srcB,
>                   dstWidthNB, dst);
> -         srcA += 2 * srcRowBytes;
> -         srcB += 2 * srcRowBytes;
> -         dst += dstRowBytes;
> +         srcA += 2 * srcRowStride;
> +         srcB += 2 * srcRowStride;
> +         dst += dstRowStride;
>         }
>
>         /* This is ugly but probably won't be used much */
>         if (border>  0) {
>            /* fill in dest border */
>            /* lower-left border pixel */
> -         assert(dstPtr);
> -         assert(srcPtr);
> -         memcpy(dstPtr, srcPtr, bpt);
> +         assert(dstPtr[layer]);
> +         assert(srcPtr[layer]);
> +         memcpy(dstPtr[layer], srcPtr[0], bpt);
>            /* lower-right border pixel */
> -         memcpy(dstPtr + (dstWidth - 1) * bpt,
> -                srcPtr + (srcWidth - 1) * bpt, bpt);
> +         memcpy(dstPtr[layer] + (dstWidth - 1) * bpt,
> +                srcPtr[layer] + (srcWidth - 1) * bpt, bpt);
>            /* upper-left border pixel */
> -         memcpy(dstPtr + dstWidth * (dstHeight - 1) * bpt,
> -                srcPtr + srcWidth * (srcHeight - 1) * bpt, bpt);
> +         memcpy(dstPtr[layer] + dstWidth * (dstHeight - 1) * bpt,
> +                srcPtr[layer] + srcWidth * (srcHeight - 1) * bpt, bpt);
>            /* upper-right border pixel */
> -         memcpy(dstPtr + (dstWidth * dstHeight - 1) * bpt,
> -                srcPtr + (srcWidth * srcHeight - 1) * bpt, bpt);
> +         memcpy(dstPtr[layer] + (dstWidth * dstHeight - 1) * bpt,
> +                srcPtr[layer] + (srcWidth * srcHeight - 1) * bpt, bpt);
>            /* lower border */
>            do_row(datatype, comps, srcWidthNB,
> -                srcPtr + bpt,
> -                srcPtr + bpt,
> -                dstWidthNB, dstPtr + bpt);
> +                srcPtr[layer] + bpt,
> +                srcPtr[layer] + bpt,
> +                dstWidthNB, dstPtr[layer] + bpt);
>            /* upper border */
>            do_row(datatype, comps, srcWidthNB,
> -                srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt,
> -                srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt,
> +                srcPtr[layer] + (srcWidth * (srcHeight - 1) + 1) * bpt,
> +                srcPtr[layer] + (srcWidth * (srcHeight - 1) + 1) * bpt,
>                   dstWidthNB,
> -                dstPtr + (dstWidth * (dstHeight - 1) + 1) * bpt);
> +                dstPtr[layer] + (dstWidth * (dstHeight - 1) + 1) * bpt);
>            /* left and right borders */
>            if (srcHeight == dstHeight) {
>               /* copy border pixel from src to dst */
>               for (row = 1; row<  srcHeight; row++) {
> -               memcpy(dstPtr + dstWidth * row * bpt,
> -                      srcPtr + srcWidth * row * bpt, bpt);
> -               memcpy(dstPtr + (dstWidth * row + dstWidth - 1) * bpt,
> -                      srcPtr + (srcWidth * row + srcWidth - 1) * bpt, bpt);
> +               memcpy(dstPtr[layer] + dstWidth * row * bpt,
> +                      srcPtr[layer] + srcWidth * row * bpt, bpt);
> +               memcpy(dstPtr[layer] + (dstWidth * row + dstWidth - 1) * bpt,
> +                      srcPtr[layer] + (srcWidth * row + srcWidth - 1) * bpt, bpt);
>               }
>            }
>            else {
>               /* average two src pixels each dest pixel */
>               for (row = 0; row<  dstHeightNB; row += 2) {
>                  do_row(datatype, comps, 1,
> -                      srcPtr + (srcWidth * (row * 2 + 1)) * bpt,
> -                      srcPtr + (srcWidth * (row * 2 + 2)) * bpt,
> -                      1, dstPtr + (dstWidth * row + 1) * bpt);
> +                      srcPtr[layer] + (srcWidth * (row * 2 + 1)) * bpt,
> +                      srcPtr[layer] + (srcWidth * (row * 2 + 2)) * bpt,
> +                      1, dstPtr[layer] + (dstWidth * row + 1) * bpt);
>                  do_row(datatype, comps, 1,
> -                      srcPtr + (srcWidth * (row * 2 + 1) + srcWidth - 1) * bpt,
> -                      srcPtr + (srcWidth * (row * 2 + 2) + srcWidth - 1) * bpt,
> -                      1, dstPtr + (dstWidth * row + 1 + dstWidth - 1) * bpt);
> +                      srcPtr[layer] + (srcWidth * (row * 2 + 1) + srcWidth - 1) * bpt,
> +                      srcPtr[layer] + (srcWidth * (row * 2 + 2) + srcWidth - 1) * bpt,
> +                      1, dstPtr[layer] + (dstWidth * row + 1 + dstWidth - 1) * bpt);
>               }
>            }
>         }
> @@ -1799,28 +1789,27 @@ make_2d_stack_mipmap(GLenum datatype, GLuint comps, GLint border,
>   /**
>    * Down-sample a texture image to produce the next lower mipmap level.
>    * \param comps  components per texel (1, 2, 3 or 4)
> - * \param srcRowStride  stride between source rows, in texels
> - * \param dstRowStride  stride between destination rows, in texels
> + * \param srcData  array[slice] of pointers to source image slices
> + * \param dstData  array[slice] of pointers to dest image slices
> + * \param srcRowStride  stride between source rows, in bytes
> + * \param dstRowStride  stride between destination rows, in bytes
>    */
>   void
>   _mesa_generate_mipmap_level(GLenum target,
>                               GLenum datatype, GLuint comps,
>                               GLint border,
>                               GLint srcWidth, GLint srcHeight, GLint srcDepth,
> -                            const GLubyte *srcData,
> +                            const GLubyte **srcData,
>                               GLint srcRowStride,
>                               GLint dstWidth, GLint dstHeight, GLint dstDepth,
> -                            GLubyte *dstData,
> +                            GLubyte **dstData,
>                               GLint dstRowStride)
>   {
> -   /*
> -    * We use simple 2x2 averaging to compute the next mipmap level.
> -    */
>      switch (target) {
>      case GL_TEXTURE_1D:
>         make_1d_mipmap(datatype, comps, border,
> -                     srcWidth, srcData,
> -                     dstWidth, dstData);
> +                     srcWidth, srcData[0],
> +                     dstWidth, dstData[0]);
>         break;
>      case GL_TEXTURE_2D:
>      case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
> @@ -1830,8 +1819,8 @@ _mesa_generate_mipmap_level(GLenum target,
>      case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
>      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
>         make_2d_mipmap(datatype, comps, border,
> -                     srcWidth, srcHeight, srcData, srcRowStride,
> -                     dstWidth, dstHeight, dstData, dstRowStride);
> +                     srcWidth, srcHeight, srcData[0], srcRowStride,
> +                     dstWidth, dstHeight, dstData[0], dstRowStride);
>         break;
>      case GL_TEXTURE_3D:
>         make_3d_mipmap(datatype, comps, border,
> @@ -1842,9 +1831,9 @@ _mesa_generate_mipmap_level(GLenum target,
>         break;
>      case GL_TEXTURE_1D_ARRAY_EXT:
>         make_1d_stack_mipmap(datatype, comps, border,
> -                           srcWidth, srcData, srcRowStride,
> +                           srcWidth, srcData[0], srcRowStride,
>                              dstWidth, dstHeight,
> -                           dstData, dstRowStride);
> +                           dstData[0], dstRowStride);
>         break;
>      case GL_TEXTURE_2D_ARRAY_EXT:
>         make_2d_stack_mipmap(datatype, comps, border,
> @@ -1857,7 +1846,7 @@ _mesa_generate_mipmap_level(GLenum target,
>         /* no mipmaps, do nothing */
>         break;
>      default:
> -      _mesa_problem(NULL, "bad dimensions in _mesa_generate_mipmaps");
> +      _mesa_problem(NULL, "bad tex target in _mesa_generate_mipmaps");
>         return;
>      }
>   }
> @@ -1919,12 +1908,14 @@ generate_mipmap_uncompressed(struct gl_context *ctx, GLenum target,
>
>      for (level = texObj->BaseLevel; level<  maxLevel; level++) {
>         /* generate image[level+1] from image[level] */
> -      const struct gl_texture_image *srcImage;
> -      struct gl_texture_image *dstImage;
> +      struct gl_texture_image *srcImage, *dstImage;
> +      GLint srcRowStride, dstRowStride;
>         GLint srcWidth, srcHeight, srcDepth;
>         GLint dstWidth, dstHeight, dstDepth;
>         GLint border;
> +      GLint slice;
>         GLboolean nextLevel;
> +      GLubyte **srcMaps, **dstMaps;
>
>         /* get src image parameters */
>         srcImage = _mesa_select_tex_image(ctx, texObj, target, level);
> @@ -1950,7 +1941,6 @@ generate_mipmap_uncompressed(struct gl_context *ctx, GLenum target,
>         /* Free old image data */
>         ctx->Driver.FreeTextureImageBuffer(ctx, dstImage);
>
> -      /* initialize new image */
>         _mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight,
>                                    dstDepth, border, srcImage->InternalFormat,
>                                    srcImage->TexFormat);
> @@ -1967,15 +1957,47 @@ generate_mipmap_uncompressed(struct gl_context *ctx, GLenum target,
>
>         ASSERT(dstImage->TexFormat);
>
> +      /* Map src texture image slices */
> +      srcMaps = (GLubyte **) malloc(srcDepth * sizeof(GLubyte *));
> +      for (slice = 0; slice<  srcDepth; slice++) {
> +         ctx->Driver.MapTextureImage(ctx, srcImage, slice,
> +                                     0, 0, srcWidth, srcHeight,
> +                                     GL_MAP_READ_BIT,
> +&srcMaps[slice],&srcRowStride);
> +      }
> +
> +      /* Map dst texture image slices */
> +      dstMaps = (GLubyte **) malloc(dstDepth * sizeof(GLubyte *));
> +      for (slice = 0; slice<  dstDepth; slice++) {
> +         ctx->Driver.MapTextureImage(ctx, dstImage, slice,
> +                                     0, 0, dstWidth, dstHeight,
> +                                     GL_MAP_WRITE_BIT,
> +&dstMaps[slice],&dstRowStride);
> +      }
> +
> +      /* generate one mipmap level (for 1D/2D/3D/array/etc texture) */
>         _mesa_generate_mipmap_level(target, datatype, comps, border,
>                                     srcWidth, srcHeight, srcDepth,
> -                                  srcImage->Data, srcImage->RowStride,
> +                                  (const GLubyte **) srcMaps, srcRowStride,
>                                     dstWidth, dstHeight, dstDepth,
> -                                  dstImage->Data, dstImage->RowStride);
> +                                  dstMaps, dstRowStride);
> +
> +      /* Unmap src image slices */
> +      for (slice = 0; slice<  srcDepth; slice++) {
> +         ctx->Driver.UnmapTextureImage(ctx, srcImage, slice);
> +      }
> +      free(srcMaps);
> +
> +      /* Unmap src image slices */
> +      for (slice = 0; slice<  dstDepth; slice++) {
> +         ctx->Driver.UnmapTextureImage(ctx, dstImage, slice);
> +      }
> +      free(dstMaps);
>
>      } /* loop over mipmap levels */
>   }
>
> +
>   static void
>   generate_mipmap_compressed(struct gl_context *ctx, GLenum target,
>   			   struct gl_texture_object *texObj,
> @@ -1985,7 +2007,7 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target,
>      GLint level;
>      gl_format temp_format;
>      GLint components;
> -   GLuint temp_src_stride, temp_dst_stride; /* in bytes */
> +   GLuint temp_src_stride; /* in bytes */
>      GLubyte *temp_src = NULL, *temp_dst = NULL;
>      GLenum temp_datatype;
>      GLenum temp_base_format;
> @@ -2048,6 +2070,7 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target,
>         GLint dstWidth, dstHeight, dstDepth;
>         GLint border;
>         GLboolean nextLevel;
> +      GLuint temp_dst_stride; /* in bytes */
>
>         /* get src image parameters */
>         srcImage = _mesa_select_tex_image(ctx, texObj, target, level);
> @@ -2084,15 +2107,19 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target,
>
>         _mesa_generate_mipmap_level(target, temp_datatype, components, border,
>                                     srcWidth, srcHeight, srcDepth,
> -                                  temp_src, temp_src_stride / components,
> +                                  (const GLubyte **)&temp_src,
> +                                  temp_src_stride,
>                                     dstWidth, dstHeight, dstDepth,
> -                                  temp_dst, temp_dst_stride / components);
> +&temp_dst, temp_dst_stride);
>
>         /* initialize new image */
>         _mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight,
>                                    dstDepth, border, srcImage->InternalFormat,
>                                    srcImage->TexFormat);
>
> +      /* Free old dest texture image buffer */
> +      ctx->Driver.FreeTextureImageBuffer(ctx, dstImage);
> +
>         ctx->Driver.TexImage2D(ctx, target, level + 1,
>   			     srcImage->InternalFormat,
>   			     dstWidth, dstHeight, border,
> @@ -2104,7 +2131,6 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target,
>   	 GLubyte *temp = temp_src;
>   	 temp_src = temp_dst;
>   	 temp_dst = temp;
> -
>   	 temp_src_stride = temp_dst_stride;
>         }
>      } /* loop over mipmap levels */
> diff --git a/src/mesa/main/mipmap.h b/src/mesa/main/mipmap.h
> index 4783950..8b7cd7d 100644
> --- a/src/mesa/main/mipmap.h
> +++ b/src/mesa/main/mipmap.h
> @@ -34,10 +34,10 @@ _mesa_generate_mipmap_level(GLenum target,
>                               GLenum datatype, GLuint comps,
>                               GLint border,
>                               GLint srcWidth, GLint srcHeight, GLint srcDepth,
> -                            const GLubyte *srcData,
> +                            const GLubyte **srcData,
>                               GLint srcRowStride,
>                               GLint dstWidth, GLint dstHeight, GLint dstDepth,
> -                            GLubyte *dstData,
> +                            GLubyte **dstData,
>                               GLint dstRowStride);
>
>
> diff --git a/src/mesa/state_tracker/st_gen_mipmap.c b/src/mesa/state_tracker/st_gen_mipmap.c
> index e53da5f..36fea3d 100644
> --- a/src/mesa/state_tracker/st_gen_mipmap.c
> +++ b/src/mesa/state_tracker/st_gen_mipmap.c
> @@ -106,209 +106,6 @@ st_render_mipmap(struct st_context *st,
>      return TRUE;
>   }
>
> -
> -/**
> - * Helper function to decompress an image.  The result is a 32-bpp RGBA
> - * image with stride==width.
> - */
> -static void
> -decompress_image(enum pipe_format format, int datatype,
> -                 const uint8_t *src, void *dst,
> -                 unsigned width, unsigned height, unsigned src_stride)
> -{
> -   const struct util_format_description *desc = util_format_description(format);
> -   const uint bw = util_format_get_blockwidth(format);
> -   const uint bh = util_format_get_blockheight(format);
> -   uint dst_stride = 4 * MAX2(width, bw);
> -
> -   if (datatype == GL_FLOAT) {
> -      desc->unpack_rgba_float((float *)dst, dst_stride * sizeof(GLfloat), src, src_stride, width, height);
> -      if (width<  bw || height<  bh) {
> -	 float *dst_p = (float *)dst;
> -	 /* We're decompressing an image smaller than the compression
> -	  * block size.  We don't want garbage pixel values in the region
> -	  * outside (width x height) so replicate pixels from the (width
> -	  * x height) region to fill out the (bw x bh) block size.
> -	  */
> -	 uint x, y;
> -	 for (y = 0; y<  bh; y++) {
> -	    for (x = 0; x<  bw; x++) {
> -	       if (x>= width || y>= height) {
> -		  uint p = (y * bw + x) * 4;
> -		  dst_p[p + 0] = dst_p[0];
> -		  dst_p[p + 1] = dst_p[1];
> -		  dst_p[p + 2] = dst_p[2];
> -		  dst_p[p + 3] = dst_p[3];
> -	       }
> -	    }
> -	 }
> -      }
> -   } else {
> -      desc->unpack_rgba_8unorm((uint8_t *)dst, dst_stride, src, src_stride, width, height);
> -      if (width<  bw || height<  bh) {
> -	 uint8_t *dst_p = (uint8_t *)dst;
> -	 /* We're decompressing an image smaller than the compression
> -	  * block size.  We don't want garbage pixel values in the region
> -	  * outside (width x height) so replicate pixels from the (width
> -	  * x height) region to fill out the (bw x bh) block size.
> -	  */
> -	 uint x, y;
> -	 for (y = 0; y<  bh; y++) {
> -	    for (x = 0; x<  bw; x++) {
> -	       if (x>= width || y>= height) {
> -		  uint p = (y * bw + x) * 4;
> -		  dst_p[p + 0] = dst_p[0];
> -		  dst_p[p + 1] = dst_p[1];
> -		  dst_p[p + 2] = dst_p[2];
> -		  dst_p[p + 3] = dst_p[3];
> -	       }
> -	    }
> -	 }
> -      }
> -   }
> -}
> -
> -/**
> - * Helper function to compress an image.  The source is a 32-bpp RGBA image
> - * with stride==width.
> - */
> -static void
> -compress_image(enum pipe_format format, int datatype,
> -               const void *src, uint8_t *dst,
> -               unsigned width, unsigned height, unsigned dst_stride)
> -{
> -   const struct util_format_description *desc = util_format_description(format);
> -   const uint src_stride = 4 * width;
> -
> -   if (datatype == GL_FLOAT)
> -      desc->pack_rgba_float(dst, dst_stride, (GLfloat *)src, src_stride * sizeof(GLfloat), width, height);
> -   else
> -      desc->pack_rgba_8unorm(dst, dst_stride, (uint8_t *)src, src_stride, width, height);
> -}
> -
> -
> -/**
> - * Software fallback for generate mipmap levels.
> - */
> -static void
> -fallback_generate_mipmap(struct gl_context *ctx, GLenum target,
> -                         struct gl_texture_object *texObj)
> -{
> -   struct pipe_context *pipe = st_context(ctx)->pipe;
> -   struct pipe_resource *pt = st_get_texobj_resource(texObj);
> -   const uint baseLevel = texObj->BaseLevel;
> -   const uint lastLevel = pt->last_level;
> -   const uint face = _mesa_tex_target_to_face(target);
> -   uint dstLevel;
> -   GLenum datatype;
> -   GLuint comps;
> -   GLboolean compressed;
> -
> -   if (ST_DEBUG&  DEBUG_FALLBACK)
> -      debug_printf("%s: fallback processing\n", __FUNCTION__);
> -
> -   assert(target != GL_TEXTURE_3D); /* not done yet */
> -
> -   compressed =
> -      _mesa_is_format_compressed(texObj->Image[face][baseLevel]->TexFormat);
> -
> -   if (compressed) {
> -      GLenum type =
> -         _mesa_get_format_datatype(texObj->Image[face][baseLevel]->TexFormat);
> -
> -      datatype = type == GL_UNSIGNED_NORMALIZED ? GL_UNSIGNED_BYTE : GL_FLOAT;
> -      comps = 4;
> -   }
> -   else {
> -      _mesa_format_to_type_and_comps(texObj->Image[face][baseLevel]->TexFormat,
> -&datatype,&comps);
> -      assert(comps>  0&&  "bad texture format in fallback_generate_mipmap()");
> -   }
> -
> -   for (dstLevel = baseLevel + 1; dstLevel<= lastLevel; dstLevel++) {
> -      const uint srcLevel = dstLevel - 1;
> -      const uint srcWidth = u_minify(pt->width0, srcLevel);
> -      const uint srcHeight = u_minify(pt->height0, srcLevel);
> -      const uint srcDepth = u_minify(pt->depth0, srcLevel);
> -      const uint dstWidth = u_minify(pt->width0, dstLevel);
> -      const uint dstHeight = u_minify(pt->height0, dstLevel);
> -      const uint dstDepth = u_minify(pt->depth0, dstLevel);
> -      struct pipe_transfer *srcTrans, *dstTrans;
> -      const ubyte *srcData;
> -      ubyte *dstData;
> -      int srcStride, dstStride;
> -
> -      srcTrans = pipe_get_transfer(pipe, pt, srcLevel,
> -                                   face,
> -                                   PIPE_TRANSFER_READ, 0, 0,
> -                                   srcWidth, srcHeight);
> -
> -      dstTrans = pipe_get_transfer(pipe, pt, dstLevel,
> -                                   face,
> -                                   PIPE_TRANSFER_WRITE, 0, 0,
> -                                   dstWidth, dstHeight);
> -
> -      srcData = (ubyte *) pipe_transfer_map(pipe, srcTrans);
> -      dstData = (ubyte *) pipe_transfer_map(pipe, dstTrans);
> -
> -      srcStride = srcTrans->stride / util_format_get_blocksize(srcTrans->resource->format);
> -      dstStride = dstTrans->stride / util_format_get_blocksize(dstTrans->resource->format);
> -
> -     /* this cannot work correctly for 3d since it does
> -        not respect layerStride. */
> -      if (compressed) {
> -         const enum pipe_format format = pt->format;
> -         const uint bw = util_format_get_blockwidth(format);
> -         const uint bh = util_format_get_blockheight(format);
> -         const uint srcWidth2 = align(srcWidth, bw);
> -         const uint srcHeight2 = align(srcHeight, bh);
> -         const uint dstWidth2 = align(dstWidth, bw);
> -         const uint dstHeight2 = align(dstHeight, bh);
> -         uint8_t *srcTemp, *dstTemp;
> -
> -         assert(comps == 4);
> -
> -         srcTemp = malloc(srcWidth2 * srcHeight2 * comps * (datatype == GL_FLOAT ? 4 : 1));
> -         dstTemp = malloc(dstWidth2 * dstHeight2 * comps * (datatype == GL_FLOAT ? 4 : 1));
> -
> -         /* decompress the src image: srcData ->  srcTemp */
> -         decompress_image(format, datatype, srcData, srcTemp, srcWidth2, srcHeight2, srcTrans->stride);
> -
> -         _mesa_generate_mipmap_level(target, datatype, comps,
> -                                     0 /*border*/,
> -                                     srcWidth2, srcHeight2, srcDepth,
> -                                     srcTemp,
> -                                     srcWidth2, /* stride in texels */
> -                                     dstWidth2, dstHeight2, dstDepth,
> -                                     dstTemp,
> -                                     dstWidth2); /* stride in texels */
> -
> -         /* compress the new image: dstTemp ->  dstData */
> -         compress_image(format, datatype, dstTemp, dstData, dstWidth2, dstHeight2, dstTrans->stride);
> -
> -         free(srcTemp);
> -         free(dstTemp);
> -      }
> -      else {
> -         _mesa_generate_mipmap_level(target, datatype, comps,
> -                                     0 /*border*/,
> -                                     srcWidth, srcHeight, srcDepth,
> -                                     srcData,
> -                                     srcStride, /* stride in texels */
> -                                     dstWidth, dstHeight, dstDepth,
> -                                     dstData,
> -                                     dstStride); /* stride in texels */
> -      }
> -
> -      pipe_transfer_unmap(pipe, srcTrans);
> -      pipe_transfer_unmap(pipe, dstTrans);
> -
> -      pipe->transfer_destroy(pipe, srcTrans);
> -      pipe->transfer_destroy(pipe, dstTrans);
> -   }
> -}
> -
> -
>   /**
>    * Compute the expected number of mipmap levels in the texture given
>    * the width/height/depth of the base image and the GL_TEXTURE_BASE_LEVEL/
> @@ -422,7 +219,7 @@ st_generate_mipmap(struct gl_context *ctx, GLenum target,
>      if (!st_render_mipmap(st, target, stObj, baseLevel, lastLevel)) {
>         /* since the util code actually also has a fallback, should
>            probably make it never fail and kill this */
> -      fallback_generate_mipmap(ctx, target, texObj);
> +      _mesa_generate_mipmap(ctx, target, texObj);
>      }
>
>      /* Fill in the Mesa gl_texture_image fields */


More information about the mesa-dev mailing list