X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fmain%2Fmipmap.c;h=88e6baa08ad15240359521f2ba00c825dbd8d378;hb=fc9c4f89b85c0116c0dc22a3eaf25f5df88ad657;hp=2bf5902fba419a7a9b0ba50ef853ef6b2e318dfe;hpb=9b387b5d3f4103c51079ea5298d33086af6da433;p=mesa.git diff --git a/src/mesa/main/mipmap.c b/src/mesa/main/mipmap.c index 2bf5902fba4..88e6baa08ad 100644 --- a/src/mesa/main/mipmap.c +++ b/src/mesa/main/mipmap.c @@ -27,6 +27,7 @@ * \file mipmap.c mipmap generation and teximage resizing functions. */ +#include "errors.h" #include "imports.h" #include "formats.h" #include "glformats.h" @@ -37,10 +38,35 @@ #include "texstore.h" #include "image.h" #include "macros.h" -#include "../../gallium/auxiliary/util/u_format_rgb9e5.h" -#include "../../gallium/auxiliary/util/u_format_r11g11b10f.h" +#include "util/half_float.h" +#include "util/format_rgb9e5.h" +#include "util/format_r11g11b10f.h" +/** + * 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/ + * GL_TEXTURE_MAX_LEVEL settings. This will tell us how many mipmap + * levels should be generated. + */ +unsigned +_mesa_compute_num_levels(struct gl_context *ctx, + struct gl_texture_object *texObj, + GLenum target) +{ + const struct gl_texture_image *baseImage; + GLuint numLevels; + + baseImage = _mesa_get_tex_image(ctx, texObj, target, texObj->BaseLevel); + + numLevels = texObj->BaseLevel + baseImage->MaxNumLevels; + numLevels = MIN2(numLevels, (GLuint) texObj->MaxLevel + 1); + if (texObj->Immutable) + numLevels = MIN2(numLevels, texObj->NumLevels); + assert(numLevels >= 1); + + return numLevels; +} static GLint bytes_per_pixel(GLenum datatype, GLuint comps) @@ -756,7 +782,7 @@ do_row(GLenum datatype, GLuint comps, GLint srcWidth, } else { - _mesa_problem(NULL, "bad format in do_row()"); + unreachable("bad format in do_row()"); } } @@ -1400,7 +1426,7 @@ do_row_3D(GLenum datatype, GLuint comps, GLint srcWidth, } else { - _mesa_problem(NULL, "bad format in do_row()"); + unreachable("bad format in do_row()"); } } @@ -1444,9 +1470,9 @@ make_1d_mipmap(GLenum datatype, GLuint comps, GLint border, static void make_2d_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, - 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 */ @@ -1714,12 +1740,12 @@ _mesa_generate_mipmap_level(GLenum target, dstWidth, dstData[0]); break; case GL_TEXTURE_2D: - case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: make_2d_mipmap(datatype, comps, border, srcWidth, srcHeight, srcData[0], srcRowStride, dstWidth, dstHeight, dstData[0], dstRowStride); @@ -1735,17 +1761,17 @@ _mesa_generate_mipmap_level(GLenum target, assert(srcHeight == 1); assert(dstHeight == 1); for (i = 0; i < dstDepth; i++) { - make_1d_mipmap(datatype, comps, border, - srcWidth, srcData[i], - dstWidth, dstData[i]); + make_1d_mipmap(datatype, comps, border, + srcWidth, srcData[i], + dstWidth, dstData[i]); } 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, - dstWidth, dstHeight, dstData[i], dstRowStride); + make_2d_mipmap(datatype, comps, border, + srcWidth, srcHeight, srcData[i], srcRowStride, + dstWidth, dstHeight, dstData[i], dstRowStride); } break; case GL_TEXTURE_RECTANGLE_NV: @@ -1753,8 +1779,7 @@ _mesa_generate_mipmap_level(GLenum target, /* no mipmaps, do nothing */ break; default: - _mesa_problem(NULL, "bad tex target in _mesa_generate_mipmaps"); - return; + unreachable("bad tex target in _mesa_generate_mipmaps"); } } @@ -1775,8 +1800,9 @@ _mesa_next_mipmap_level_size(GLenum target, GLint border, *dstWidth = srcWidth; /* can't go smaller */ } - if ((srcHeight - 2 * border > 1) && - (target != GL_TEXTURE_1D_ARRAY_EXT)) { + if ((srcHeight - 2 * border > 1) && + target != GL_TEXTURE_1D_ARRAY_EXT && + target != GL_PROXY_TEXTURE_1D_ARRAY_EXT) { *dstHeight = (srcHeight - 2 * border) / 2 + 2 * border; } else { @@ -1784,8 +1810,10 @@ _mesa_next_mipmap_level_size(GLenum target, GLint border, } if ((srcDepth - 2 * border > 1) && - (target != GL_TEXTURE_2D_ARRAY_EXT && - target != GL_TEXTURE_CUBE_MAP_ARRAY)) { + target != GL_TEXTURE_2D_ARRAY_EXT && + target != GL_PROXY_TEXTURE_2D_ARRAY_EXT && + target != GL_TEXTURE_CUBE_MAP_ARRAY && + target != GL_PROXY_TEXTURE_CUBE_MAP_ARRAY) { *dstDepth = (srcDepth - 2 * border) / 2 + 2 * border; } else { @@ -1809,11 +1837,11 @@ _mesa_next_mipmap_level_size(GLenum target, GLint border, * 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) +static GLboolean +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; @@ -1837,12 +1865,7 @@ _mesa_prepare_mipmap_level(struct gl_context *ctx, 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; + const GLenum target = _mesa_cube_face_target(texObj->Target, face); dstImage = _mesa_get_tex_image(ctx, texObj, target, level); if (!dstImage) { @@ -1868,7 +1891,7 @@ _mesa_prepare_mipmap_level(struct gl_context *ctx, /* in case the mipmap level is part of an FBO: */ _mesa_update_fbo_texture(ctx, texObj, face, level); - ctx->NewState |= _NEW_TEXTURE; + ctx->NewState |= _NEW_TEXTURE_OBJECT; } } @@ -1876,11 +1899,54 @@ _mesa_prepare_mipmap_level(struct gl_context *ctx, } +/** + * Prepare all mipmap levels beyond 'baseLevel' for mipmap generation. + * When finished, all the gl_texture_image structures for the smaller + * mipmap levels will be consistent with the base level (in terms of + * dimensions, format, etc). + */ +void +_mesa_prepare_mipmap_levels(struct gl_context *ctx, + struct gl_texture_object *texObj, + unsigned baseLevel, unsigned maxLevel) +{ + const struct gl_texture_image *baseImage = + _mesa_select_tex_image(texObj, texObj->Target, baseLevel); + const GLint border = 0; + GLint width = baseImage->Width; + GLint height = baseImage->Height; + GLint depth = baseImage->Depth; + const GLenum intFormat = baseImage->InternalFormat; + const mesa_format texFormat = baseImage->TexFormat; + GLint newWidth, newHeight, newDepth; + + /* Prepare baseLevel + 1, baseLevel + 2, ... */ + for (unsigned level = baseLevel + 1; level <= maxLevel; level++) { + if (!_mesa_next_mipmap_level_size(texObj->Target, border, + width, height, depth, + &newWidth, &newHeight, &newDepth)) { + /* all done */ + break; + } + + if (!prepare_mipmap_level(ctx, texObj, level, + newWidth, newHeight, newDepth, + border, intFormat, texFormat)) { + break; + } + + width = newWidth; + height = newHeight; + depth = newDepth; + } +} + + static void generate_mipmap_uncompressed(struct gl_context *ctx, GLenum target, - struct gl_texture_object *texObj, - const struct gl_texture_image *srcImage, - GLuint maxLevel) + struct gl_texture_object *texObj, + const struct gl_texture_image *srcImage, + GLuint maxLevel) { GLuint level; GLenum datatype; @@ -1896,7 +1962,6 @@ generate_mipmap_uncompressed(struct gl_context *ctx, GLenum target, GLint dstWidth, dstHeight, dstDepth; GLint border; GLint slice; - GLboolean nextLevel; GLubyte **srcMaps, **dstMaps; GLboolean success = GL_TRUE; @@ -1908,31 +1973,20 @@ generate_mipmap_uncompressed(struct gl_context *ctx, GLenum target, srcDepth = srcImage->Depth; border = srcImage->Border; - nextLevel = _mesa_next_mipmap_level_size(target, border, - srcWidth, srcHeight, srcDepth, - &dstWidth, &dstHeight, &dstDepth); - if (!nextLevel) - return; - - if (!_mesa_prepare_mipmap_level(ctx, texObj, level + 1, - dstWidth, dstHeight, dstDepth, - border, srcImage->InternalFormat, - srcImage->TexFormat)) { - return; - } - /* get dest gl_texture_image */ - dstImage = _mesa_get_tex_image(ctx, texObj, target, level + 1); + dstImage = _mesa_select_tex_image(texObj, target, level + 1); if (!dstImage) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps"); - return; + break; } + dstWidth = dstImage->Width; + dstHeight = dstImage->Height; + dstDepth = dstImage->Depth; if (target == GL_TEXTURE_1D_ARRAY) { - srcDepth = srcHeight; - dstDepth = dstHeight; - srcHeight = 1; - dstHeight = 1; + srcDepth = srcHeight; + dstDepth = dstHeight; + srcHeight = 1; + dstHeight = 1; } /* Map src texture image slices */ @@ -2010,9 +2064,9 @@ generate_mipmap_uncompressed(struct gl_context *ctx, GLenum target, static void generate_mipmap_compressed(struct gl_context *ctx, GLenum target, - struct gl_texture_object *texObj, - struct gl_texture_image *srcImage, - GLuint maxLevel) + struct gl_texture_object *texObj, + struct gl_texture_image *srcImage, + GLuint maxLevel) { GLuint level; mesa_format temp_format; @@ -2025,8 +2079,8 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target, /* only two types of compressed textures at this time */ assert(texObj->Target == GL_TEXTURE_2D || - texObj->Target == GL_TEXTURE_2D_ARRAY || - texObj->Target == GL_TEXTURE_CUBE_MAP_ARB || + texObj->Target == GL_TEXTURE_2D_ARRAY || + texObj->Target == GL_TEXTURE_CUBE_MAP || texObj->Target == GL_TEXTURE_CUBE_MAP_ARRAY); /* @@ -2094,7 +2148,6 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target, GLint srcWidth, srcHeight, srcDepth; GLint dstWidth, dstHeight, dstDepth; GLint border; - GLboolean nextLevel; GLuint temp_dst_row_stride, temp_dst_img_stride; /* in bytes */ GLint i; @@ -2106,29 +2159,25 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target, srcDepth = srcImage->Depth; border = srcImage->Border; - nextLevel = _mesa_next_mipmap_level_size(target, border, - srcWidth, srcHeight, srcDepth, - &dstWidth, &dstHeight, &dstDepth); - if (!nextLevel) - break; + /* get dest gl_texture_image */ + dstImage = _mesa_select_tex_image(texObj, target, level + 1); + if (!dstImage) { + break; + } + dstWidth = dstImage->Width; + dstHeight = dstImage->Height; + dstDepth = dstImage->Depth; /* 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 = malloc(temp_dst_img_stride * dstDepth); - if (!temp_dst) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps"); + temp_dst = malloc(temp_dst_img_stride * dstDepth); + if (!temp_dst) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps"); goto end; - } - } - - /* 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"); - goto end; + } } /* for 2D arrays, setup array[depth] of slice pointers */ @@ -2149,14 +2198,6 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target, dstWidth, dstHeight, dstDepth, temp_dst_slices, temp_dst_row_stride); - if (!_mesa_prepare_mipmap_level(ctx, texObj, level + 1, - dstWidth, dstHeight, dstDepth, - border, srcImage->InternalFormat, - srcImage->TexFormat)) { - /* all done */ - goto end; - } - /* The image space was allocated above so use glTexSubImage now */ ctx->Driver.TexSubImage(ctx, 2, dstImage, 0, 0, 0, dstWidth, dstHeight, dstDepth, @@ -2165,9 +2206,9 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target, /* swap src and dest pointers */ { - GLubyte *temp = temp_src; - temp_src = temp_dst; - temp_dst = temp; + GLubyte *temp = temp_src; + temp_src = temp_dst; + temp_dst = temp; temp_src_row_stride = temp_dst_row_stride; temp_src_img_stride = temp_dst_img_stride; } @@ -2204,6 +2245,8 @@ _mesa_generate_mipmap(struct gl_context *ctx, GLenum target, maxLevel = MIN2(maxLevel, texObj->MaxLevel); + _mesa_prepare_mipmap_levels(ctx, texObj, texObj->BaseLevel, maxLevel); + if (_mesa_is_format_compressed(srcImage->TexFormat)) { generate_mipmap_compressed(ctx, target, texObj, srcImage, maxLevel); } else {