mesa: fix invalid target error handling for teximage
[mesa.git] / src / mesa / main / teximage.c
index 32ca172d47cc57707353106f38ec1ccdaca12bfa..b80d5a9b675f98375113653daf3d192b0f3b9830 100644 (file)
@@ -122,11 +122,61 @@ adjust_for_oes_float_texture(const struct gl_context *ctx,
    return format;
 }
 
    return format;
 }
 
+/**
+ * Returns a corresponding base format for a given internal floating point
+ * format as specifed by OES_texture_float.
+ */
+static GLenum
+oes_float_internal_format(const struct gl_context *ctx,
+                          GLenum format, GLenum type)
+{
+   switch (type) {
+   case GL_FLOAT:
+      if (ctx->Extensions.OES_texture_float) {
+         switch (format) {
+         case GL_RGBA32F:
+            return GL_RGBA;
+         case GL_RGB32F:
+            return GL_RGB;
+         case GL_ALPHA32F_ARB:
+            return GL_ALPHA;
+         case GL_LUMINANCE32F_ARB:
+            return GL_LUMINANCE;
+         case GL_LUMINANCE_ALPHA32F_ARB:
+            return GL_LUMINANCE_ALPHA;
+         default:
+            break;
+         }
+      }
+      break;
+
+   case GL_HALF_FLOAT_OES:
+      if (ctx->Extensions.OES_texture_half_float) {
+         switch (format) {
+         case GL_RGBA16F:
+            return GL_RGBA;
+         case GL_RGB16F:
+            return GL_RGB;
+         case GL_ALPHA16F_ARB:
+            return GL_ALPHA;
+         case GL_LUMINANCE16F_ARB:
+            return GL_LUMINANCE;
+         case GL_LUMINANCE_ALPHA16F_ARB:
+            return GL_LUMINANCE_ALPHA;
+         default:
+            break;
+         }
+      }
+      break;
+   }
+   return format;
+}
+
 
 /**
  * Install gl_texture_image in a gl_texture_object according to the target
  * and level parameters.
 
 /**
  * Install gl_texture_image in a gl_texture_object according to the target
  * and level parameters.
- * 
+ *
  * \param tObj texture object.
  * \param target texture target.
  * \param level image level.
  * \param tObj texture object.
  * \param target texture target.
  * \param level image level.
@@ -373,23 +423,15 @@ get_proxy_tex_image(struct gl_context *ctx, GLenum target, GLint level)
 
    switch (target) {
    case GL_PROXY_TEXTURE_1D:
 
    switch (target) {
    case GL_PROXY_TEXTURE_1D:
-      if (level >= ctx->Const.MaxTextureLevels)
-         return NULL;
       texIndex = TEXTURE_1D_INDEX;
       break;
    case GL_PROXY_TEXTURE_2D:
       texIndex = TEXTURE_1D_INDEX;
       break;
    case GL_PROXY_TEXTURE_2D:
-      if (level >= ctx->Const.MaxTextureLevels)
-         return NULL;
       texIndex = TEXTURE_2D_INDEX;
       break;
    case GL_PROXY_TEXTURE_3D:
       texIndex = TEXTURE_2D_INDEX;
       break;
    case GL_PROXY_TEXTURE_3D:
-      if (level >= ctx->Const.Max3DTextureLevels)
-         return NULL;
       texIndex = TEXTURE_3D_INDEX;
       break;
    case GL_PROXY_TEXTURE_CUBE_MAP:
       texIndex = TEXTURE_3D_INDEX;
       break;
    case GL_PROXY_TEXTURE_CUBE_MAP:
-      if (level >= ctx->Const.MaxCubeTextureLevels)
-         return NULL;
       texIndex = TEXTURE_CUBE_INDEX;
       break;
    case GL_PROXY_TEXTURE_RECTANGLE_NV:
       texIndex = TEXTURE_CUBE_INDEX;
       break;
    case GL_PROXY_TEXTURE_RECTANGLE_NV:
@@ -398,28 +440,18 @@ get_proxy_tex_image(struct gl_context *ctx, GLenum target, GLint level)
       texIndex = TEXTURE_RECT_INDEX;
       break;
    case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
       texIndex = TEXTURE_RECT_INDEX;
       break;
    case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
-      if (level >= ctx->Const.MaxTextureLevels)
-         return NULL;
       texIndex = TEXTURE_1D_ARRAY_INDEX;
       break;
    case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
       texIndex = TEXTURE_1D_ARRAY_INDEX;
       break;
    case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
-      if (level >= ctx->Const.MaxTextureLevels)
-         return NULL;
       texIndex = TEXTURE_2D_ARRAY_INDEX;
       break;
    case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
       texIndex = TEXTURE_2D_ARRAY_INDEX;
       break;
    case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
-      if (level >= ctx->Const.MaxCubeTextureLevels)
-         return NULL;
       texIndex = TEXTURE_CUBE_ARRAY_INDEX;
       break;
    case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
       texIndex = TEXTURE_CUBE_ARRAY_INDEX;
       break;
    case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
-      if (level > 0)
-         return 0;
       texIndex = TEXTURE_2D_MULTISAMPLE_INDEX;
       break;
    case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
       texIndex = TEXTURE_2D_MULTISAMPLE_INDEX;
       break;
    case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
-      if (level > 0)
-         return 0;
       texIndex = TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX;
       break;
    default:
       texIndex = TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX;
       break;
    default:
@@ -453,14 +485,14 @@ get_proxy_tex_image(struct gl_context *ctx, GLenum target, GLint level)
  * \sa gl_constants.
  */
 GLint
  * \sa gl_constants.
  */
 GLint
-_mesa_max_texture_levels(struct gl_context *ctx, GLenum target)
+_mesa_max_texture_levels(const struct gl_context *ctx, GLenum target)
 {
    switch (target) {
    case GL_TEXTURE_1D:
    case GL_PROXY_TEXTURE_1D:
    case GL_TEXTURE_2D:
    case GL_PROXY_TEXTURE_2D:
 {
    switch (target) {
    case GL_TEXTURE_1D:
    case GL_PROXY_TEXTURE_1D:
    case GL_TEXTURE_2D:
    case GL_PROXY_TEXTURE_2D:
-      return ctx->Const.MaxTextureLevels;
+      return ffs(util_next_power_of_two(ctx->Const.MaxTextureSize));
    case GL_TEXTURE_3D:
    case GL_PROXY_TEXTURE_3D:
       return ctx->Const.Max3DTextureLevels;
    case GL_TEXTURE_3D:
    case GL_PROXY_TEXTURE_3D:
       return ctx->Const.Max3DTextureLevels;
@@ -482,7 +514,7 @@ _mesa_max_texture_levels(struct gl_context *ctx, GLenum target)
    case GL_TEXTURE_2D_ARRAY_EXT:
    case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
       return ctx->Extensions.EXT_texture_array
    case GL_TEXTURE_2D_ARRAY_EXT:
    case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
       return ctx->Extensions.EXT_texture_array
-         ? ctx->Const.MaxTextureLevels : 0;
+         ? ffs(util_next_power_of_two(ctx->Const.MaxTextureSize)) : 0;
    case GL_TEXTURE_CUBE_MAP_ARRAY:
    case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
       return _mesa_has_texture_cube_map_array(ctx)
    case GL_TEXTURE_CUBE_MAP_ARRAY:
    case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
       return _mesa_has_texture_cube_map_array(ctx)
@@ -498,7 +530,7 @@ _mesa_max_texture_levels(struct gl_context *ctx, GLenum target)
          && ctx->Extensions.ARB_texture_multisample
          ? 1 : 0;
    case GL_TEXTURE_EXTERNAL_OES:
          && ctx->Extensions.ARB_texture_multisample
          ? 1 : 0;
    case GL_TEXTURE_EXTERNAL_OES:
-      /* fall-through */
+      return _mesa_has_OES_EGL_image_external(ctx) ? 1 : 0;
    default:
       return 0; /* bad target */
    }
    default:
       return 0; /* bad target */
    }
@@ -787,14 +819,15 @@ clear_teximage_fields(struct gl_texture_image *img)
  * Fills in the fields of \p img with the given information.
  * Note: width, height and depth include the border.
  */
  * Fills in the fields of \p img with the given information.
  * Note: width, height and depth include the border.
  */
-static void
-init_teximage_fields_ms(struct gl_context *ctx,
+void
+_mesa_init_teximage_fields_ms(struct gl_context *ctx,
                         struct gl_texture_image *img,
                         GLsizei width, GLsizei height, GLsizei depth,
                         GLint border, GLenum internalFormat,
                         mesa_format format,
                         GLuint numSamples, GLboolean fixedSampleLocations)
 {
                         struct gl_texture_image *img,
                         GLsizei width, GLsizei height, GLsizei depth,
                         GLint border, GLenum internalFormat,
                         mesa_format format,
                         GLuint numSamples, GLboolean fixedSampleLocations)
 {
+   const GLint base_format =_mesa_base_tex_format(ctx, internalFormat);
    GLenum target;
    assert(img);
    assert(width >= 0);
    GLenum target;
    assert(img);
    assert(width >= 0);
@@ -802,8 +835,8 @@ init_teximage_fields_ms(struct gl_context *ctx,
    assert(depth >= 0);
 
    target = img->TexObject->Target;
    assert(depth >= 0);
 
    target = img->TexObject->Target;
-   img->_BaseFormat = _mesa_base_tex_format( ctx, internalFormat );
-   assert(img->_BaseFormat != -1);
+   assert(base_format != -1);
+   img->_BaseFormat = (GLenum16)base_format;
    img->InternalFormat = internalFormat;
    img->Border = border;
    img->Width = width;
    img->InternalFormat = internalFormat;
    img->Border = border;
    img->Width = width;
@@ -900,8 +933,8 @@ _mesa_init_teximage_fields(struct gl_context *ctx,
                            GLint border, GLenum internalFormat,
                            mesa_format format)
 {
                            GLint border, GLenum internalFormat,
                            mesa_format format)
 {
-   init_teximage_fields_ms(ctx, img, width, height, depth, border,
-                           internalFormat, format, 0, GL_TRUE);
+   _mesa_init_teximage_fields_ms(ctx, img, width, height, depth, border,
+                                 internalFormat, format, 0, GL_TRUE);
 }
 
 
 }
 
 
@@ -940,8 +973,7 @@ _mesa_legal_texture_dimensions(struct gl_context *ctx, GLenum target,
    switch (target) {
    case GL_TEXTURE_1D:
    case GL_PROXY_TEXTURE_1D:
    switch (target) {
    case GL_TEXTURE_1D:
    case GL_PROXY_TEXTURE_1D:
-      maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); /* level zero size */
-      maxSize >>= level;  /* level size */
+      maxSize = ctx->Const.MaxTextureSize >> level;
       if (width < 2 * border || width > 2 * border + maxSize)
          return GL_FALSE;
       if (!ctx->Extensions.ARB_texture_non_power_of_two) {
       if (width < 2 * border || width > 2 * border + maxSize)
          return GL_FALSE;
       if (!ctx->Extensions.ARB_texture_non_power_of_two) {
@@ -954,8 +986,7 @@ _mesa_legal_texture_dimensions(struct gl_context *ctx, GLenum target,
    case GL_PROXY_TEXTURE_2D:
    case GL_TEXTURE_2D_MULTISAMPLE:
    case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
    case GL_PROXY_TEXTURE_2D:
    case GL_TEXTURE_2D_MULTISAMPLE:
    case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
-      maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
-      maxSize >>= level;
+      maxSize = ctx->Const.MaxTextureSize >> level;
       if (width < 2 * border || width > 2 * border + maxSize)
          return GL_FALSE;
       if (height < 2 * border || height > 2 * border + maxSize)
       if (width < 2 * border || width > 2 * border + maxSize)
          return GL_FALSE;
       if (height < 2 * border || height > 2 * border + maxSize)
@@ -1025,8 +1056,7 @@ _mesa_legal_texture_dimensions(struct gl_context *ctx, GLenum target,
 
    case GL_TEXTURE_1D_ARRAY_EXT:
    case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
 
    case GL_TEXTURE_1D_ARRAY_EXT:
    case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
-      maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
-      maxSize >>= level;
+      maxSize = ctx->Const.MaxTextureSize >> level;
       if (width < 2 * border || width > 2 * border + maxSize)
          return GL_FALSE;
       if (height < 0 || height > ctx->Const.MaxArrayTextureLayers)
       if (width < 2 * border || width > 2 * border + maxSize)
          return GL_FALSE;
       if (height < 0 || height > ctx->Const.MaxArrayTextureLayers)
@@ -1041,8 +1071,7 @@ _mesa_legal_texture_dimensions(struct gl_context *ctx, GLenum target,
    case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
    case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
    case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
    case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
    case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
    case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
-      maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
-      maxSize >>= level;
+      maxSize = ctx->Const.MaxTextureSize >> level;
       if (width < 2 * border || width > 2 * border + maxSize)
          return GL_FALSE;
       if (height < 2 * border || height > 2 * border + maxSize)
       if (width < 2 * border || width > 2 * border + maxSize)
          return GL_FALSE;
       if (height < 2 * border || height > 2 * border + maxSize)
@@ -1248,7 +1277,7 @@ error_check_subtexture_dimensions(struct gl_context *ctx, GLuint dims,
  */
 GLboolean
 _mesa_test_proxy_teximage(struct gl_context *ctx, GLenum target,
  */
 GLboolean
 _mesa_test_proxy_teximage(struct gl_context *ctx, GLenum target,
-                          GLuint numLevels, GLint level,
+                          GLuint numLevels, ASSERTED GLint level,
                           mesa_format format, GLuint numSamples,
                           GLint width, GLint height, GLint depth)
 {
                           mesa_format format, GLuint numSamples,
                           GLint width, GLint height, GLint depth)
 {
@@ -1302,7 +1331,7 @@ _mesa_test_proxy_teximage(struct gl_context *ctx, GLenum target,
  * Return true if the format is only valid for glCompressedTexImage.
  */
 static bool
  * Return true if the format is only valid for glCompressedTexImage.
  */
 static bool
-compressedteximage_only_format(const struct gl_context *ctx, GLenum format)
+compressedteximage_only_format(GLenum format)
 {
    switch (format) {
    case GL_PALETTE4_RGB8_OES:
 {
    switch (format) {
    case GL_PALETTE4_RGB8_OES:
@@ -1315,6 +1344,9 @@ compressedteximage_only_format(const struct gl_context *ctx, GLenum format)
    case GL_PALETTE8_R5_G6_B5_OES:
    case GL_PALETTE8_RGBA4_OES:
    case GL_PALETTE8_RGB5_A1_OES:
    case GL_PALETTE8_R5_G6_B5_OES:
    case GL_PALETTE8_RGBA4_OES:
    case GL_PALETTE8_RGB5_A1_OES:
+   case GL_ATC_RGB_AMD:
+   case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
+   case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
       return true;
    default:
       return false;
       return true;
    default:
       return false;
@@ -1325,11 +1357,11 @@ compressedteximage_only_format(const struct gl_context *ctx, GLenum format)
  * Return true if the format doesn't support online compression.
  */
 bool
  * Return true if the format doesn't support online compression.
  */
 bool
-_mesa_format_no_online_compression(const struct gl_context *ctx, GLenum format)
+_mesa_format_no_online_compression(GLenum format)
 {
    return _mesa_is_astc_format(format) ||
           _mesa_is_etc2_format(format) ||
 {
    return _mesa_is_astc_format(format) ||
           _mesa_is_etc2_format(format) ||
-          compressedteximage_only_format(ctx, format);
+          compressedteximage_only_format(format);
 }
 
 /* Writes to an GL error pointer if non-null and returns whether or not the
 }
 
 /* Writes to an GL error pointer if non-null and returns whether or not the
@@ -1412,8 +1444,26 @@ _mesa_target_can_be_compressed(const struct gl_context *ctx, GLenum target,
        *
        * This should also be applicable for glTexStorage3D(). Other available
        * targets for these functions are: TEXTURE_3D and TEXTURE_CUBE_MAP_ARRAY.
        *
        * This should also be applicable for glTexStorage3D(). Other available
        * targets for these functions are: TEXTURE_3D and TEXTURE_CUBE_MAP_ARRAY.
+       *
+       * Section 8.7, page 179 of OpenGL ES 3.2 adds:
+       *
+       *      An INVALID_OPERATION error is generated by CompressedTexImage3D
+       *      if internalformat is one of the the formats in table 8.17 and target is
+       *      not TEXTURE_2D_ARRAY, TEXTURE_CUBE_MAP_ARRAY or TEXTURE_3D.
+       *
+       *      An INVALID_OPERATION error is generated by CompressedTexImage3D
+       *      if internalformat is TEXTURE_CUBE_MAP_ARRAY and the â€śCube Map
+       *      Array” column of table 8.17 is not checked, or if internalformat
+       *      is TEXTURE_- 3D and the â€ś3D Tex.” column of table 8.17 is not
+       *      checked.
+       *
+       * The instances of <internalformat> above should say <target>.
+       *
+       * Such table 8.17 has checked "Cube Map Array" column for all the
+       * cases. So in practice, TEXTURE_CUBE_MAP_ARRAY is now valid for OpenGL ES 3.2
        */
        */
-      if (layout == MESA_FORMAT_LAYOUT_ETC2 && _mesa_is_gles3(ctx))
+      if (layout == MESA_FORMAT_LAYOUT_ETC2 && _mesa_is_gles3(ctx) &&
+          !_mesa_is_gles32(ctx))
             return write_error(error, GL_INVALID_OPERATION);
       target_can_be_compresed = _mesa_has_texture_cube_map_array(ctx);
       break;
             return write_error(error, GL_INVALID_OPERATION);
       target_can_be_compresed = _mesa_has_texture_cube_map_array(ctx);
       break;
@@ -1581,9 +1631,8 @@ legal_texsubimage_target(struct gl_context *ctx, GLuint dims, GLenum target,
  * of GL_ARB_texture_storage/GL_ARB_bindless_texture).
  */
 static GLboolean
  * of GL_ARB_texture_storage/GL_ARB_bindless_texture).
  */
 static GLboolean
-mutable_tex_object(struct gl_context *ctx, GLenum target)
+mutable_tex_object(struct gl_texture_object *texObj)
 {
 {
-   struct gl_texture_object *texObj = _mesa_get_current_tex_object(ctx, target);
    if (!texObj)
       return GL_FALSE;
 
    if (!texObj)
       return GL_FALSE;
 
@@ -1719,7 +1768,6 @@ texture_formats_agree(GLenum internalFormat,
  * \param format pixel data format given by the user.
  * \param type pixel data type given by the user.
  * \param internalFormat internal format given by the user.
  * \param format pixel data format given by the user.
  * \param type pixel data type given by the user.
  * \param internalFormat internal format given by the user.
- * \param dimensions texture image dimensions (must be 1, 2 or 3).
  * \param callerName name of the caller function to print in the error message
  *
  * \return true if a error is found, false otherwise
  * \param callerName name of the caller function to print in the error message
  *
  * \return true if a error is found, false otherwise
@@ -1728,31 +1776,17 @@ texture_formats_agree(GLenum internalFormat,
  */
 static bool
 texture_format_error_check_gles(struct gl_context *ctx, GLenum format,
  */
 static bool
 texture_format_error_check_gles(struct gl_context *ctx, GLenum format,
-                                GLenum type, GLenum internalFormat,
-                                GLuint dimensions, const char *callerName)
+                                GLenum type, GLenum internalFormat, const char *callerName)
 {
 {
-   GLenum err;
-
-   if (_mesa_is_gles3(ctx)) {
-      err = _mesa_es3_error_check_format_and_type(ctx, format, type,
-                                                  internalFormat);
-      if (err != GL_NO_ERROR) {
-         _mesa_error(ctx, err,
-                     "%s(format = %s, type = %s, internalformat = %s)",
-                     callerName, _mesa_enum_to_string(format),
-                     _mesa_enum_to_string(type),
-                     _mesa_enum_to_string(internalFormat));
-         return true;
-      }
-   }
-   else {
-      err = _mesa_es_error_check_format_and_type(ctx, format, type, dimensions);
-      if (err != GL_NO_ERROR) {
-         _mesa_error(ctx, err, "%s(format = %s, type = %s)",
-                     callerName, _mesa_enum_to_string(format),
-                     _mesa_enum_to_string(type));
-         return true;
-      }
+   GLenum err = _mesa_gles_error_check_format_and_type(ctx, format, type,
+                                                       internalFormat);
+   if (err != GL_NO_ERROR) {
+      _mesa_error(ctx, err,
+                  "%s(format = %s, type = %s, internalformat = %s)",
+                  callerName, _mesa_enum_to_string(format),
+                  _mesa_enum_to_string(type),
+                  _mesa_enum_to_string(internalFormat));
+      return true;
    }
 
    return false;
    }
 
    return false;
@@ -1786,6 +1820,7 @@ texture_format_error_check_gles(struct gl_context *ctx, GLenum format,
 static GLboolean
 texture_error_check( struct gl_context *ctx,
                      GLuint dimensions, GLenum target,
 static GLboolean
 texture_error_check( struct gl_context *ctx,
                      GLuint dimensions, GLenum target,
+                     struct gl_texture_object* texObj,
                      GLint level, GLint internalFormat,
                      GLenum format, GLenum type,
                      GLint width, GLint height,
                      GLint level, GLint internalFormat,
                      GLenum format, GLenum type,
                      GLint width, GLint height,
@@ -1856,9 +1891,11 @@ texture_error_check( struct gl_context *ctx,
     * Formats and types that require additional extensions (e.g., GL_FLOAT
     * requires GL_OES_texture_float) are filtered elsewhere.
     */
     * Formats and types that require additional extensions (e.g., GL_FLOAT
     * requires GL_OES_texture_float) are filtered elsewhere.
     */
+   char bufCallerName[20];
+   _mesa_snprintf(bufCallerName, 20, "glTexImage%dD", dimensions);
    if (_mesa_is_gles(ctx) &&
    if (_mesa_is_gles(ctx) &&
-       texture_format_error_check_gles(ctx, format, type, internalFormat,
-                                       dimensions, "glTexImage%dD")) {
+       texture_format_error_check_gles(ctx, format, type,
+                                       internalFormat, bufCallerName)) {
       return GL_TRUE;
    }
 
       return GL_TRUE;
    }
 
@@ -1924,7 +1961,7 @@ texture_error_check( struct gl_context *ctx,
                      "glTexImage%dD(target can't be compressed)", dimensions);
          return GL_TRUE;
       }
                      "glTexImage%dD(target can't be compressed)", dimensions);
          return GL_TRUE;
       }
-      if (_mesa_format_no_online_compression(ctx, internalFormat)) {
+      if (_mesa_format_no_online_compression(internalFormat)) {
          _mesa_error(ctx, GL_INVALID_OPERATION,
                      "glTexImage%dD(no compression for format)", dimensions);
          return GL_TRUE;
          _mesa_error(ctx, GL_INVALID_OPERATION,
                      "glTexImage%dD(no compression for format)", dimensions);
          return GL_TRUE;
@@ -1946,7 +1983,7 @@ texture_error_check( struct gl_context *ctx,
       return GL_TRUE;
    }
 
       return GL_TRUE;
    }
 
-   if (!mutable_tex_object(ctx, target)) {
+   if (!mutable_tex_object(texObj)) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "glTexImage%dD(immutable texture)", dimensions);
       return GL_TRUE;
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "glTexImage%dD(immutable texture)", dimensions);
       return GL_TRUE;
@@ -1965,8 +2002,8 @@ texture_error_check( struct gl_context *ctx,
  */
 static GLenum
 compressed_texture_error_check(struct gl_context *ctx, GLint dimensions,
  */
 static GLenum
 compressed_texture_error_check(struct gl_context *ctx, GLint dimensions,
-                               GLenum target, GLint level,
-                               GLenum internalFormat, GLsizei width,
+                               GLenum target, struct gl_texture_object* texObj,
+                               GLint level, GLenum internalFormat, GLsizei width,
                                GLsizei height, GLsizei depth, GLint border,
                                GLsizei imageSize, const GLvoid *data)
 {
                                GLsizei height, GLsizei depth, GLint border,
                                GLsizei imageSize, const GLvoid *data)
 {
@@ -2082,7 +2119,7 @@ compressed_texture_error_check(struct gl_context *ctx, GLint dimensions,
       goto error;
    }
 
       goto error;
    }
 
-   if (!mutable_tex_object(ctx, target)) {
+   if (!mutable_tex_object(texObj)) {
       reason = "immutable texture";
       error = GL_INVALID_OPERATION;
       goto error;
       reason = "immutable texture";
       error = GL_INVALID_OPERATION;
       goto error;
@@ -2128,7 +2165,7 @@ texsubimage_error_check(struct gl_context *ctx, GLuint dimensions,
                         GLint xoffset, GLint yoffset, GLint zoffset,
                         GLint width, GLint height, GLint depth,
                         GLenum format, GLenum type, const GLvoid *pixels,
                         GLint xoffset, GLint yoffset, GLint zoffset,
                         GLint width, GLint height, GLint depth,
                         GLenum format, GLenum type, const GLvoid *pixels,
-                        bool dsa, const char *callerName)
+                        const char *callerName)
 {
    struct gl_texture_image *texImage;
    GLenum err;
 {
    struct gl_texture_image *texImage;
    GLenum err;
@@ -2168,6 +2205,19 @@ texsubimage_error_check(struct gl_context *ctx, GLuint dimensions,
       return GL_TRUE;
    }
 
       return GL_TRUE;
    }
 
+   if (!texture_formats_agree(texImage->InternalFormat, format)) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "%s(incompatible internalFormat = %s, format = %s)",
+                  callerName,
+                  _mesa_enum_to_string(texImage->InternalFormat),
+                  _mesa_enum_to_string(format));
+      return GL_TRUE;
+   }
+
+   GLenum internalFormat = _mesa_is_gles(ctx) ?
+      oes_float_internal_format(ctx, texImage->InternalFormat, type) :
+      texImage->InternalFormat;
+
    /* OpenGL ES 1.x and OpenGL ES 2.0 impose additional restrictions on the
     * combinations of format, internalFormat, and type that can be used.
     * Formats and types that require additional extensions (e.g., GL_FLOAT
    /* OpenGL ES 1.x and OpenGL ES 2.0 impose additional restrictions on the
     * combinations of format, internalFormat, and type that can be used.
     * Formats and types that require additional extensions (e.g., GL_FLOAT
@@ -2175,8 +2225,7 @@ texsubimage_error_check(struct gl_context *ctx, GLuint dimensions,
     */
    if (_mesa_is_gles(ctx) &&
        texture_format_error_check_gles(ctx, format, type,
     */
    if (_mesa_is_gles(ctx) &&
        texture_format_error_check_gles(ctx, format, type,
-                                       texImage->InternalFormat,
-                                       dimensions, callerName)) {
+                                       internalFormat, callerName)) {
       return GL_TRUE;
    }
 
       return GL_TRUE;
    }
 
@@ -2194,7 +2243,7 @@ texsubimage_error_check(struct gl_context *ctx, GLuint dimensions,
    }
 
    if (_mesa_is_format_compressed(texImage->TexFormat)) {
    }
 
    if (_mesa_is_format_compressed(texImage->TexFormat)) {
-      if (_mesa_format_no_online_compression(ctx, texImage->InternalFormat)) {
+      if (_mesa_format_no_online_compression(texImage->InternalFormat)) {
          _mesa_error(ctx, GL_INVALID_OPERATION,
                "%s(no compression for format)", callerName);
          return GL_TRUE;
          _mesa_error(ctx, GL_INVALID_OPERATION,
                "%s(no compression for format)", callerName);
          return GL_TRUE;
@@ -2235,8 +2284,8 @@ texsubimage_error_check(struct gl_context *ctx, GLuint dimensions,
  */
 static GLboolean
 copytexture_error_check( struct gl_context *ctx, GLuint dimensions,
  */
 static GLboolean
 copytexture_error_check( struct gl_context *ctx, GLuint dimensions,
-                         GLenum target, GLint level, GLint internalFormat,
-                         GLint width, GLint height, GLint border )
+                         GLenum target, struct gl_texture_object* texObj,
+                         GLint level, GLint internalFormat, GLint border )
 {
    GLint baseFormat;
    GLint rb_base_format;
 {
    GLint baseFormat;
    GLint rb_base_format;
@@ -2348,8 +2397,8 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions,
 
    if (_mesa_is_gles(ctx)) {
       bool valid = true;
 
    if (_mesa_is_gles(ctx)) {
       bool valid = true;
-      if (_mesa_base_format_component_count(baseFormat) >
-          _mesa_base_format_component_count(rb_base_format)) {
+      if (_mesa_components_in_format(baseFormat) >
+          _mesa_components_in_format(rb_base_format)) {
          valid = false;
       }
       if (baseFormat == GL_DEPTH_COMPONENT ||
          valid = false;
       }
       if (baseFormat == GL_DEPTH_COMPONENT ||
@@ -2376,14 +2425,10 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions,
    }
 
    if (_mesa_is_gles3(ctx)) {
    }
 
    if (_mesa_is_gles3(ctx)) {
-      bool rb_is_srgb = false;
+      bool rb_is_srgb = (ctx->Extensions.EXT_sRGB &&
+                         _mesa_is_format_srgb(rb->Format));
       bool dst_is_srgb = false;
 
       bool dst_is_srgb = false;
 
-      if (ctx->Extensions.EXT_framebuffer_sRGB &&
-          _mesa_get_format_color_encoding(rb->Format) == GL_SRGB) {
-         rb_is_srgb = true;
-      }
-
       if (_mesa_get_linear_internalformat(internalFormat) != internalFormat) {
          dst_is_srgb = true;
       }
       if (_mesa_get_linear_internalformat(internalFormat) != internalFormat) {
          dst_is_srgb = true;
       }
@@ -2409,7 +2454,8 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions,
        * types for SNORM formats. Also, conversion to SNORM formats is not
        * allowed by Table 3.2 on Page 110.
        */
        * types for SNORM formats. Also, conversion to SNORM formats is not
        * allowed by Table 3.2 on Page 110.
        */
-      if (_mesa_is_enum_format_snorm(internalFormat)) {
+      if (!_mesa_has_EXT_render_snorm(ctx) &&
+          _mesa_is_enum_format_snorm(internalFormat)) {
          _mesa_error(ctx, GL_INVALID_OPERATION,
                      "glCopyTexImage%dD(internalFormat=%s)", dimensions,
                      _mesa_enum_to_string(internalFormat));
          _mesa_error(ctx, GL_INVALID_OPERATION,
                      "glCopyTexImage%dD(internalFormat=%s)", dimensions,
                      _mesa_enum_to_string(internalFormat));
@@ -2444,7 +2490,8 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions,
                     _mesa_is_enum_format_unsigned_int(internalFormat) !=
                       _mesa_is_enum_format_unsigned_int(rb_internal_format)) {
             _mesa_error(ctx, GL_INVALID_OPERATION,
                     _mesa_is_enum_format_unsigned_int(internalFormat) !=
                       _mesa_is_enum_format_unsigned_int(rb_internal_format)) {
             _mesa_error(ctx, GL_INVALID_OPERATION,
-                        "glCopyTexImage%dD(signed vs unsigned integer)", dimensions);
+                        "glCopyTexImage%dD(signed vs unsigned integer)",
+                        dimensions);
             return GL_TRUE;
          }
       }
             return GL_TRUE;
          }
       }
@@ -2470,7 +2517,7 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions,
                      "glCopyTexImage%dD(target can't be compressed)", dimensions);
          return GL_TRUE;
       }
                      "glCopyTexImage%dD(target can't be compressed)", dimensions);
          return GL_TRUE;
       }
-      if (_mesa_format_no_online_compression(ctx, internalFormat)) {
+      if (_mesa_format_no_online_compression(internalFormat)) {
          _mesa_error(ctx, GL_INVALID_OPERATION,
                "glCopyTexImage%dD(no compression for format)", dimensions);
          return GL_TRUE;
          _mesa_error(ctx, GL_INVALID_OPERATION,
                "glCopyTexImage%dD(no compression for format)", dimensions);
          return GL_TRUE;
@@ -2482,7 +2529,7 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions,
       }
    }
 
       }
    }
 
-   if (!mutable_tex_object(ctx, target)) {
+   if (!mutable_tex_object(texObj)) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "glCopyTexImage%dD(immutable texture)", dimensions);
       return GL_TRUE;
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "glCopyTexImage%dD(immutable texture)", dimensions);
       return GL_TRUE;
@@ -2552,7 +2599,7 @@ copytexsubimage_error_check(struct gl_context *ctx, GLuint dimensions,
    }
 
    if (_mesa_is_format_compressed(texImage->TexFormat)) {
    }
 
    if (_mesa_is_format_compressed(texImage->TexFormat)) {
-      if (_mesa_format_no_online_compression(ctx, texImage->InternalFormat)) {
+      if (_mesa_format_no_online_compression(texImage->InternalFormat)) {
          _mesa_error(ctx, GL_INVALID_OPERATION,
                "%s(no compression for format)", caller);
          return GL_TRUE;
          _mesa_error(ctx, GL_INVALID_OPERATION,
                "%s(no compression for format)", caller);
          return GL_TRUE;
@@ -2564,6 +2611,20 @@ copytexsubimage_error_check(struct gl_context *ctx, GLuint dimensions,
       return GL_TRUE;
    }
 
       return GL_TRUE;
    }
 
+   /* From OpenGL ES 3.2 spec, section 8.6:
+    *
+    *     "An INVALID_OPERATION error is generated by CopyTexSubImage3D,
+    *      CopyTexImage2D, or CopyTexSubImage2D if the internalformat of the
+    *      texture image being (re)specified is RGB9_E5"
+    */
+   if (texImage->InternalFormat == GL_RGB9_E5 &&
+       !_mesa_is_desktop_gl(ctx)) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "%s(invalid internal format %s)", caller,
+                  _mesa_enum_to_string(texImage->InternalFormat));
+      return GL_TRUE;
+   }
+
    if (!_mesa_source_buffer_exists(ctx, texImage->_BaseFormat)) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "%s(missing readbuffer, format=%s)", caller,
    if (!_mesa_source_buffer_exists(ctx, texImage->_BaseFormat)) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "%s(missing readbuffer, format=%s)", caller,
@@ -2617,7 +2678,7 @@ struct cb_info
  * Check render to texture callback.  Called from _mesa_HashWalk().
  */
 static void
  * Check render to texture callback.  Called from _mesa_HashWalk().
  */
 static void
-check_rtt_cb(GLuint key, void *data, void *userData)
+check_rtt_cb(UNUSED GLuint key, void *data, void *userData)
 {
    struct gl_framebuffer *fb = (struct gl_framebuffer *) data;
    const struct cb_info *info = (struct cb_info *) userData;
 {
    struct gl_framebuffer *fb = (struct gl_framebuffer *) data;
    const struct cb_info *info = (struct cb_info *) userData;
@@ -2694,7 +2755,8 @@ check_gen_mipmap(struct gl_context *ctx, GLenum target,
 
 /** Debug helper: override the user-requested internal format */
 static GLenum
 
 /** Debug helper: override the user-requested internal format */
 static GLenum
-override_internal_format(GLenum internalFormat, GLint width, GLint height)
+override_internal_format(GLenum internalFormat, UNUSED GLint width,
+                         UNUSED GLint height)
 {
 #if 0
    if (internalFormat == GL_RGBA16F_ARB ||
 {
 #if 0
    if (internalFormat == GL_RGBA16F_ARB ||
@@ -2755,7 +2817,7 @@ _mesa_choose_texture_format(struct gl_context *ctx,
    /* see if we've already chosen a format for the previous level */
    if (level > 0) {
       struct gl_texture_image *prevImage =
    /* see if we've already chosen a format for the previous level */
    if (level > 0) {
       struct gl_texture_image *prevImage =
-        _mesa_select_tex_image(texObj, target, level - 1);
+         _mesa_select_tex_image(texObj, target, level - 1);
       /* See if the prev level is defined and has an internal format which
        * matches the new internal format.
        */
       /* See if the prev level is defined and has an internal format which
        * matches the new internal format.
        */
@@ -2768,38 +2830,6 @@ _mesa_choose_texture_format(struct gl_context *ctx,
       }
    }
 
       }
    }
 
-   /* If the application requested compression to an S3TC format but we don't
-    * have the DXTn library, force a generic compressed format instead.
-    */
-   if (internalFormat != format && format != GL_NONE) {
-      const GLenum before = internalFormat;
-
-      switch (internalFormat) {
-      case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
-         if (!ctx->Mesa_DXTn)
-            internalFormat = GL_COMPRESSED_RGB;
-         break;
-      case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
-      case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
-      case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
-         if (!ctx->Mesa_DXTn)
-            internalFormat = GL_COMPRESSED_RGBA;
-         break;
-      default:
-         break;
-      }
-
-      if (before != internalFormat) {
-         _mesa_warning(ctx,
-                       "DXT compression requested (%s), "
-                       "but libtxc_dxtn library not installed.  Using %s "
-                       "instead.",
-                       _mesa_enum_to_string(before),
-                       _mesa_enum_to_string(internalFormat));
-      }
-   }
-
-   /* choose format from scratch */
    f = ctx->Driver.ChooseTextureFormat(ctx, target, internalFormat,
                                        format, type);
    assert(f != MESA_FORMAT_NONE);
    f = ctx->Driver.ChooseTextureFormat(ctx, target, internalFormat,
                                        format, type);
    assert(f != MESA_FORMAT_NONE);
@@ -2852,10 +2882,70 @@ strip_texture_border(GLenum target,
    }
 }
 
    }
 }
 
+static struct gl_texture_object *
+lookup_texture_ext_dsa(struct gl_context *ctx, GLenum target, GLuint texture,
+                       const char *caller)
+{
+   GLenum boundTarget;
+   switch (target) {
+   case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+   case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+   case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+   case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+      boundTarget = GL_TEXTURE_CUBE_MAP;
+      break;
+   default:
+      boundTarget = target;
+      break;
+   }
+
+   int targetIndex = _mesa_tex_target_to_index(ctx, boundTarget);
+   if (targetIndex < 0) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "%s(target = %s)", caller,
+                  _mesa_enum_to_string(target));
+            return NULL;
+   }
+   assert(targetIndex < NUM_TEXTURE_TARGETS);
+
+   struct gl_texture_object *texObj;
+   if (texture == 0) {
+      /* Use a default texture object */
+      texObj = ctx->Shared->DefaultTex[targetIndex];
+      assert(texObj);
+   } else {
+      texObj = _mesa_lookup_texture(ctx, texture);
+      if (!texObj && ctx->API == API_OPENGL_CORE) {
+         _mesa_error(ctx, GL_INVALID_OPERATION, "%s(non-gen name)", caller);
+         return NULL;
+      }
+
+      if (!texObj) {
+         texObj = ctx->Driver.NewTextureObject(ctx, texture, boundTarget);
+         if (!texObj) {
+            _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller);
+            return NULL;
+         }
+
+         /* insert into hash table */
+         _mesa_HashInsert(ctx->Shared->TexObjects, texObj->Name, texObj);
+      }
+
+      if (texObj->Target != boundTarget) {
+         _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s != %s)",
+                     caller, _mesa_enum_to_string(texObj->Target),
+                     _mesa_enum_to_string(target));
+         return NULL;
+      }
+   }
+
+   return texObj;
+}
 
 /**
 
 /**
- * Common code to implement all the glTexImage1D/2D/3D functions
- * as well as glCompressedTexImage1D/2D/3D.
+ * Common code to implement all the glTexImage1D/2D/3D functions,
+ * glCompressedTexImage1D/2D/3D and glTextureImage1D/2D/3DEXT
  * \param compressed  only GL_TRUE for glCompressedTexImage1D/2D/3D calls.
  * \param format  the user's image format (only used if !compressed)
  * \param type  the user's image type (only used if !compressed)
  * \param compressed  only GL_TRUE for glCompressedTexImage1D/2D/3D calls.
  * \param format  the user's image format (only used if !compressed)
  * \param type  the user's image type (only used if !compressed)
@@ -2863,6 +2953,7 @@ strip_texture_border(GLenum target,
  */
 static ALWAYS_INLINE void
 teximage(struct gl_context *ctx, GLboolean compressed, GLuint dims,
  */
 static ALWAYS_INLINE void
 teximage(struct gl_context *ctx, GLboolean compressed, GLuint dims,
+         struct gl_texture_object *texObj,
          GLenum target, GLint level, GLint internalFormat,
          GLsizei width, GLsizei height, GLsizei depth,
          GLint border, GLenum format, GLenum type,
          GLenum target, GLint level, GLint internalFormat,
          GLsizei width, GLsizei height, GLsizei depth,
          GLint border, GLenum format, GLenum type,
@@ -2871,7 +2962,6 @@ teximage(struct gl_context *ctx, GLboolean compressed, GLuint dims,
    const char *func = compressed ? "glCompressedTexImage" : "glTexImage";
    struct gl_pixelstore_attrib unpack_no_border;
    const struct gl_pixelstore_attrib *unpack = &ctx->Unpack;
    const char *func = compressed ? "glCompressedTexImage" : "glTexImage";
    struct gl_pixelstore_attrib unpack_no_border;
    const struct gl_pixelstore_attrib *unpack = &ctx->Unpack;
-   struct gl_texture_object *texObj;
    mesa_format texFormat;
    bool dimensionsOK = true, sizeOK = true;
 
    mesa_format texFormat;
    bool dimensionsOK = true, sizeOK = true;
 
@@ -2898,28 +2988,33 @@ teximage(struct gl_context *ctx, GLboolean compressed, GLuint dims,
 
    internalFormat = override_internal_format(internalFormat, width, height);
 
 
    internalFormat = override_internal_format(internalFormat, width, height);
 
-   if (!no_error) {
-      /* target error checking */
-      if (!legal_teximage_target(ctx, dims, target)) {
-         _mesa_error(ctx, GL_INVALID_ENUM, "%s%uD(target=%s)",
-                     func, dims, _mesa_enum_to_string(target));
-         return;
-      }
+   if (!no_error &&
+       /* target error checking */
+       !legal_teximage_target(ctx, dims, target)) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "%s%uD(target=%s)",
+                  func, dims, _mesa_enum_to_string(target));
+      return;
+   }
 
 
+   if (!texObj)
+      texObj = _mesa_get_current_tex_object(ctx, target);
+
+   if (!no_error) {
       /* general error checking */
       if (compressed) {
       /* general error checking */
       if (compressed) {
-         if (compressed_texture_error_check(ctx, dims, target, level,
-                                            internalFormat,
+         if (compressed_texture_error_check(ctx, dims, target, texObj,
+                                            level, internalFormat,
                                             width, height, depth,
                                             border, imageSize, pixels))
             return;
       } else {
                                             width, height, depth,
                                             border, imageSize, pixels))
             return;
       } else {
-         if (texture_error_check(ctx, dims, target, level, internalFormat,
+         if (texture_error_check(ctx, dims, target, texObj, level, internalFormat,
                                  format, type, width, height, depth, border,
                                  pixels))
             return;
       }
    }
                                  format, type, width, height, depth, border,
                                  pixels))
             return;
       }
    }
+   assert(texObj);
 
    /* Here we convert a cpal compressed image into a regular glTexImage2D
     * call by decompressing the texture.  If we really want to support cpal
 
    /* Here we convert a cpal compressed image into a regular glTexImage2D
     * call by decompressing the texture.  If we really want to support cpal
@@ -2943,9 +3038,6 @@ teximage(struct gl_context *ctx, GLboolean compressed, GLuint dims,
       }
    }
 
       }
    }
 
-   texObj = _mesa_get_current_tex_object(ctx, target);
-   assert(texObj);
-
    if (compressed) {
       /* For glCompressedTexImage() the driver has no choice about the
        * texture format since we'll never transcode the user's compressed
    if (compressed) {
       /* For glCompressedTexImage() the driver has no choice about the
        * texture format since we'll never transcode the user's compressed
@@ -3025,22 +3117,22 @@ teximage(struct gl_context *ctx, GLboolean compressed, GLuint dims,
        * rarely-tested software fallback rendering.
        */
       if (border && ctx->Const.StripTextureBorder) {
        * rarely-tested software fallback rendering.
        */
       if (border && ctx->Const.StripTextureBorder) {
-        strip_texture_border(target, &width, &height, &depth, unpack,
-                             &unpack_no_border);
+         strip_texture_border(target, &width, &height, &depth, unpack,
+                              &unpack_no_border);
          border = 0;
          border = 0;
-        unpack = &unpack_no_border;
+         unpack = &unpack_no_border;
       }
 
       if (ctx->NewState & _NEW_PIXEL)
       }
 
       if (ctx->NewState & _NEW_PIXEL)
-        _mesa_update_state(ctx);
+         _mesa_update_state(ctx);
 
       _mesa_lock_texture(ctx, texObj);
       {
 
       _mesa_lock_texture(ctx, texObj);
       {
-        texImage = _mesa_get_tex_image(ctx, texObj, target, level);
+         texImage = _mesa_get_tex_image(ctx, texObj, target, level);
 
 
-        if (!texImage) {
-           _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s%uD", func, dims);
-        }
+         if (!texImage) {
+            _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s%uD", func, dims);
+         }
          else {
             ctx->Driver.FreeTextureImageBuffer(ctx, texImage);
 
          else {
             ctx->Driver.FreeTextureImageBuffer(ctx, texImage);
 
@@ -3071,6 +3163,7 @@ teximage(struct gl_context *ctx, GLboolean compressed, GLuint dims,
    }
 }
 
    }
 }
 
+
 /* This is a wrapper around teximage() so that we can force the KHR_no_error
  * logic to be inlined without inlining the function into all the callers.
  */
 /* This is a wrapper around teximage() so that we can force the KHR_no_error
  * logic to be inlined without inlining the function into all the callers.
  */
@@ -3081,7 +3174,7 @@ teximage_err(struct gl_context *ctx, GLboolean compressed, GLuint dims,
              GLint border, GLenum format, GLenum type,
              GLsizei imageSize, const GLvoid *pixels)
 {
              GLint border, GLenum format, GLenum type,
              GLsizei imageSize, const GLvoid *pixels)
 {
-   teximage(ctx, compressed, dims, target, level, internalFormat, width, height,
+   teximage(ctx, compressed, dims, NULL, target, level, internalFormat, width, height,
             depth, border, format, type, imageSize, pixels, false);
 }
 
             depth, border, format, type, imageSize, pixels, false);
 }
 
@@ -3093,7 +3186,7 @@ teximage_no_error(struct gl_context *ctx, GLboolean compressed, GLuint dims,
                   GLint border, GLenum format, GLenum type,
                   GLsizei imageSize, const GLvoid *pixels)
 {
                   GLint border, GLenum format, GLenum type,
                   GLsizei imageSize, const GLvoid *pixels)
 {
-   teximage(ctx, compressed, dims, target, level, internalFormat, width, height,
+   teximage(ctx, compressed, dims, NULL, target, level, internalFormat, width, height,
             depth, border, format, type, imageSize, pixels, true);
 }
 
             depth, border, format, type, imageSize, pixels, true);
 }
 
@@ -3111,6 +3204,39 @@ _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
                 border, format, type, 0, pixels);
 }
 
                 border, format, type, 0, pixels);
 }
 
+void GLAPIENTRY
+_mesa_TextureImage1DEXT(GLuint texture, GLenum target, GLint level,
+                      GLint internalFormat, GLsizei width, GLint border,
+                      GLenum format, GLenum type, const GLvoid *pixels )
+{
+   struct gl_texture_object*  texObj;
+   GET_CURRENT_CONTEXT(ctx);
+
+   texObj = _mesa_lookup_or_create_texture(ctx, target, texture, false, true,
+                                           "glTextureImage1DEXT");
+   if (!texObj)
+      return;
+   teximage(ctx, GL_FALSE, 1, texObj, target, level, internalFormat,
+            width, 1, 1, border, format, type, 0, pixels, false);
+}
+
+void GLAPIENTRY
+_mesa_MultiTexImage1DEXT(GLenum texunit, GLenum target, GLint level,
+                         GLint internalFormat, GLsizei width, GLint border,
+                         GLenum format, GLenum type, const GLvoid *pixels )
+{
+   struct gl_texture_object*  texObj;
+   GET_CURRENT_CONTEXT(ctx);
+
+   texObj = _mesa_get_texobj_by_target_and_texunit(ctx, target,
+                                                   texunit - GL_TEXTURE0,
+                                                   true,
+                                                   "glMultiTexImage1DEXT");
+   if (!texObj)
+      return;
+   teximage(ctx, GL_FALSE, 1, texObj, target, level, internalFormat, width, 1, 1,
+                border, format, type, 0, pixels, false);
+}
 
 void GLAPIENTRY
 _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
 
 void GLAPIENTRY
 _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
@@ -3123,6 +3249,41 @@ _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
                 border, format, type, 0, pixels);
 }
 
                 border, format, type, 0, pixels);
 }
 
+void GLAPIENTRY
+_mesa_TextureImage2DEXT(GLuint texture, GLenum target, GLint level,
+                      GLint internalFormat, GLsizei width, GLsizei height,
+                      GLint border,
+                      GLenum format, GLenum type, const GLvoid *pixels )
+{
+   struct gl_texture_object*  texObj;
+   GET_CURRENT_CONTEXT(ctx);
+
+   texObj = _mesa_lookup_or_create_texture(ctx, target, texture, false, true,
+                                           "glTextureImage2DEXT");
+   if (!texObj)
+      return;
+   teximage(ctx, GL_FALSE, 2, texObj, target, level, internalFormat,
+            width, height, 1, border, format, type, 0, pixels, false);
+}
+
+void GLAPIENTRY
+_mesa_MultiTexImage2DEXT(GLenum texunit, GLenum target, GLint level,
+                         GLint internalFormat, GLsizei width, GLsizei height,
+                         GLint border,
+                         GLenum format, GLenum type, const GLvoid *pixels )
+{
+   struct gl_texture_object*  texObj;
+   GET_CURRENT_CONTEXT(ctx);
+
+   texObj = _mesa_get_texobj_by_target_and_texunit(ctx, target,
+                                                   texunit - GL_TEXTURE0,
+                                                   true,
+                                                   "glMultiTexImage2DEXT");
+   if (!texObj)
+      return;
+   teximage(ctx, GL_FALSE, 2, texObj, target, level, internalFormat, width, height, 1,
+                border, format, type, 0, pixels, false);
+}
 
 /*
  * Called by the API or display list executor.
 
 /*
  * Called by the API or display list executor.
@@ -3139,6 +3300,43 @@ _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
                 width, height, depth, border, format, type, 0, pixels);
 }
 
                 width, height, depth, border, format, type, 0, pixels);
 }
 
+void GLAPIENTRY
+_mesa_TextureImage3DEXT(GLuint texture, GLenum target, GLint level,
+                      GLint internalFormat, GLsizei width, GLsizei height,
+                      GLsizei depth, GLint border,
+                      GLenum format, GLenum type, const GLvoid *pixels )
+{
+   struct gl_texture_object*  texObj;
+   GET_CURRENT_CONTEXT(ctx);
+
+   texObj = _mesa_lookup_or_create_texture(ctx, target, texture, false, true,
+                                           "glTextureImage3DEXT");
+   if (!texObj)
+      return;
+   teximage(ctx, GL_FALSE, 3, texObj, target, level, internalFormat,
+            width, height, depth, border, format, type, 0, pixels, false);
+}
+
+
+void GLAPIENTRY
+_mesa_MultiTexImage3DEXT(GLenum texunit, GLenum target, GLint level,
+                         GLint internalFormat, GLsizei width, GLsizei height,
+                         GLsizei depth, GLint border, GLenum format, GLenum type,
+                         const GLvoid *pixels )
+{
+   struct gl_texture_object*  texObj;
+   GET_CURRENT_CONTEXT(ctx);
+
+   texObj = _mesa_get_texobj_by_target_and_texunit(ctx, target,
+                                                   texunit - GL_TEXTURE0,
+                                                   true,
+                                                   "glMultiTexImage3DEXT");
+   if (!texObj)
+      return;
+   teximage(ctx, GL_FALSE, 3, texObj, target, level, internalFormat,
+                width, height, depth, border, format, type, 0, pixels, false);
+}
+
 
 void GLAPIENTRY
 _mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat,
 
 void GLAPIENTRY
 _mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat,
@@ -3242,14 +3440,13 @@ _mesa_EGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image)
       ctx->Driver.FreeTextureImageBuffer(ctx, texImage);
 
       ctx->Driver.EGLImageTargetTexture2D(ctx, target,
       ctx->Driver.FreeTextureImageBuffer(ctx, texImage);
 
       ctx->Driver.EGLImageTargetTexture2D(ctx, target,
-                                         texObj, texImage, image);
+                                          texObj, texImage, image);
 
       _mesa_dirty_texobj(ctx, texObj);
    }
    _mesa_unlock_texture(ctx, texObj);
 }
 
 
       _mesa_dirty_texobj(ctx, texObj);
    }
    _mesa_unlock_texture(ctx, texObj);
 }
 
-
 /**
  * Helper that implements the glTexSubImage1/2/3D()
  * and glTextureSubImage1/2/3D() functions.
 /**
  * Helper that implements the glTexSubImage1/2/3D()
  * and glTextureSubImage1/2/3D() functions.
@@ -3261,8 +3458,7 @@ texture_sub_image(struct gl_context *ctx, GLuint dims,
                   GLenum target, GLint level,
                   GLint xoffset, GLint yoffset, GLint zoffset,
                   GLsizei width, GLsizei height, GLsizei depth,
                   GLenum target, GLint level,
                   GLint xoffset, GLint yoffset, GLint zoffset,
                   GLsizei width, GLsizei height, GLsizei depth,
-                  GLenum format, GLenum type, const GLvoid *pixels,
-                  bool dsa)
+                  GLenum format, GLenum type, const GLvoid *pixels)
 {
    FLUSH_VERTICES(ctx, 0);
 
 {
    FLUSH_VERTICES(ctx, 0);
 
@@ -3329,7 +3525,7 @@ texsubimage_err(struct gl_context *ctx, GLuint dims, GLenum target, GLint level,
    if (texsubimage_error_check(ctx, dims, texObj, target, level,
                                xoffset, yoffset, zoffset,
                                width, height, depth, format, type,
    if (texsubimage_error_check(ctx, dims, texObj, target, level,
                                xoffset, yoffset, zoffset,
                                width, height, depth, format, type,
-                               pixels, false, callerName)) {
+                               pixels, callerName)) {
       return;   /* error was detected */
    }
 
       return;   /* error was detected */
    }
 
@@ -3346,7 +3542,7 @@ texsubimage_err(struct gl_context *ctx, GLuint dims, GLenum target, GLint level,
 
    texture_sub_image(ctx, dims, texObj, texImage, target, level,
                      xoffset, yoffset, zoffset, width, height, depth,
 
    texture_sub_image(ctx, dims, texObj, texImage, target, level,
                      xoffset, yoffset, zoffset, width, height, depth,
-                     format, type, pixels, false);
+                     format, type, pixels);
 }
 
 
 }
 
 
@@ -3364,7 +3560,7 @@ texsubimage(struct gl_context *ctx, GLuint dims, GLenum target, GLint level,
 
    texture_sub_image(ctx, dims, texObj, texImage, target, level,
                      xoffset, yoffset, zoffset, width, height, depth,
 
    texture_sub_image(ctx, dims, texObj, texImage, target, level,
                      xoffset, yoffset, zoffset, width, height, depth,
-                     format, type, pixels, false);
+                     format, type, pixels);
 }
 
 
 }
 
 
@@ -3374,11 +3570,11 @@ texsubimage(struct gl_context *ctx, GLuint dims, GLenum target, GLint level,
  */
 static ALWAYS_INLINE void
 texturesubimage(struct gl_context *ctx, GLuint dims,
  */
 static ALWAYS_INLINE void
 texturesubimage(struct gl_context *ctx, GLuint dims,
-                GLuint texture, GLint level,
+                GLuint texture, GLenum target, GLint level,
                 GLint xoffset, GLint yoffset, GLint zoffset,
                 GLsizei width, GLsizei height, GLsizei depth,
                 GLenum format, GLenum type, const GLvoid *pixels,
                 GLint xoffset, GLint yoffset, GLint zoffset,
                 GLsizei width, GLsizei height, GLsizei depth,
                 GLenum format, GLenum type, const GLvoid *pixels,
-                const char *callerName, bool no_error)
+                const char *callerName, bool no_error, bool ext_dsa)
 {
    struct gl_texture_object *texObj;
    struct gl_texture_image *texImage;
 {
    struct gl_texture_object *texObj;
    struct gl_texture_image *texImage;
@@ -3394,7 +3590,11 @@ texturesubimage(struct gl_context *ctx, GLuint dims,
 
    /* Get the texture object by Name. */
    if (!no_error) {
 
    /* Get the texture object by Name. */
    if (!no_error) {
-      texObj = _mesa_lookup_texture_err(ctx, texture, callerName);
+      if (!ext_dsa) {
+         texObj = _mesa_lookup_texture_err(ctx, texture, callerName);
+      } else {
+         texObj = lookup_texture_ext_dsa(ctx, target, texture, callerName);
+      }
       if (!texObj)
          return;
    } else {
       if (!texObj)
          return;
    } else {
@@ -3412,7 +3612,7 @@ texturesubimage(struct gl_context *ctx, GLuint dims,
       if (texsubimage_error_check(ctx, dims, texObj, texObj->Target, level,
                                   xoffset, yoffset, zoffset,
                                   width, height, depth, format, type,
       if (texsubimage_error_check(ctx, dims, texObj, texObj->Target, level,
                                   xoffset, yoffset, zoffset,
                                   width, height, depth, format, type,
-                                  pixels, true, callerName)) {
+                                  pixels, callerName)) {
          return;   /* error was detected */
       }
    }
          return;   /* error was detected */
       }
    }
@@ -3467,7 +3667,7 @@ texturesubimage(struct gl_context *ctx, GLuint dims,
          texture_sub_image(ctx, 3, texObj, texImage, texObj->Target,
                            level, xoffset, yoffset, 0,
                            width, height, 1, format,
          texture_sub_image(ctx, 3, texObj, texImage, texObj->Target,
                            level, xoffset, yoffset, 0,
                            width, height, 1, format,
-                           type, pixels, true);
+                           type, pixels);
          pixels = (GLubyte *) pixels + imageStride;
       }
    }
          pixels = (GLubyte *) pixels + imageStride;
       }
    }
@@ -3478,36 +3678,36 @@ texturesubimage(struct gl_context *ctx, GLuint dims,
       texture_sub_image(ctx, dims, texObj, texImage, texObj->Target,
                         level, xoffset, yoffset, zoffset,
                         width, height, depth, format,
       texture_sub_image(ctx, dims, texObj, texImage, texObj->Target,
                         level, xoffset, yoffset, zoffset,
                         width, height, depth, format,
-                        type, pixels, true);
+                        type, pixels);
    }
 }
 
 
 static void
 texturesubimage_error(struct gl_context *ctx, GLuint dims,
    }
 }
 
 
 static void
 texturesubimage_error(struct gl_context *ctx, GLuint dims,
-                      GLuint texture, GLint level,
+                      GLuint texture, GLenum target, GLint level,
                       GLint xoffset, GLint yoffset, GLint zoffset,
                       GLsizei width, GLsizei height, GLsizei depth,
                       GLenum format, GLenum type, const GLvoid *pixels,
                       GLint xoffset, GLint yoffset, GLint zoffset,
                       GLsizei width, GLsizei height, GLsizei depth,
                       GLenum format, GLenum type, const GLvoid *pixels,
-                      const char *callerName)
+                      const char *callerName, bool ext_dsa)
 {
 {
-   texturesubimage(ctx, dims, texture, level, xoffset, yoffset, zoffset,
-                   width, height, depth, format, type, pixels, callerName,
-                   false);
+   texturesubimage(ctx, dims, texture, target, level, xoffset, yoffset,
+                   zoffset, width, height, depth, format, type, pixels,
+                   callerName, false, ext_dsa);
 }
 
 
 static void
 texturesubimage_no_error(struct gl_context *ctx, GLuint dims,
 }
 
 
 static void
 texturesubimage_no_error(struct gl_context *ctx, GLuint dims,
-                         GLuint texture, GLint level,
+                         GLuint texture, GLenum target, GLint level,
                          GLint xoffset, GLint yoffset, GLint zoffset,
                          GLsizei width, GLsizei height, GLsizei depth,
                          GLenum format, GLenum type, const GLvoid *pixels,
                          GLint xoffset, GLint yoffset, GLint zoffset,
                          GLsizei width, GLsizei height, GLsizei depth,
                          GLenum format, GLenum type, const GLvoid *pixels,
-                         const char *callerName)
+                         const char *callerName, bool ext_dsa)
 {
 {
-   texturesubimage(ctx, dims, texture, level, xoffset, yoffset, zoffset,
-                   width, height, depth, format, type, pixels, callerName,
-                   true);
+   texturesubimage(ctx, dims, texture, target, level, xoffset, yoffset,
+                   zoffset, width, height, depth, format, type, pixels,
+                   callerName, true, ext_dsa);
 }
 
 
 }
 
 
@@ -3605,8 +3805,44 @@ _mesa_TextureSubImage1D_no_error(GLuint texture, GLint level, GLint xoffset,
                                  const GLvoid *pixels)
 {
    GET_CURRENT_CONTEXT(ctx);
                                  const GLvoid *pixels)
 {
    GET_CURRENT_CONTEXT(ctx);
-   texturesubimage_no_error(ctx, 1, texture, level, xoffset, 0, 0, width, 1, 1,
-                            format, type, pixels, "glTextureSubImage1D");
+   texturesubimage_no_error(ctx, 1, texture, 0, level, xoffset, 0, 0, width,
+                            1, 1, format, type, pixels, "glTextureSubImage1D",
+                            false);
+}
+
+
+void GLAPIENTRY
+_mesa_TextureSubImage1DEXT(GLuint texture, GLenum target, GLint level,
+                        GLint xoffset, GLsizei width,
+                        GLenum format, GLenum type,
+                        const GLvoid *pixels)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   texturesubimage_error(ctx, 1, texture, target, level, xoffset, 0, 0, width, 1,
+                         1, format, type, pixels, "glTextureSubImage1DEXT",
+                         false);
+}
+
+
+void GLAPIENTRY
+_mesa_MultiTexSubImage1DEXT(GLenum texunit, GLenum target, GLint level,
+                            GLint xoffset, GLsizei width,
+                            GLenum format, GLenum type,
+                            const GLvoid *pixels)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_texture_object *texObj;
+   struct gl_texture_image *texImage;
+
+   texObj = _mesa_get_texobj_by_target_and_texunit(ctx, target,
+                                                   texunit - GL_TEXTURE0,
+                                                   false,
+                                                   "glMultiTexImage1DEXT");
+   texImage = _mesa_select_tex_image(texObj, target, level);
+
+   texture_sub_image(ctx, 1, texObj, texImage, target, level,
+                     xoffset, 0, 0, width, 1, 1,
+                     format, type, pixels);
 }
 
 
 }
 
 
@@ -3617,8 +3853,9 @@ _mesa_TextureSubImage1D(GLuint texture, GLint level,
                         const GLvoid *pixels)
 {
    GET_CURRENT_CONTEXT(ctx);
                         const GLvoid *pixels)
 {
    GET_CURRENT_CONTEXT(ctx);
-   texturesubimage_error(ctx, 1, texture, level, xoffset, 0, 0, width, 1, 1,
-                         format, type, pixels, "glTextureSubImage1D");
+   texturesubimage_error(ctx, 1, texture, 0, level, xoffset, 0, 0, width, 1,
+                         1, format, type, pixels, "glTextureSubImage1D",
+                         false);
 }
 
 
 }
 
 
@@ -3629,9 +3866,44 @@ _mesa_TextureSubImage2D_no_error(GLuint texture, GLint level, GLint xoffset,
                                  const GLvoid *pixels)
 {
    GET_CURRENT_CONTEXT(ctx);
                                  const GLvoid *pixels)
 {
    GET_CURRENT_CONTEXT(ctx);
-   texturesubimage_no_error(ctx, 2, texture, level, xoffset, yoffset, 0, width,
-                            height, 1, format, type, pixels,
-                            "glTextureSubImage2D");
+   texturesubimage_no_error(ctx, 2, texture, 0, level, xoffset, yoffset, 0,
+                            width, height, 1, format, type, pixels,
+                            "glTextureSubImage2D", false);
+}
+
+
+void GLAPIENTRY
+_mesa_TextureSubImage2DEXT(GLuint texture, GLenum target, GLint level,
+                           GLint xoffset, GLint yoffset, GLsizei width,
+                           GLsizei height, GLenum format, GLenum type,
+                           const GLvoid *pixels)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   texturesubimage_error(ctx, 2, texture, target, level, xoffset, yoffset, 0,
+                         width, height, 1, format, type, pixels,
+                         "glTextureSubImage2DEXT", true);
+}
+
+
+void GLAPIENTRY
+_mesa_MultiTexSubImage2DEXT(GLenum texunit, GLenum target, GLint level,
+                            GLint xoffset, GLint yoffset, GLsizei width,
+                            GLsizei height, GLenum format, GLenum type,
+                            const GLvoid *pixels)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_texture_object *texObj;
+   struct gl_texture_image *texImage;
+
+   texObj = _mesa_get_texobj_by_target_and_texunit(ctx, target,
+                                                   texunit - GL_TEXTURE0,
+                                                   false,
+                                                   "glMultiTexImage2DEXT");
+   texImage = _mesa_select_tex_image(texObj, target, level);
+
+   texture_sub_image(ctx, 2, texObj, texImage, target, level,
+                     xoffset, yoffset, 0, width, height, 1,
+                     format, type, pixels);
 }
 
 
 }
 
 
@@ -3643,9 +3915,9 @@ _mesa_TextureSubImage2D(GLuint texture, GLint level,
                         const GLvoid *pixels)
 {
    GET_CURRENT_CONTEXT(ctx);
                         const GLvoid *pixels)
 {
    GET_CURRENT_CONTEXT(ctx);
-   texturesubimage_error(ctx, 2, texture, level, xoffset, yoffset, 0, width,
-                         height, 1, format, type, pixels,
-                         "glTextureSubImage2D");
+   texturesubimage_error(ctx, 2, texture, 0, level, xoffset, yoffset, 0,
+                         width, height, 1, format, type, pixels,
+                         "glTextureSubImage2D", false);
 }
 
 
 }
 
 
@@ -3656,9 +3928,44 @@ _mesa_TextureSubImage3D_no_error(GLuint texture, GLint level, GLint xoffset,
                                  GLenum type, const GLvoid *pixels)
 {
    GET_CURRENT_CONTEXT(ctx);
                                  GLenum type, const GLvoid *pixels)
 {
    GET_CURRENT_CONTEXT(ctx);
-   texturesubimage_no_error(ctx, 3, texture, level, xoffset, yoffset, zoffset,
-                            width, height, depth, format, type, pixels,
-                            "glTextureSubImage3D");
+   texturesubimage_no_error(ctx, 3, texture, 0, level, xoffset, yoffset,
+                            zoffset, width, height, depth, format, type,
+                            pixels, "glTextureSubImage3D", false);
+}
+
+
+void GLAPIENTRY
+_mesa_TextureSubImage3DEXT(GLuint texture, GLenum target, GLint level,
+                           GLint xoffset, GLint yoffset, GLint zoffset,
+                           GLsizei width, GLsizei height, GLsizei depth,
+                           GLenum format, GLenum type, const GLvoid *pixels)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   texturesubimage_error(ctx, 3, texture, target, level, xoffset, yoffset,
+                         zoffset, width, height, depth, format, type,
+                         pixels, "glTextureSubImage3DEXT", true);
+}
+
+
+void GLAPIENTRY
+_mesa_MultiTexSubImage3DEXT(GLenum texunit, GLenum target, GLint level,
+                           GLint xoffset, GLint yoffset, GLint zoffset,
+                           GLsizei width, GLsizei height, GLsizei depth,
+                           GLenum format, GLenum type, const GLvoid *pixels)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_texture_object *texObj;
+   struct gl_texture_image *texImage;
+
+   texObj = _mesa_get_texobj_by_target_and_texunit(ctx, target,
+                                                   texunit - GL_TEXTURE0,
+                                                   false,
+                                                   "glMultiTexImage3DEXT");
+   texImage = _mesa_select_tex_image(texObj, target, level);
+
+   texture_sub_image(ctx, 3, texObj, texImage, target, level,
+                     xoffset, yoffset, zoffset, width, height, depth,
+                     format, type, pixels);
 }
 
 
 }
 
 
@@ -3670,9 +3977,9 @@ _mesa_TextureSubImage3D(GLuint texture, GLint level,
                         const GLvoid *pixels)
 {
    GET_CURRENT_CONTEXT(ctx);
                         const GLvoid *pixels)
 {
    GET_CURRENT_CONTEXT(ctx);
-   texturesubimage_error(ctx, 3, texture, level, xoffset, yoffset, zoffset,
+   texturesubimage_error(ctx, 3, texture, 0, level, xoffset, yoffset, zoffset,
                          width, height, depth, format, type, pixels,
                          width, height, depth, format, type, pixels,
-                         "glTextureSubImage3D");
+                         "glTextureSubImage3D", false);
 }
 
 
 }
 
 
@@ -3694,6 +4001,7 @@ get_copy_tex_image_source(struct gl_context *ctx, mesa_format texFormat)
    }
 }
 
    }
 }
 
+
 static void
 copytexsubimage_by_slice(struct gl_context *ctx,
                          struct gl_texture_image *texImage,
 static void
 copytexsubimage_by_slice(struct gl_context *ctx,
                          struct gl_texture_image *texImage,
@@ -3724,6 +4032,7 @@ copytexsubimage_by_slice(struct gl_context *ctx,
    }
 }
 
    }
 }
 
+
 static GLboolean
 formats_differ_in_component_sizes(mesa_format f1, mesa_format f2)
 {
 static GLboolean
 formats_differ_in_component_sizes(mesa_format f1, mesa_format f2)
 {
@@ -3755,7 +4064,7 @@ formats_differ_in_component_sizes(mesa_format f1, mesa_format f2)
 static bool
 can_avoid_reallocation(const struct gl_texture_image *texImage,
                        GLenum internalFormat,
 static bool
 can_avoid_reallocation(const struct gl_texture_image *texImage,
                        GLenum internalFormat,
-                       mesa_format texFormat, GLint x, GLint y, GLsizei width,
+                       mesa_format texFormat, GLsizei width,
                        GLsizei height, GLint border)
 {
    if (texImage->InternalFormat != internalFormat)
                        GLsizei height, GLint border)
 {
    if (texImage->InternalFormat != internalFormat)
@@ -3871,13 +4180,12 @@ copy_texture_sub_image_no_error(struct gl_context *ctx, GLuint dims,
  * Implement the glCopyTexImage1/2D() functions.
  */
 static ALWAYS_INLINE void
  * Implement the glCopyTexImage1/2D() functions.
  */
 static ALWAYS_INLINE void
-copyteximage(struct gl_context *ctx, GLuint dims,
+copyteximage(struct gl_context *ctx, GLuint dims, struct gl_texture_object *texObj,
              GLenum target, GLint level, GLenum internalFormat,
              GLint x, GLint y, GLsizei width, GLsizei height, GLint border,
              bool no_error)
 {
    struct gl_texture_image *texImage;
              GLenum target, GLint level, GLenum internalFormat,
              GLint x, GLint y, GLsizei width, GLsizei height, GLint border,
              bool no_error)
 {
    struct gl_texture_image *texImage;
-   struct gl_texture_object *texObj;
    mesa_format texFormat;
 
    FLUSH_VERTICES(ctx, 0);
    mesa_format texFormat;
 
    FLUSH_VERTICES(ctx, 0);
@@ -3893,8 +4201,8 @@ copyteximage(struct gl_context *ctx, GLuint dims,
       _mesa_update_state(ctx);
 
    if (!no_error) {
       _mesa_update_state(ctx);
 
    if (!no_error) {
-      if (copytexture_error_check(ctx, dims, target, level, internalFormat,
-                                  width, height, border))
+      if (copytexture_error_check(ctx, dims, target, texObj, level,
+                                  internalFormat, border))
          return;
 
       if (!_mesa_legal_texture_dimensions(ctx, target, level, width, height,
          return;
 
       if (!_mesa_legal_texture_dimensions(ctx, target, level, width, height,
@@ -3906,7 +4214,6 @@ copyteximage(struct gl_context *ctx, GLuint dims,
       }
    }
 
       }
    }
 
-   texObj = _mesa_get_current_tex_object(ctx, target);
    assert(texObj);
 
    texFormat = _mesa_choose_texture_format(ctx, texObj, target, level,
    assert(texObj);
 
    texFormat = _mesa_choose_texture_format(ctx, texObj, target, level,
@@ -3919,7 +4226,7 @@ copyteximage(struct gl_context *ctx, GLuint dims,
    {
       texImage = _mesa_select_tex_image(texObj, target, level);
       if (texImage && can_avoid_reallocation(texImage, internalFormat, texFormat,
    {
       texImage = _mesa_select_tex_image(texObj, target, level);
       if (texImage && can_avoid_reallocation(texImage, internalFormat, texFormat,
-                                             x, y, width, height, border)) {
+                                             width, height, border)) {
          _mesa_unlock_texture(ctx, texObj);
          if (no_error) {
             copy_texture_sub_image_no_error(ctx, dims, texObj, target, level, 0,
          _mesa_unlock_texture(ctx, texObj);
          if (no_error) {
             copy_texture_sub_image_no_error(ctx, dims, texObj, target, level, 0,
@@ -3963,7 +4270,7 @@ copyteximage(struct gl_context *ctx, GLuint dims,
        */
       else if (formats_differ_in_component_sizes (texFormat, rb->Format)) {
             _mesa_error(ctx, GL_INVALID_OPERATION,
        */
       else if (formats_differ_in_component_sizes (texFormat, rb->Format)) {
             _mesa_error(ctx, GL_INVALID_OPERATION,
-                        "glCopyTexImage%uD(componenet size changed in"
+                        "glCopyTexImage%uD(component size changed in"
                         " internal format)", dims);
             return;
       }
                         " internal format)", dims);
             return;
       }
@@ -3983,8 +4290,8 @@ copyteximage(struct gl_context *ctx, GLuint dims,
       x += border;
       width -= border * 2;
       if (dims == 2) {
       x += border;
       width -= border * 2;
       if (dims == 2) {
-        y += border;
-        height -= border * 2;
+         y += border;
+         height -= border * 2;
       }
       border = 0;
    }
       }
       border = 0;
    }
@@ -3994,7 +4301,7 @@ copyteximage(struct gl_context *ctx, GLuint dims,
       texImage = _mesa_get_tex_image(ctx, texObj, target, level);
 
       if (!texImage) {
       texImage = _mesa_get_tex_image(ctx, texObj, target, level);
 
       if (!texImage) {
-        _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage%uD", dims);
+         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage%uD", dims);
       }
       else {
          GLint srcX = x, srcY = y, dstX = 0, dstY = 0, dstZ = 0;
       }
       else {
          GLint srcX = x, srcY = y, dstX = 0, dstY = 0, dstZ = 0;
@@ -4033,20 +4340,24 @@ copyteximage(struct gl_context *ctx, GLuint dims,
 
 
 static void
 
 
 static void
-copyteximage_err(struct gl_context *ctx, GLuint dims, GLenum target,
+copyteximage_err(struct gl_context *ctx, GLuint dims,
+                 GLenum target,
                  GLint level, GLenum internalFormat, GLint x, GLint y,
                  GLsizei width, GLsizei height, GLint border)
 {
                  GLint level, GLenum internalFormat, GLint x, GLint y,
                  GLsizei width, GLsizei height, GLint border)
 {
-   copyteximage(ctx, dims, target, level, internalFormat, x, y, width, height,
+   struct gl_texture_object* texObj = _mesa_get_current_tex_object(ctx, target);
+   copyteximage(ctx, dims, texObj, target, level, internalFormat, x, y, width, height,
                 border, false);
 }
 
                 border, false);
 }
 
+
 static void
 copyteximage_no_error(struct gl_context *ctx, GLuint dims, GLenum target,
                       GLint level, GLenum internalFormat, GLint x, GLint y,
                       GLsizei width, GLsizei height, GLint border)
 {
 static void
 copyteximage_no_error(struct gl_context *ctx, GLuint dims, GLenum target,
                       GLint level, GLenum internalFormat, GLint x, GLint y,
                       GLsizei width, GLsizei height, GLint border)
 {
-   copyteximage(ctx, dims, target, level, internalFormat, x, y, width, height,
+   struct gl_texture_object* texObj = _mesa_get_current_tex_object(ctx, target);
+   copyteximage(ctx, dims, texObj, target, level, internalFormat, x, y, width, height,
                 border, true);
 }
 
                 border, true);
 }
 
@@ -4063,6 +4374,41 @@ _mesa_CopyTexImage1D( GLenum target, GLint level,
 }
 
 
 }
 
 
+void GLAPIENTRY
+_mesa_CopyTextureImage1DEXT( GLuint texture, GLenum target, GLint level,
+                             GLenum internalFormat,
+                             GLint x, GLint y,
+                             GLsizei width, GLint border )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_texture_object* texObj =
+      _mesa_lookup_or_create_texture(ctx, target, texture, false, true,
+                                     "glCopyTextureImage1DEXT");
+   if (!texObj)
+      return;
+   copyteximage(ctx, 1, texObj, target, level, internalFormat, x, y, width, 1,
+                border, false);
+}
+
+
+void GLAPIENTRY
+_mesa_CopyMultiTexImage1DEXT( GLenum texunit, GLenum target, GLint level,
+                              GLenum internalFormat,
+                              GLint x, GLint y,
+                              GLsizei width, GLint border )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_texture_object* texObj =
+      _mesa_get_texobj_by_target_and_texunit(ctx, target,
+                                             texunit - GL_TEXTURE0,
+                                             false,
+                                             "glCopyMultiTexImage1DEXT");
+   if (!texObj)
+      return;
+   copyteximage(ctx, 1, texObj, target, level, internalFormat, x, y, width, 1,
+                border, false);
+}
+
 
 void GLAPIENTRY
 _mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
 
 void GLAPIENTRY
 _mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
@@ -4075,6 +4421,43 @@ _mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
 }
 
 
 }
 
 
+void GLAPIENTRY
+_mesa_CopyTextureImage2DEXT( GLuint texture, GLenum target, GLint level,
+                             GLenum internalFormat,
+                             GLint x, GLint y,
+                             GLsizei width, GLsizei height,
+                             GLint border )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_texture_object* texObj =
+      _mesa_lookup_or_create_texture(ctx, target, texture, false, true,
+                                     "glCopyTextureImage2DEXT");
+   if (!texObj)
+      return;
+   copyteximage(ctx, 2, texObj, target, level, internalFormat, x, y, width, height,
+                border, false);
+}
+
+
+void GLAPIENTRY
+_mesa_CopyMultiTexImage2DEXT( GLenum texunit, GLenum target, GLint level,
+                              GLenum internalFormat,
+                              GLint x, GLint y,
+                              GLsizei width, GLsizei height, GLint border )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_texture_object* texObj =
+      _mesa_get_texobj_by_target_and_texunit(ctx, target,
+                                             texunit - GL_TEXTURE0,
+                                             false,
+                                             "glCopyMultiTexImage2DEXT");
+   if (!texObj)
+      return;
+   copyteximage(ctx, 2, texObj, target, level, internalFormat, x, y, width, height,
+                border, false);
+}
+
+
 void GLAPIENTRY
 _mesa_CopyTexImage1D_no_error(GLenum target, GLint level, GLenum internalFormat,
                               GLint x, GLint y, GLsizei width, GLint border)
 void GLAPIENTRY
 _mesa_CopyTexImage1D_no_error(GLenum target, GLint level, GLenum internalFormat,
                               GLint x, GLint y, GLsizei width, GLint border)
@@ -4097,8 +4480,8 @@ _mesa_CopyTexImage2D_no_error(GLenum target, GLint level, GLenum internalFormat,
 
 
 void GLAPIENTRY
 
 
 void GLAPIENTRY
-_mesa_CopyTexSubImage1D( GLenum target, GLint level,
-                         GLint xoffset, GLint x, GLint y, GLsizei width )
+_mesa_CopyTexSubImage1D(GLenum target, GLint level,
+                        GLint xoffset, GLint x, GLint y, GLsizei width)
 {
    struct gl_texture_object* texObj;
    const char *self = "glCopyTexSubImage1D";
 {
    struct gl_texture_object* texObj;
    const char *self = "glCopyTexSubImage1D";
@@ -4121,10 +4504,11 @@ _mesa_CopyTexSubImage1D( GLenum target, GLint level,
                               x, y, width, 1, self);
 }
 
                               x, y, width, 1, self);
 }
 
+
 void GLAPIENTRY
 void GLAPIENTRY
-_mesa_CopyTexSubImage2D( GLenum target, GLint level,
-                         GLint xoffset, GLint yoffset,
-                         GLint x, GLint y, GLsizei width, GLsizei height )
+_mesa_CopyTexSubImage2D(GLenum target, GLint level,
+                        GLint xoffset, GLint yoffset,
+                        GLint x, GLint y, GLsizei width, GLsizei height)
 {
    struct gl_texture_object* texObj;
    const char *self = "glCopyTexSubImage2D";
 {
    struct gl_texture_object* texObj;
    const char *self = "glCopyTexSubImage2D";
@@ -4148,11 +4532,10 @@ _mesa_CopyTexSubImage2D( GLenum target, GLint level,
 }
 
 
 }
 
 
-
 void GLAPIENTRY
 void GLAPIENTRY
-_mesa_CopyTexSubImage3D( GLenum target, GLint level,
-                         GLint xoffset, GLint yoffset, GLint zoffset,
-                         GLint x, GLint y, GLsizei width, GLsizei height )
+_mesa_CopyTexSubImage3D(GLenum target, GLint level,
+                        GLint xoffset, GLint yoffset, GLint zoffset,
+                        GLint x, GLint y, GLsizei width, GLsizei height)
 {
    struct gl_texture_object* texObj;
    const char *self = "glCopyTexSubImage3D";
 {
    struct gl_texture_object* texObj;
    const char *self = "glCopyTexSubImage3D";
@@ -4175,6 +4558,7 @@ _mesa_CopyTexSubImage3D( GLenum target, GLint level,
                               zoffset, x, y, width, height, self);
 }
 
                               zoffset, x, y, width, height, self);
 }
 
+
 void GLAPIENTRY
 _mesa_CopyTextureSubImage1D(GLuint texture, GLint level,
                             GLint xoffset, GLint x, GLint y, GLsizei width)
 void GLAPIENTRY
 _mesa_CopyTextureSubImage1D(GLuint texture, GLint level,
                             GLint xoffset, GLint x, GLint y, GLsizei width)
@@ -4198,6 +4582,51 @@ _mesa_CopyTextureSubImage1D(GLuint texture, GLint level,
                               0, x, y, width, 1, self);
 }
 
                               0, x, y, width, 1, self);
 }
 
+
+void GLAPIENTRY
+_mesa_CopyTextureSubImage1DEXT(GLuint texture, GLenum target, GLint level,
+                               GLint xoffset, GLint x, GLint y, GLsizei width)
+{
+   struct gl_texture_object* texObj;
+   const char *self = "glCopyTextureSubImage1DEXT";
+   GET_CURRENT_CONTEXT(ctx);
+
+   texObj = _mesa_lookup_or_create_texture(ctx, target, texture, false, true,
+                                           self);
+   if (!texObj)
+      return;
+
+   /* Check target (proxies not allowed). */
+   if (!legal_texsubimage_target(ctx, 1, texObj->Target, true)) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid target %s)", self,
+                  _mesa_enum_to_string(texObj->Target));
+      return;
+   }
+
+   copy_texture_sub_image_err(ctx, 1, texObj, texObj->Target, level, xoffset, 0,
+                              0, x, y, width, 1, self);
+}
+
+
+void GLAPIENTRY
+_mesa_CopyMultiTexSubImage1DEXT(GLenum texunit, GLenum target, GLint level,
+                                GLint xoffset, GLint x, GLint y, GLsizei width)
+{
+   struct gl_texture_object* texObj;
+   const char *self = "glCopyMultiTexSubImage1DEXT";
+   GET_CURRENT_CONTEXT(ctx);
+
+   texObj = _mesa_get_texobj_by_target_and_texunit(ctx, target,
+                                                   texunit - GL_TEXTURE0,
+                                                   false, self);
+   if (!texObj)
+      return;
+
+   copy_texture_sub_image_err(ctx, 1, texObj, texObj->Target, level, xoffset, 0,
+                              0, x, y, width, 1, self);
+}
+
+
 void GLAPIENTRY
 _mesa_CopyTextureSubImage2D(GLuint texture, GLint level,
                             GLint xoffset, GLint yoffset,
 void GLAPIENTRY
 _mesa_CopyTextureSubImage2D(GLuint texture, GLint level,
                             GLint xoffset, GLint yoffset,
@@ -4223,6 +4652,49 @@ _mesa_CopyTextureSubImage2D(GLuint texture, GLint level,
 }
 
 
 }
 
 
+void GLAPIENTRY
+_mesa_CopyTextureSubImage2DEXT(GLuint texture, GLenum target, GLint level,
+                               GLint xoffset, GLint yoffset,
+                               GLint x, GLint y, GLsizei width, GLsizei height)
+{
+   struct gl_texture_object* texObj;
+   const char *self = "glCopyTextureSubImage2DEXT";
+   GET_CURRENT_CONTEXT(ctx);
+
+   texObj = _mesa_lookup_or_create_texture(ctx, target, texture, false, true, self);
+   if (!texObj)
+      return;
+
+   /* Check target (proxies not allowed). */
+   if (!legal_texsubimage_target(ctx, 2, texObj->Target, true)) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid target %s)", self,
+                  _mesa_enum_to_string(texObj->Target));
+      return;
+   }
+
+   copy_texture_sub_image_err(ctx, 2, texObj, texObj->Target, level, xoffset,
+                              yoffset, 0, x, y, width, height, self);
+}
+
+
+void GLAPIENTRY
+_mesa_CopyMultiTexSubImage2DEXT(GLenum texunit, GLenum target, GLint level,
+                               GLint xoffset, GLint yoffset,
+                               GLint x, GLint y, GLsizei width, GLsizei height)
+{
+   struct gl_texture_object* texObj;
+   const char *self = "glCopyMultiTexSubImage2DEXT";
+   GET_CURRENT_CONTEXT(ctx);
+
+   texObj = _mesa_get_texobj_by_target_and_texunit(ctx, target,
+                                                   texunit - GL_TEXTURE0,
+                                                   false, self);
+   if (!texObj)
+      return;
+
+   copy_texture_sub_image_err(ctx, 2, texObj, texObj->Target, level, xoffset,
+                              yoffset, 0, x, y, width, height, self);
+}
 
 void GLAPIENTRY
 _mesa_CopyTextureSubImage3D(GLuint texture, GLint level,
 
 void GLAPIENTRY
 _mesa_CopyTextureSubImage3D(GLuint texture, GLint level,
@@ -4257,6 +4729,67 @@ _mesa_CopyTextureSubImage3D(GLuint texture, GLint level,
 }
 
 
 }
 
 
+void GLAPIENTRY
+_mesa_CopyTextureSubImage3DEXT(GLuint texture, GLenum target, GLint level,
+                               GLint xoffset, GLint yoffset, GLint zoffset,
+                               GLint x, GLint y, GLsizei width, GLsizei height)
+{
+   struct gl_texture_object* texObj;
+   const char *self = "glCopyTextureSubImage3D";
+   GET_CURRENT_CONTEXT(ctx);
+
+   texObj = _mesa_lookup_or_create_texture(ctx, target, texture, false, true, self);
+   if (!texObj)
+      return;
+
+   /* Check target (proxies not allowed). */
+   if (!legal_texsubimage_target(ctx, 3, texObj->Target, true)) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid target %s)", self,
+                  _mesa_enum_to_string(texObj->Target));
+      return;
+   }
+
+   if (texObj->Target == GL_TEXTURE_CUBE_MAP) {
+      /* Act like CopyTexSubImage2D */
+      copy_texture_sub_image_err(ctx, 2, texObj,
+                                GL_TEXTURE_CUBE_MAP_POSITIVE_X + zoffset,
+                                level, xoffset, yoffset, 0, x, y, width, height,
+                                self);
+   }
+   else
+      copy_texture_sub_image_err(ctx, 3, texObj, texObj->Target, level, xoffset,
+                                 yoffset, zoffset, x, y, width, height, self);
+}
+
+
+void GLAPIENTRY
+_mesa_CopyMultiTexSubImage3DEXT(GLenum texunit, GLenum target, GLint level,
+                                GLint xoffset, GLint yoffset, GLint zoffset,
+                                GLint x, GLint y, GLsizei width, GLsizei height)
+{
+   struct gl_texture_object* texObj;
+   const char *self = "glCopyMultiTexSubImage3D";
+   GET_CURRENT_CONTEXT(ctx);
+
+   texObj = _mesa_get_texobj_by_target_and_texunit(ctx, target,
+                                                   texunit - GL_TEXTURE0,
+                                                   false, self);
+   if (!texObj)
+      return;
+
+   if (texObj->Target == GL_TEXTURE_CUBE_MAP) {
+      /* Act like CopyTexSubImage2D */
+      copy_texture_sub_image_err(ctx, 2, texObj,
+                                GL_TEXTURE_CUBE_MAP_POSITIVE_X + zoffset,
+                                level, xoffset, yoffset, 0, x, y, width, height,
+                                self);
+   }
+   else
+      copy_texture_sub_image_err(ctx, 3, texObj, texObj->Target, level, xoffset,
+                                 yoffset, zoffset, x, y, width, height, self);
+}
+
+
 void GLAPIENTRY
 _mesa_CopyTexSubImage1D_no_error(GLenum target, GLint level, GLint xoffset,
                                  GLint x, GLint y, GLsizei width)
 void GLAPIENTRY
 _mesa_CopyTexSubImage1D_no_error(GLenum target, GLint level, GLint xoffset,
                                  GLint x, GLint y, GLsizei width)
@@ -4268,6 +4801,7 @@ _mesa_CopyTexSubImage1D_no_error(GLenum target, GLint level, GLint xoffset,
                                    x, y, width, 1);
 }
 
                                    x, y, width, 1);
 }
 
+
 void GLAPIENTRY
 _mesa_CopyTexSubImage2D_no_error(GLenum target, GLint level, GLint xoffset,
                                  GLint yoffset, GLint x, GLint y, GLsizei width,
 void GLAPIENTRY
 _mesa_CopyTexSubImage2D_no_error(GLenum target, GLint level, GLint xoffset,
                                  GLint yoffset, GLint x, GLint y, GLsizei width,
@@ -4280,6 +4814,7 @@ _mesa_CopyTexSubImage2D_no_error(GLenum target, GLint level, GLint xoffset,
                                    yoffset, 0, x, y, width, height);
 }
 
                                    yoffset, 0, x, y, width, height);
 }
 
+
 void GLAPIENTRY
 _mesa_CopyTexSubImage3D_no_error(GLenum target, GLint level, GLint xoffset,
                                  GLint yoffset, GLint zoffset, GLint x, GLint y,
 void GLAPIENTRY
 _mesa_CopyTexSubImage3D_no_error(GLenum target, GLint level, GLint xoffset,
                                  GLint yoffset, GLint zoffset, GLint x, GLint y,
@@ -4292,6 +4827,7 @@ _mesa_CopyTexSubImage3D_no_error(GLenum target, GLint level, GLint xoffset,
                                    yoffset, zoffset, x, y, width, height);
 }
 
                                    yoffset, zoffset, x, y, width, height);
 }
 
+
 void GLAPIENTRY
 _mesa_CopyTextureSubImage1D_no_error(GLuint texture, GLint level, GLint xoffset,
                                      GLint x, GLint y, GLsizei width)
 void GLAPIENTRY
 _mesa_CopyTextureSubImage1D_no_error(GLuint texture, GLint level, GLint xoffset,
                                      GLint x, GLint y, GLsizei width)
@@ -4303,6 +4839,7 @@ _mesa_CopyTextureSubImage1D_no_error(GLuint texture, GLint level, GLint xoffset,
                                    xoffset, 0, 0, x, y, width, 1);
 }
 
                                    xoffset, 0, 0, x, y, width, 1);
 }
 
+
 void GLAPIENTRY
 _mesa_CopyTextureSubImage2D_no_error(GLuint texture, GLint level, GLint xoffset,
                                      GLint yoffset, GLint x, GLint y,
 void GLAPIENTRY
 _mesa_CopyTextureSubImage2D_no_error(GLuint texture, GLint level, GLint xoffset,
                                      GLint yoffset, GLint x, GLint y,
@@ -4315,6 +4852,7 @@ _mesa_CopyTextureSubImage2D_no_error(GLuint texture, GLint level, GLint xoffset,
                                    xoffset, yoffset, 0, x, y, width, height);
 }
 
                                    xoffset, yoffset, 0, x, y, width, height);
 }
 
+
 void GLAPIENTRY
 _mesa_CopyTextureSubImage3D_no_error(GLuint texture, GLint level, GLint xoffset,
                                      GLint yoffset, GLint zoffset, GLint x,
 void GLAPIENTRY
 _mesa_CopyTextureSubImage3D_no_error(GLuint texture, GLint level, GLint xoffset,
                                      GLint yoffset, GLint zoffset, GLint x,
@@ -4410,6 +4948,7 @@ check_clear_tex_image(struct gl_context *ctx,
    return true;
 }
 
    return true;
 }
 
+
 static struct gl_texture_object *
 get_tex_obj_for_clear(struct gl_context *ctx,
                       const char *function,
 static struct gl_texture_object *
 get_tex_obj_for_clear(struct gl_context *ctx,
                       const char *function,
@@ -4473,11 +5012,12 @@ get_tex_images_for_clear(struct gl_context *ctx,
    return numFaces;
 }
 
    return numFaces;
 }
 
+
 void GLAPIENTRY
 void GLAPIENTRY
-_mesa_ClearTexSubImage( GLuint texture, GLint level,
-                        GLint xoffset, GLint yoffset, GLint zoffset,
-                        GLsizei width, GLsizei height, GLsizei depth,
-                        GLenum format, GLenum type, const void *data )
+_mesa_ClearTexSubImage(GLuint texture, GLint level,
+                       GLint xoffset, GLint yoffset, GLint zoffset,
+                       GLsizei width, GLsizei height, GLsizei depth,
+                       GLenum format, GLenum type, const void *data)
 {
    GET_CURRENT_CONTEXT(ctx);
    struct gl_texture_object *texObj;
 {
    GET_CURRENT_CONTEXT(ctx);
    struct gl_texture_object *texObj;
@@ -4522,8 +5062,7 @@ _mesa_ClearTexSubImage( GLuint texture, GLint level,
    }
 
    if (numImages == 1) {
    }
 
    if (numImages == 1) {
-      if (check_clear_tex_image(ctx, "glClearTexSubImage",
-                                texImages[0],
+      if (check_clear_tex_image(ctx, "glClearTexSubImage", texImages[0],
                                 format, type, data, clearValue[0])) {
          ctx->Driver.ClearTexSubImage(ctx,
                                       texImages[0],
                                 format, type, data, clearValue[0])) {
          ctx->Driver.ClearTexSubImage(ctx,
                                       texImages[0],
@@ -4535,8 +5074,7 @@ _mesa_ClearTexSubImage( GLuint texture, GLint level,
       /* loop over cube face images */
       for (i = zoffset; i < zoffset + depth; i++) {
          assert(i < MAX_FACES);
       /* loop over cube face images */
       for (i = zoffset; i < zoffset + depth; i++) {
          assert(i < MAX_FACES);
-         if (!check_clear_tex_image(ctx, "glClearTexSubImage",
-                                    texImages[i],
+         if (!check_clear_tex_image(ctx, "glClearTexSubImage", texImages[i],
                                     format, type, data, clearValue[i]))
             goto out;
       }
                                     format, type, data, clearValue[i]))
             goto out;
       }
@@ -4553,6 +5091,7 @@ _mesa_ClearTexSubImage( GLuint texture, GLint level,
    _mesa_unlock_texture(ctx, texObj);
 }
 
    _mesa_unlock_texture(ctx, texObj);
 }
 
+
 void GLAPIENTRY
 _mesa_ClearTexImage( GLuint texture, GLint level,
                      GLenum format, GLenum type, const void *data )
 void GLAPIENTRY
 _mesa_ClearTexImage( GLuint texture, GLint level,
                      GLenum format, GLenum type, const void *data )
@@ -4574,10 +5113,8 @@ _mesa_ClearTexImage( GLuint texture, GLint level,
                                         texObj, level, texImages);
 
    for (i = 0; i < numImages; i++) {
                                         texObj, level, texImages);
 
    for (i = 0; i < numImages; i++) {
-      if (!check_clear_tex_image(ctx, "glClearTexImage",
-                                 texImages[i],
-                                 format, type, data,
-                                 clearValue[i]))
+      if (!check_clear_tex_image(ctx, "glClearTexImage", texImages[i], format,
+                                 type, data, clearValue[i]))
          goto out;
    }
 
          goto out;
    }
 
@@ -4612,10 +5149,12 @@ out:
  */
 static GLboolean
 compressed_subtexture_target_check(struct gl_context *ctx, GLenum target,
  */
 static GLboolean
 compressed_subtexture_target_check(struct gl_context *ctx, GLenum target,
-                                   GLint dims, GLenum format, bool dsa,
+                                   GLint dims, GLenum intFormat, bool dsa,
                                    const char *caller)
 {
    GLboolean targetOK;
                                    const char *caller)
 {
    GLboolean targetOK;
+   mesa_format format;
+   enum mesa_format_layout layout;
 
    if (dsa && target == GL_TEXTURE_RECTANGLE) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid target %s)", caller,
 
    if (dsa && target == GL_TEXTURE_RECTANGLE) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid target %s)", caller,
@@ -4676,21 +5215,44 @@ compressed_subtexture_target_check(struct gl_context *ctx, GLenum target,
           * which is (at this time) only bptc. Otherwise we'd say s3tc (and
           * more) are valid here, which they are not, but of course not
           * mentioned by core spec.
           * which is (at this time) only bptc. Otherwise we'd say s3tc (and
           * more) are valid here, which they are not, but of course not
           * mentioned by core spec.
+          *
+          * Also, from GL_KHR_texture_compression_astc_{hdr,ldr}:
+          *
+          *    "Add a second new column "3D Tex." which is empty for all non-ASTC
+          *     formats. If only the LDR profile is supported by the implementation,
+          *     this column is also empty for all ASTC formats. If both the LDR and HDR
+          *     profiles are supported, this column is checked for all ASTC formats."
+          *
+          *    "An INVALID_OPERATION error is generated by CompressedTexSubImage3D if
+          *     <format> is one of the formats in table 8.19 and <target> is not
+          *     TEXTURE_2D_ARRAY, TEXTURE_CUBE_MAP_ARRAY, or TEXTURE_3D.
+          *
+          *     An INVALID_OPERATION error is generated by CompressedTexSubImage3D if
+          *     <format> is TEXTURE_CUBE_MAP_ARRAY and the "Cube Map Array" column of
+          *     table 8.19 is *not* checked, or if <format> is TEXTURE_3D and the "3D
+          *     Tex." column of table 8.19 is *not* checked"
+          *
+          * And from GL_KHR_texture_compression_astc_sliced_3d:
+          *
+          *    "Modify the "3D Tex." column to be checked for all ASTC formats."
           */
           */
-         switch (format) {
-         /* These are the only 3D compression formats supported at this time */
-         case GL_COMPRESSED_RGBA_BPTC_UNORM:
-         case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
-         case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
-         case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
+         format = _mesa_glenum_to_compressed_format(intFormat);
+         layout = _mesa_get_format_layout(format);
+         switch (layout) {
+         case MESA_FORMAT_LAYOUT_BPTC:
             /* valid format */
             break;
             /* valid format */
             break;
+         case MESA_FORMAT_LAYOUT_ASTC:
+            targetOK =
+               ctx->Extensions.KHR_texture_compression_astc_hdr ||
+               ctx->Extensions.KHR_texture_compression_astc_sliced_3d;
+            break;
          default:
             /* invalid format */
             _mesa_error(ctx, GL_INVALID_OPERATION,
                         "%s(invalid target %s for format %s)", caller,
                         _mesa_enum_to_string(target),
          default:
             /* invalid format */
             _mesa_error(ctx, GL_INVALID_OPERATION,
                         "%s(invalid target %s for format %s)", caller,
                         _mesa_enum_to_string(target),
-                        _mesa_enum_to_string(format));
+                        _mesa_enum_to_string(intFormat));
             return GL_TRUE;
          }
          break;
             return GL_TRUE;
          }
          break;
@@ -4733,15 +5295,12 @@ compressed_subtexture_error_check(struct gl_context *ctx, GLint dims,
 
    /* this will catch any invalid compressed format token */
    if (!_mesa_is_compressed_format(ctx, format)) {
 
    /* this will catch any invalid compressed format token */
    if (!_mesa_is_compressed_format(ctx, format)) {
-      _mesa_error(ctx, GL_INVALID_ENUM,
-                  "%s(format)", callerName);
+      _mesa_error(ctx, GL_INVALID_ENUM, "%s(format)", callerName);
       return GL_TRUE;
    }
 
    if (level < 0 || level >= _mesa_max_texture_levels(ctx, target)) {
       return GL_TRUE;
    }
 
    if (level < 0 || level >= _mesa_max_texture_levels(ctx, target)) {
-      _mesa_error(ctx, GL_INVALID_VALUE,
-                  "%s(level=%d)",
-                  callerName, level);
+      _mesa_error(ctx, GL_INVALID_VALUE, "%s(level=%d)", callerName, level);
       return GL_TRUE;
    }
 
       return GL_TRUE;
    }
 
@@ -4759,9 +5318,7 @@ compressed_subtexture_error_check(struct gl_context *ctx, GLint dims,
 
    expectedSize = compressed_tex_size(width, height, depth, format);
    if (expectedSize != imageSize) {
 
    expectedSize = compressed_tex_size(width, height, depth, format);
    if (expectedSize != imageSize) {
-      _mesa_error(ctx, GL_INVALID_VALUE,
-                  "%s(size=%d)",
-                  callerName, imageSize);
+      _mesa_error(ctx, GL_INVALID_VALUE, "%s(size=%d)", callerName, imageSize);
       return GL_TRUE;
    }
 
       return GL_TRUE;
    }
 
@@ -4773,28 +5330,24 @@ compressed_subtexture_error_check(struct gl_context *ctx, GLint dims,
    }
 
    if ((GLint) format != texImage->InternalFormat) {
    }
 
    if ((GLint) format != texImage->InternalFormat) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "%s(format=%s)",
+      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(format=%s)",
                   callerName, _mesa_enum_to_string(format));
       return GL_TRUE;
    }
 
                   callerName, _mesa_enum_to_string(format));
       return GL_TRUE;
    }
 
-   if (compressedteximage_only_format(ctx, format)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "%s(format=%s cannot be updated)",
+   if (compressedteximage_only_format(format)) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(format=%s cannot be updated)",
                   callerName, _mesa_enum_to_string(format));
       return GL_TRUE;
    }
 
                   callerName, _mesa_enum_to_string(format));
       return GL_TRUE;
    }
 
-   if (error_check_subtexture_negative_dimensions(ctx, dims,
-                                                  width, height, depth,
-                                                  callerName)) {
+   if (error_check_subtexture_negative_dimensions(ctx, dims, width, height,
+                                                  depth, callerName)) {
       return GL_TRUE;
    }
 
       return GL_TRUE;
    }
 
-   if (error_check_subtexture_dimensions(ctx, dims,
-                                         texImage, xoffset, yoffset, zoffset,
-                                         width, height, depth,
+   if (error_check_subtexture_dimensions(ctx, dims, texImage, xoffset, yoffset,
+                                         zoffset, width, height, depth,
                                          callerName)) {
       return GL_TRUE;
    }
                                          callerName)) {
       return GL_TRUE;
    }
@@ -4815,6 +5368,44 @@ _mesa_CompressedTexImage1D(GLenum target, GLint level,
 }
 
 
 }
 
 
+void GLAPIENTRY
+_mesa_CompressedTextureImage1DEXT(GLuint texture, GLenum target, GLint level,
+                                  GLenum internalFormat, GLsizei width,
+                                  GLint border, GLsizei imageSize,
+                                  const GLvoid *pixels)
+{
+   struct gl_texture_object*  texObj;
+   GET_CURRENT_CONTEXT(ctx);
+
+   texObj = _mesa_lookup_or_create_texture(ctx, target, texture, false, true,
+                                           "glCompressedTextureImage1DEXT");
+   if (!texObj)
+      return;
+   teximage(ctx, GL_TRUE, 1, texObj, target, level, internalFormat,
+            width, 1, 1, border, GL_NONE, GL_NONE, imageSize, pixels, false);
+}
+
+
+void GLAPIENTRY
+_mesa_CompressedMultiTexImage1DEXT(GLenum texunit, GLenum target, GLint level,
+                                   GLenum internalFormat, GLsizei width,
+                                   GLint border, GLsizei imageSize,
+                                   const GLvoid *pixels)
+{
+   struct gl_texture_object*  texObj;
+   GET_CURRENT_CONTEXT(ctx);
+
+   texObj = _mesa_get_texobj_by_target_and_texunit(ctx, target,
+                                                   texunit - GL_TEXTURE0,
+                                                   true,
+                                                   "glCompressedMultiTexImage1DEXT");
+   if (!texObj)
+      return;
+   teximage(ctx, GL_TRUE, 1, texObj, target, level, internalFormat,
+            width, 1, 1, border, GL_NONE, GL_NONE, imageSize, pixels, false);
+}
+
+
 void GLAPIENTRY
 _mesa_CompressedTexImage2D(GLenum target, GLint level,
                               GLenum internalFormat, GLsizei width,
 void GLAPIENTRY
 _mesa_CompressedTexImage2D(GLenum target, GLint level,
                               GLenum internalFormat, GLsizei width,
@@ -4827,6 +5418,44 @@ _mesa_CompressedTexImage2D(GLenum target, GLint level,
 }
 
 
 }
 
 
+void GLAPIENTRY
+_mesa_CompressedTextureImage2DEXT(GLuint texture, GLenum target, GLint level,
+                                  GLenum internalFormat, GLsizei width,
+                                  GLsizei height, GLint border, GLsizei imageSize,
+                                  const GLvoid *pixels)
+{
+   struct gl_texture_object*  texObj;
+   GET_CURRENT_CONTEXT(ctx);
+
+   texObj = _mesa_lookup_or_create_texture(ctx, target, texture, false, true,
+                                           "glCompressedTextureImage2DEXT");
+   if (!texObj)
+      return;
+   teximage(ctx, GL_TRUE, 2, texObj, target, level, internalFormat,
+            width, height, 1, border, GL_NONE, GL_NONE, imageSize, pixels, false);
+}
+
+
+void GLAPIENTRY
+_mesa_CompressedMultiTexImage2DEXT(GLenum texunit, GLenum target, GLint level,
+                                   GLenum internalFormat, GLsizei width,
+                                   GLsizei height, GLint border, GLsizei imageSize,
+                                   const GLvoid *pixels)
+{
+   struct gl_texture_object*  texObj;
+   GET_CURRENT_CONTEXT(ctx);
+
+   texObj = _mesa_get_texobj_by_target_and_texunit(ctx, target,
+                                                   texunit - GL_TEXTURE0,
+                                                   true,
+                                                   "glCompressedMultiTexImage2DEXT");
+   if (!texObj)
+      return;
+   teximage(ctx, GL_TRUE, 2, texObj, target, level, internalFormat,
+            width, height, 1, border, GL_NONE, GL_NONE, imageSize, pixels, false);
+}
+
+
 void GLAPIENTRY
 _mesa_CompressedTexImage3D(GLenum target, GLint level,
                               GLenum internalFormat, GLsizei width,
 void GLAPIENTRY
 _mesa_CompressedTexImage3D(GLenum target, GLint level,
                               GLenum internalFormat, GLsizei width,
@@ -4839,6 +5468,44 @@ _mesa_CompressedTexImage3D(GLenum target, GLint level,
 }
 
 
 }
 
 
+void GLAPIENTRY
+_mesa_CompressedTextureImage3DEXT(GLuint texture, GLenum target, GLint level,
+                                  GLenum internalFormat, GLsizei width,
+                                  GLsizei height, GLsizei depth, GLint border,
+                                  GLsizei imageSize, const GLvoid *pixels)
+{
+   struct gl_texture_object*  texObj;
+   GET_CURRENT_CONTEXT(ctx);
+
+   texObj = _mesa_lookup_or_create_texture(ctx, target, texture, false, true,
+                                           "glCompressedTextureImage3DEXT");
+   if (!texObj)
+      return;
+   teximage(ctx, GL_TRUE, 3, texObj, target, level, internalFormat,
+            width, height, depth, border, GL_NONE, GL_NONE, imageSize, pixels, false);
+}
+
+
+void GLAPIENTRY
+_mesa_CompressedMultiTexImage3DEXT(GLenum texunit, GLenum target, GLint level,
+                                   GLenum internalFormat, GLsizei width,
+                                   GLsizei height, GLsizei depth, GLint border,
+                                   GLsizei imageSize, const GLvoid *pixels)
+{
+   struct gl_texture_object*  texObj;
+   GET_CURRENT_CONTEXT(ctx);
+
+   texObj = _mesa_get_texobj_by_target_and_texunit(ctx, target,
+                                                   texunit - GL_TEXTURE0,
+                                                   true,
+                                                   "glCompressedMultiTexImage3DEXT");
+   if (!texObj)
+      return;
+   teximage(ctx, GL_TRUE, 3, texObj, target, level, internalFormat,
+            width, height, depth, border, GL_NONE, GL_NONE, imageSize, pixels, false);
+}
+
+
 void GLAPIENTRY
 _mesa_CompressedTexImage1D_no_error(GLenum target, GLint level,
                                     GLenum internalFormat, GLsizei width,
 void GLAPIENTRY
 _mesa_CompressedTexImage1D_no_error(GLenum target, GLint level,
                                     GLenum internalFormat, GLsizei width,
@@ -4909,43 +5576,80 @@ compressed_texture_sub_image(struct gl_context *ctx, GLuint dims,
 }
 
 
 }
 
 
-static ALWAYS_INLINE void
-compressed_tex_sub_image(unsigned dim, GLenum target, GLuint texture,
+enum tex_mode {
+   /* Use bound texture to current unit */
+   TEX_MODE_CURRENT_NO_ERROR = 0,
+   TEX_MODE_CURRENT_ERROR,
+   /* Use the specified texture name */
+   TEX_MODE_DSA_NO_ERROR,
+   TEX_MODE_DSA_ERROR,
+   /* Use the specified texture name + target */
+   TEX_MODE_EXT_DSA_TEXTURE,
+   /* Use the specified texture unit + target */
+   TEX_MODE_EXT_DSA_TEXUNIT,
+};
+
+
+static void
+compressed_tex_sub_image(unsigned dim, GLenum target, GLuint textureOrIndex,
                          GLint level, GLint xoffset, GLint yoffset,
                          GLint zoffset, GLsizei width, GLsizei height,
                          GLsizei depth, GLenum format, GLsizei imageSize,
                          GLint level, GLint xoffset, GLint yoffset,
                          GLint zoffset, GLsizei width, GLsizei height,
                          GLsizei depth, GLenum format, GLsizei imageSize,
-                         const GLvoid *data, bool dsa, bool no_error,
+                         const GLvoid *data, enum tex_mode mode,
                          const char *caller)
 {
                          const char *caller)
 {
-   struct gl_texture_object *texObj;
+   struct gl_texture_object *texObj = NULL;
    struct gl_texture_image *texImage;
    struct gl_texture_image *texImage;
-
+   bool no_error = false;
    GET_CURRENT_CONTEXT(ctx);
 
    GET_CURRENT_CONTEXT(ctx);
 
-   if (dsa) {
-      if (no_error) {
-         texObj = _mesa_lookup_texture(ctx, texture);
-      } else {
-         texObj = _mesa_lookup_texture_err(ctx, texture, caller);
-         if (!texObj)
-            return;
-      }
-
-      target = texObj->Target;
+   switch (mode) {
+      case TEX_MODE_DSA_ERROR:
+         assert(target == 0);
+         texObj = _mesa_lookup_texture_err(ctx, textureOrIndex, caller);
+         if (texObj)
+            target = texObj->Target;
+         break;
+      case TEX_MODE_DSA_NO_ERROR:
+         assert(target == 0);
+         texObj = _mesa_lookup_texture(ctx, textureOrIndex);
+         if (texObj)
+            target = texObj->Target;
+         no_error = true;
+         break;
+      case TEX_MODE_EXT_DSA_TEXTURE:
+         texObj = _mesa_lookup_or_create_texture(ctx, target, textureOrIndex,
+                                                 false, true, caller);
+         break;
+      case TEX_MODE_EXT_DSA_TEXUNIT:
+         texObj = _mesa_get_texobj_by_target_and_texunit(ctx, target,
+                                                         textureOrIndex,
+                                                         false,
+                                                         caller);
+         break;
+      case TEX_MODE_CURRENT_NO_ERROR:
+         no_error = true;
+      case TEX_MODE_CURRENT_ERROR:
+      default:
+         assert(textureOrIndex == 0);
+         break;
    }
 
    if (!no_error &&
    }
 
    if (!no_error &&
-       compressed_subtexture_target_check(ctx, target, dim, format, dsa,
+       compressed_subtexture_target_check(ctx, target, dim, format,
+                                          mode == TEX_MODE_DSA_ERROR,
                                           caller)) {
       return;
    }
 
                                           caller)) {
       return;
    }
 
-   if (!dsa) {
+   if (mode == TEX_MODE_CURRENT_NO_ERROR ||
+       mode == TEX_MODE_CURRENT_ERROR) {
       texObj = _mesa_get_current_tex_object(ctx, target);
       texObj = _mesa_get_current_tex_object(ctx, target);
-         if (!no_error && !texObj)
-            return;
    }
 
    }
 
+   if (!texObj)
+      return;
+
    if (!no_error &&
        compressed_subtexture_error_check(ctx, dim, texObj, target, level,
                                          xoffset, yoffset, zoffset, width,
    if (!no_error &&
        compressed_subtexture_error_check(ctx, dim, texObj, target, level,
                                          xoffset, yoffset, zoffset, width,
@@ -4955,7 +5659,9 @@ compressed_tex_sub_image(unsigned dim, GLenum target, GLuint texture,
    }
 
    /* Must handle special case GL_TEXTURE_CUBE_MAP. */
    }
 
    /* Must handle special case GL_TEXTURE_CUBE_MAP. */
-   if (dim == 3 && dsa && texObj->Target == GL_TEXTURE_CUBE_MAP) {
+   if (dim == 3 &&
+       (mode == TEX_MODE_DSA_ERROR || mode == TEX_MODE_DSA_NO_ERROR) &&
+       texObj->Target == GL_TEXTURE_CUBE_MAP) {
       const char *pixels = data;
       GLint image_stride;
 
       const char *pixels = data;
       GLint image_stride;
 
@@ -4997,31 +5703,6 @@ compressed_tex_sub_image(unsigned dim, GLenum target, GLuint texture,
    }
 }
 
    }
 }
 
-static void
-compressed_tex_sub_image_error(unsigned dim, GLenum target, GLuint texture,
-                               GLint level, GLint xoffset, GLint yoffset,
-                               GLint zoffset, GLsizei width, GLsizei height,
-                               GLsizei depth, GLenum format, GLsizei imageSize,
-                               const GLvoid *data, bool dsa,
-                               const char *caller)
-{
-   compressed_tex_sub_image(dim, target, texture, level, xoffset, yoffset,
-                            zoffset, width, height, depth, format, imageSize,
-                            data, dsa, false, caller);
-}
-
-static void
-compressed_tex_sub_image_no_error(unsigned dim, GLenum target, GLuint texture,
-                                  GLint level, GLint xoffset, GLint yoffset,
-                                  GLint zoffset, GLsizei width, GLsizei height,
-                                  GLsizei depth, GLenum format, GLsizei imageSize,
-                                  const GLvoid *data, bool dsa,
-                                  const char *caller)
-{
-   compressed_tex_sub_image(dim, target, texture, level, xoffset, yoffset,
-                            zoffset, width, height, depth, format, imageSize,
-                            data, dsa, true, caller);
-}
 
 void GLAPIENTRY
 _mesa_CompressedTexSubImage1D_no_error(GLenum target, GLint level,
 
 void GLAPIENTRY
 _mesa_CompressedTexSubImage1D_no_error(GLenum target, GLint level,
@@ -5029,9 +5710,11 @@ _mesa_CompressedTexSubImage1D_no_error(GLenum target, GLint level,
                                        GLenum format, GLsizei imageSize,
                                        const GLvoid *data)
 {
                                        GLenum format, GLsizei imageSize,
                                        const GLvoid *data)
 {
-   compressed_tex_sub_image_no_error(1, target, 0, level, xoffset, 0, 0, width,
-                                     1, 1, format, imageSize, data, false,
-                                     "glCompressedTexSubImage1D");
+   compressed_tex_sub_image(1, target, 0,
+                            level, xoffset, 0, 0, width,
+                            1, 1, format, imageSize, data,
+                            TEX_MODE_CURRENT_NO_ERROR,
+                            "glCompressedTexSubImage1D");
 }
 
 
 }
 
 
@@ -5040,9 +5723,11 @@ _mesa_CompressedTexSubImage1D(GLenum target, GLint level, GLint xoffset,
                               GLsizei width, GLenum format,
                               GLsizei imageSize, const GLvoid *data)
 {
                               GLsizei width, GLenum format,
                               GLsizei imageSize, const GLvoid *data)
 {
-   compressed_tex_sub_image_error(1, target, 0, level, xoffset, 0, 0, width, 1,
-                                  1, format, imageSize, data, false,
-                                  "glCompressedTexSubImage1D");
+   compressed_tex_sub_image(1, target, 0,
+                            level, xoffset, 0, 0, width,
+                            1, 1, format, imageSize, data,
+                            TEX_MODE_CURRENT_ERROR,
+                            "glCompressedTexSubImage1D");
 }
 
 
 }
 
 
@@ -5052,9 +5737,11 @@ _mesa_CompressedTextureSubImage1D_no_error(GLuint texture, GLint level,
                                            GLenum format, GLsizei imageSize,
                                            const GLvoid *data)
 {
                                            GLenum format, GLsizei imageSize,
                                            const GLvoid *data)
 {
-   compressed_tex_sub_image_no_error(1, 0, texture, level, xoffset, 0, 0, width,
-                                     1, 1, format, imageSize, data, true,
-                                     "glCompressedTextureSubImage1D");
+   compressed_tex_sub_image(1, 0, texture,
+                            level, xoffset, 0, 0,
+                            width, 1, 1, format, imageSize, data,
+                            TEX_MODE_DSA_NO_ERROR,
+                            "glCompressedTextureSubImage1D");
 }
 
 
 }
 
 
@@ -5063,11 +5750,42 @@ _mesa_CompressedTextureSubImage1D(GLuint texture, GLint level, GLint xoffset,
                                   GLsizei width, GLenum format,
                                   GLsizei imageSize, const GLvoid *data)
 {
                                   GLsizei width, GLenum format,
                                   GLsizei imageSize, const GLvoid *data)
 {
-   compressed_tex_sub_image_error(1, 0, texture, level, xoffset, 0, 0, width,
-                                  1, 1, format, imageSize, data, true,
-                                  "glCompressedTextureSubImage1D");
+   compressed_tex_sub_image(1, 0, texture,
+                            level, xoffset, 0, 0,
+                            width, 1, 1, format, imageSize, data,
+                            TEX_MODE_DSA_ERROR,
+                            "glCompressedTextureSubImage1D");
 }
 
 }
 
+
+void GLAPIENTRY
+_mesa_CompressedTextureSubImage1DEXT(GLuint texture, GLenum target,
+                                     GLint level, GLint xoffset,
+                                     GLsizei width, GLenum format,
+                                     GLsizei imageSize, const GLvoid *data)
+{
+   compressed_tex_sub_image(1, target, texture, level, xoffset, 0,
+                            0, width, 1, 1, format, imageSize,
+                            data,
+                            TEX_MODE_EXT_DSA_TEXTURE,
+                            "glCompressedTextureSubImage1DEXT");
+}
+
+
+void GLAPIENTRY
+_mesa_CompressedMultiTexSubImage1DEXT(GLenum texunit, GLenum target,
+                                      GLint level, GLint xoffset,
+                                      GLsizei width, GLenum format,
+                                      GLsizei imageSize, const GLvoid *data)
+{
+   compressed_tex_sub_image(1, target, texunit - GL_TEXTURE0, level,
+                            xoffset, 0, 0, width, 1, 1, format, imageSize,
+                            data,
+                            TEX_MODE_EXT_DSA_TEXUNIT,
+                            "glCompressedMultiTexSubImage1DEXT");
+}
+
+
 void GLAPIENTRY
 _mesa_CompressedTexSubImage2D_no_error(GLenum target, GLint level,
                                        GLint xoffset, GLint yoffset,
 void GLAPIENTRY
 _mesa_CompressedTexSubImage2D_no_error(GLenum target, GLint level,
                                        GLint xoffset, GLint yoffset,
@@ -5075,9 +5793,11 @@ _mesa_CompressedTexSubImage2D_no_error(GLenum target, GLint level,
                                        GLenum format, GLsizei imageSize,
                                        const GLvoid *data)
 {
                                        GLenum format, GLsizei imageSize,
                                        const GLvoid *data)
 {
-   compressed_tex_sub_image_no_error(2, target, 0, level, xoffset, yoffset, 0,
-                                     width, height, 1, format, imageSize, data,
-                                     false, "glCompressedTexSubImage2D");
+   compressed_tex_sub_image(2, target, 0, level,
+                            xoffset, yoffset, 0,
+                            width, height, 1, format, imageSize, data,
+                            TEX_MODE_CURRENT_NO_ERROR,
+                            "glCompressedTexSubImage2D");
 }
 
 
 }
 
 
@@ -5087,9 +5807,40 @@ _mesa_CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset,
                               GLenum format, GLsizei imageSize,
                               const GLvoid *data)
 {
                               GLenum format, GLsizei imageSize,
                               const GLvoid *data)
 {
-   compressed_tex_sub_image_error(2, target, 0, level, xoffset, yoffset, 0,
-                                  width, height, 1, format, imageSize, data,
-                                  false, "glCompressedTexSubImage2D");
+   compressed_tex_sub_image(2, target, 0, level,
+                            xoffset, yoffset, 0,
+                            width, height, 1, format, imageSize, data,
+                            TEX_MODE_CURRENT_ERROR,
+                            "glCompressedTexSubImage2D");
+}
+
+
+void GLAPIENTRY
+_mesa_CompressedTextureSubImage2DEXT(GLuint texture, GLenum target,
+                                     GLint level, GLint xoffset,
+                                     GLint yoffset, GLsizei width,
+                                     GLsizei height, GLenum format,
+                                     GLsizei imageSize, const GLvoid *data)
+{
+   compressed_tex_sub_image(2, target, texture, level, xoffset,
+                            yoffset, 0, width, height, 1, format,
+                            imageSize, data,
+                            TEX_MODE_EXT_DSA_TEXTURE,
+                            "glCompressedTextureSubImage2DEXT");
+}
+
+
+void GLAPIENTRY
+_mesa_CompressedMultiTexSubImage2DEXT(GLenum texunit, GLenum target,
+                                      GLint level, GLint xoffset, GLint yoffset,
+                                      GLsizei width, GLsizei height, GLenum format,
+                                      GLsizei imageSize, const GLvoid *data)
+{
+   compressed_tex_sub_image(2, target, texunit - GL_TEXTURE0, level,
+                            xoffset, yoffset, 0, width, height, 1, format,
+                            imageSize, data,
+                            TEX_MODE_EXT_DSA_TEXUNIT,
+                            "glCompressedMultiTexSubImage2DEXT");
 }
 
 
 }
 
 
@@ -5100,9 +5851,10 @@ _mesa_CompressedTextureSubImage2D_no_error(GLuint texture, GLint level,
                                            GLenum format, GLsizei imageSize,
                                            const GLvoid *data)
 {
                                            GLenum format, GLsizei imageSize,
                                            const GLvoid *data)
 {
-   compressed_tex_sub_image_no_error(2, 0, texture, level, xoffset, yoffset, 0,
-                                     width, height, 1, format, imageSize, data,
-                                     true, "glCompressedTextureSubImage2D");
+   compressed_tex_sub_image(2, 0, texture, level, xoffset, yoffset, 0,
+                            width, height, 1, format, imageSize, data,
+                            TEX_MODE_DSA_NO_ERROR,
+                            "glCompressedTextureSubImage2D");
 }
 
 
 }
 
 
@@ -5113,9 +5865,10 @@ _mesa_CompressedTextureSubImage2D(GLuint texture, GLint level, GLint xoffset,
                                   GLenum format, GLsizei imageSize,
                                   const GLvoid *data)
 {
                                   GLenum format, GLsizei imageSize,
                                   const GLvoid *data)
 {
-   compressed_tex_sub_image_error(2, 0, texture, level, xoffset, yoffset, 0,
-                                  width, height, 1, format, imageSize, data,
-                                  true, "glCompressedTextureSubImage2D");
+   compressed_tex_sub_image(2, 0, texture, level, xoffset, yoffset, 0,
+                            width, height, 1, format, imageSize, data,
+                            TEX_MODE_DSA_ERROR,
+                            "glCompressedTextureSubImage2D");
 }
 
 void GLAPIENTRY
 }
 
 void GLAPIENTRY
@@ -5126,10 +5879,11 @@ _mesa_CompressedTexSubImage3D_no_error(GLenum target, GLint level,
                                        GLenum format, GLsizei imageSize,
                                        const GLvoid *data)
 {
                                        GLenum format, GLsizei imageSize,
                                        const GLvoid *data)
 {
-   compressed_tex_sub_image_no_error(3, target, 0, level, xoffset, yoffset,
-                                     zoffset, width, height, depth, format,
-                                     imageSize, data, false,
-                                     "glCompressedTexSubImage3D");
+   compressed_tex_sub_image(3, target, 0, level, xoffset, yoffset,
+                            zoffset, width, height, depth, format,
+                            imageSize, data,
+                            TEX_MODE_CURRENT_NO_ERROR,
+                            "glCompressedTexSubImage3D");
 }
 
 void GLAPIENTRY
 }
 
 void GLAPIENTRY
@@ -5138,10 +5892,11 @@ _mesa_CompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset,
                               GLsizei height, GLsizei depth, GLenum format,
                               GLsizei imageSize, const GLvoid *data)
 {
                               GLsizei height, GLsizei depth, GLenum format,
                               GLsizei imageSize, const GLvoid *data)
 {
-   compressed_tex_sub_image_error(3, target, 0, level, xoffset, yoffset,
-                                  zoffset, width, height, depth, format,
-                                  imageSize, data, false,
-                                  "glCompressedTexSubImage3D");
+   compressed_tex_sub_image(3, target, 0, level, xoffset, yoffset,
+                            zoffset, width, height, depth, format,
+                            imageSize, data,
+                            TEX_MODE_CURRENT_ERROR,
+                            "glCompressedTexSubImage3D");
 }
 
 void GLAPIENTRY
 }
 
 void GLAPIENTRY
@@ -5152,10 +5907,11 @@ _mesa_CompressedTextureSubImage3D_no_error(GLuint texture, GLint level,
                                            GLenum format, GLsizei imageSize,
                                            const GLvoid *data)
 {
                                            GLenum format, GLsizei imageSize,
                                            const GLvoid *data)
 {
-   compressed_tex_sub_image_no_error(3, 0, texture, level, xoffset, yoffset,
-                                     zoffset, width, height, depth, format,
-                                     imageSize, data, true,
-                                     "glCompressedTextureSubImage3D");
+   compressed_tex_sub_image(3, 0, texture, level, xoffset, yoffset,
+                            zoffset, width, height, depth, format,
+                            imageSize, data,
+                            TEX_MODE_DSA_NO_ERROR,
+                            "glCompressedTextureSubImage3D");
 }
 
 void GLAPIENTRY
 }
 
 void GLAPIENTRY
@@ -5165,12 +5921,45 @@ _mesa_CompressedTextureSubImage3D(GLuint texture, GLint level, GLint xoffset,
                                   GLenum format, GLsizei imageSize,
                                   const GLvoid *data)
 {
                                   GLenum format, GLsizei imageSize,
                                   const GLvoid *data)
 {
-   compressed_tex_sub_image_error(3, 0, texture, level, xoffset, yoffset,
-                                  zoffset, width, height, depth, format,
-                                  imageSize, data, true,
-                                  "glCompressedTextureSubImage3D");
+   compressed_tex_sub_image(3, 0, texture, level, xoffset, yoffset,
+                            zoffset, width, height, depth, format,
+                            imageSize, data,
+                            TEX_MODE_DSA_ERROR,
+                            "glCompressedTextureSubImage3D");
+}
+
+
+void GLAPIENTRY
+_mesa_CompressedTextureSubImage3DEXT(GLuint texture, GLenum target,
+                                     GLint level, GLint xoffset,
+                                     GLint yoffset, GLint zoffset,
+                                     GLsizei width, GLsizei height,
+                                     GLsizei depth, GLenum format,
+                                     GLsizei imageSize, const GLvoid *data)
+{
+   compressed_tex_sub_image(3, target, texture, level, xoffset, yoffset,
+                            zoffset, width, height, depth, format,
+                            imageSize, data,
+                            TEX_MODE_EXT_DSA_TEXTURE,
+                            "glCompressedTextureSubImage3DEXT");
 }
 
 }
 
+
+void GLAPIENTRY
+_mesa_CompressedMultiTexSubImage3DEXT(GLenum texunit, GLenum target,
+                                      GLint level, GLint xoffset, GLint yoffset,
+                                      GLint zoffset, GLsizei width, GLsizei height,
+                                      GLsizei depth, GLenum format,
+                                      GLsizei imageSize, const GLvoid *data)
+{
+   compressed_tex_sub_image(3, target, texunit - GL_TEXTURE0, level,
+                            xoffset, yoffset, zoffset, width, height, depth,
+                            format, imageSize, data,
+                            TEX_MODE_EXT_DSA_TEXUNIT,
+                            "glCompressedMultiTexSubImage3DEXT");
+}
+
+
 mesa_format
 _mesa_get_texbuffer_format(const struct gl_context *ctx, GLenum internalFormat)
 {
 mesa_format
 _mesa_get_texbuffer_format(const struct gl_context *ctx, GLenum internalFormat)
 {
@@ -5279,7 +6068,7 @@ _mesa_get_texbuffer_format(const struct gl_context *ctx, GLenum internalFormat)
    case GL_RGBA8:
       return MESA_FORMAT_R8G8B8A8_UNORM;
    case GL_RGBA16:
    case GL_RGBA8:
       return MESA_FORMAT_R8G8B8A8_UNORM;
    case GL_RGBA16:
-      if (_mesa_is_gles(ctx))
+      if (_mesa_is_gles(ctx) && !_mesa_has_EXT_texture_norm16(ctx))
          return MESA_FORMAT_NONE;
       return MESA_FORMAT_RGBA_UNORM16;
    case GL_RGBA16F_ARB:
          return MESA_FORMAT_NONE;
       return MESA_FORMAT_RGBA_UNORM16;
    case GL_RGBA16F_ARB:
@@ -5302,7 +6091,7 @@ _mesa_get_texbuffer_format(const struct gl_context *ctx, GLenum internalFormat)
    case GL_RG8:
       return MESA_FORMAT_R8G8_UNORM;
    case GL_RG16:
    case GL_RG8:
       return MESA_FORMAT_R8G8_UNORM;
    case GL_RG16:
-      if (_mesa_is_gles(ctx))
+      if (_mesa_is_gles(ctx) && !_mesa_has_EXT_texture_norm16(ctx))
          return MESA_FORMAT_NONE;
       return MESA_FORMAT_R16G16_UNORM;
    case GL_RG16F:
          return MESA_FORMAT_NONE;
       return MESA_FORMAT_R16G16_UNORM;
    case GL_RG16F:
@@ -5325,7 +6114,7 @@ _mesa_get_texbuffer_format(const struct gl_context *ctx, GLenum internalFormat)
    case GL_R8:
       return MESA_FORMAT_R_UNORM8;
    case GL_R16:
    case GL_R8:
       return MESA_FORMAT_R_UNORM8;
    case GL_R16:
-      if (_mesa_is_gles(ctx))
+      if (_mesa_is_gles(ctx) && !_mesa_has_EXT_texture_norm16(ctx))
          return MESA_FORMAT_NONE;
       return MESA_FORMAT_R_UNORM16;
    case GL_R16F:
          return MESA_FORMAT_NONE;
       return MESA_FORMAT_R_UNORM16;
    case GL_R16F:
@@ -5407,8 +6196,8 @@ texture_buffer_range(struct gl_context *ctx,
    GLsizeiptr oldSize = texObj->BufferSize;
    mesa_format format;
 
    GLsizeiptr oldSize = texObj->BufferSize;
    mesa_format format;
 
-   /* NOTE: ARB_texture_buffer_object has interactions with
-    * the compatibility profile that are not implemented.
+   /* NOTE: ARB_texture_buffer_object might not be supported in
+    * the compatibility profile.
     */
    if (!_mesa_has_ARB_texture_buffer_object(ctx) &&
        !_mesa_has_OES_texture_buffer(ctx)) {
     */
    if (!_mesa_has_ARB_texture_buffer_object(ctx) &&
        !_mesa_has_OES_texture_buffer(ctx)) {
@@ -5685,7 +6474,8 @@ _mesa_TextureBufferRange(GLuint texture, GLenum internalFormat, GLuint buffer,
 }
 
 GLboolean
 }
 
 GLboolean
-_mesa_is_renderable_texture_format(struct gl_context *ctx, GLenum internalformat)
+_mesa_is_renderable_texture_format(const struct gl_context *ctx,
+                                   GLenum internalformat)
 {
    /* Everything that is allowed for renderbuffers,
     * except for a base format of GL_STENCIL_INDEX, unless supported.
 {
    /* Everything that is allowed for renderbuffers,
     * except for a base format of GL_STENCIL_INDEX, unless supported.
@@ -5751,14 +6541,10 @@ texture_image_multisample(struct gl_context *ctx, GLuint dims,
    }
 
    if (!check_multisample_target(dims, target, dsa)) {
    }
 
    if (!check_multisample_target(dims, target, dsa)) {
-      if (dsa) {
-         _mesa_error(ctx, GL_INVALID_OPERATION, "%s(target)", func);
-         return;
-      }
-      else {
-         _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func);
-         return;
-      }
+      GLenum err = dsa ? GL_INVALID_OPERATION : GL_INVALID_ENUM;
+      _mesa_error(ctx, err, "%s(target=%s)", func,
+                  _mesa_enum_to_string(target));
+      return;
    }
 
    /* check that the specified internalformat is color/depth/stencil-renderable;
    }
 
    /* check that the specified internalformat is color/depth/stencil-renderable;
@@ -5787,7 +6573,7 @@ texture_image_multisample(struct gl_context *ctx, GLuint dims,
    }
 
    sample_count_error = _mesa_check_sample_count(ctx, target,
    }
 
    sample_count_error = _mesa_check_sample_count(ctx, target,
-         internalformat, samples);
+         internalformat, samples, samples);
    samplesOK = sample_count_error == GL_NO_ERROR;
 
    /* Page 254 of OpenGL 4.4 spec says:
    samplesOK = sample_count_error == GL_NO_ERROR;
 
    /* Page 254 of OpenGL 4.4 spec says:
@@ -5799,7 +6585,7 @@ texture_image_multisample(struct gl_context *ctx, GLuint dims,
     *    However, if samples is not supported, then no error is generated.
     */
    if (!samplesOK && !_mesa_is_proxy_texture(target)) {
     *    However, if samples is not supported, then no error is generated.
     */
    if (!samplesOK && !_mesa_is_proxy_texture(target)) {
-      _mesa_error(ctx, sample_count_error, "%s(samples)", func);
+      _mesa_error(ctx, sample_count_error, "%s(samples=%d)", func, samples);
       return;
    }
 
       return;
    }
 
@@ -5829,9 +6615,9 @@ texture_image_multisample(struct gl_context *ctx, GLuint dims,
 
    if (_mesa_is_proxy_texture(target)) {
       if (samplesOK && dimensionsOK && sizeOK) {
 
    if (_mesa_is_proxy_texture(target)) {
       if (samplesOK && dimensionsOK && sizeOK) {
-         init_teximage_fields_ms(ctx, texImage, width, height, depth, 0,
-                                 internalformat, texFormat,
-                                 samples, fixedsamplelocations);
+         _mesa_init_teximage_fields_ms(ctx, texImage, width, height, depth, 0,
+                                       internalformat, texFormat,
+                                       samples, fixedsamplelocations);
       }
       else {
          /* clear all image fields */
       }
       else {
          /* clear all image fields */
@@ -5858,9 +6644,9 @@ texture_image_multisample(struct gl_context *ctx, GLuint dims,
 
       ctx->Driver.FreeTextureImageBuffer(ctx, texImage);
 
 
       ctx->Driver.FreeTextureImageBuffer(ctx, texImage);
 
-      init_teximage_fields_ms(ctx, texImage, width, height, depth, 0,
-                              internalformat, texFormat,
-                              samples, fixedsamplelocations);
+      _mesa_init_teximage_fields_ms(ctx, texImage, width, height, depth, 0,
+                                    internalformat, texFormat,
+                                    samples, fixedsamplelocations);
 
       if (width > 0 && height > 0 && depth > 0) {
          if (memObj) {
 
       if (width > 0 && height > 0 && depth > 0) {
          if (memObj) {
@@ -5936,7 +6722,7 @@ _mesa_TexImage3DMultisample(GLenum target, GLsizei samples,
 
 static bool
 valid_texstorage_ms_parameters(GLsizei width, GLsizei height, GLsizei depth,
 
 static bool
 valid_texstorage_ms_parameters(GLsizei width, GLsizei height, GLsizei depth,
-                               GLsizei samples, unsigned dims)
+                               unsigned dims)
 {
    GET_CURRENT_CONTEXT(ctx);
 
 {
    GET_CURRENT_CONTEXT(ctx);
 
@@ -5961,7 +6747,7 @@ _mesa_TexStorage2DMultisample(GLenum target, GLsizei samples,
    if (!texObj)
       return;
 
    if (!texObj)
       return;
 
-   if (!valid_texstorage_ms_parameters(width, height, 1, samples, 2))
+   if (!valid_texstorage_ms_parameters(width, height, 1, 2))
       return;
 
    texture_image_multisample(ctx, 2, texObj, NULL, target, samples,
       return;
 
    texture_image_multisample(ctx, 2, texObj, NULL, target, samples,
@@ -5983,7 +6769,7 @@ _mesa_TexStorage3DMultisample(GLenum target, GLsizei samples,
    if (!texObj)
       return;
 
    if (!texObj)
       return;
 
-   if (!valid_texstorage_ms_parameters(width, height, depth, samples, 3))
+   if (!valid_texstorage_ms_parameters(width, height, depth, 3))
       return;
 
    texture_image_multisample(ctx, 3, texObj, NULL, target, samples,
       return;
 
    texture_image_multisample(ctx, 3, texObj, NULL, target, samples,
@@ -6006,7 +6792,7 @@ _mesa_TextureStorage2DMultisample(GLuint texture, GLsizei samples,
    if (!texObj)
       return;
 
    if (!texObj)
       return;
 
-   if (!valid_texstorage_ms_parameters(width, height, 1, samples, 2))
+   if (!valid_texstorage_ms_parameters(width, height, 1, 2))
       return;
 
    texture_image_multisample(ctx, 2, texObj, NULL, texObj->Target,
       return;
 
    texture_image_multisample(ctx, 2, texObj, NULL, texObj->Target,
@@ -6030,7 +6816,7 @@ _mesa_TextureStorage3DMultisample(GLuint texture, GLsizei samples,
    if (!texObj)
       return;
 
    if (!texObj)
       return;
 
-   if (!valid_texstorage_ms_parameters(width, height, depth, samples, 3))
+   if (!valid_texstorage_ms_parameters(width, height, depth, 3))
       return;
 
    texture_image_multisample(ctx, 3, texObj, NULL, texObj->Target, samples,
       return;
 
    texture_image_multisample(ctx, 3, texObj, NULL, texObj->Target, samples,