[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