tree-wide: replace MAYBE_UNUSED with ASSERTED
[mesa.git] / src / mesa / main / teximage.c
index 9e139d746f10816a26a5e94918f45c008ed46a0e..5c28c21234e806fa03cda11bd70ef08b7f10a66e 100644 (file)
@@ -176,7 +176,7 @@ oes_float_internal_format(const struct gl_context *ctx,
 /**
  * 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.
@@ -423,23 +423,15 @@ get_proxy_tex_image(struct gl_context *ctx, GLenum target, GLint level)
 
    switch (target) {
    case GL_PROXY_TEXTURE_1D:
-      if (level >= ctx->Const.MaxTextureLevels)
-         return NULL;
       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:
-      if (level >= ctx->Const.Max3DTextureLevels)
-         return NULL;
       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:
@@ -448,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:
-      if (level >= ctx->Const.MaxTextureLevels)
-         return NULL;
       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:
-      if (level >= ctx->Const.MaxCubeTextureLevels)
-         return NULL;
       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:
-      if (level > 0)
-         return 0;
       texIndex = TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX;
       break;
    default:
@@ -503,14 +485,14 @@ get_proxy_tex_image(struct gl_context *ctx, GLenum target, GLint level)
  * \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:
-      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;
@@ -532,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
-         ? 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)
@@ -548,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:
-      /* fall-through */
+      return _mesa_has_OES_EGL_image_external(ctx) ? 1 : 0;
    default:
       return 0; /* bad target */
    }
@@ -837,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.
  */
-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)
 {
+   const GLint base_format =_mesa_base_tex_format(ctx, internalFormat);
    GLenum target;
    assert(img);
    assert(width >= 0);
@@ -852,8 +835,8 @@ init_teximage_fields_ms(struct gl_context *ctx,
    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;
@@ -950,8 +933,8 @@ _mesa_init_teximage_fields(struct gl_context *ctx,
                            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);
 }
 
 
@@ -990,8 +973,7 @@ _mesa_legal_texture_dimensions(struct gl_context *ctx, GLenum target,
    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) {
@@ -1004,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:
-      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)
@@ -1075,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:
-      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)
@@ -1091,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:
-      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)
@@ -1298,7 +1277,7 @@ error_check_subtexture_dimensions(struct gl_context *ctx, GLuint dims,
  */
 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)
 {
@@ -1352,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
-compressedteximage_only_format(const struct gl_context *ctx, GLenum format)
+compressedteximage_only_format(GLenum format)
 {
    switch (format) {
    case GL_PALETTE4_RGB8_OES:
@@ -1365,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_ATC_RGB_AMD:
+   case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
+   case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
       return true;
    default:
       return false;
@@ -1375,11 +1357,11 @@ compressedteximage_only_format(const struct gl_context *ctx, GLenum format)
  * 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) ||
-          compressedteximage_only_format(ctx, format);
+          compressedteximage_only_format(format);
 }
 
 /* Writes to an GL error pointer if non-null and returns whether or not the
@@ -1649,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
-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;
 
@@ -1797,8 +1778,8 @@ static bool
 texture_format_error_check_gles(struct gl_context *ctx, GLenum format,
                                 GLenum type, GLenum internalFormat, const char *callerName)
 {
-   GLenum err = _mesa_es3_error_check_format_and_type(ctx, format, type,
-                                                      internalFormat);
+   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)",
@@ -1839,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,
+                     struct gl_texture_object* texObj,
                      GLint level, GLint internalFormat,
                      GLenum format, GLenum type,
                      GLint width, GLint height,
@@ -1910,7 +1892,7 @@ texture_error_check( struct gl_context *ctx,
     * requires GL_OES_texture_float) are filtered elsewhere.
     */
    char bufCallerName[20];
-   snprintf(bufCallerName, 20, "glTexImage%dD", dimensions);
+   _mesa_snprintf(bufCallerName, 20, "glTexImage%dD", dimensions);
    if (_mesa_is_gles(ctx) &&
        texture_format_error_check_gles(ctx, format, type,
                                        internalFormat, bufCallerName)) {
@@ -1979,7 +1961,7 @@ texture_error_check( struct gl_context *ctx,
                      "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;
@@ -2001,7 +1983,7 @@ texture_error_check( struct gl_context *ctx,
       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;
@@ -2020,8 +2002,8 @@ texture_error_check( struct gl_context *ctx,
  */
 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)
 {
@@ -2137,7 +2119,7 @@ compressed_texture_error_check(struct gl_context *ctx, GLint dimensions,
       goto error;
    }
 
-   if (!mutable_tex_object(ctx, target)) {
+   if (!mutable_tex_object(texObj)) {
       reason = "immutable texture";
       error = GL_INVALID_OPERATION;
       goto error;
@@ -2183,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,
-                        bool dsa, const char *callerName)
+                        const char *callerName)
 {
    struct gl_texture_image *texImage;
    GLenum err;
@@ -2252,7 +2234,7 @@ texsubimage_error_check(struct gl_context *ctx, GLuint dimensions,
    }
 
    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;
@@ -2293,8 +2275,8 @@ texsubimage_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;
@@ -2406,8 +2388,8 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions,
 
    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 ||
@@ -2434,14 +2416,10 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions,
    }
 
    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;
 
-      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;
       }
@@ -2467,7 +2445,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.
        */
-      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));
@@ -2529,7 +2508,7 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions,
                      "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;
@@ -2541,7 +2520,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;
@@ -2611,7 +2590,7 @@ copytexsubimage_error_check(struct gl_context *ctx, GLuint dimensions,
    }
 
    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;
@@ -2690,7 +2669,7 @@ struct cb_info
  * 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;
@@ -2767,7 +2746,8 @@ check_gen_mipmap(struct gl_context *ctx, GLenum target,
 
 /** 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 ||
@@ -2893,10 +2873,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)
@@ -2904,6 +2944,7 @@ strip_texture_border(GLenum target,
  */
 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,
@@ -2912,7 +2953,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;
-   struct gl_texture_object *texObj;
    mesa_format texFormat;
    bool dimensionsOK = true, sizeOK = true;
 
@@ -2939,6 +2979,9 @@ teximage(struct gl_context *ctx, GLboolean compressed, GLuint dims,
 
    internalFormat = override_internal_format(internalFormat, width, height);
 
+   if (!texObj)
+      texObj = _mesa_get_current_tex_object(ctx, target);
+
    if (!no_error) {
       /* target error checking */
       if (!legal_teximage_target(ctx, dims, target)) {
@@ -2949,18 +2992,19 @@ teximage(struct gl_context *ctx, GLboolean compressed, GLuint dims,
 
       /* 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 {
-         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;
       }
    }
+   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
@@ -2984,9 +3028,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
@@ -3123,7 +3164,7 @@ teximage_err(struct gl_context *ctx, GLboolean compressed, GLuint dims,
              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);
 }
 
@@ -3135,7 +3176,7 @@ teximage_no_error(struct gl_context *ctx, GLboolean compressed, GLuint dims,
                   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);
 }
 
@@ -3153,6 +3194,21 @@ _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
                 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_TexImage2D( GLenum target, GLint level, GLint internalFormat,
@@ -3165,6 +3221,22 @@ _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
                 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);
+}
 
 /*
  * Called by the API or display list executor.
@@ -3181,6 +3253,23 @@ _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
                 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_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat,
@@ -3291,7 +3380,6 @@ _mesa_EGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image)
    _mesa_unlock_texture(ctx, texObj);
 }
 
-
 /**
  * Helper that implements the glTexSubImage1/2/3D()
  * and glTextureSubImage1/2/3D() functions.
@@ -3303,8 +3391,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 format, GLenum type, const GLvoid *pixels,
-                  bool dsa)
+                  GLenum format, GLenum type, const GLvoid *pixels)
 {
    FLUSH_VERTICES(ctx, 0);
 
@@ -3371,7 +3458,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,
-                               pixels, false, callerName)) {
+                               pixels, callerName)) {
       return;   /* error was detected */
    }
 
@@ -3388,7 +3475,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,
-                     format, type, pixels, false);
+                     format, type, pixels);
 }
 
 
@@ -3406,7 +3493,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,
-                     format, type, pixels, false);
+                     format, type, pixels);
 }
 
 
@@ -3416,11 +3503,11 @@ texsubimage(struct gl_context *ctx, GLuint dims, GLenum target, GLint level,
  */
 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,
-                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;
@@ -3436,7 +3523,11 @@ texturesubimage(struct gl_context *ctx, GLuint dims,
 
    /* 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 {
@@ -3454,7 +3545,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,
-                                  pixels, true, callerName)) {
+                                  pixels, callerName)) {
          return;   /* error was detected */
       }
    }
@@ -3509,7 +3600,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,
-                           type, pixels, true);
+                           type, pixels);
          pixels = (GLubyte *) pixels + imageStride;
       }
    }
@@ -3520,36 +3611,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,
-                        type, pixels, true);
+                        type, pixels);
    }
 }
 
 
 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,
-                      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,
-                         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,
-                         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);
 }
 
 
@@ -3647,8 +3738,22 @@ _mesa_TextureSubImage1D_no_error(GLuint texture, GLint level, GLint xoffset,
                                  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);
 }
 
 
@@ -3659,8 +3764,9 @@ _mesa_TextureSubImage1D(GLuint texture, GLint level,
                         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);
 }
 
 
@@ -3671,9 +3777,22 @@ _mesa_TextureSubImage2D_no_error(GLuint texture, GLint level, GLint xoffset,
                                  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);
 }
 
 
@@ -3685,9 +3804,9 @@ _mesa_TextureSubImage2D(GLuint texture, GLint level,
                         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);
 }
 
 
@@ -3698,11 +3817,22 @@ _mesa_TextureSubImage3D_no_error(GLuint texture, GLint level, GLint xoffset,
                                  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_TextureSubImage3D(GLuint texture, GLint level,
@@ -3712,9 +3842,9 @@ _mesa_TextureSubImage3D(GLuint texture, GLint level,
                         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,
-                         "glTextureSubImage3D");
+                         "glTextureSubImage3D", false);
 }
 
 
@@ -3799,7 +3929,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,
-                       mesa_format texFormat, GLint x, GLint y, GLsizei width,
+                       mesa_format texFormat, GLsizei width,
                        GLsizei height, GLint border)
 {
    if (texImage->InternalFormat != internalFormat)
@@ -3915,13 +4045,12 @@ copy_texture_sub_image_no_error(struct gl_context *ctx, GLuint dims,
  * 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;
-   struct gl_texture_object *texObj;
    mesa_format texFormat;
 
    FLUSH_VERTICES(ctx, 0);
@@ -3937,8 +4066,8 @@ copyteximage(struct gl_context *ctx, GLuint dims,
       _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,
@@ -3950,7 +4079,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,
@@ -3963,7 +4091,7 @@ copyteximage(struct gl_context *ctx, GLuint dims,
    {
       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,
@@ -4007,7 +4135,7 @@ copyteximage(struct gl_context *ctx, GLuint dims,
        */
       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;
       }
@@ -4077,11 +4205,13 @@ copyteximage(struct gl_context *ctx, GLuint dims,
 
 
 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)
 {
-   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);
 }
 
@@ -4091,7 +4221,8 @@ 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);
 }
 
@@ -4108,6 +4239,23 @@ _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_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
                       GLint x, GLint y, GLsizei width, GLsizei height,
@@ -4119,6 +4267,24 @@ _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_CopyTexImage1D_no_error(GLenum target, GLint level, GLenum internalFormat,
                               GLint x, GLint y, GLsizei width, GLint border)
@@ -4244,6 +4410,31 @@ _mesa_CopyTextureSubImage1D(GLuint texture, GLint level,
 }
 
 
+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_CopyTextureSubImage2D(GLuint texture, GLint level,
                             GLint xoffset, GLint yoffset,
@@ -4269,6 +4460,31 @@ _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_CopyTextureSubImage3D(GLuint texture, GLint level,
                             GLint xoffset, GLint yoffset, GLint zoffset,
@@ -4302,6 +4518,39 @@ _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_CopyTexSubImage1D_no_error(GLenum target, GLint level, GLint xoffset,
                                  GLint x, GLint y, GLsizei width)
@@ -4847,7 +5096,7 @@ compressed_subtexture_error_check(struct gl_context *ctx, GLint dims,
       return GL_TRUE;
    }
 
-   if (compressedteximage_only_format(ctx, format)) {
+   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;
@@ -4979,8 +5228,8 @@ compressed_tex_sub_image(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, bool no_error,
-                         const char *caller)
+                         const GLvoid *data, bool dsa, bool ext_dsa,
+                         bool no_error, const char *caller)
 {
    struct gl_texture_object *texObj = NULL;
    struct gl_texture_image *texImage;
@@ -4990,13 +5239,20 @@ compressed_tex_sub_image(unsigned dim, GLenum target, GLuint texture,
    if (dsa) {
       if (no_error) {
          texObj = _mesa_lookup_texture(ctx, texture);
+         target = texObj->Target;
       } else {
-         texObj = _mesa_lookup_texture_err(ctx, texture, caller);
-         if (!texObj)
-            return;
-      }
+         if (!ext_dsa) {
+            texObj = _mesa_lookup_texture_err(ctx, texture, caller);
+            if (!texObj)
+               return;
 
-      target = texObj->Target;
+            target = texObj->Target;
+         } else {
+            texObj = lookup_texture_ext_dsa(ctx, target, texture, caller);
+            if (!texObj)
+               return;
+         }
+      }
    }
 
    if (!no_error &&
@@ -5067,12 +5323,12 @@ 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 GLvoid *data, bool dsa, bool ext_dsa,
                                const char *caller)
 {
    compressed_tex_sub_image(dim, target, texture, level, xoffset, yoffset,
                             zoffset, width, height, depth, format, imageSize,
-                            data, dsa, false, caller);
+                            data, dsa, ext_dsa, false, caller);
 }
 
 static void
@@ -5080,12 +5336,12 @@ 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 GLvoid *data, bool dsa, bool ext_dsa,
                                   const char *caller)
 {
    compressed_tex_sub_image(dim, target, texture, level, xoffset, yoffset,
                             zoffset, width, height, depth, format, imageSize,
-                            data, dsa, true, caller);
+                            data, dsa, ext_dsa, true, caller);
 }
 
 void GLAPIENTRY
@@ -5096,7 +5352,7 @@ _mesa_CompressedTexSubImage1D_no_error(GLenum target, GLint level,
 {
    compressed_tex_sub_image_no_error(1, target, 0, level, xoffset, 0, 0, width,
                                      1, 1, format, imageSize, data, false,
-                                     "glCompressedTexSubImage1D");
+                                     false, "glCompressedTexSubImage1D");
 }
 
 
@@ -5106,7 +5362,7 @@ _mesa_CompressedTexSubImage1D(GLenum target, GLint level, GLint xoffset,
                               GLsizei imageSize, const GLvoid *data)
 {
    compressed_tex_sub_image_error(1, target, 0, level, xoffset, 0, 0, width, 1,
-                                  1, format, imageSize, data, false,
+                                  1, format, imageSize, data, false, false,
                                   "glCompressedTexSubImage1D");
 }
 
@@ -5117,8 +5373,9 @@ _mesa_CompressedTextureSubImage1D_no_error(GLuint texture, GLint level,
                                            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,
+   compressed_tex_sub_image_no_error(1, 0, texture, level, xoffset, 0, 0,
+                                     width, 1, 1, format, imageSize, data,
+                                     true, false,
                                      "glCompressedTextureSubImage1D");
 }
 
@@ -5129,10 +5386,11 @@ _mesa_CompressedTextureSubImage1D(GLuint texture, GLint level, GLint xoffset,
                                   GLsizei imageSize, const GLvoid *data)
 {
    compressed_tex_sub_image_error(1, 0, texture, level, xoffset, 0, 0, width,
-                                  1, 1, format, imageSize, data, true,
+                                  1, 1, format, imageSize, data, true, false,
                                   "glCompressedTextureSubImage1D");
 }
 
+
 void GLAPIENTRY
 _mesa_CompressedTexSubImage2D_no_error(GLenum target, GLint level,
                                        GLint xoffset, GLint yoffset,
@@ -5142,7 +5400,8 @@ _mesa_CompressedTexSubImage2D_no_error(GLenum target, GLint level,
 {
    compressed_tex_sub_image_no_error(2, target, 0, level, xoffset, yoffset, 0,
                                      width, height, 1, format, imageSize, data,
-                                     false, "glCompressedTexSubImage2D");
+                                     false, false,
+                                     "glCompressedTexSubImage2D");
 }
 
 
@@ -5154,7 +5413,22 @@ _mesa_CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset,
 {
    compressed_tex_sub_image_error(2, target, 0, level, xoffset, yoffset, 0,
                                   width, height, 1, format, imageSize, data,
-                                  false, "glCompressedTexSubImage2D");
+                                  false, false,
+                                  "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_error(2, target, texture, level, xoffset, yoffset,
+                                  0, width, height, 1, format, imageSize,
+                                  data, true, true,
+                                  "glCompressedTextureSubImage2DEXT");
 }
 
 
@@ -5167,7 +5441,8 @@ _mesa_CompressedTextureSubImage2D_no_error(GLuint texture, GLint level,
 {
    compressed_tex_sub_image_no_error(2, 0, texture, level, xoffset, yoffset, 0,
                                      width, height, 1, format, imageSize, data,
-                                     true, "glCompressedTextureSubImage2D");
+                                     true, false,
+                                     "glCompressedTextureSubImage2D");
 }
 
 
@@ -5180,7 +5455,8 @@ _mesa_CompressedTextureSubImage2D(GLuint texture, GLint level, GLint xoffset,
 {
    compressed_tex_sub_image_error(2, 0, texture, level, xoffset, yoffset, 0,
                                   width, height, 1, format, imageSize, data,
-                                  true, "glCompressedTextureSubImage2D");
+                                  true, false,
+                                  "glCompressedTextureSubImage2D");
 }
 
 void GLAPIENTRY
@@ -5193,7 +5469,7 @@ _mesa_CompressedTexSubImage3D_no_error(GLenum target, GLint level,
 {
    compressed_tex_sub_image_no_error(3, target, 0, level, xoffset, yoffset,
                                      zoffset, width, height, depth, format,
-                                     imageSize, data, false,
+                                     imageSize, data, false, false,
                                      "glCompressedTexSubImage3D");
 }
 
@@ -5205,7 +5481,7 @@ _mesa_CompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset,
 {
    compressed_tex_sub_image_error(3, target, 0, level, xoffset, yoffset,
                                   zoffset, width, height, depth, format,
-                                  imageSize, data, false,
+                                  imageSize, data, false, false,
                                   "glCompressedTexSubImage3D");
 }
 
@@ -5219,7 +5495,7 @@ _mesa_CompressedTextureSubImage3D_no_error(GLuint texture, GLint level,
 {
    compressed_tex_sub_image_no_error(3, 0, texture, level, xoffset, yoffset,
                                      zoffset, width, height, depth, format,
-                                     imageSize, data, true,
+                                     imageSize, data, true,  false,
                                      "glCompressedTextureSubImage3D");
 }
 
@@ -5232,7 +5508,7 @@ _mesa_CompressedTextureSubImage3D(GLuint texture, GLint level, GLint xoffset,
 {
    compressed_tex_sub_image_error(3, 0, texture, level, xoffset, yoffset,
                                   zoffset, width, height, depth, format,
-                                  imageSize, data, true,
+                                  imageSize, data, true, false,
                                   "glCompressedTextureSubImage3D");
 }
 
@@ -5344,7 +5620,7 @@ _mesa_get_texbuffer_format(const struct gl_context *ctx, GLenum internalFormat)
    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:
@@ -5367,7 +5643,7 @@ _mesa_get_texbuffer_format(const struct gl_context *ctx, GLenum internalFormat)
    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:
@@ -5390,7 +5666,7 @@ _mesa_get_texbuffer_format(const struct gl_context *ctx, GLenum internalFormat)
    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:
@@ -5849,7 +6125,7 @@ texture_image_multisample(struct gl_context *ctx, GLuint dims,
    }
 
    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:
@@ -5891,9 +6167,9 @@ texture_image_multisample(struct gl_context *ctx, GLuint dims,
 
    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 */
@@ -5920,9 +6196,9 @@ texture_image_multisample(struct gl_context *ctx, GLuint dims,
 
       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) {
@@ -5998,7 +6274,7 @@ _mesa_TexImage3DMultisample(GLenum target, GLsizei samples,
 
 static bool
 valid_texstorage_ms_parameters(GLsizei width, GLsizei height, GLsizei depth,
-                               GLsizei samples, unsigned dims)
+                               unsigned dims)
 {
    GET_CURRENT_CONTEXT(ctx);
 
@@ -6023,7 +6299,7 @@ _mesa_TexStorage2DMultisample(GLenum target, GLsizei samples,
    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,
@@ -6045,7 +6321,7 @@ _mesa_TexStorage3DMultisample(GLenum target, GLsizei samples,
    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,
@@ -6068,7 +6344,7 @@ _mesa_TextureStorage2DMultisample(GLuint texture, GLsizei samples,
    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,
@@ -6092,7 +6368,7 @@ _mesa_TextureStorage3DMultisample(GLuint texture, GLsizei samples,
    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,