From 101abee6c4fc2c9284ff2ba6f9f9138327d6963d Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 19 Dec 2007 14:26:14 -0800 Subject: [PATCH] [intel] Fix and reenable (software) SGIS_generate_mipmap The core problem was that _mesa_generate_mipmap was not respecting RowStride of the source image. Additionally, the intel private data associated with the images (level and face) was not being initialized for the _mesa_generate_mipmap-generated images. --- src/mesa/drivers/dri/i915/intel_context.c | 2 +- .../drivers/dri/intel/intel_mipmap_tree.c | 2 +- src/mesa/drivers/dri/intel/intel_tex.c | 41 +++++++++ src/mesa/drivers/dri/intel/intel_tex.h | 4 + src/mesa/drivers/dri/intel/intel_tex_copy.c | 19 ++--- src/mesa/drivers/dri/intel/intel_tex_image.c | 22 +++-- .../drivers/dri/intel/intel_tex_subimage.c | 4 +- .../drivers/dri/intel/intel_tex_validate.c | 4 + src/mesa/main/mipmap.c | 84 ++++++++++--------- src/mesa/main/mtypes.h | 2 +- 10 files changed, 117 insertions(+), 67 deletions(-) diff --git a/src/mesa/drivers/dri/i915/intel_context.c b/src/mesa/drivers/dri/i915/intel_context.c index 5d34642a5dc..f407f7ec475 100644 --- a/src/mesa/drivers/dri/i915/intel_context.c +++ b/src/mesa/drivers/dri/i915/intel_context.c @@ -202,7 +202,7 @@ const struct dri_extension card_extensions[] = { {"GL_NV_blend_square", NULL}, {"GL_NV_vertex_program", GL_NV_vertex_program_functions}, {"GL_NV_vertex_program1_1", NULL}, -/* { "GL_SGIS_generate_mipmap", NULL }, */ + { "GL_SGIS_generate_mipmap", NULL }, {NULL, NULL} }; diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c index 6610771b6e2..76375850331 100644 --- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c +++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c @@ -351,7 +351,7 @@ intel_miptree_image_data(struct intel_context *intel, GLuint i; GLuint height = 0; - DBG("%s\n", __FUNCTION__); + DBG("%s: %d/%d\n", __FUNCTION__, face, level); for (i = 0; i < depth; i++) { height = dst->level[level].height; if(dst->compressed) diff --git a/src/mesa/drivers/dri/intel/intel_tex.c b/src/mesa/drivers/dri/intel/intel_tex.c index e02972ec637..f016b6b4dc4 100644 --- a/src/mesa/drivers/dri/intel/intel_tex.c +++ b/src/mesa/drivers/dri/intel/intel_tex.c @@ -1,5 +1,6 @@ #include "swrast/swrast.h" #include "texobj.h" +#include "mipmap.h" #include "intel_context.h" #include "intel_mipmap_tree.h" #include "intel_tex.h" @@ -156,6 +157,46 @@ timed_memcpy(void *dest, const void *src, size_t n) } #endif /* DO_DEBUG */ +/** + * Generate new mipmap data from BASE+1 to BASE+p (the minimally-sized mipmap + * level). + * + * The texture object's miptree must be mapped. + * + * It would be really nice if this was just called by Mesa whenever mipmaps + * needed to be regenerated, rather than us having to remember to do so in + * each texture image modification path. + * + * This function should also include an accelerated path. + */ +void +intel_generate_mipmap(GLcontext *ctx, GLenum target, + const struct gl_texture_unit *texUnit, + struct gl_texture_object *texObj) +{ + struct intel_texture_object *intelObj = intel_texture_object(texObj); + GLuint nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; + int face, i; + + _mesa_generate_mipmap(ctx, target, texUnit, texObj); + + /* Update the level information in our private data in the new images, since + * it didn't get set as part of a normal TexImage path. + */ + for (face = 0; face < nr_faces; face++) { + for (i = texObj->BaseLevel + 1; i < texObj->MaxLevel; i++) { + struct intel_texture_image *intelImage; + + intelImage = intel_texture_image(texObj->Image[face][i]); + if (intelImage == NULL) + break; + + intelImage->level = i; + intelImage->face = face; + } + } +} + void intelInitTextureFuncs(struct dd_function_table *functions) diff --git a/src/mesa/drivers/dri/intel/intel_tex.h b/src/mesa/drivers/dri/intel/intel_tex.h index b77d7a1d8af..2973e0ceb9f 100644 --- a/src/mesa/drivers/dri/intel/intel_tex.h +++ b/src/mesa/drivers/dri/intel/intel_tex.h @@ -148,4 +148,8 @@ void intel_tex_unmap_images(struct intel_context *intel, int intel_compressed_num_bytes(GLuint mesaFormat); +void intel_generate_mipmap(GLcontext *ctx, GLenum target, + const struct gl_texture_unit *texUnit, + struct gl_texture_object *texObj); + #endif diff --git a/src/mesa/drivers/dri/intel/intel_tex_copy.c b/src/mesa/drivers/dri/intel/intel_tex_copy.c index f1a455a04cd..521ce06640f 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_copy.c +++ b/src/mesa/drivers/dri/intel/intel_tex_copy.c @@ -29,6 +29,7 @@ #include "enums.h" #include "image.h" #include "teximage.h" +#include "mipmap.h" #include "swrast/swrast.h" #include "intel_screen.h" @@ -85,12 +86,14 @@ get_teximage_source(struct intel_context *intel, GLenum internalFormat) static GLboolean do_copy_texsubimage(struct intel_context *intel, + GLenum target, struct intel_texture_image *intelImage, GLenum internalFormat, GLint dstx, GLint dsty, GLint x, GLint y, GLsizei width, GLsizei height) { GLcontext *ctx = &intel->ctx; + struct gl_texture_object *texObj = intelImage->base.TexObject; const struct intel_region *src = get_teximage_source(intel, internalFormat); @@ -156,16 +159,12 @@ do_copy_texsubimage(struct intel_context *intel, UNLOCK_HARDWARE(intel); -#if 0 - /* GL_SGIS_generate_mipmap -- this can be accelerated now. - * XXX Add a ctx->Driver.GenerateMipmaps() function? - */ - if (level == texObj->BaseLevel && texObj->GenerateMipmap) { + /* GL_SGIS_generate_mipmap */ + if (intelImage->level == texObj->BaseLevel && texObj->GenerateMipmap) { intel_generate_mipmap(ctx, target, &ctx->Texture.Unit[ctx->Texture.CurrentUnit], texObj); } -#endif return GL_TRUE; } @@ -197,7 +196,7 @@ intelCopyTexImage1D(GLcontext * ctx, GLenum target, GLint level, GL_RGBA, CHAN_TYPE, NULL, &ctx->DefaultPacking, texObj, texImage); - if (!do_copy_texsubimage(intel_context(ctx), + if (!do_copy_texsubimage(intel_context(ctx), target, intel_texture_image(texImage), internalFormat, 0, 0, x, y, width, 1)) goto fail; @@ -234,7 +233,7 @@ intelCopyTexImage2D(GLcontext * ctx, GLenum target, GLint level, &ctx->DefaultPacking, texObj, texImage); - if (!do_copy_texsubimage(intel_context(ctx), + if (!do_copy_texsubimage(intel_context(ctx), target, intel_texture_image(texImage), internalFormat, 0, 0, x, y, width, height)) goto fail; @@ -264,7 +263,7 @@ intelCopyTexSubImage1D(GLcontext * ctx, GLenum target, GLint level, /* Need to check texture is compatible with source format. */ - if (!do_copy_texsubimage(intel_context(ctx), + if (!do_copy_texsubimage(intel_context(ctx), target, intel_texture_image(texImage), internalFormat, xoffset, 0, x, y, width, 1)) { _swrast_copy_texsubimage1d(ctx, target, level, xoffset, x, y, width); @@ -290,7 +289,7 @@ intelCopyTexSubImage2D(GLcontext * ctx, GLenum target, GLint level, /* Need to check texture is compatible with source format. */ - if (!do_copy_texsubimage(intel_context(ctx), + if (!do_copy_texsubimage(intel_context(ctx), target, intel_texture_image(texImage), internalFormat, xoffset, yoffset, x, y, width, height)) { diff --git a/src/mesa/drivers/dri/intel/intel_tex_image.c b/src/mesa/drivers/dri/intel/intel_tex_image.c index c2af74095c9..4f5f75d0492 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_image.c +++ b/src/mesa/drivers/dri/intel/intel_tex_image.c @@ -466,6 +466,7 @@ intelTexImage(GLcontext * ctx, intelImage->level, &dstRowStride, intelImage->base.ImageOffsets); + texImage->RowStride = dstRowStride / intelImage->mt->cpp; } else { /* Allocate regular memory and store the image there temporarily. */ @@ -483,8 +484,8 @@ intelTexImage(GLcontext * ctx, texImage->Data = malloc(sizeInBytes); } - DBG("Upload image %dx%dx%d row_len %x " - "pitch %x\n", + DBG("Upload image %dx%dx%d row_len %d " + "pitch %d\n", width, height, depth, width * texelBytes, dstRowStride); /* Copy data. Would like to know when it's ok for us to eg. use @@ -504,6 +505,13 @@ intelTexImage(GLcontext * ctx, _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage"); } + /* GL_SGIS_generate_mipmap */ + if (level == texObj->BaseLevel && texObj->GenerateMipmap) { + intel_generate_mipmap(ctx, target, + &ctx->Texture.Unit[ctx->Texture.CurrentUnit], + texObj); + } + _mesa_unmap_teximage_pbo(ctx, unpack); if (intelImage->mt) { @@ -512,16 +520,6 @@ intelTexImage(GLcontext * ctx, } UNLOCK_HARDWARE(intel); - -#if 0 - /* GL_SGIS_generate_mipmap -- this can be accelerated now. - */ - if (level == texObj->BaseLevel && texObj->GenerateMipmap) { - intel_generate_mipmap(ctx, target, - &ctx->Texture.Unit[ctx->Texture.CurrentUnit], - texObj); - } -#endif } void diff --git a/src/mesa/drivers/dri/intel/intel_tex_subimage.c b/src/mesa/drivers/dri/intel/intel_tex_subimage.c index 5410df203f4..bd27b86bf32 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_subimage.c +++ b/src/mesa/drivers/dri/intel/intel_tex_subimage.c @@ -90,14 +90,12 @@ intelTexSubimage(GLcontext * ctx, _mesa_error(ctx, GL_OUT_OF_MEMORY, "intelTexSubImage"); } -#if 0 /* GL_SGIS_generate_mipmap */ if (level == texObj->BaseLevel && texObj->GenerateMipmap) { - _mesa_generate_mipmap(ctx, target, + intel_generate_mipmap(ctx, target, &ctx->Texture.Unit[ctx->Texture.CurrentUnit], texObj); } -#endif _mesa_unmap_teximage_pbo(ctx, packing); diff --git a/src/mesa/drivers/dri/intel/intel_tex_validate.c b/src/mesa/drivers/dri/intel/intel_tex_validate.c index 8df66ad4450..d260a721d9a 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_validate.c +++ b/src/mesa/drivers/dri/intel/intel_tex_validate.c @@ -75,6 +75,10 @@ intel_calculate_first_last_level(struct intel_texture_object *intelObj) intelObj->lastLevel = lastLevel; } +/** + * Copies the image's contents at its level into the object's miptree, + * and updates the image to point at the object's miptree. + */ static void copy_image_data_to_tree(struct intel_context *intel, struct intel_texture_object *intelObj, diff --git a/src/mesa/main/mipmap.c b/src/mesa/main/mipmap.c index a9260c847b0..44357fbd6a3 100644 --- a/src/mesa/main/mipmap.c +++ b/src/mesa/main/mipmap.c @@ -531,20 +531,19 @@ make_1d_mipmap(const struct gl_texture_format *format, GLint border, } -/** - * XXX need to use the tex image's row stride! - */ static void make_2d_mipmap(const struct gl_texture_format *format, GLint border, - GLint srcWidth, GLint srcHeight, const GLubyte *srcPtr, - GLint dstWidth, GLint dstHeight, GLubyte *dstPtr) + GLint srcWidth, GLint srcHeight, + const GLubyte *srcPtr, GLint srcRowStride, + GLint dstWidth, GLint dstHeight, + GLubyte *dstPtr, GLint dstRowStride) { const GLint bpt = format->TexelBytes; const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */ const GLint dstWidthNB = dstWidth - 2 * border; const GLint dstHeightNB = dstHeight - 2 * border; - const GLint srcRowStride = bpt * srcWidth; - const GLint dstRowStride = bpt * dstWidth; + const GLint srcRowBytes = bpt * srcRowStride; + const GLint dstRowBytes = bpt * dstRowStride; const GLubyte *srcA, *srcB; GLubyte *dst; GLint row; @@ -552,7 +551,7 @@ make_2d_mipmap(const struct gl_texture_format *format, GLint border, /* Compute src and dst pointers, skipping any border */ srcA = srcPtr + border * ((srcWidth + 1) * bpt); if (srcHeight > 1) - srcB = srcA + srcRowStride; + srcB = srcA + srcRowBytes; else srcB = srcA; dst = dstPtr + border * ((dstWidth + 1) * bpt); @@ -560,9 +559,9 @@ make_2d_mipmap(const struct gl_texture_format *format, GLint border, for (row = 0; row < dstHeightNB; row++) { do_row(format, srcWidthNB, srcA, srcB, dstWidthNB, dst); - srcA += 2 * srcRowStride; - srcB += 2 * srcRowStride; - dst += dstRowStride; + srcA += 2 * srcRowBytes; + srcB += 2 * srcRowBytes; + dst += dstRowBytes; } /* This is ugly but probably won't be used much */ @@ -620,9 +619,9 @@ make_2d_mipmap(const struct gl_texture_format *format, GLint border, static void make_3d_mipmap(const struct gl_texture_format *format, GLint border, GLint srcWidth, GLint srcHeight, GLint srcDepth, - const GLubyte *srcPtr, + const GLubyte *srcPtr, GLint srcRowStride, GLint dstWidth, GLint dstHeight, GLint dstDepth, - GLubyte *dstPtr) + GLubyte *dstPtr, GLint dstRowStride) { const GLint bpt = format->TexelBytes; const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */ @@ -717,13 +716,13 @@ make_3d_mipmap(const struct gl_texture_format *format, GLint border, /* Luckily we can leverage the make_2d_mipmap() function here! */ if (border > 0) { /* do front border image */ - make_2d_mipmap(format, 1, srcWidth, srcHeight, srcPtr, - dstWidth, dstHeight, dstPtr); + make_2d_mipmap(format, 1, srcWidth, srcHeight, srcPtr, srcRowStride, + dstWidth, dstHeight, dstPtr, dstRowStride); /* do back border image */ make_2d_mipmap(format, 1, srcWidth, srcHeight, - srcPtr + bytesPerSrcImage * (srcDepth - 1), + srcPtr + bytesPerSrcImage * (srcDepth - 1), srcRowStride, dstWidth, dstHeight, - dstPtr + bytesPerDstImage * (dstDepth - 1)); + dstPtr + bytesPerDstImage * (dstDepth - 1), dstRowStride); /* do four remaining border edges that span the image slices */ if (srcDepth == dstDepth) { /* just copy border pixels from src to dst */ @@ -798,15 +797,16 @@ make_3d_mipmap(const struct gl_texture_format *format, GLint border, static void make_1d_stack_mipmap(const struct gl_texture_format *format, GLint border, - GLint srcWidth, const GLubyte *srcPtr, - GLint dstWidth, GLint dstHeight, GLubyte *dstPtr) + GLint srcWidth, const GLubyte *srcPtr, GLuint srcRowStride, + GLint dstWidth, GLint dstHeight, + GLubyte *dstPtr, GLuint dstRowStride ) { const GLint bpt = format->TexelBytes; const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */ const GLint dstWidthNB = dstWidth - 2 * border; const GLint dstHeightNB = dstHeight - 2 * border; - const GLint srcRowStride = bpt * srcWidth; - const GLint dstRowStride = bpt * dstWidth; + const GLint srcRowBytes = bpt * srcRowStride; + const GLint dstRowBytes = bpt * dstRowStride; const GLubyte *src; GLubyte *dst; GLint row; @@ -818,8 +818,8 @@ make_1d_stack_mipmap(const struct gl_texture_format *format, GLint border, for (row = 0; row < dstHeightNB; row++) { do_row(format, srcWidthNB, src, src, dstWidthNB, dst); - src += srcRowStride; - dst += dstRowStride; + src += srcRowBytes; + dst += dstRowBytes; } if (border) { @@ -840,17 +840,18 @@ make_1d_stack_mipmap(const struct gl_texture_format *format, GLint border, */ static void make_2d_stack_mipmap(const struct gl_texture_format *format, GLint border, - GLint srcWidth, GLint srcHeight, const GLubyte *srcPtr, + GLint srcWidth, GLint srcHeight, + const GLubyte *srcPtr, GLint srcRowStride, GLint dstWidth, GLint dstHeight, GLint dstDepth, - GLubyte *dstPtr) + GLubyte *dstPtr, GLint dstRowStride) { const GLint bpt = format->TexelBytes; 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 srcRowStride = bpt * srcWidth; - const GLint dstRowStride = bpt * dstWidth; + const GLint srcRowBytes = bpt * srcRowStride; + const GLint dstRowBytes = bpt * dstRowStride; const GLubyte *srcA, *srcB; GLubyte *dst; GLint layer; @@ -859,7 +860,7 @@ make_2d_stack_mipmap(const struct gl_texture_format *format, GLint border, /* Compute src and dst pointers, skipping any border */ srcA = srcPtr + border * ((srcWidth + 1) * bpt); if (srcHeight > 1) - srcB = srcA + srcRowStride; + srcB = srcA + srcRowBytes; else srcB = srcA; dst = dstPtr + border * ((dstWidth + 1) * bpt); @@ -868,9 +869,9 @@ make_2d_stack_mipmap(const struct gl_texture_format *format, GLint border, for (row = 0; row < dstHeightNB; row++) { do_row(format, srcWidthNB, srcA, srcB, dstWidthNB, dst); - srcA += 2 * srcRowStride; - srcB += 2 * srcRowStride; - dst += dstRowStride; + srcA += 2 * srcRowBytes; + srcB += 2 * srcRowBytes; + dst += dstRowBytes; } /* This is ugly but probably won't be used much */ @@ -1132,23 +1133,28 @@ _mesa_generate_mipmap(GLcontext *ctx, GLenum target, case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: make_2d_mipmap(convertFormat, border, - srcWidth, srcHeight, srcData, - dstWidth, dstHeight, dstData); + srcWidth, srcHeight, srcData, srcImage->RowStride, + dstWidth, dstHeight, dstData, dstImage->RowStride); break; case GL_TEXTURE_3D: make_3d_mipmap(convertFormat, border, - srcWidth, srcHeight, srcDepth, srcData, - dstWidth, dstHeight, dstDepth, dstData); + srcWidth, srcHeight, srcDepth, + srcData, srcImage->RowStride, + dstWidth, dstHeight, dstDepth, + dstData, dstImage->RowStride); break; case GL_TEXTURE_1D_ARRAY_EXT: make_1d_stack_mipmap(convertFormat, border, - srcWidth, srcData, - dstWidth, dstHeight, dstData); + srcWidth, srcData, srcImage->RowStride, + dstWidth, dstHeight, + dstData, dstImage->RowStride); break; case GL_TEXTURE_2D_ARRAY_EXT: make_2d_stack_mipmap(convertFormat, border, - srcWidth, srcHeight, srcData, - dstWidth, dstHeight, dstDepth, dstData); + srcWidth, srcHeight, + srcData, srcImage->RowStride, + dstWidth, dstHeight, + dstDepth, dstData, dstImage->RowStride); break; case GL_TEXTURE_RECTANGLE_NV: /* no mipmaps, do nothing */ diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 94b70943889..0da487ea044 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -1365,7 +1365,7 @@ struct gl_texture_image GLboolean IsCompressed; /**< GL_ARB_texture_compression */ GLuint CompressedSize; /**< GL_ARB_texture_compression */ - GLuint RowStride; /**< == Width unless IsClientData and padded */ + GLuint RowStride; /**< Padded width in units of texels */ GLuint *ImageOffsets; /**< if 3D texture: array [Depth] of offsets to each 2D slice in 'Data', in texels */ GLvoid *Data; /**< Image data, accessed via FetchTexel() */ -- 2.30.2