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

Eric Anholt eric at anholt.net
Tue Sep 27 12:27:31 PDT 2011


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 */
-- 
1.7.5.4



More information about the mesa-dev mailing list