diff options
author | Brian Paul <[email protected]> | 2011-08-01 23:04:12 -0700 |
---|---|---|
committer | Eric Anholt <[email protected]> | 2011-10-03 13:29:30 -0700 |
commit | e0304180c32227342dbb67b707bfae446543bb48 (patch) | |
tree | 05224697ca0948eded9adb328a215bc2c5a3a24f | |
parent | 1165b64f561a7bdd3f603d9e30a2340774ba31ee (diff) |
mesa: Convert _mesa_generate_mipmap to MapTexImage()-based access.
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.
Reviewed-by: Eric Anholt <[email protected]>
-rw-r--r-- | src/mesa/drivers/dri/intel/intel_tex.c | 30 | ||||
-rw-r--r-- | src/mesa/drivers/dri/nouveau/nouveau_texture.c | 10 | ||||
-rw-r--r-- | src/mesa/drivers/dri/radeon/radeon_texture.c | 50 | ||||
-rw-r--r-- | src/mesa/main/mipmap.c | 270 | ||||
-rw-r--r-- | src/mesa/main/mipmap.h | 4 | ||||
-rw-r--r-- | 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 55b3e349b4c..bc7b1f64b3e 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 9dc21869ca8..508c8a59dbd 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 7f824ce2038..6bd89671083 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 7325a420f0e..cc46f5c4d22 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; @@ -2049,6 +2071,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); @@ -2085,15 +2108,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, @@ -2105,7 +2132,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 4783950218a..8b7cd7d5a4a 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 e53da5fd4ae..36fea3d7ff8 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 */ |