X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fmain%2Fmipmap.c;h=cc109cc52664129db5ddca5086f2af3190d1f8aa;hb=17cde55c538009764207bd29b78a909d2c5d14b4;hp=f04a98b0337fbcfa62706ebcc206f899b31e1ce2;hpb=c80aaad77e7d884ebe83ac72467d55ac505da5ee;p=mesa.git diff --git a/src/mesa/main/mipmap.c b/src/mesa/main/mipmap.c index f04a98b0337..cc109cc5266 100644 --- a/src/mesa/main/mipmap.c +++ b/src/mesa/main/mipmap.c @@ -1,6 +1,5 @@ /* * Mesa 3-D graphics library - * Version: 7.1 * * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. * @@ -17,9 +16,10 @@ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. */ @@ -29,9 +29,11 @@ #include "imports.h" #include "formats.h" +#include "glformats.h" #include "mipmap.h" #include "mtypes.h" #include "teximage.h" +#include "texobj.h" #include "texstore.h" #include "image.h" #include "macros.h" @@ -43,7 +45,13 @@ static GLint bytes_per_pixel(GLenum datatype, GLuint comps) { - GLint b = _mesa_sizeof_packed_type(datatype); + GLint b; + + if (datatype == GL_UNSIGNED_INT_8_24_REV_MESA || + datatype == GL_UNSIGNED_INT_24_8_MESA) + return 4; + + b = _mesa_sizeof_packed_type(datatype); assert(b >= 0); if (_mesa_type_is_packed(datatype)) @@ -470,7 +478,7 @@ do_row(GLenum datatype, GLuint comps, GLint srcWidth, GLuint *dst = (GLuint *) dstRow; for (i = j = 0, k = k0; i < (GLuint) dstWidth; i++, j += colStride, k += colStride) { - dst[i] = (GLfloat)(rowA[j] / 4 + rowA[k] / 4 + rowB[j] / 4 + rowB[k] / 4); + dst[i] = rowA[j] / 4 + rowA[k] / 4 + rowB[j] / 4 + rowB[k] / 4; } } @@ -717,6 +725,36 @@ do_row(GLenum datatype, GLuint comps, GLint srcWidth, } } + else if (datatype == GL_UNSIGNED_INT_24_8_MESA && comps == 2) { + GLuint i, j, k; + const GLuint *rowA = (const GLuint *) srcRowA; + const GLuint *rowB = (const GLuint *) srcRowB; + GLuint *dst = (GLuint *) dstRow; + /* note: averaging stencil values seems weird, but what else? */ + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + GLuint z = (((rowA[j] >> 8) + (rowA[k] >> 8) + + (rowB[j] >> 8) + (rowB[k] >> 8)) / 4) << 8; + GLuint s = ((rowA[j] & 0xff) + (rowA[k] & 0xff) + + (rowB[j] & 0xff) + (rowB[k] & 0xff)) / 4; + dst[i] = z | s; + } + } + else if (datatype == GL_UNSIGNED_INT_8_24_REV_MESA && comps == 2) { + GLuint i, j, k; + const GLuint *rowA = (const GLuint *) srcRowA; + const GLuint *rowB = (const GLuint *) srcRowB; + GLuint *dst = (GLuint *) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + GLuint z = ((rowA[j] & 0xffffff) + (rowA[k] & 0xffffff) + + (rowB[j] & 0xffffff) + (rowB[k] & 0xffffff)) / 4; + GLuint s = (((rowA[j] >> 24) + (rowA[k] >> 24) + + (rowB[j] >> 24) + (rowB[k] >> 24)) / 4) << 24; + dst[i] = z | s; + } + } + else { _mesa_problem(NULL, "bad format in do_row()"); } @@ -955,7 +993,7 @@ do_row_3D(GLenum datatype, GLuint comps, GLint srcWidth, } } else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 3)) { - DECLARE_ROW_POINTERS(GLhalfARB, 4); + DECLARE_ROW_POINTERS(GLhalfARB, 3); for (i = j = 0, k = k0; i < (GLuint) dstWidth; i++, j += colStride, k += colStride) { @@ -965,7 +1003,7 @@ do_row_3D(GLenum datatype, GLuint comps, GLint srcWidth, } } else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 2)) { - DECLARE_ROW_POINTERS(GLhalfARB, 4); + DECLARE_ROW_POINTERS(GLhalfARB, 2); for (i = j = 0, k = k0; i < (GLuint) dstWidth; i++, j += colStride, k += colStride) { @@ -974,7 +1012,7 @@ do_row_3D(GLenum datatype, GLuint comps, GLint srcWidth, } } else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 1)) { - DECLARE_ROW_POINTERS(GLhalfARB, 4); + DECLARE_ROW_POINTERS(GLhalfARB, 1); for (i = j = 0, k = k0; i < (GLuint) dstWidth; i++, j += colStride, k += colStride) { @@ -1510,23 +1548,18 @@ make_3d_mipmap(GLenum datatype, GLuint comps, GLint border, const GLint dstDepthNB = dstDepth - 2 * border; GLint img, row; GLint bytesPerSrcImage, bytesPerDstImage; - GLint bytesPerSrcRow, bytesPerDstRow; GLint srcImageOffset, srcRowOffset; (void) srcDepthNB; /* silence warnings */ - - bytesPerSrcImage = srcWidth * srcHeight * bpt; - bytesPerDstImage = dstWidth * dstHeight * bpt; - - bytesPerSrcRow = srcWidth * bpt; - bytesPerDstRow = dstWidth * bpt; + bytesPerSrcImage = srcRowStride * srcHeight * bpt; + bytesPerDstImage = dstRowStride * dstHeight * bpt; /* Offset between adjacent src images to be averaged together */ srcImageOffset = (srcDepth == dstDepth) ? 0 : 1; /* Offset between adjacent src rows to be averaged together */ - srcRowOffset = (srcHeight == dstHeight) ? 0 : srcWidth * bpt; + srcRowOffset = (srcHeight == dstHeight) ? 0 : srcRowStride; /* * Need to average together up to 8 src pixels for each dest pixel. @@ -1544,14 +1577,14 @@ 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[img * 2 + border] - + bytesPerSrcRow * border + bpt * border; + + srcRowStride * border + bpt * border; /* second source image pointer, skipping border */ const GLubyte *imgSrcB = srcPtr[img * 2 + srcImageOffset + border] - + bytesPerSrcRow * border + bpt * border; + + srcRowStride * border + bpt * border; /* address of the dest image, skipping border */ GLubyte *imgDst = dstPtr[img + border] - + bytesPerDstRow * border + bpt * border; + + dstRowStride * border + bpt * border; /* setup the four source row pointers and the dest row pointer */ const GLubyte *srcImgARowA = imgSrcA; @@ -1567,11 +1600,11 @@ make_3d_mipmap(GLenum datatype, GLuint comps, GLint border, dstWidthNB, dstImgRow); /* advance to next rows */ - srcImgARowA += bytesPerSrcRow + srcRowOffset; - srcImgARowB += bytesPerSrcRow + srcRowOffset; - srcImgBRowA += bytesPerSrcRow + srcRowOffset; - srcImgBRowB += bytesPerSrcRow + srcRowOffset; - dstImgRow += bytesPerDstRow; + srcImgARowA += srcRowStride + srcRowOffset; + srcImgARowB += srcRowStride + srcRowOffset; + srcImgBRowA += srcRowStride + srcRowOffset; + srcImgBRowB += srcRowStride + srcRowOffset; + dstImgRow += dstRowStride; } } @@ -1600,8 +1633,8 @@ make_3d_mipmap(GLenum datatype, GLuint comps, GLint border, memcpy(dst, src, bpt); /* do border along [img][row=dstHeight-1][col=0] */ - src = srcPtr[img * 2] + (srcHeight - 1) * bytesPerSrcRow; - dst = dstPtr[img] + (dstHeight - 1) * bytesPerDstRow; + src = srcPtr[img * 2] + (srcHeight - 1) * srcRowStride; + dst = dstPtr[img] + (dstHeight - 1) * dstRowStride; memcpy(dst, src, bpt); /* do border along [img][row=0][col=dstWidth-1] */ @@ -1630,10 +1663,10 @@ make_3d_mipmap(GLenum datatype, GLuint comps, GLint border, /* do border along [img][row=dstHeight-1][col=0] */ srcA = srcPtr[img * 2 + 0] - + (srcHeight - 1) * bytesPerSrcRow; + + (srcHeight - 1) * srcRowStride; srcB = srcPtr[img * 2 + srcImageOffset] - + (srcHeight - 1) * bytesPerSrcRow; - dst = dstPtr[img] + (dstHeight - 1) * bytesPerDstRow; + + (srcHeight - 1) * srcRowStride; + dst = dstPtr[img] + (dstHeight - 1) * dstRowStride; do_row(datatype, comps, 1, srcA, srcB, 1, dst); /* do border along [img][row=0][col=dstWidth-1] */ @@ -1708,6 +1741,7 @@ _mesa_generate_mipmap_level(GLenum target, } break; case GL_TEXTURE_2D_ARRAY_EXT: + case GL_TEXTURE_CUBE_MAP_ARRAY: for (i = 0; i < dstDepth; i++) { make_2d_mipmap(datatype, comps, border, srcWidth, srcHeight, srcData[i], srcRowStride, @@ -1715,6 +1749,7 @@ _mesa_generate_mipmap_level(GLenum target, } break; case GL_TEXTURE_RECTANGLE_NV: + case GL_TEXTURE_EXTERNAL_OES: /* no mipmaps, do nothing */ break; default: @@ -1728,8 +1763,8 @@ _mesa_generate_mipmap_level(GLenum target, * compute next (level+1) image size * \return GL_FALSE if no smaller size can be generated (eg. src is 1x1x1 size) */ -static GLboolean -next_mipmap_level_size(GLenum target, GLint border, +GLboolean +_mesa_next_mipmap_level_size(GLenum target, GLint border, GLint srcWidth, GLint srcHeight, GLint srcDepth, GLint *dstWidth, GLint *dstHeight, GLint *dstDepth) { @@ -1749,7 +1784,8 @@ next_mipmap_level_size(GLenum target, GLint border, } if ((srcDepth - 2 * border > 1) && - (target != GL_TEXTURE_2D_ARRAY_EXT)) { + (target != GL_TEXTURE_2D_ARRAY_EXT && + target != GL_TEXTURE_CUBE_MAP_ARRAY)) { *dstDepth = (srcDepth - 2 * border) / 2 + 2 * border; } else { @@ -1766,13 +1802,87 @@ next_mipmap_level_size(GLenum target, GLint border, } } + +/** + * Helper function for mipmap generation. + * Make sure the specified destination mipmap level is the right size/format + * for mipmap generation. If not, (re) allocate it. + * \return GL_TRUE if successful, GL_FALSE if mipmap generation should stop + */ +GLboolean +_mesa_prepare_mipmap_level(struct gl_context *ctx, + struct gl_texture_object *texObj, GLuint level, + GLsizei width, GLsizei height, GLsizei depth, + GLsizei border, GLenum intFormat, mesa_format format) +{ + const GLuint numFaces = _mesa_num_tex_faces(texObj->Target); + GLuint face; + + if (texObj->Immutable) { + /* The texture was created with glTexStorage() so the number/size of + * mipmap levels is fixed and the storage for all images is already + * allocated. + */ + if (!texObj->Image[0][level]) { + /* No more levels to create - we're done */ + return GL_FALSE; + } + else { + /* Nothing to do - the texture memory must have already been + * allocated to the right size so we're all set. + */ + return GL_TRUE; + } + } + + for (face = 0; face < numFaces; face++) { + struct gl_texture_image *dstImage; + GLenum target; + + if (numFaces == 1) + target = texObj->Target; + else + target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + face; + + dstImage = _mesa_get_tex_image(ctx, texObj, target, level); + if (!dstImage) { + /* out of memory */ + return GL_FALSE; + } + + if (dstImage->Width != width || + dstImage->Height != height || + dstImage->Depth != depth || + dstImage->Border != border || + dstImage->InternalFormat != intFormat || + dstImage->TexFormat != format) { + /* need to (re)allocate image */ + ctx->Driver.FreeTextureImageBuffer(ctx, dstImage); + + _mesa_init_teximage_fields(ctx, dstImage, + width, height, depth, + border, intFormat, format); + + ctx->Driver.AllocTextureImageBuffer(ctx, dstImage); + + /* in case the mipmap level is part of an FBO: */ + _mesa_update_fbo_texture(ctx, texObj, face, level); + + ctx->NewState |= _NEW_TEXTURE; + } + } + + return GL_TRUE; +} + + static void generate_mipmap_uncompressed(struct gl_context *ctx, GLenum target, struct gl_texture_object *texObj, const struct gl_texture_image *srcImage, GLuint maxLevel) { - GLint level; + GLuint level; GLenum datatype; GLuint comps; @@ -1788,6 +1898,7 @@ generate_mipmap_uncompressed(struct gl_context *ctx, GLenum target, GLint slice; GLboolean nextLevel; GLubyte **srcMaps, **dstMaps; + GLboolean success = GL_TRUE; /* get src image parameters */ srcImage = _mesa_select_tex_image(ctx, texObj, target, level); @@ -1797,37 +1908,26 @@ generate_mipmap_uncompressed(struct gl_context *ctx, GLenum target, srcDepth = srcImage->Depth; border = srcImage->Border; - nextLevel = next_mipmap_level_size(target, border, + nextLevel = _mesa_next_mipmap_level_size(target, border, srcWidth, srcHeight, srcDepth, &dstWidth, &dstHeight, &dstDepth); if (!nextLevel) return; - /* get dest gl_texture_image */ - dstImage = _mesa_get_tex_image(ctx, texObj, target, level + 1); - if (!dstImage) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps"); + if (!_mesa_prepare_mipmap_level(ctx, texObj, level + 1, + dstWidth, dstHeight, dstDepth, + border, srcImage->InternalFormat, + srcImage->TexFormat)) { return; } - /* Free old image data */ - ctx->Driver.FreeTextureImageBuffer(ctx, dstImage); - - _mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight, - dstDepth, border, srcImage->InternalFormat, - srcImage->TexFormat); - - /* Alloc storage for new texture image */ - if (!ctx->Driver.AllocTextureImageBuffer(ctx, dstImage, - dstImage->TexFormat, - dstWidth, dstHeight, - dstDepth)) { + /* get dest gl_texture_image */ + dstImage = _mesa_get_tex_image(ctx, texObj, target, level + 1); + if (!dstImage) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps"); return; } - ASSERT(dstImage->TexFormat); - if (target == GL_TEXTURE_1D_ARRAY) { srcDepth = srcHeight; dstDepth = dstHeight; @@ -1836,42 +1936,74 @@ generate_mipmap_uncompressed(struct gl_context *ctx, GLenum target, } /* 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); + srcMaps = calloc(srcDepth, sizeof(GLubyte *)); + if (srcMaps) { + for (slice = 0; slice < srcDepth; slice++) { + ctx->Driver.MapTextureImage(ctx, srcImage, slice, + 0, 0, srcWidth, srcHeight, + GL_MAP_READ_BIT, + &srcMaps[slice], &srcRowStride); + if (!srcMaps[slice]) { + success = GL_FALSE; + break; + } + } + } + else { + success = GL_FALSE; } /* 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); + dstMaps = calloc(dstDepth, sizeof(GLubyte *)); + if (dstMaps) { + for (slice = 0; slice < dstDepth; slice++) { + ctx->Driver.MapTextureImage(ctx, dstImage, slice, + 0, 0, dstWidth, dstHeight, + GL_MAP_WRITE_BIT, + &dstMaps[slice], &dstRowStride); + if (!dstMaps[slice]) { + success = GL_FALSE; + break; + } + } + } + else { + success = GL_FALSE; } - /* generate one mipmap level (for 1D/2D/3D/array/etc texture) */ - _mesa_generate_mipmap_level(target, datatype, comps, border, - srcWidth, srcHeight, srcDepth, - (const GLubyte **) srcMaps, srcRowStride, - dstWidth, dstHeight, dstDepth, - dstMaps, dstRowStride); + if (success) { + /* generate one mipmap level (for 1D/2D/3D/array/etc texture) */ + _mesa_generate_mipmap_level(target, datatype, comps, border, + srcWidth, srcHeight, srcDepth, + (const GLubyte **) srcMaps, srcRowStride, + dstWidth, dstHeight, dstDepth, + dstMaps, dstRowStride); + } /* Unmap src image slices */ - for (slice = 0; slice < srcDepth; slice++) { - ctx->Driver.UnmapTextureImage(ctx, srcImage, slice); + if (srcMaps) { + for (slice = 0; slice < srcDepth; slice++) { + if (srcMaps[slice]) { + ctx->Driver.UnmapTextureImage(ctx, srcImage, slice); + } + } + free(srcMaps); } - free(srcMaps); /* Unmap dst image slices */ - for (slice = 0; slice < dstDepth; slice++) { - ctx->Driver.UnmapTextureImage(ctx, dstImage, slice); + if (dstMaps) { + for (slice = 0; slice < dstDepth; slice++) { + if (dstMaps[slice]) { + ctx->Driver.UnmapTextureImage(ctx, dstImage, slice); + } + } + free(dstMaps); } - free(dstMaps); + if (!success) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "mipmap generation"); + break; + } } /* loop over mipmap levels */ } @@ -1882,17 +2014,20 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target, struct gl_texture_image *srcImage, GLuint maxLevel) { - GLint level; - gl_format temp_format; + GLuint level; + mesa_format temp_format; GLint components; - GLuint temp_src_stride; /* in bytes */ + GLuint temp_src_row_stride, temp_src_img_stride; /* in bytes */ GLubyte *temp_src = NULL, *temp_dst = NULL; GLenum temp_datatype; GLenum temp_base_format; + GLubyte **temp_src_slices = NULL, **temp_dst_slices = NULL; /* only two types of compressed textures at this time */ assert(texObj->Target == GL_TEXTURE_2D || - texObj->Target == GL_TEXTURE_CUBE_MAP_ARB); + texObj->Target == GL_TEXTURE_2D_ARRAY || + texObj->Target == GL_TEXTURE_CUBE_MAP_ARB || + texObj->Target == GL_TEXTURE_CUBE_MAP_ARRAY); /* * Choose a format for the temporary, uncompressed base image. @@ -1916,15 +2051,21 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target, /* allocate storage for the temporary, uncompressed image */ - /* 20 extra bytes, just be safe when calling last FetchTexel */ - temp_src_stride = _mesa_format_row_stride(temp_format, srcImage->Width); - temp_src = (GLubyte *) malloc(temp_src_stride * srcImage->Height + 20); - if (!temp_src) { + temp_src_row_stride = _mesa_format_row_stride(temp_format, srcImage->Width); + temp_src_img_stride = _mesa_format_image_size(temp_format, srcImage->Width, + srcImage->Height, 1); + temp_src = malloc(temp_src_img_stride * srcImage->Depth); + + /* Allocate storage for arrays of slice pointers */ + temp_src_slices = malloc(srcImage->Depth * sizeof(GLubyte *)); + temp_dst_slices = malloc(srcImage->Depth * sizeof(GLubyte *)); + + if (!temp_src || !temp_src_slices || !temp_dst_slices) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps"); - return; + goto end; } - /* decompress base image to the temporary */ + /* decompress base image to the temporary src buffer */ { /* save pixel packing mode */ struct gl_pixelstore_attrib save = ctx->Pack; @@ -1940,7 +2081,6 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target, ctx->Pack = save; } - for (level = texObj->BaseLevel; level < maxLevel; level++) { /* generate image[level+1] from image[level] */ const struct gl_texture_image *srcImage; @@ -1949,7 +2089,8 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target, GLint dstWidth, dstHeight, dstDepth; GLint border; GLboolean nextLevel; - GLuint temp_dst_stride; /* in bytes */ + GLuint temp_dst_row_stride, temp_dst_img_stride; /* in bytes */ + GLuint i; /* get src image parameters */ srcImage = _mesa_select_tex_image(ctx, texObj, target, level); @@ -1959,18 +2100,21 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target, srcDepth = srcImage->Depth; border = srcImage->Border; - nextLevel = next_mipmap_level_size(target, border, + nextLevel = _mesa_next_mipmap_level_size(target, border, srcWidth, srcHeight, srcDepth, &dstWidth, &dstHeight, &dstDepth); if (!nextLevel) break; - temp_dst_stride = _mesa_format_row_stride(temp_format, dstWidth); + /* Compute dst image strides and alloc memory on first iteration */ + temp_dst_row_stride = _mesa_format_row_stride(temp_format, dstWidth); + temp_dst_img_stride = _mesa_format_image_size(temp_format, dstWidth, + dstHeight, 1); if (!temp_dst) { - temp_dst = (GLubyte *) malloc(temp_dst_stride * dstHeight); + temp_dst = malloc(temp_dst_img_stride * dstDepth); if (!temp_dst) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps"); - break; + goto end; } } @@ -1978,44 +2122,56 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target, dstImage = _mesa_get_tex_image(ctx, texObj, target, level + 1); if (!dstImage) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps"); - return; + goto end; } - /* Free old image data */ - ctx->Driver.FreeTextureImageBuffer(ctx, dstImage); + /* for 2D arrays, setup array[depth] of slice pointers */ + for (i = 0; i < srcDepth; i++) { + temp_src_slices[i] = temp_src + temp_src_img_stride * i; + } + for (i = 0; i < dstDepth; i++) { + temp_dst_slices[i] = temp_dst + temp_dst_img_stride * i; + } + /* Rescale src image to dest image. + * This will loop over the slices of a 2D array. + */ _mesa_generate_mipmap_level(target, temp_datatype, components, border, srcWidth, srcHeight, srcDepth, - (const GLubyte **) &temp_src, - temp_src_stride, + (const GLubyte **) temp_src_slices, + temp_src_row_stride, dstWidth, dstHeight, dstDepth, - &temp_dst, temp_dst_stride); - - /* initialize new image */ - _mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight, - dstDepth, border, srcImage->InternalFormat, - srcImage->TexFormat); + temp_dst_slices, temp_dst_row_stride); - /* Free old dest texture image buffer */ - ctx->Driver.FreeTextureImageBuffer(ctx, dstImage); + if (!_mesa_prepare_mipmap_level(ctx, texObj, level + 1, + dstWidth, dstHeight, dstDepth, + border, srcImage->InternalFormat, + srcImage->TexFormat)) { + /* all done */ + goto end; + } - ctx->Driver.TexImage2D(ctx, target, level + 1, - srcImage->InternalFormat, - dstWidth, dstHeight, border, - temp_base_format, temp_datatype, - temp_dst, &ctx->DefaultPacking, texObj, dstImage); + /* The image space was allocated above so use glTexSubImage now */ + ctx->Driver.TexSubImage(ctx, 2, dstImage, + 0, 0, 0, dstWidth, dstHeight, dstDepth, + temp_base_format, temp_datatype, + temp_dst, &ctx->DefaultPacking); /* swap src and dest pointers */ { GLubyte *temp = temp_src; temp_src = temp_dst; temp_dst = temp; - temp_src_stride = temp_dst_stride; + temp_src_row_stride = temp_dst_row_stride; + temp_src_img_stride = temp_dst_img_stride; } } /* loop over mipmap levels */ +end: free(temp_src); free(temp_dst); + free(temp_src_slices); + free(temp_dst_slices); } /**