diff options
Diffstat (limited to 'src/mesa/main/teximage.c')
-rw-r--r-- | src/mesa/main/teximage.c | 1137 |
1 files changed, 585 insertions, 552 deletions
diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c index a8160c27357..b946f3c69d7 100644 --- a/src/mesa/main/teximage.c +++ b/src/mesa/main/teximage.c @@ -33,9 +33,7 @@ #include "glheader.h" #include "bufferobj.h" #include "context.h" -#if FEATURE_convolve #include "convolve.h" -#endif #include "enums.h" #include "fbobject.h" #include "framebuffer.h" @@ -45,7 +43,7 @@ #include "macros.h" #include "state.h" #include "texcompress.h" -#include "texformat.h" +#include "texfetch.h" #include "teximage.h" #include "texstate.h" #include "texstore.h" @@ -84,63 +82,6 @@ _mesa_free_texmemory(void *m) } - - -#if 0 -static void PrintTexture(GLcontext *ctx, const struct gl_texture_image *img) -{ -#if CHAN_TYPE != GL_UNSIGNED_BYTE - _mesa_problem(NULL, "PrintTexture not supported"); -#else - GLuint i, j, c; - const GLubyte *data = (const GLubyte *) img->Data; - - if (!data) { - _mesa_printf("No texture data\n"); - return; - } - - switch (img->Format) { - case GL_ALPHA: - case GL_LUMINANCE: - case GL_INTENSITY: - case GL_COLOR_INDEX: - c = 1; - break; - case GL_LUMINANCE_ALPHA: - c = 2; - break; - case GL_RGB: - c = 3; - break; - case GL_RGBA: - c = 4; - break; - default: - _mesa_problem(NULL, "error in PrintTexture\n"); - return; - } - - for (i = 0; i < img->Height; i++) { - for (j = 0; j < img->Width; j++) { - if (c==1) - _mesa_printf("%02x ", data[0]); - else if (c==2) - _mesa_printf("%02x%02x ", data[0], data[1]); - else if (c==3) - _mesa_printf("%02x%02x%02x ", data[0], data[1], data[2]); - else if (c==4) - _mesa_printf("%02x%02x%02x%02x ", data[0], data[1], data[2], data[3]); - data += (img->RowStride - img->Width) * c; - } - /* XXX use img->ImageStride here */ - _mesa_printf("\n"); - } -#endif -} -#endif - - /* * Compute floor(log_base_2(n)). * If n < 0 return -1. @@ -642,6 +583,17 @@ _mesa_select_tex_object(GLcontext *ctx, const struct gl_texture_unit *texUnit, /** + * Return pointer to texture object for given target on current texture unit. + */ +struct gl_texture_object * +_mesa_get_current_tex_object(GLcontext *ctx, GLenum target) +{ + struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx); + return _mesa_select_tex_object(ctx, texUnit, target); +} + + +/** * Get a texture image pointer from a texture object, given a texture * target and mipmap level. The target and level parameters should * have already been error-checked. @@ -902,11 +854,9 @@ clear_teximage_fields(struct gl_texture_image *img) img->HeightLog2 = 0; img->DepthLog2 = 0; img->Data = NULL; - img->TexFormat = &_mesa_null_texformat; + img->TexFormat = MESA_FORMAT_NONE; img->FetchTexelc = NULL; img->FetchTexelf = NULL; - img->IsCompressed = 0; - img->CompressedSize = 0; } @@ -969,9 +919,6 @@ _mesa_init_teximage_fields(GLcontext *ctx, GLenum target, img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2); - img->IsCompressed = GL_FALSE; - img->CompressedSize = 0; - if ((width == 1 || _mesa_is_pow_two(img->Width2)) && (height == 1 || _mesa_is_pow_two(img->Height2)) && (depth == 1 || _mesa_is_pow_two(img->Depth2))) @@ -1004,6 +951,9 @@ _mesa_init_teximage_fields(GLcontext *ctx, GLenum target, img->HeightScale = (GLfloat) img->Height; img->DepthScale = (GLfloat) img->Depth; } + + img->FetchTexelc = NULL; + img->FetchTexelf = NULL; } @@ -1317,8 +1267,8 @@ texture_error_check( GLcontext *ctx, GLenum target, if (_mesa_base_tex_format(ctx, internalFormat) < 0) { if (!isProxy) { _mesa_error(ctx, GL_INVALID_VALUE, - "glTexImage%dD(internalFormat=0x%x)", - dimensions, internalFormat); + "glTexImage%dD(internalFormat=%s)", + dimensions, _mesa_lookup_enum_by_nr(internalFormat)); } return GL_TRUE; } @@ -1530,6 +1480,11 @@ subtexture_error_check( GLcontext *ctx, GLuint dimensions, return GL_FALSE; } + +/** + * Do second part of glTexSubImage which depends on the destination texture. + * \return GL_TRUE if error recorded, GL_FALSE otherwise + */ static GLboolean subtexture_error_check2( GLcontext *ctx, GLuint dimensions, GLenum target, GLint level, @@ -1577,41 +1532,35 @@ subtexture_error_check2( GLcontext *ctx, GLuint dimensions, } } -#if FEATURE_EXT_texture_sRGB - if (destTex->InternalFormat == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT || - destTex->InternalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT || - destTex->InternalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT || - destTex->InternalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT) { - if ((width & 0x3) || (height & 0x3) || - (xoffset & 0x3) || (yoffset & 0x3)) - _mesa_error(ctx, GL_INVALID_OPERATION, - "glTexSubImage%dD(size or offset not multiple of 4)", - dimensions); - return GL_TRUE; - } -#endif + if (_mesa_is_format_compressed(destTex->TexFormat)) { + GLuint bw, bh; - if (destTex->IsCompressed) { if (!target_can_be_compressed(ctx, target)) { _mesa_error(ctx, GL_INVALID_ENUM, - "glTexSubImage%D(target)", dimensions); + "glTexSubImage%D(target=%s)", dimensions, + _mesa_lookup_enum_by_nr(target)); return GL_TRUE; } - /* offset must be multiple of 4 */ - if ((xoffset & 3) || (yoffset & 3)) { + + /* do tests which depend on compression block size */ + _mesa_get_format_block_size(destTex->TexFormat, &bw, &bh); + + /* offset must be multiple of block size */ + if ((xoffset % bw != 0) || (yoffset % bh != 0)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glTexSubImage%D(xoffset or yoffset)", dimensions); + "glTexSubImage%D(xoffset = %d, yoffset = %d)", + dimensions, xoffset, yoffset); return GL_TRUE; } - /* size must be multiple of 4 or equal to whole texture size */ - if ((width & 3) && (GLuint) width != destTex->Width) { + /* size must be multiple of bw by bh or equal to whole texture size */ + if ((width % bw != 0) && (GLuint) width != destTex->Width) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glTexSubImage%D(width)", dimensions); + "glTexSubImage%D(width = %d)", dimensions, width); return GL_TRUE; } - if ((height & 3) && (GLuint) height != destTex->Height) { + if ((height % bh != 0) && (GLuint) height != destTex->Height) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glTexSubImage%D(width)", dimensions); + "glTexSubImage%D(height = %d)", dimensions, height); return GL_TRUE; } } @@ -1953,7 +1902,7 @@ copytexsubimage_error_check2( GLcontext *ctx, GLuint dimensions, } } - if (teximage->IsCompressed) { + if (_mesa_is_format_compressed(teximage->TexFormat)) { if (!target_can_be_compressed(ctx, target)) { _mesa_error(ctx, GL_INVALID_ENUM, "glCopyTexSubImage%d(target)", dimensions); @@ -2076,6 +2025,25 @@ update_fbo_texture(GLcontext *ctx, struct gl_texture_object *texObj, } +/** + * If the texture object's GenerateMipmap flag is set and we've + * changed the texture base level image, regenerate the rest of the + * mipmap levels now. + */ +static INLINE void +check_gen_mipmap(GLcontext *ctx, GLenum target, + struct gl_texture_object *texObj, GLint level) +{ + ASSERT(target != GL_TEXTURE_CUBE_MAP); + if (texObj->GenerateMipmap && + level == texObj->BaseLevel && + level < texObj->MaxLevel) { + ASSERT(ctx->Driver.GenerateMipmap); + ctx->Driver.GenerateMipmap(ctx, target, texObj); + } +} + + /** Debug helper: override the user-requested internal format */ static GLenum override_internal_format(GLenum internalFormat, GLint width, GLint height) @@ -2149,7 +2117,6 @@ _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat, if (target == GL_TEXTURE_1D) { /* non-proxy target */ - struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; struct gl_texture_image *texImage; const GLuint face = _mesa_tex_target_to_face(target); @@ -2162,43 +2129,50 @@ _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat, if (ctx->NewState & _MESA_NEW_TRANSFER_STATE) _mesa_update_state(ctx); - texUnit = _mesa_get_current_tex_unit(ctx); - texObj = _mesa_select_tex_object(ctx, texUnit, target); + texObj = _mesa_get_current_tex_object(ctx, target); _mesa_lock_texture(ctx, texObj); { texImage = _mesa_get_tex_image(ctx, texObj, target, level); if (!texImage) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D"); - goto out; - } - - if (texImage->Data) { - ctx->Driver.FreeTexImageData( ctx, texImage ); } + else { + if (texImage->Data) { + ctx->Driver.FreeTexImageData( ctx, texImage ); + } + + ASSERT(texImage->Data == NULL); + + clear_teximage_fields(texImage); /* not really needed, but helpful */ + _mesa_init_teximage_fields(ctx, target, texImage, + postConvWidth, 1, 1, + border, internalFormat); + + /* Choose actual texture format */ + texImage->TexFormat = + ctx->Driver.ChooseTextureFormat(ctx, internalFormat, + format, type); + ASSERT(texImage->TexFormat != MESA_FORMAT_NONE); + + /* Give the texture to the driver. <pixels> may be null. */ + ASSERT(ctx->Driver.TexImage1D); + ctx->Driver.TexImage1D(ctx, target, level, internalFormat, + width, border, format, type, pixels, + &ctx->Unpack, texObj, texImage); + + ASSERT(texImage->TexFormat); + + _mesa_set_fetch_functions(texImage, 1); + + check_gen_mipmap(ctx, target, texObj, level); + + update_fbo_texture(ctx, texObj, face, level); - ASSERT(texImage->Data == NULL); - - clear_teximage_fields(texImage); /* not really needed, but helpful */ - _mesa_init_teximage_fields(ctx, target, texImage, - postConvWidth, 1, 1, - border, internalFormat); - - ASSERT(ctx->Driver.TexImage1D); - - /* Give the texture to the driver! <pixels> may be null! */ - (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat, - width, border, format, type, pixels, - &ctx->Unpack, texObj, texImage); - - ASSERT(texImage->TexFormat); - - update_fbo_texture(ctx, texObj, face, level); - - /* state update */ - texObj->_Complete = GL_FALSE; - ctx->NewState |= _NEW_TEXTURE; - } - out: + /* state update */ + texObj->_Complete = GL_FALSE; + ctx->NewState |= _NEW_TEXTURE; + } + } _mesa_unlock_texture(ctx, texObj); } else if (target == GL_PROXY_TEXTURE_1D) { @@ -2217,8 +2191,8 @@ _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat, _mesa_init_teximage_fields(ctx, target, texImage, postConvWidth, 1, 1, border, internalFormat); - texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx, - internalFormat, format, type); + texImage->TexFormat = + ctx->Driver.ChooseTextureFormat(ctx, internalFormat, format, type); } } else { @@ -2263,7 +2237,6 @@ _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat, (ctx->Extensions.MESA_texture_array && target == GL_TEXTURE_1D_ARRAY_EXT)) { /* non-proxy target */ - struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; struct gl_texture_image *texImage; const GLuint face = _mesa_tex_target_to_face(target); @@ -2277,42 +2250,49 @@ _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat, if (ctx->NewState & _MESA_NEW_TRANSFER_STATE) _mesa_update_state(ctx); - texUnit = _mesa_get_current_tex_unit(ctx); - texObj = _mesa_select_tex_object(ctx, texUnit, target); + texObj = _mesa_get_current_tex_object(ctx, target); _mesa_lock_texture(ctx, texObj); { texImage = _mesa_get_tex_image(ctx, texObj, target, level); if (!texImage) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); - goto out; - } - - if (texImage->Data) { - ctx->Driver.FreeTexImageData( ctx, texImage ); } - - ASSERT(texImage->Data == NULL); - clear_teximage_fields(texImage); /* not really needed, but helpful */ - _mesa_init_teximage_fields(ctx, target, texImage, - postConvWidth, postConvHeight, 1, - border, internalFormat); - - ASSERT(ctx->Driver.TexImage2D); - - /* Give the texture to the driver! <pixels> may be null! */ - (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat, - width, height, border, format, type, pixels, - &ctx->Unpack, texObj, texImage); - - ASSERT(texImage->TexFormat); - - update_fbo_texture(ctx, texObj, face, level); - - /* state update */ - texObj->_Complete = GL_FALSE; - ctx->NewState |= _NEW_TEXTURE; - } - out: + else { + if (texImage->Data) { + ctx->Driver.FreeTexImageData( ctx, texImage ); + } + + ASSERT(texImage->Data == NULL); + clear_teximage_fields(texImage); /* not really needed, but helpful */ + _mesa_init_teximage_fields(ctx, target, texImage, + postConvWidth, postConvHeight, 1, + border, internalFormat); + + /* Choose actual texture format */ + texImage->TexFormat = + ctx->Driver.ChooseTextureFormat(ctx, internalFormat, + format, type); + ASSERT(texImage->TexFormat != MESA_FORMAT_NONE); + + /* Give the texture to the driver. <pixels> may be null. */ + ASSERT(ctx->Driver.TexImage2D); + ctx->Driver.TexImage2D(ctx, target, level, internalFormat, + width, height, border, format, type, + pixels, &ctx->Unpack, texObj, texImage); + + ASSERT(texImage->TexFormat); + + _mesa_set_fetch_functions(texImage, 2); + + check_gen_mipmap(ctx, target, texObj, level); + + update_fbo_texture(ctx, texObj, face, level); + + /* state update */ + texObj->_Complete = GL_FALSE; + ctx->NewState |= _NEW_TEXTURE; + } + } _mesa_unlock_texture(ctx, texObj); } else if (target == GL_PROXY_TEXTURE_2D || @@ -2337,8 +2317,8 @@ _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat, _mesa_init_teximage_fields(ctx, target, texImage, postConvWidth, postConvHeight, 1, border, internalFormat); - texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx, - internalFormat, format, type); + texImage->TexFormat = + ctx->Driver.ChooseTextureFormat(ctx, internalFormat, format, type); } } else { @@ -2374,7 +2354,6 @@ _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat, (ctx->Extensions.MESA_texture_array && target == GL_TEXTURE_2D_ARRAY_EXT)) { /* non-proxy target */ - struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; struct gl_texture_image *texImage; const GLuint face = _mesa_tex_target_to_face(target); @@ -2387,42 +2366,49 @@ _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat, if (ctx->NewState & _MESA_NEW_TRANSFER_STATE) _mesa_update_state(ctx); - texUnit = _mesa_get_current_tex_unit(ctx); - texObj = _mesa_select_tex_object(ctx, texUnit, target); + texObj = _mesa_get_current_tex_object(ctx, target); _mesa_lock_texture(ctx, texObj); { texImage = _mesa_get_tex_image(ctx, texObj, target, level); if (!texImage) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D"); - goto out; } - - if (texImage->Data) { - ctx->Driver.FreeTexImageData( ctx, texImage ); - } - - ASSERT(texImage->Data == NULL); - clear_teximage_fields(texImage); /* not really needed, but helpful */ - _mesa_init_teximage_fields(ctx, target, texImage, - width, height, depth, - border, internalFormat); + else { + if (texImage->Data) { + ctx->Driver.FreeTexImageData( ctx, texImage ); + } + + ASSERT(texImage->Data == NULL); + clear_teximage_fields(texImage); /* not really needed, but helpful */ + _mesa_init_teximage_fields(ctx, target, texImage, + width, height, depth, + border, internalFormat); + + /* Choose actual texture format */ + texImage->TexFormat = + ctx->Driver.ChooseTextureFormat(ctx, internalFormat, + format, type); + ASSERT(texImage->TexFormat != MESA_FORMAT_NONE); - ASSERT(ctx->Driver.TexImage3D); + /* Give the texture to the driver. <pixels> may be null. */ + ASSERT(ctx->Driver.TexImage3D); + ctx->Driver.TexImage3D(ctx, target, level, internalFormat, + width, height, depth, border, format, type, + pixels, &ctx->Unpack, texObj, texImage); - /* Give the texture to the driver! <pixels> may be null! */ - (*ctx->Driver.TexImage3D)(ctx, target, level, internalFormat, - width, height, depth, border, format, type, - pixels, &ctx->Unpack, texObj, texImage); + ASSERT(texImage->TexFormat); - ASSERT(texImage->TexFormat); + _mesa_set_fetch_functions(texImage, 3); - update_fbo_texture(ctx, texObj, face, level); + check_gen_mipmap(ctx, target, texObj, level); - /* state update */ - texObj->_Complete = GL_FALSE; - ctx->NewState |= _NEW_TEXTURE; + update_fbo_texture(ctx, texObj, face, level); + + /* state update */ + texObj->_Complete = GL_FALSE; + ctx->NewState |= _NEW_TEXTURE; + } } - out: _mesa_unlock_texture(ctx, texObj); } else if (target == GL_PROXY_TEXTURE_3D || @@ -2441,8 +2427,8 @@ _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat, /* no error, set the tex image parameters */ _mesa_init_teximage_fields(ctx, target, texImage, width, height, depth, border, internalFormat); - texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx, - internalFormat, format, type); + texImage->TexFormat = + ctx->Driver.ChooseTextureFormat(ctx, internalFormat, format, type); } } else { @@ -2471,9 +2457,8 @@ _mesa_TexSubImage1D( GLenum target, GLint level, const GLvoid *pixels ) { GLsizei postConvWidth = width; - struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; - struct gl_texture_image *texImage = NULL; + struct gl_texture_image *texImage; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); @@ -2499,8 +2484,7 @@ _mesa_TexSubImage1D( GLenum target, GLint level, } - texUnit = _mesa_get_current_tex_unit(ctx); - texObj = _mesa_select_tex_object(ctx, texUnit, target); + texObj = _mesa_get_current_tex_object(ctx, target); assert(texObj); _mesa_lock_texture(ctx, texObj); @@ -2508,23 +2492,24 @@ _mesa_TexSubImage1D( GLenum target, GLint level, texImage = _mesa_select_tex_image(ctx, texObj, target, level); if (subtexture_error_check2(ctx, 1, target, level, xoffset, 0, 0, - postConvWidth, 1, 1, format, type, texImage)) { - goto out; /* error was detected */ + postConvWidth, 1, 1, + format, type, texImage)) { + /* error was recorded */ } + else if (width > 0) { + /* If we have a border, xoffset=-1 is legal. Bias by border width */ + xoffset += texImage->Border; - if (width == 0) - goto out; /* no-op, not an error */ + ASSERT(ctx->Driver.TexSubImage1D); + ctx->Driver.TexSubImage1D(ctx, target, level, xoffset, width, + format, type, pixels, &ctx->Unpack, + texObj, texImage); - /* If we have a border, xoffset=-1 is legal. Bias by border width */ - xoffset += texImage->Border; + check_gen_mipmap(ctx, target, texObj, level); - ASSERT(ctx->Driver.TexSubImage1D); - (*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width, - format, type, pixels, &ctx->Unpack, - texObj, texImage); - ctx->NewState |= _NEW_TEXTURE; + ctx->NewState |= _NEW_TEXTURE; + } } - out: _mesa_unlock_texture(ctx, texObj); } @@ -2537,7 +2522,6 @@ _mesa_TexSubImage2D( GLenum target, GLint level, const GLvoid *pixels ) { GLsizei postConvWidth = width, postConvHeight = height; - struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; struct gl_texture_image *texImage; GET_CURRENT_CONTEXT(ctx); @@ -2566,32 +2550,32 @@ _mesa_TexSubImage2D( GLenum target, GLint level, return; /* error was detected */ } - texUnit = _mesa_get_current_tex_unit(ctx); - texObj = _mesa_select_tex_object(ctx, texUnit, target); + texObj = _mesa_get_current_tex_object(ctx, target); + _mesa_lock_texture(ctx, texObj); { texImage = _mesa_select_tex_image(ctx, texObj, target, level); if (subtexture_error_check2(ctx, 2, target, level, xoffset, yoffset, 0, - postConvWidth, postConvHeight, 1, format, type, - texImage)) { - goto out; /* error was detected */ + postConvWidth, postConvHeight, 1, + format, type, texImage)) { + /* error was recorded */ } + else if (width > 0 && height >= 0) { + /* If we have a border, xoffset=-1 is legal. Bias by border width */ + xoffset += texImage->Border; + yoffset += texImage->Border; - if (width == 0 || height == 0) - goto out; /* no-op, not an error */ + ASSERT(ctx->Driver.TexSubImage2D); + ctx->Driver.TexSubImage2D(ctx, target, level, xoffset, yoffset, + width, height, format, type, pixels, + &ctx->Unpack, texObj, texImage); - /* If we have a border, xoffset=-1 is legal. Bias by border width */ - xoffset += texImage->Border; - yoffset += texImage->Border; - - ASSERT(ctx->Driver.TexSubImage2D); - (*ctx->Driver.TexSubImage2D)(ctx, target, level, xoffset, yoffset, - width, height, format, type, pixels, - &ctx->Unpack, texObj, texImage); - ctx->NewState |= _NEW_TEXTURE; + check_gen_mipmap(ctx, target, texObj, level); + + ctx->NewState |= _NEW_TEXTURE; + } } - out: _mesa_unlock_texture(ctx, texObj); } @@ -2604,7 +2588,6 @@ _mesa_TexSubImage3D( GLenum target, GLint level, GLenum format, GLenum type, const GLvoid *pixels ) { - struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; struct gl_texture_image *texImage; GET_CURRENT_CONTEXT(ctx); @@ -2625,35 +2608,36 @@ _mesa_TexSubImage3D( GLenum target, GLint level, return; /* error was detected */ } - texUnit = _mesa_get_current_tex_unit(ctx); - texObj = _mesa_select_tex_object(ctx, texUnit, target); + texObj = _mesa_get_current_tex_object(ctx, target); _mesa_lock_texture(ctx, texObj); { texImage = _mesa_select_tex_image(ctx, texObj, target, level); - if (subtexture_error_check2(ctx, 3, target, level, xoffset, yoffset, zoffset, - width, height, depth, format, type, texImage)) { - goto out; /* error was detected */ + if (subtexture_error_check2(ctx, 3, target, level, + xoffset, yoffset, zoffset, + width, height, depth, + format, type, texImage)) { + /* error was recorded */ } + else if (width > 0 && height > 0 && height > 0) { + /* If we have a border, xoffset=-1 is legal. Bias by border width */ + xoffset += texImage->Border; + yoffset += texImage->Border; + zoffset += texImage->Border; - if (width == 0 || height == 0 || height == 0) - goto out; /* no-op, not an error */ + ASSERT(ctx->Driver.TexSubImage3D); + ctx->Driver.TexSubImage3D(ctx, target, level, + xoffset, yoffset, zoffset, + width, height, depth, + format, type, pixels, + &ctx->Unpack, texObj, texImage ); - /* If we have a border, xoffset=-1 is legal. Bias by border width */ - xoffset += texImage->Border; - yoffset += texImage->Border; - zoffset += texImage->Border; + check_gen_mipmap(ctx, target, texObj, level); - ASSERT(ctx->Driver.TexSubImage3D); - (*ctx->Driver.TexSubImage3D)(ctx, target, level, - xoffset, yoffset, zoffset, - width, height, depth, - format, type, pixels, - &ctx->Unpack, texObj, texImage ); - ctx->NewState |= _NEW_TEXTURE; + ctx->NewState |= _NEW_TEXTURE; + } } - out: _mesa_unlock_texture(ctx, texObj); } @@ -2665,7 +2649,6 @@ _mesa_CopyTexImage1D( GLenum target, GLint level, GLint x, GLint y, GLsizei width, GLint border ) { - struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; struct gl_texture_image *texImage; GLsizei postConvWidth = width; @@ -2692,40 +2675,48 @@ _mesa_CopyTexImage1D( GLenum target, GLint level, postConvWidth, 1, border)) return; - texUnit = _mesa_get_current_tex_unit(ctx); - texObj = _mesa_select_tex_object(ctx, texUnit, target); + texObj = _mesa_get_current_tex_object(ctx, target); + _mesa_lock_texture(ctx, texObj); { texImage = _mesa_get_tex_image(ctx, texObj, target, level); if (!texImage) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D"); - goto out; } + else { + if (texImage->Data) { + ctx->Driver.FreeTexImageData( ctx, texImage ); + } - if (texImage->Data) { - ctx->Driver.FreeTexImageData( ctx, texImage ); - } - - ASSERT(texImage->Data == NULL); + ASSERT(texImage->Data == NULL); + + clear_teximage_fields(texImage); /* not really needed, but helpful */ + _mesa_init_teximage_fields(ctx, target, texImage, postConvWidth, 1, 1, + border, internalFormat); + + /* Choose actual texture format */ + texImage->TexFormat = + ctx->Driver.ChooseTextureFormat(ctx, internalFormat, + GL_NONE, GL_NONE); + ASSERT(texImage->TexFormat != MESA_FORMAT_NONE); - clear_teximage_fields(texImage); /* not really needed, but helpful */ - _mesa_init_teximage_fields(ctx, target, texImage, postConvWidth, 1, 1, - border, internalFormat); + ASSERT(ctx->Driver.CopyTexImage1D); + ctx->Driver.CopyTexImage1D(ctx, target, level, internalFormat, + x, y, width, border); + ASSERT(texImage->TexFormat); - ASSERT(ctx->Driver.CopyTexImage1D); - (*ctx->Driver.CopyTexImage1D)(ctx, target, level, internalFormat, - x, y, width, border); + _mesa_set_fetch_functions(texImage, 1); - ASSERT(texImage->TexFormat); + check_gen_mipmap(ctx, target, texObj, level); - update_fbo_texture(ctx, texObj, face, level); + update_fbo_texture(ctx, texObj, face, level); - /* state update */ - texObj->_Complete = GL_FALSE; - ctx->NewState |= _NEW_TEXTURE; + /* state update */ + texObj->_Complete = GL_FALSE; + ctx->NewState |= _NEW_TEXTURE; + } } - out: _mesa_unlock_texture(ctx, texObj); } @@ -2736,7 +2727,6 @@ _mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border ) { - struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; struct gl_texture_image *texImage; GLsizei postConvWidth = width, postConvHeight = height; @@ -2764,8 +2754,7 @@ _mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat, postConvWidth, postConvHeight, border)) return; - texUnit = _mesa_get_current_tex_unit(ctx); - texObj = _mesa_select_tex_object(ctx, texUnit, target); + texObj = _mesa_get_current_tex_object(ctx, target); _mesa_lock_texture(ctx, texObj); { @@ -2773,33 +2762,42 @@ _mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat, if (!texImage) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D"); - goto out; - } - - if (texImage->Data) { - ctx->Driver.FreeTexImageData( ctx, texImage ); } - - ASSERT(texImage->Data == NULL); + else { + if (texImage->Data) { + ctx->Driver.FreeTexImageData( ctx, texImage ); + } + + ASSERT(texImage->Data == NULL); + + clear_teximage_fields(texImage); /* not really needed, but helpful */ + _mesa_init_teximage_fields(ctx, target, texImage, + postConvWidth, postConvHeight, 1, + border, internalFormat); + + /* Choose actual texture format */ + texImage->TexFormat = + ctx->Driver.ChooseTextureFormat(ctx, internalFormat, + GL_NONE, GL_NONE); + ASSERT(texImage->TexFormat != MESA_FORMAT_NONE); + + ASSERT(ctx->Driver.CopyTexImage2D); + ctx->Driver.CopyTexImage2D(ctx, target, level, internalFormat, + x, y, width, height, border); - clear_teximage_fields(texImage); /* not really needed, but helpful */ - _mesa_init_teximage_fields(ctx, target, texImage, - postConvWidth, postConvHeight, 1, - border, internalFormat); - - ASSERT(ctx->Driver.CopyTexImage2D); - (*ctx->Driver.CopyTexImage2D)(ctx, target, level, internalFormat, - x, y, width, height, border); - - ASSERT(texImage->TexFormat); + ASSERT(texImage->TexFormat); - update_fbo_texture(ctx, texObj, face, level); + _mesa_set_fetch_functions(texImage, 2); - /* state update */ - texObj->_Complete = GL_FALSE; - ctx->NewState |= _NEW_TEXTURE; + check_gen_mipmap(ctx, target, texObj, level); + + update_fbo_texture(ctx, texObj, face, level); + + /* state update */ + texObj->_Complete = GL_FALSE; + ctx->NewState |= _NEW_TEXTURE; + } } - out: _mesa_unlock_texture(ctx, texObj); } @@ -2808,7 +2806,6 @@ void GLAPIENTRY _mesa_CopyTexSubImage1D( GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width ) { - struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; struct gl_texture_image *texImage; GLsizei postConvWidth = width; @@ -2829,8 +2826,7 @@ _mesa_CopyTexSubImage1D( GLenum target, GLint level, if (copytexsubimage_error_check1(ctx, 1, target, level)) return; - texUnit = _mesa_get_current_tex_unit(ctx); - texObj = _mesa_select_tex_object(ctx, texUnit, target); + texObj = _mesa_get_current_tex_object(ctx, target); _mesa_lock_texture(ctx, texObj); { @@ -2844,23 +2840,25 @@ _mesa_CopyTexSubImage1D( GLenum target, GLint level, if (copytexsubimage_error_check2(ctx, 1, target, level, xoffset, 0, 0, postConvWidth, 1, - texImage)) - goto out; - + texImage)) { + /* error was recorded */ + } + else { + /* If we have a border, xoffset=-1 is legal. Bias by border width */ + xoffset += texImage->Border; - /* If we have a border, xoffset=-1 is legal. Bias by border width */ - xoffset += texImage->Border; + if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y, + &width, &height)) { + ASSERT(ctx->Driver.CopyTexSubImage1D); + ctx->Driver.CopyTexSubImage1D(ctx, target, level, + xoffset, x, y, width); - if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y, - &width, &height)) { - ASSERT(ctx->Driver.CopyTexSubImage1D); - ctx->Driver.CopyTexSubImage1D(ctx, target, level, - xoffset, x, y, width); - } + check_gen_mipmap(ctx, target, texObj, level); - ctx->NewState |= _NEW_TEXTURE; + ctx->NewState |= _NEW_TEXTURE; + } + } } - out: _mesa_unlock_texture(ctx, texObj); } @@ -2871,7 +2869,6 @@ _mesa_CopyTexSubImage2D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height ) { - struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; struct gl_texture_image *texImage; GLsizei postConvWidth = width, postConvHeight = height; @@ -2889,8 +2886,7 @@ _mesa_CopyTexSubImage2D( GLenum target, GLint level, if (copytexsubimage_error_check1(ctx, 2, target, level)) return; - texUnit = _mesa_get_current_tex_unit(ctx); - texObj = _mesa_select_tex_object(ctx, texUnit, target); + texObj = _mesa_get_current_tex_object(ctx, target); _mesa_lock_texture(ctx, texObj); { @@ -2903,24 +2899,29 @@ _mesa_CopyTexSubImage2D( GLenum target, GLint level, } #endif - if (copytexsubimage_error_check2(ctx, 2, target, level, xoffset, yoffset, 0, - postConvWidth, postConvHeight, texImage)) - goto out; + if (copytexsubimage_error_check2(ctx, 2, target, level, + xoffset, yoffset, 0, + postConvWidth, postConvHeight, + texImage)) { + /* error was recorded */ + } + else { + /* If we have a border, xoffset=-1 is legal. Bias by border width */ + xoffset += texImage->Border; + yoffset += texImage->Border; - /* If we have a border, xoffset=-1 is legal. Bias by border width */ - xoffset += texImage->Border; - yoffset += texImage->Border; + if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y, + &width, &height)) { + ASSERT(ctx->Driver.CopyTexSubImage2D); + ctx->Driver.CopyTexSubImage2D(ctx, target, level, xoffset, yoffset, + x, y, width, height); - if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y, - &width, &height)) { - ASSERT(ctx->Driver.CopyTexSubImage2D); - ctx->Driver.CopyTexSubImage2D(ctx, target, level, - xoffset, yoffset, x, y, width, height); - } + check_gen_mipmap(ctx, target, texObj, level); - ctx->NewState |= _NEW_TEXTURE; + ctx->NewState |= _NEW_TEXTURE; + } + } } - out: _mesa_unlock_texture(ctx, texObj); } @@ -2931,7 +2932,6 @@ _mesa_CopyTexSubImage3D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height ) { - struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; struct gl_texture_image *texImage; GLsizei postConvWidth = width, postConvHeight = height; @@ -2949,8 +2949,7 @@ _mesa_CopyTexSubImage3D( GLenum target, GLint level, if (copytexsubimage_error_check1(ctx, 3, target, level)) return; - texUnit = _mesa_get_current_tex_unit(ctx); - texObj = _mesa_select_tex_object(ctx, texUnit, target); + texObj = _mesa_get_current_tex_object(ctx, target); _mesa_lock_texture(ctx, texObj); { @@ -2965,25 +2964,28 @@ _mesa_CopyTexSubImage3D( GLenum target, GLint level, if (copytexsubimage_error_check2(ctx, 3, target, level, xoffset, yoffset, zoffset, postConvWidth, postConvHeight, - texImage)) - goto out; - - /* If we have a border, xoffset=-1 is legal. Bias by border width */ - xoffset += texImage->Border; - yoffset += texImage->Border; - zoffset += texImage->Border; - - if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y, - &width, &height)) { - ASSERT(ctx->Driver.CopyTexSubImage3D); - ctx->Driver.CopyTexSubImage3D(ctx, target, level, - xoffset, yoffset, zoffset, - x, y, width, height); + texImage)) { + /* error was recored */ } + else { + /* If we have a border, xoffset=-1 is legal. Bias by border width */ + xoffset += texImage->Border; + yoffset += texImage->Border; + zoffset += texImage->Border; + + if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y, + &width, &height)) { + ASSERT(ctx->Driver.CopyTexSubImage3D); + ctx->Driver.CopyTexSubImage3D(ctx, target, level, + xoffset, yoffset, zoffset, + x, y, width, height); + + check_gen_mipmap(ctx, target, texObj, level); - ctx->NewState |= _NEW_TEXTURE; + ctx->NewState |= _NEW_TEXTURE; + } + } } - out: _mesa_unlock_texture(ctx, texObj); } @@ -2996,6 +2998,29 @@ _mesa_CopyTexSubImage3D( GLenum target, GLint level, /** + * Return expected size of a compressed texture. + */ +static GLuint +compressed_tex_size(GLsizei width, GLsizei height, GLsizei depth, + GLenum glformat) +{ + gl_format mesaFormat = _mesa_glenum_to_compressed_format(glformat); + return _mesa_format_image_size(mesaFormat, width, height, depth); +} + + +/* + * Return compressed texture block size, in pixels. + */ +static void +get_compressed_block_size(GLenum glformat, GLuint *bw, GLuint *bh) +{ + gl_format mesaFormat = _mesa_glenum_to_compressed_format(glformat); + _mesa_get_format_block_size(mesaFormat, bw, bh); +} + + +/** * Error checking for glCompressedTexImage[123]D(). * \return error code or GL_NO_ERROR. */ @@ -3077,8 +3102,7 @@ compressed_texture_error_check(GLcontext *ctx, GLint dimensions, if (level < 0 || level >= maxLevels) return GL_INVALID_VALUE; - expectedSize = _mesa_compressed_texture_size_glenum(ctx, width, height, - depth, internalFormat); + expectedSize = compressed_tex_size(width, height, depth, internalFormat); if (expectedSize != imageSize) return GL_INVALID_VALUE; @@ -3111,6 +3135,7 @@ compressed_subtexture_error_check(GLcontext *ctx, GLint dimensions, GLenum format, GLsizei imageSize) { GLint expectedSize, maxLevels = 0, maxTextureSize; + GLuint bw, bh; (void) zoffset; if (dimensions == 1) { @@ -3160,20 +3185,21 @@ compressed_subtexture_error_check(GLcontext *ctx, GLint dimensions, if (level < 0 || level >= maxLevels) return GL_INVALID_VALUE; - /* XXX these tests are specific to the compressed format. - * this code should be generalized in some way. + /* + * do checks which depend on compression block size */ - if ((xoffset & 3) != 0 || (yoffset & 3) != 0) + get_compressed_block_size(format, &bw, &bh); + + if ((xoffset % bw != 0) || (yoffset % bh != 0)) return GL_INVALID_VALUE; - if ((width & 3) != 0 && width != 2 && width != 1) + if ((width % bw != 0) && width != 2 && width != 1) return GL_INVALID_VALUE; - if ((height & 3) != 0 && height != 2 && height != 1) + if ((height % bh != 0) && height != 2 && height != 1) return GL_INVALID_VALUE; - expectedSize = _mesa_compressed_texture_size_glenum(ctx, width, height, - depth, format); + expectedSize = compressed_tex_size(width, height, depth, format); if (expectedSize != imageSize) return GL_INVALID_VALUE; @@ -3181,6 +3207,55 @@ compressed_subtexture_error_check(GLcontext *ctx, GLint dimensions, } +/** + * Do second part of glCompressedTexSubImage error checking. + * \return GL_TRUE if error found, GL_FALSE otherwise. + */ +static GLboolean +compressed_subtexture_error_check2(GLcontext *ctx, GLuint dims, + GLsizei width, GLsizei height, + GLsizei depth, GLenum format, + struct gl_texture_image *texImage) +{ + + if ((GLint) format != texImage->InternalFormat) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glCompressedTexSubImage%uD(format=0x%x)", dims, format); + return GL_TRUE; + } + + if (((width == 1 || width == 2) && + (GLuint) width != texImage->Width) || + (width > texImage->Width)) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glCompressedTexSubImage%uD(width=%d)", dims, width); + return GL_TRUE; + } + + if (dims >= 2) { + if (((height == 1 || height == 2) && + (GLuint) height != texImage->Height) || + (height > texImage->Height)) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glCompressedTexSubImage%uD(height=%d)", dims, height); + return GL_TRUE; + } + } + + if (dims >= 3) { + if (((depth == 1 || depth == 2) && + (GLuint) depth != texImage->Depth) || + (depth > texImage->Depth)) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glCompressedTexSubImage%uD(depth=%d)", dims, depth); + return GL_TRUE; + } + } + + return GL_FALSE; +} + + void GLAPIENTRY _mesa_CompressedTexImage1DARB(GLenum target, GLint level, @@ -3199,7 +3274,6 @@ _mesa_CompressedTexImage1DARB(GLenum target, GLint level, if (target == GL_TEXTURE_1D) { /* non-proxy target */ - struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; struct gl_texture_image *texImage; GLenum error = compressed_texture_error_check(ctx, 1, target, level, @@ -3209,36 +3283,44 @@ _mesa_CompressedTexImage1DARB(GLenum target, GLint level, return; } - texUnit = _mesa_get_current_tex_unit(ctx); - texObj = _mesa_select_tex_object(ctx, texUnit, target); + texObj = _mesa_get_current_tex_object(ctx, target); _mesa_lock_texture(ctx, texObj); { texImage = _mesa_get_tex_image(ctx, texObj, target, level); if (!texImage) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1D"); - goto out; - } - - if (texImage->Data) { - ctx->Driver.FreeTexImageData( ctx, texImage ); } - ASSERT(texImage->Data == NULL); + else { + if (texImage->Data) { + ctx->Driver.FreeTexImageData( ctx, texImage ); + } + ASSERT(texImage->Data == NULL); + + _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1, + border, internalFormat); + + /* Choose actual texture format */ + texImage->TexFormat = + ctx->Driver.ChooseTextureFormat(ctx, internalFormat, + GL_NONE, GL_NONE); + ASSERT(texImage->TexFormat != MESA_FORMAT_NONE); - _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1, - border, internalFormat); + ASSERT(ctx->Driver.CompressedTexImage1D); + ctx->Driver.CompressedTexImage1D(ctx, target, level, + internalFormat, width, border, + imageSize, data, + texObj, texImage); - ASSERT(ctx->Driver.CompressedTexImage1D); - (*ctx->Driver.CompressedTexImage1D)(ctx, target, level, - internalFormat, width, border, - imageSize, data, - texObj, texImage); + _mesa_set_fetch_functions(texImage, 1); - /* state update */ - texObj->_Complete = GL_FALSE; - ctx->NewState |= _NEW_TEXTURE; + check_gen_mipmap(ctx, target, texObj, level); + + /* state update */ + texObj->_Complete = GL_FALSE; + ctx->NewState |= _NEW_TEXTURE; + } } - out: _mesa_unlock_texture(ctx, texObj); } else if (target == GL_PROXY_TEXTURE_1D) { @@ -3260,11 +3342,10 @@ _mesa_CompressedTexImage1DARB(GLenum target, GLint level, } else { /* store the teximage parameters */ - struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; struct gl_texture_image *texImage; - texUnit = _mesa_get_current_tex_unit(ctx); - texObj = _mesa_select_tex_object(ctx, texUnit, target); + + texObj = _mesa_get_current_tex_object(ctx, target); _mesa_lock_texture(ctx, texObj); { @@ -3302,9 +3383,9 @@ _mesa_CompressedTexImage2DARB(GLenum target, GLint level, target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) { /* non-proxy target */ - struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; struct gl_texture_image *texImage; + GLenum error = compressed_texture_error_check(ctx, 2, target, level, internalFormat, width, height, 1, border, imageSize); if (error) { @@ -3312,36 +3393,44 @@ _mesa_CompressedTexImage2DARB(GLenum target, GLint level, return; } - texUnit = _mesa_get_current_tex_unit(ctx); - texObj = _mesa_select_tex_object(ctx, texUnit, target); + texObj = _mesa_get_current_tex_object(ctx, target); _mesa_lock_texture(ctx, texObj); { texImage = _mesa_get_tex_image(ctx, texObj, target, level); if (!texImage) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D"); - goto out; } - - if (texImage->Data) { - ctx->Driver.FreeTexImageData( ctx, texImage ); - } - ASSERT(texImage->Data == NULL); - - _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1, - border, internalFormat); - - ASSERT(ctx->Driver.CompressedTexImage2D); - (*ctx->Driver.CompressedTexImage2D)(ctx, target, level, - internalFormat, width, height, - border, imageSize, data, - texObj, texImage); - - /* state update */ - texObj->_Complete = GL_FALSE; - ctx->NewState |= _NEW_TEXTURE; - } - out: + else { + if (texImage->Data) { + ctx->Driver.FreeTexImageData( ctx, texImage ); + } + ASSERT(texImage->Data == NULL); + + _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1, + border, internalFormat); + + /* Choose actual texture format */ + texImage->TexFormat = + ctx->Driver.ChooseTextureFormat(ctx, internalFormat, + GL_NONE, GL_NONE); + ASSERT(texImage->TexFormat != MESA_FORMAT_NONE); + + ASSERT(ctx->Driver.CompressedTexImage2D); + ctx->Driver.CompressedTexImage2D(ctx, target, level, + internalFormat, width, height, + border, imageSize, data, + texObj, texImage); + + _mesa_set_fetch_functions(texImage, 2); + + check_gen_mipmap(ctx, target, texObj, level); + + /* state update */ + texObj->_Complete = GL_FALSE; + ctx->NewState |= _NEW_TEXTURE; + } + } _mesa_unlock_texture(ctx, texObj); } else if (target == GL_PROXY_TEXTURE_2D || @@ -3365,11 +3454,10 @@ _mesa_CompressedTexImage2DARB(GLenum target, GLint level, } else { /* store the teximage parameters */ - struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; struct gl_texture_image *texImage; - texUnit = _mesa_get_current_tex_unit(ctx); - texObj = _mesa_select_tex_object(ctx, texUnit, target); + + texObj = _mesa_get_current_tex_object(ctx, target); _mesa_lock_texture(ctx, texObj); { @@ -3404,7 +3492,6 @@ _mesa_CompressedTexImage3DARB(GLenum target, GLint level, if (target == GL_TEXTURE_3D) { /* non-proxy target */ - struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; struct gl_texture_image *texImage; GLenum error = compressed_texture_error_check(ctx, 3, target, level, @@ -3414,36 +3501,46 @@ _mesa_CompressedTexImage3DARB(GLenum target, GLint level, return; } - texUnit = _mesa_get_current_tex_unit(ctx); - texObj = _mesa_select_tex_object(ctx, texUnit, target); + texObj = _mesa_get_current_tex_object(ctx, target); + _mesa_lock_texture(ctx, texObj); { texImage = _mesa_get_tex_image(ctx, texObj, target, level); if (!texImage) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3D"); - goto out; - } - - if (texImage->Data) { - ctx->Driver.FreeTexImageData( ctx, texImage ); } - ASSERT(texImage->Data == NULL); - - _mesa_init_teximage_fields(ctx, target, texImage, width, height, depth, - border, internalFormat); - - ASSERT(ctx->Driver.CompressedTexImage3D); - (*ctx->Driver.CompressedTexImage3D)(ctx, target, level, - internalFormat, - width, height, depth, - border, imageSize, data, - texObj, texImage); - - /* state update */ - texObj->_Complete = GL_FALSE; - ctx->NewState |= _NEW_TEXTURE; - } - out: + else { + if (texImage->Data) { + ctx->Driver.FreeTexImageData( ctx, texImage ); + } + ASSERT(texImage->Data == NULL); + + _mesa_init_teximage_fields(ctx, target, texImage, + width, height, depth, + border, internalFormat); + + /* Choose actual texture format */ + texImage->TexFormat = + ctx->Driver.ChooseTextureFormat(ctx, internalFormat, + GL_NONE, GL_NONE); + ASSERT(texImage->TexFormat != MESA_FORMAT_NONE); + + ASSERT(ctx->Driver.CompressedTexImage3D); + ctx->Driver.CompressedTexImage3D(ctx, target, level, + internalFormat, + width, height, depth, + border, imageSize, data, + texObj, texImage); + + _mesa_set_fetch_functions(texImage, 3); + + check_gen_mipmap(ctx, target, texObj, level); + + /* state update */ + texObj->_Complete = GL_FALSE; + ctx->NewState |= _NEW_TEXTURE; + } + } _mesa_unlock_texture(ctx, texObj); } else if (target == GL_PROXY_TEXTURE_3D) { @@ -3465,11 +3562,11 @@ _mesa_CompressedTexImage3DARB(GLenum target, GLint level, } else { /* store the teximage parameters */ - struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; struct gl_texture_image *texImage; - texUnit = _mesa_get_current_tex_unit(ctx); - texObj = _mesa_select_tex_object(ctx, texUnit, target); + + texObj = _mesa_get_current_tex_object(ctx, target); + _mesa_lock_texture(ctx, texObj); { texImage = _mesa_select_tex_image(ctx, texObj, target, level); @@ -3486,116 +3583,100 @@ _mesa_CompressedTexImage3DARB(GLenum target, GLint level, } -void GLAPIENTRY -_mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset, - GLsizei width, GLenum format, - GLsizei imageSize, const GLvoid *data) +/** + * Common helper for glCompressedTexSubImage1/2/3D(). + */ +static void +compressed_tex_sub_image(GLuint dims, GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLsizei imageSize, const GLvoid *data) { - struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; struct gl_texture_image *texImage; GLenum error; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); - error = compressed_subtexture_error_check(ctx, 1, target, level, + error = compressed_subtexture_error_check(ctx, dims, target, level, xoffset, 0, 0, /* pos */ - width, 1, 1, /* size */ + width, height, depth, /* size */ format, imageSize); if (error) { - _mesa_error(ctx, error, "glCompressedTexSubImage1D"); + _mesa_error(ctx, error, "glCompressedTexSubImage%uD", dims); return; } - texUnit = _mesa_get_current_tex_unit(ctx); - texObj = _mesa_select_tex_object(ctx, texUnit, target); + texObj = _mesa_get_current_tex_object(ctx, target); + _mesa_lock_texture(ctx, texObj); { texImage = _mesa_select_tex_image(ctx, texObj, target, level); assert(texImage); - if ((GLint) format != texImage->InternalFormat) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glCompressedTexSubImage1D(format)"); - goto out; - } + if (compressed_subtexture_error_check2(ctx, dims, width, height, depth, + format, texImage)) { + /* error was recorded */ + } + else if (width > 0 && height > 0 && depth > 0) { + switch (dims) { + case 1: + if (ctx->Driver.CompressedTexSubImage1D) { + ctx->Driver.CompressedTexSubImage1D(ctx, target, level, + xoffset, width, + format, imageSize, data, + texObj, texImage); + } + break; + case 2: + if (ctx->Driver.CompressedTexSubImage2D) { + ctx->Driver.CompressedTexSubImage2D(ctx, target, level, + xoffset, yoffset, + width, height, + format, imageSize, data, + texObj, texImage); + } + break; + case 3: + if (ctx->Driver.CompressedTexSubImage3D) { + ctx->Driver.CompressedTexSubImage3D(ctx, target, level, + xoffset, yoffset, zoffset, + width, height, depth, + format, imageSize, data, + texObj, texImage); + } + break; + default: + ; + } - if ((width == 1 || width == 2) && (GLuint) width != texImage->Width) { - _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage1D(width)"); - goto out; - } - - if (width == 0) - goto out; /* no-op, not an error */ + check_gen_mipmap(ctx, target, texObj, level); - if (ctx->Driver.CompressedTexSubImage1D) { - (*ctx->Driver.CompressedTexSubImage1D)(ctx, target, level, - xoffset, width, - format, imageSize, data, - texObj, texImage); + ctx->NewState |= _NEW_TEXTURE; } - ctx->NewState |= _NEW_TEXTURE; } - out: _mesa_unlock_texture(ctx, texObj); } void GLAPIENTRY +_mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset, + GLsizei width, GLenum format, + GLsizei imageSize, const GLvoid *data) +{ + compressed_tex_sub_image(1, target, level, xoffset, 0, 0, width, 1, 1, + format, imageSize, data); +} + + +void GLAPIENTRY _mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data) { - struct gl_texture_unit *texUnit; - struct gl_texture_object *texObj; - struct gl_texture_image *texImage; - GLenum error; - GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); - - error = compressed_subtexture_error_check(ctx, 2, target, level, - xoffset, yoffset, 0, /* pos */ - width, height, 1, /* size */ - format, imageSize); - if (error) { - /* XXX proxy target? */ - _mesa_error(ctx, error, "glCompressedTexSubImage2D"); - return; - } - - texUnit = _mesa_get_current_tex_unit(ctx); - texObj = _mesa_select_tex_object(ctx, texUnit, target); - _mesa_lock_texture(ctx, texObj); - { - texImage = _mesa_select_tex_image(ctx, texObj, target, level); - assert(texImage); - - if ((GLint) format != texImage->InternalFormat) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glCompressedTexSubImage2D(format)"); - goto out; - } - - if (((width == 1 || width == 2) && (GLuint) width != texImage->Width) || - ((height == 1 || height == 2) && (GLuint) height != texImage->Height)) { - _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage2D(size)"); - goto out; - } - - if (width == 0 || height == 0) - goto out; /* no-op, not an error */ - - if (ctx->Driver.CompressedTexSubImage2D) { - (*ctx->Driver.CompressedTexSubImage2D)(ctx, target, level, - xoffset, yoffset, width, height, - format, imageSize, data, - texObj, texImage); - } - ctx->NewState |= _NEW_TEXTURE; - } - out: - _mesa_unlock_texture(ctx, texObj); + compressed_tex_sub_image(2, target, level, xoffset, yoffset, 0, + width, height, 1, format, imageSize, data); } @@ -3605,56 +3686,8 @@ _mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data) { - struct gl_texture_unit *texUnit; - struct gl_texture_object *texObj; - struct gl_texture_image *texImage; - GLenum error; - GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); - - error = compressed_subtexture_error_check(ctx, 3, target, level, - xoffset, yoffset, zoffset,/*pos*/ - width, height, depth, /*size*/ - format, imageSize); - if (error) { - _mesa_error(ctx, error, "glCompressedTexSubImage3D"); - return; - } - - texUnit = _mesa_get_current_tex_unit(ctx); - texObj = _mesa_select_tex_object(ctx, texUnit, target); - _mesa_lock_texture(ctx, texObj); - { - texImage = _mesa_select_tex_image(ctx, texObj, target, level); - assert(texImage); - - if ((GLint) format != texImage->InternalFormat) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glCompressedTexSubImage3D(format)"); - goto out; - } - - if (((width == 1 || width == 2) && (GLuint) width != texImage->Width) || - ((height == 1 || height == 2) && (GLuint) height != texImage->Height) || - ((depth == 1 || depth == 2) && (GLuint) depth != texImage->Depth)) { - _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage3D(size)"); - goto out; - } - - if (width == 0 || height == 0 || depth == 0) - goto out; /* no-op, not an error */ - - if (ctx->Driver.CompressedTexSubImage3D) { - (*ctx->Driver.CompressedTexSubImage3D)(ctx, target, level, - xoffset, yoffset, zoffset, - width, height, depth, - format, imageSize, data, - texObj, texImage); - } - ctx->NewState |= _NEW_TEXTURE; - } - out: - _mesa_unlock_texture(ctx, texObj); + compressed_tex_sub_image(3, target, level, xoffset, yoffset, zoffset, + width, height, depth, format, imageSize, data); } |