diff options
Diffstat (limited to 'src/mesa/main/teximage.c')
| -rw-r--r-- | src/mesa/main/teximage.c | 1105 | 
1 files changed, 568 insertions, 537 deletions
| diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c index a8160c2735..b10076875b 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,23 @@ 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) { +      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 +2115,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 +2127,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); -	 ASSERT(texImage->Data == NULL); +            _mesa_set_fetch_functions(texImage, 1); -	 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); +            check_gen_mipmap(ctx, target, texObj, level); -	 /* 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); -	 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);     }     else if (target == GL_PROXY_TEXTURE_1D) { @@ -2217,8 +2189,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 +2235,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 +2248,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); +         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! */ -	 (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat, -				   width, height, border, format, type, pixels, -				   &ctx->Unpack, texObj, texImage); -	  -	 ASSERT(texImage->TexFormat); +            /* 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); -	 update_fbo_texture(ctx, texObj, face, level); +            ASSERT(texImage->TexFormat); -	 /* state update */ -	 texObj->_Complete = GL_FALSE; -	 ctx->NewState |= _NEW_TEXTURE; +            _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; +         }        } -   out:        _mesa_unlock_texture(ctx, texObj);     }     else if (target == GL_PROXY_TEXTURE_2D || @@ -2337,8 +2315,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 +2352,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 +2364,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 +2425,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 +2455,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 +2482,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 +2490,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 +2520,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 +2548,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; + +         ASSERT(ctx->Driver.TexSubImage2D); +         ctx->Driver.TexSubImage2D(ctx, target, level, xoffset, yoffset, +                                   width, height, format, type, pixels, +                                   &ctx->Unpack, texObj, texImage); -      if (width == 0 || height == 0) -	 goto out;  /* no-op, not an error */ +         check_gen_mipmap(ctx, target, texObj, level); -      /* 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; +         ctx->NewState |= _NEW_TEXTURE; +      }     } - out:     _mesa_unlock_texture(ctx, texObj);  } @@ -2604,7 +2586,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 +2606,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 +2647,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 +2673,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); +         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); +         ASSERT(ctx->Driver.CopyTexImage1D); +         ctx->Driver.CopyTexImage1D(ctx, target, level, internalFormat, +                                    x, y, width, border); -      ASSERT(ctx->Driver.CopyTexImage1D); -      (*ctx->Driver.CopyTexImage1D)(ctx, target, level, internalFormat, -				    x, y, width, border); +         ASSERT(texImage->TexFormat); -      ASSERT(texImage->TexFormat); +         _mesa_set_fetch_functions(texImage, 1); -      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);  } @@ -2736,7 +2725,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 +2752,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 +2760,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 ); +         } -      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->Data == NULL); -      update_fbo_texture(ctx, texObj, face, level); +         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); + +         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; +         /* state update */ +         texObj->_Complete = GL_FALSE; +         ctx->NewState |= _NEW_TEXTURE; +      }     } - out:     _mesa_unlock_texture(ctx, texObj);  } @@ -2808,7 +2804,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 +2824,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 +2838,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 +2867,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 +2884,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 +2897,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 (_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 we have a border, xoffset=-1 is legal.  Bias by border width */ -      xoffset += texImage->Border; -      yoffset += texImage->Border; +            check_gen_mipmap(ctx, target, texObj, level); -      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); +            ctx->NewState |= _NEW_TEXTURE; +         }        } - -      ctx->NewState |= _NEW_TEXTURE;     } - out:     _mesa_unlock_texture(ctx, texObj);  } @@ -2931,7 +2930,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 +2947,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 +2962,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); -      ctx->NewState |= _NEW_TEXTURE; +            check_gen_mipmap(ctx, target, texObj, level); + +            ctx->NewState |= _NEW_TEXTURE; +         } +      }     } - out:     _mesa_unlock_texture(ctx, texObj);  } @@ -2996,6 +2996,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 +3100,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 +3133,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 +3183,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 +3205,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 +3272,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 +3281,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); +            _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); +            /* Choose actual texture format */ +            texImage->TexFormat = +               ctx->Driver.ChooseTextureFormat(ctx, internalFormat, +                                               GL_NONE, GL_NONE); +            ASSERT(texImage->TexFormat != MESA_FORMAT_NONE); -	 /* state update */ -	 texObj->_Complete = GL_FALSE; -	 ctx->NewState |= _NEW_TEXTURE; +            ASSERT(ctx->Driver.CompressedTexImage1D); +            ctx->Driver.CompressedTexImage1D(ctx, target, level, +                                             internalFormat, width, border, +                                             imageSize, data, +                                             texObj, texImage); + +            _mesa_set_fetch_functions(texImage, 1); + +            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 +3340,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 +3381,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 +3391,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); +         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); -	 _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1, -				    border, internalFormat); +            check_gen_mipmap(ctx, target, texObj, level); -	 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; +            /* state update */ +            texObj->_Complete = GL_FALSE; +            ctx->NewState |= _NEW_TEXTURE; +         }        } -   out:        _mesa_unlock_texture(ctx, texObj);     }     else if (target == GL_PROXY_TEXTURE_2D || @@ -3365,11 +3452,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 +3490,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 +3499,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); +         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_init_teximage_fields(ctx, target, texImage, width, height, depth, -				    border, internalFormat); +            _mesa_set_fetch_functions(texImage, 3); -	 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; +            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_3D) { @@ -3465,11 +3560,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 +3581,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 +3684,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);  } | 
