glsl: Change _mesa_glsl_parse_state ctor to use gl_shader_stage enum.
[mesa.git] / src / mesa / main / teximage.c
index d07f6e9dc9ec790d2cd8c1fb8ab507b2052bc0b3..9c3f1e86e5b7e0ae8550d52d40f8d45948d3770d 100644 (file)
@@ -48,6 +48,7 @@
 #include "texobj.h"
 #include "texstate.h"
 #include "texstorage.h"
+#include "textureview.h"
 #include "mtypes.h"
 #include "glformats.h"
 
@@ -180,7 +181,7 @@ _mesa_base_tex_format( struct gl_context *ctx, GLint internalFormat )
    default:
       ; /* fallthrough */
    }
-         
+
    if (ctx->Extensions.TDFX_texture_compression_FXT1) {
       switch (internalFormat) {
          case GL_COMPRESSED_RGB_FXT1_3DFX:
@@ -300,14 +301,12 @@ _mesa_base_tex_format( struct gl_context *ctx, GLint internalFormat )
       }
    }
 
-   if (ctx->Extensions.EXT_packed_depth_stencil) {
-      switch (internalFormat) {
-         case GL_DEPTH_STENCIL_EXT:
-         case GL_DEPTH24_STENCIL8_EXT:
-            return GL_DEPTH_STENCIL_EXT;
-         default:
-            ; /* fallthrough */
-      }
+   switch (internalFormat) {
+   case GL_DEPTH_STENCIL:
+   case GL_DEPTH24_STENCIL8:
+      return GL_DEPTH_STENCIL;
+   default:
+      ; /* fallthrough */
    }
 
    if (ctx->Extensions.EXT_texture_sRGB) {
@@ -315,15 +314,17 @@ _mesa_base_tex_format( struct gl_context *ctx, GLint internalFormat )
       case GL_SRGB_EXT:
       case GL_SRGB8_EXT:
       case GL_COMPRESSED_SRGB_EXT:
-      case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
          return GL_RGB;
+      case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+         return ctx->Extensions.EXT_texture_compression_s3tc ? GL_RGB : -1;
       case GL_SRGB_ALPHA_EXT:
       case GL_SRGB8_ALPHA8_EXT:
       case GL_COMPRESSED_SRGB_ALPHA_EXT:
+         return GL_RGBA;
       case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
       case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
       case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
-         return GL_RGBA;
+         return ctx->Extensions.EXT_texture_compression_s3tc ? GL_RGBA : -1;
       case GL_SLUMINANCE_ALPHA_EXT:
       case GL_SLUMINANCE8_ALPHA8_EXT:
       case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT:
@@ -613,7 +614,7 @@ set_tex_image(struct gl_texture_object *tObj,
 
 /**
  * Allocate a texture image structure.
- * 
+ *
  * Called via ctx->Driver.NewTextureImage() unless overriden by a device
  * driver.
  *
@@ -659,22 +660,29 @@ _mesa_delete_texture_image(struct gl_context *ctx,
 GLboolean
 _mesa_is_proxy_texture(GLenum target)
 {
+   unsigned i;
+   static const GLenum targets[] = {
+      GL_PROXY_TEXTURE_1D,
+      GL_PROXY_TEXTURE_2D,
+      GL_PROXY_TEXTURE_3D,
+      GL_PROXY_TEXTURE_CUBE_MAP,
+      GL_PROXY_TEXTURE_RECTANGLE,
+      GL_PROXY_TEXTURE_1D_ARRAY,
+      GL_PROXY_TEXTURE_2D_ARRAY,
+      GL_PROXY_TEXTURE_CUBE_MAP_ARRAY,
+      GL_PROXY_TEXTURE_2D_MULTISAMPLE,
+      GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY
+   };
    /*
-    * NUM_TEXTURE_TARGETS should match number of terms below, except there's no
+    * NUM_TEXTURE_TARGETS should match number of terms above, except there's no
     * proxy for GL_TEXTURE_BUFFER and GL_TEXTURE_EXTERNAL_OES.
     */
-   assert(NUM_TEXTURE_TARGETS == 10 + 2);
-
-   return (target == GL_PROXY_TEXTURE_1D ||
-           target == GL_PROXY_TEXTURE_2D ||
-           target == GL_PROXY_TEXTURE_3D ||
-           target == GL_PROXY_TEXTURE_CUBE_MAP_ARB ||
-           target == GL_PROXY_TEXTURE_RECTANGLE_NV ||
-           target == GL_PROXY_TEXTURE_1D_ARRAY_EXT ||
-           target == GL_PROXY_TEXTURE_2D_ARRAY_EXT ||
-           target == GL_PROXY_TEXTURE_CUBE_MAP_ARRAY ||
-           target == GL_PROXY_TEXTURE_2D_MULTISAMPLE ||
-           target == GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY);
+   STATIC_ASSERT(NUM_TEXTURE_TARGETS == Elements(targets) + 2);
+
+   for (i = 0; i < Elements(targets); ++i)
+      if (target == targets[i])
+         return GL_TRUE;
+   return GL_FALSE;
 }
 
 
@@ -743,8 +751,7 @@ _mesa_select_tex_object(struct gl_context *ctx,
                         const struct gl_texture_unit *texUnit,
                         GLenum target)
 {
-   const GLboolean arrayTex = (ctx->Extensions.MESA_texture_array ||
-                               ctx->Extensions.EXT_texture_array);
+   const GLboolean arrayTex = ctx->Extensions.EXT_texture_array;
 
    switch (target) {
       case GL_TEXTURE_1D:
@@ -796,7 +803,7 @@ _mesa_select_tex_object(struct gl_context *ctx,
                 ctx->Extensions.ARB_texture_buffer_object ?
                 texUnit->CurrentTex[TEXTURE_BUFFER_INDEX] : NULL;
       case GL_TEXTURE_EXTERNAL_OES:
-         return ctx->Extensions.OES_EGL_image_external
+         return _mesa_is_gles(ctx) && ctx->Extensions.OES_EGL_image_external
             ? texUnit->CurrentTex[TEXTURE_EXTERNAL_INDEX] : NULL;
       case GL_TEXTURE_2D_MULTISAMPLE:
          return ctx->Extensions.ARB_texture_multisample
@@ -868,7 +875,7 @@ _mesa_get_tex_image(struct gl_context *ctx, struct gl_texture_object *texObj,
 
    if (!texObj)
       return NULL;
-   
+
    texImage = _mesa_select_tex_image(ctx, texObj, target, level);
    if (!texImage) {
       texImage = ctx->Driver.NewTextureImage(ctx);
@@ -974,7 +981,7 @@ get_proxy_tex_image(struct gl_context *ctx, GLenum target, GLint level)
  *
  * \param ctx GL context.
  * \param target texture target.
- * 
+ *
  * \return the maximum number of allowed mipmap levels for the given
  * texture target, or zero if passed a bad target.
  *
@@ -1009,8 +1016,7 @@ _mesa_max_texture_levels(struct gl_context *ctx, GLenum target)
    case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
    case GL_TEXTURE_2D_ARRAY_EXT:
    case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
-      return (ctx->Extensions.MESA_texture_array ||
-              ctx->Extensions.EXT_texture_array)
+      return ctx->Extensions.EXT_texture_array
          ? ctx->Const.MaxTextureLevels : 0;
    case GL_TEXTURE_CUBE_MAP_ARRAY:
    case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
@@ -1095,24 +1101,33 @@ _mesa_get_tex_max_num_levels(GLenum target, GLsizei width, GLsizei height,
    switch (target) {
    case GL_TEXTURE_1D:
    case GL_TEXTURE_1D_ARRAY:
+   case GL_PROXY_TEXTURE_1D:
+   case GL_PROXY_TEXTURE_1D_ARRAY:
       size = width;
       break;
    case GL_TEXTURE_CUBE_MAP:
    case GL_TEXTURE_CUBE_MAP_ARRAY:
-      ASSERT(width == height);
+   case GL_PROXY_TEXTURE_CUBE_MAP:
+   case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
       size = width;
       break;
    case GL_TEXTURE_2D:
    case GL_TEXTURE_2D_ARRAY:
+   case GL_PROXY_TEXTURE_2D:
+   case GL_PROXY_TEXTURE_2D_ARRAY:
       size = MAX2(width, height);
       break;
    case GL_TEXTURE_3D:
+   case GL_PROXY_TEXTURE_3D:
       size = MAX3(width, height, depth);
       break;
    case GL_TEXTURE_RECTANGLE:
    case GL_TEXTURE_EXTERNAL_OES:
    case GL_TEXTURE_2D_MULTISAMPLE:
    case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
+   case GL_PROXY_TEXTURE_RECTANGLE:
+   case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
+   case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
       return 1;
    default:
       assert(0);
@@ -1428,6 +1443,8 @@ _mesa_legal_texture_dimensions(struct gl_context *ctx, GLenum target,
    case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
       maxSize = 1 << (ctx->Const.MaxCubeTextureLevels - 1);
       maxSize >>= level;
+      if (width != height)
+         return GL_FALSE;
       if (width < 2 * border || width > 2 * border + maxSize)
          return GL_FALSE;
       if (height < 2 * border || height > 2 * border + maxSize)
@@ -1481,7 +1498,9 @@ _mesa_legal_texture_dimensions(struct gl_context *ctx, GLenum target,
          return GL_FALSE;
       if (height < 2 * border || height > 2 * border + maxSize)
          return GL_FALSE;
-      if (depth < 1 || depth > ctx->Const.MaxArrayTextureLayers)
+      if (depth < 1 || depth > ctx->Const.MaxArrayTextureLayers || depth % 6)
+         return GL_FALSE;
+      if (width != height)
          return GL_FALSE;
       if (level >= ctx->Const.MaxCubeTextureLevels)
          return GL_FALSE;
@@ -1611,7 +1630,7 @@ error_check_subtexture_dimensions(struct gl_context *ctx,
          _mesa_error(ctx, GL_INVALID_OPERATION,
                      "%s%dD(height = %d)", function, dims, subHeight);
          return GL_TRUE;
-      }         
+      }
    }
 
    return GL_FALSE;
@@ -1704,14 +1723,13 @@ target_can_be_compressed(const struct gl_context *ctx, GLenum target,
       return ctx->Extensions.ARB_texture_cube_map;
    case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
    case GL_TEXTURE_2D_ARRAY_EXT:
-      return (ctx->Extensions.MESA_texture_array ||
-              ctx->Extensions.EXT_texture_array);
+      return ctx->Extensions.EXT_texture_array;
    case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
    case GL_TEXTURE_CUBE_MAP_ARRAY:
       return ctx->Extensions.ARB_texture_cube_map_array;
    default:
       return GL_FALSE;
-   }      
+   }
 }
 
 
@@ -1753,9 +1771,7 @@ legal_teximage_target(struct gl_context *ctx, GLuint dims, GLenum target)
             && ctx->Extensions.NV_texture_rectangle;
       case GL_TEXTURE_1D_ARRAY_EXT:
       case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
-         return _mesa_is_desktop_gl(ctx)
-            && (ctx->Extensions.MESA_texture_array ||
-                ctx->Extensions.EXT_texture_array);
+         return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array;
       default:
          return GL_FALSE;
       }
@@ -1766,14 +1782,10 @@ legal_teximage_target(struct gl_context *ctx, GLuint dims, GLenum target)
       case GL_PROXY_TEXTURE_3D:
          return _mesa_is_desktop_gl(ctx);
       case GL_TEXTURE_2D_ARRAY_EXT:
-         return (_mesa_is_desktop_gl(ctx)
-                 && (ctx->Extensions.MESA_texture_array ||
-                     ctx->Extensions.EXT_texture_array))
+         return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array)
             || _mesa_is_gles3(ctx);
       case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
-         return _mesa_is_desktop_gl(ctx)
-            && (ctx->Extensions.MESA_texture_array ||
-                ctx->Extensions.EXT_texture_array);
+         return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array;
       case GL_TEXTURE_CUBE_MAP_ARRAY:
       case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
          return ctx->Extensions.ARB_texture_cube_map_array;
@@ -1814,9 +1826,7 @@ legal_texsubimage_target(struct gl_context *ctx, GLuint dims, GLenum target)
          return _mesa_is_desktop_gl(ctx)
             && ctx->Extensions.NV_texture_rectangle;
       case GL_TEXTURE_1D_ARRAY_EXT:
-         return _mesa_is_desktop_gl(ctx)
-            && (ctx->Extensions.MESA_texture_array ||
-                ctx->Extensions.EXT_texture_array);
+         return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array;
       default:
          return GL_FALSE;
       }
@@ -1825,9 +1835,7 @@ legal_texsubimage_target(struct gl_context *ctx, GLuint dims, GLenum target)
       case GL_TEXTURE_3D:
          return GL_TRUE;
       case GL_TEXTURE_2D_ARRAY_EXT:
-         return (_mesa_is_desktop_gl(ctx)
-                 && (ctx->Extensions.MESA_texture_array ||
-                     ctx->Extensions.EXT_texture_array))
+         return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array)
             || _mesa_is_gles3(ctx);
       case GL_TEXTURE_CUBE_MAP_ARRAY:
       case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
@@ -1850,12 +1858,8 @@ legal_texsubimage_target(struct gl_context *ctx, GLuint dims, GLenum target)
 static GLboolean
 mutable_tex_object(struct gl_context *ctx, GLenum target)
 {
-   if (ctx->Extensions.ARB_texture_storage) {
-      struct gl_texture_object *texObj =
-         _mesa_get_current_tex_object(ctx, target);
-      return !texObj->Immutable;
-   }
-   return GL_TRUE;
+   struct gl_texture_object *texObj = _mesa_get_current_tex_object(ctx, target);
+   return !texObj->Immutable;
 }
 
 
@@ -1873,7 +1877,7 @@ compressed_tex_size(GLsizei width, GLsizei height, GLsizei depth,
 
 /**
  * Test the glTexImage[123]D() parameters for errors.
- * 
+ *
  * \param ctx GL context.
  * \param dimensions texture image dimensions (must be 1, 2 or 3).
  * \param target texture target given by the user (already validated).
@@ -1885,7 +1889,7 @@ compressed_tex_size(GLsizei width, GLsizei height, GLsizei depth,
  * \param height image height given by the user.
  * \param depth image depth given by the user.
  * \param border image border given by the user.
- * 
+ *
  * \return GL_TRUE if a error is found, GL_FALSE otherwise
  *
  * Verifies each of the parameters against the constants specified in
@@ -1955,12 +1959,12 @@ texture_error_check( struct gl_context *ctx,
                                                      internalFormat);
       } else {
          if (format != internalFormat) {
-         _mesa_error(ctx, GL_INVALID_OPERATION,
-                     "glTexImage%dD(format = %s, internalFormat = %s)",
-                     dimensions,
-                     _mesa_lookup_enum_by_nr(format),
-                     _mesa_lookup_enum_by_nr(internalFormat));
-         return GL_TRUE;
+            _mesa_error(ctx, GL_INVALID_OPERATION,
+                        "glTexImage%dD(format = %s, internalFormat = %s)",
+                        dimensions,
+                        _mesa_lookup_enum_by_nr(format),
+                        _mesa_lookup_enum_by_nr(internalFormat));
+            return GL_TRUE;
          }
 
          err = _mesa_es_error_check_format_and_type(format, type, dimensions);
@@ -1976,27 +1980,6 @@ texture_error_check( struct gl_context *ctx,
       }
    }
 
-   if ((target == GL_PROXY_TEXTURE_CUBE_MAP_ARB ||
-        _mesa_is_cube_face(target)) && width != height) {
-      _mesa_error(ctx, GL_INVALID_VALUE,
-                  "glTexImage2D(cube width != height)");
-      return GL_TRUE;
-   }
-
-   if ((target == GL_PROXY_TEXTURE_CUBE_MAP_ARRAY ||
-        target == GL_TEXTURE_CUBE_MAP_ARRAY) && width != height) {
-      _mesa_error(ctx, GL_INVALID_VALUE,
-                  "glTexImage3D(cube array width != height)");
-      return GL_TRUE;
-   }
-
-   if ((target == GL_PROXY_TEXTURE_CUBE_MAP_ARRAY ||
-        target == GL_TEXTURE_CUBE_MAP_ARRAY) && (depth % 6)) {
-      _mesa_error(ctx, GL_INVALID_VALUE,
-                  "glTexImage3D(cube array depth not multiple of 6)");
-      return GL_TRUE;
-   }
-
    /* Check internalFormat */
    if (_mesa_base_tex_format(ctx, internalFormat) < 0) {
       _mesa_error(ctx, GL_INVALID_VALUE,
@@ -2228,14 +2211,6 @@ compressed_texture_error_check(struct gl_context *ctx, GLint dimensions,
       goto error;
    }
 
-   /* For cube map, width must equal height */
-   if ((target == GL_PROXY_TEXTURE_CUBE_MAP_ARB ||
-        _mesa_is_cube_face(target)) && width != height) {
-      reason = "width != height";
-      error = GL_INVALID_VALUE;
-      goto error;
-   }
-
    /* check image size in bytes */
    if (expectedSize != imageSize) {
       /* Per GL_ARB_texture_compression:  GL_INVALID_VALUE is generated [...]
@@ -2264,7 +2239,7 @@ error:
 
 /**
  * Test glTexSubImage[123]D() parameters for errors.
- * 
+ *
  * \param ctx GL context.
  * \param dimensions texture image dimensions (must be 1, 2 or 3).
  * \param target texture target given by the user (already validated)
@@ -2277,7 +2252,7 @@ error:
  * \param width image width given by the user.
  * \param height image height given by the user.
  * \param depth image depth given by the user.
- * 
+ *
  * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
  *
  * Verifies each of the parameters against the constants specified in
@@ -2382,7 +2357,7 @@ texsubimage_error_check(struct gl_context *ctx, GLuint dimensions,
 
 /**
  * Test glCopyTexImage[12]D() parameters for errors.
- * 
+ *
  * \param ctx GL context.
  * \param dimensions texture image dimensions (must be 1, 2 or 3).
  * \param target texture target given by the user.
@@ -2391,9 +2366,9 @@ texsubimage_error_check(struct gl_context *ctx, GLuint dimensions,
  * \param width image width given by the user.
  * \param height image height given by the user.
  * \param border texture border.
- * 
+ *
  * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
- * 
+ *
  * Verifies each of the parameters against the constants specified in
  * __struct gl_contextRec::Const and the supported extensions, and according
  * to the OpenGL specification.
@@ -2413,7 +2388,7 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions,
       _mesa_error(ctx, GL_INVALID_ENUM, "glCopyTexImage%uD(target=%s)",
                   dimensions, _mesa_lookup_enum_by_nr(target));
       return GL_TRUE;
-   }       
+   }
 
    /* level check */
    if (level < 0 || level >= _mesa_max_texture_levels(ctx, target)) {
@@ -2581,13 +2556,6 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions,
       }
    }
 
-   if ((target == GL_PROXY_TEXTURE_CUBE_MAP_ARB ||
-        _mesa_is_cube_face(target)) && width != height) {
-      _mesa_error(ctx, GL_INVALID_VALUE,
-                  "glTexImage2D(cube width != height)");
-      return GL_TRUE;
-   }
-
    if (_mesa_is_compressed_format(ctx, internalFormat)) {
       if (!target_can_be_compressed(ctx, target, internalFormat)) {
          _mesa_error(ctx, GL_INVALID_ENUM,
@@ -2888,7 +2856,7 @@ _mesa_choose_texture_format(struct gl_context *ctx,
    }
 
    /* If the application requested compression to an S3TC format but we don't
-    * have the DTXn library, force a generic compressed format instead.
+    * have the DXTn library, force a generic compressed format instead.
     */
    if (internalFormat != format && format != GL_NONE) {
       const GLenum before = internalFormat;
@@ -2925,6 +2893,7 @@ _mesa_choose_texture_format(struct gl_context *ctx,
    return f;
 }
 
+
 /**
  * Adjust pixel unpack params and image dimensions to strip off the
  * one-pixel texture border.
@@ -2962,7 +2931,9 @@ strip_texture_border(GLenum target,
       *height = *height - 2;  /* reduce the height by two border pixels */
    }
 
-   if (*depth >= 3 && target != GL_TEXTURE_2D_ARRAY && target != GL_TEXTURE_CUBE_MAP_ARRAY) {
+   if (*depth >= 3 &&
+       target != GL_TEXTURE_2D_ARRAY &&
+       target != GL_TEXTURE_CUBE_MAP_ARRAY) {
       unpackNew->SkipImages++;  /* skip the border */
       *depth = *depth - 2;      /* reduce the depth by two border pixels */
    }
@@ -3161,7 +3132,7 @@ teximage(struct gl_context *ctx, GLboolean compressed, GLuint dims,
 
             _mesa_update_fbo_texture(ctx, texObj, face, level);
 
-            _mesa_dirty_texobj(ctx, texObj, GL_TRUE);
+            _mesa_dirty_texobj(ctx, texObj);
          }
       }
       _mesa_unlock_texture(ctx, texObj);
@@ -3238,7 +3209,8 @@ _mesa_EGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image)
       valid_target = ctx->Extensions.OES_EGL_image;
       break;
    case GL_TEXTURE_EXTERNAL_OES:
-      valid_target = ctx->Extensions.OES_EGL_image_external;
+      valid_target =
+         _mesa_is_gles(ctx) ? ctx->Extensions.OES_EGL_image_external : false;
       break;
    default:
       valid_target = false;
@@ -3279,7 +3251,7 @@ _mesa_EGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image)
       ctx->Driver.EGLImageTargetTexture2D(ctx, target,
                                          texObj, texImage, image);
 
-      _mesa_dirty_texobj(ctx, texObj, GL_TRUE);
+      _mesa_dirty_texobj(ctx, texObj);
    }
    _mesa_unlock_texture(ctx, texObj);
 
@@ -3314,7 +3286,7 @@ texsubimage(struct gl_context *ctx, GLuint dims, GLenum target, GLint level,
       _mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage%uD(target=%s)",
                   dims, _mesa_lookup_enum_by_nr(target));
       return;
-   }       
+   }
 
    if (ctx->NewState & _NEW_PIXEL)
       _mesa_update_state(ctx);
@@ -3423,6 +3395,35 @@ get_copy_tex_image_source(struct gl_context *ctx, gl_format texFormat)
    }
 }
 
+static void
+copytexsubimage_by_slice(struct gl_context *ctx,
+                         struct gl_texture_image *texImage,
+                         GLuint dims,
+                         GLint xoffset, GLint yoffset, GLint zoffset,
+                         struct gl_renderbuffer *rb,
+                         GLint x, GLint y,
+                         GLsizei width, GLsizei height)
+{
+   if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) {
+      int slice;
+
+      /* For 1D arrays, we copy each scanline of the source rectangle into the
+       * next array slice.
+       */
+      assert(zoffset == 0);
+
+      for (slice = 0; slice < height; slice++) {
+         assert(yoffset + slice < texImage->Height);
+         ctx->Driver.CopyTexSubImage(ctx, 2, texImage,
+                                     xoffset, 0, yoffset + slice,
+                                     rb, x, y + slice, width, 1);
+      }
+   } else {
+      ctx->Driver.CopyTexSubImage(ctx, dims, texImage,
+                                  xoffset, yoffset, zoffset,
+                                  rb, x, y, width, height);
+   }
+}
 
 
 /**
@@ -3511,8 +3512,9 @@ copyteximage(struct gl_context *ctx, GLuint dims,
                struct gl_renderbuffer *srcRb =
                   get_copy_tex_image_source(ctx, texImage->TexFormat);
 
-               ctx->Driver.CopyTexSubImage(ctx, dims, texImage, dstX, dstY, dstZ,
-                                           srcRb, srcX, srcY, width, height);
+               copytexsubimage_by_slice(ctx, texImage, dims,
+                                        dstX, dstY, dstZ,
+                                        srcRb, srcX, srcY, width, height);
             }
 
             check_gen_mipmap(ctx, target, texObj, level);
@@ -3520,7 +3522,7 @@ copyteximage(struct gl_context *ctx, GLuint dims,
 
          _mesa_update_fbo_texture(ctx, texObj, face, level);
 
-         _mesa_dirty_texobj(ctx, texObj, GL_TRUE);
+         _mesa_dirty_texobj(ctx, texObj);
       }
    }
    _mesa_unlock_texture(ctx, texObj);
@@ -3604,9 +3606,9 @@ copytexsubimage(struct gl_context *ctx, GLuint dims, GLenum target, GLint level,
          struct gl_renderbuffer *srcRb =
             get_copy_tex_image_source(ctx, texImage->TexFormat);
 
-         ctx->Driver.CopyTexSubImage(ctx, dims, texImage,
-                                     xoffset, yoffset, zoffset,
-                                     srcRb, x, y, width, height);
+         copytexsubimage_by_slice(ctx, texImage, dims,
+                                  xoffset, yoffset, zoffset,
+                                  srcRb, x, y, width, height);
 
          check_gen_mipmap(ctx, target, texObj, level);
 
@@ -3699,7 +3701,7 @@ compressed_subtexture_error_check(struct gl_context *ctx, GLint dims,
       targetOK = GL_FALSE;
       break;
    }
+
    if (!targetOK) {
       _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage%uD(target)",
                   dims);
@@ -3876,87 +3878,108 @@ _mesa_CompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset,
 static gl_format
 get_texbuffer_format(const struct gl_context *ctx, GLenum internalFormat)
 {
+   if (ctx->API != API_OPENGL_CORE) {
+      switch (internalFormat) {
+      case GL_ALPHA8:
+         return MESA_FORMAT_A8;
+      case GL_ALPHA16:
+         return MESA_FORMAT_A16;
+      case GL_ALPHA16F_ARB:
+         return MESA_FORMAT_ALPHA_FLOAT16;
+      case GL_ALPHA32F_ARB:
+         return MESA_FORMAT_ALPHA_FLOAT32;
+      case GL_ALPHA8I_EXT:
+         return MESA_FORMAT_ALPHA_INT8;
+      case GL_ALPHA16I_EXT:
+         return MESA_FORMAT_ALPHA_INT16;
+      case GL_ALPHA32I_EXT:
+         return MESA_FORMAT_ALPHA_INT32;
+      case GL_ALPHA8UI_EXT:
+         return MESA_FORMAT_ALPHA_UINT8;
+      case GL_ALPHA16UI_EXT:
+         return MESA_FORMAT_ALPHA_UINT16;
+      case GL_ALPHA32UI_EXT:
+         return MESA_FORMAT_ALPHA_UINT32;
+      case GL_LUMINANCE8:
+         return MESA_FORMAT_L8;
+      case GL_LUMINANCE16:
+         return MESA_FORMAT_L16;
+      case GL_LUMINANCE16F_ARB:
+         return MESA_FORMAT_LUMINANCE_FLOAT16;
+      case GL_LUMINANCE32F_ARB:
+         return MESA_FORMAT_LUMINANCE_FLOAT32;
+      case GL_LUMINANCE8I_EXT:
+         return MESA_FORMAT_LUMINANCE_INT8;
+      case GL_LUMINANCE16I_EXT:
+         return MESA_FORMAT_LUMINANCE_INT16;
+      case GL_LUMINANCE32I_EXT:
+         return MESA_FORMAT_LUMINANCE_INT32;
+      case GL_LUMINANCE8UI_EXT:
+         return MESA_FORMAT_LUMINANCE_UINT8;
+      case GL_LUMINANCE16UI_EXT:
+         return MESA_FORMAT_LUMINANCE_UINT16;
+      case GL_LUMINANCE32UI_EXT:
+         return MESA_FORMAT_LUMINANCE_UINT32;
+      case GL_LUMINANCE8_ALPHA8:
+         return MESA_FORMAT_AL88;
+      case GL_LUMINANCE16_ALPHA16:
+         return MESA_FORMAT_AL1616;
+      case GL_LUMINANCE_ALPHA16F_ARB:
+         return MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16;
+      case GL_LUMINANCE_ALPHA32F_ARB:
+         return MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32;
+      case GL_LUMINANCE_ALPHA8I_EXT:
+         return MESA_FORMAT_LUMINANCE_ALPHA_INT8;
+      case GL_LUMINANCE_ALPHA16I_EXT:
+         return MESA_FORMAT_LUMINANCE_ALPHA_INT8;
+      case GL_LUMINANCE_ALPHA32I_EXT:
+         return MESA_FORMAT_LUMINANCE_ALPHA_INT16;
+      case GL_LUMINANCE_ALPHA8UI_EXT:
+         return MESA_FORMAT_LUMINANCE_ALPHA_UINT8;
+      case GL_LUMINANCE_ALPHA16UI_EXT:
+         return MESA_FORMAT_LUMINANCE_ALPHA_UINT16;
+      case GL_LUMINANCE_ALPHA32UI_EXT:
+         return MESA_FORMAT_LUMINANCE_ALPHA_UINT32;
+      case GL_INTENSITY8:
+         return MESA_FORMAT_I8;
+      case GL_INTENSITY16:
+         return MESA_FORMAT_I16;
+      case GL_INTENSITY16F_ARB:
+         return MESA_FORMAT_INTENSITY_FLOAT16;
+      case GL_INTENSITY32F_ARB:
+         return MESA_FORMAT_INTENSITY_FLOAT32;
+      case GL_INTENSITY8I_EXT:
+         return MESA_FORMAT_INTENSITY_INT8;
+      case GL_INTENSITY16I_EXT:
+         return MESA_FORMAT_INTENSITY_INT16;
+      case GL_INTENSITY32I_EXT:
+         return MESA_FORMAT_INTENSITY_INT32;
+      case GL_INTENSITY8UI_EXT:
+         return MESA_FORMAT_INTENSITY_UINT8;
+      case GL_INTENSITY16UI_EXT:
+         return MESA_FORMAT_INTENSITY_UINT16;
+      case GL_INTENSITY32UI_EXT:
+         return MESA_FORMAT_INTENSITY_UINT32;
+      default:
+         break;
+      }
+   }
+
+   if (ctx->API == API_OPENGL_CORE &&
+       ctx->Extensions.ARB_texture_buffer_object_rgb32) {
+      switch (internalFormat) {
+      case GL_RGB32F:
+         return MESA_FORMAT_RGB_FLOAT32;
+      case GL_RGB32UI:
+         return MESA_FORMAT_RGB_UINT32;
+      case GL_RGB32I:
+         return MESA_FORMAT_RGB_INT32;
+      default:
+         break;
+      }
+   }
+
    switch (internalFormat) {
-   case GL_ALPHA8:
-      return MESA_FORMAT_A8;
-   case GL_ALPHA16:
-      return MESA_FORMAT_A16;
-   case GL_ALPHA16F_ARB:
-      return MESA_FORMAT_ALPHA_FLOAT16;
-   case GL_ALPHA32F_ARB:
-      return MESA_FORMAT_ALPHA_FLOAT32;
-   case GL_ALPHA8I_EXT:
-      return MESA_FORMAT_ALPHA_INT8;
-   case GL_ALPHA16I_EXT:
-      return MESA_FORMAT_ALPHA_INT16;
-   case GL_ALPHA32I_EXT:
-      return MESA_FORMAT_ALPHA_INT32;
-   case GL_ALPHA8UI_EXT:
-      return MESA_FORMAT_ALPHA_UINT8;
-   case GL_ALPHA16UI_EXT:
-      return MESA_FORMAT_ALPHA_UINT16;
-   case GL_ALPHA32UI_EXT:
-      return MESA_FORMAT_ALPHA_UINT32;
-   case GL_LUMINANCE8:
-      return MESA_FORMAT_L8;
-   case GL_LUMINANCE16:
-      return MESA_FORMAT_L16;
-   case GL_LUMINANCE16F_ARB:
-      return MESA_FORMAT_LUMINANCE_FLOAT16;
-   case GL_LUMINANCE32F_ARB:
-      return MESA_FORMAT_LUMINANCE_FLOAT32;
-   case GL_LUMINANCE8I_EXT:
-      return MESA_FORMAT_LUMINANCE_INT8;
-   case GL_LUMINANCE16I_EXT:
-      return MESA_FORMAT_LUMINANCE_INT16;
-   case GL_LUMINANCE32I_EXT:
-      return MESA_FORMAT_LUMINANCE_INT32;
-   case GL_LUMINANCE8UI_EXT:
-      return MESA_FORMAT_LUMINANCE_UINT8;
-   case GL_LUMINANCE16UI_EXT:
-      return MESA_FORMAT_LUMINANCE_UINT16;
-   case GL_LUMINANCE32UI_EXT:
-      return MESA_FORMAT_LUMINANCE_UINT32;
-   case GL_LUMINANCE8_ALPHA8:
-      return MESA_FORMAT_AL88;
-   case GL_LUMINANCE16_ALPHA16:
-      return MESA_FORMAT_AL1616;
-   case GL_LUMINANCE_ALPHA16F_ARB:
-      return MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16;
-   case GL_LUMINANCE_ALPHA32F_ARB:
-      return MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32;
-   case GL_LUMINANCE_ALPHA8I_EXT:
-      return MESA_FORMAT_LUMINANCE_ALPHA_INT8;
-   case GL_LUMINANCE_ALPHA16I_EXT:
-      return MESA_FORMAT_LUMINANCE_ALPHA_INT8;
-   case GL_LUMINANCE_ALPHA32I_EXT:
-      return MESA_FORMAT_LUMINANCE_ALPHA_INT16;
-   case GL_LUMINANCE_ALPHA8UI_EXT:
-      return MESA_FORMAT_LUMINANCE_ALPHA_UINT8;
-   case GL_LUMINANCE_ALPHA16UI_EXT:
-      return MESA_FORMAT_LUMINANCE_ALPHA_UINT16;
-   case GL_LUMINANCE_ALPHA32UI_EXT:
-      return MESA_FORMAT_LUMINANCE_ALPHA_UINT32;
-   case GL_INTENSITY8:
-      return MESA_FORMAT_I8;
-   case GL_INTENSITY16:
-      return MESA_FORMAT_I16;
-   case GL_INTENSITY16F_ARB:
-      return MESA_FORMAT_INTENSITY_FLOAT16;
-   case GL_INTENSITY32F_ARB:
-      return MESA_FORMAT_INTENSITY_FLOAT32;
-   case GL_INTENSITY8I_EXT:
-      return MESA_FORMAT_INTENSITY_INT8;
-   case GL_INTENSITY16I_EXT:
-      return MESA_FORMAT_INTENSITY_INT16;
-   case GL_INTENSITY32I_EXT:
-      return MESA_FORMAT_INTENSITY_INT32;
-   case GL_INTENSITY8UI_EXT:
-      return MESA_FORMAT_INTENSITY_UINT8;
-   case GL_INTENSITY16UI_EXT:
-      return MESA_FORMAT_INTENSITY_UINT16;
-   case GL_INTENSITY32UI_EXT:
-      return MESA_FORMAT_INTENSITY_UINT32;
    case GL_RGBA8:
       return MESA_FORMAT_RGBA8888_REV;
    case GL_RGBA16:
@@ -4020,20 +4043,15 @@ get_texbuffer_format(const struct gl_context *ctx, GLenum internalFormat)
    case GL_R32UI:
       return MESA_FORMAT_R_UINT32;
 
-   case GL_RGB32F:
-      return MESA_FORMAT_RGB_FLOAT32;
-   case GL_RGB32UI:
-      return MESA_FORMAT_RGB_UINT32;
-   case GL_RGB32I:
-      return MESA_FORMAT_RGB_INT32;
-
    default:
       return MESA_FORMAT_NONE;
    }
 }
 
-static gl_format
-validate_texbuffer_format(const struct gl_context *ctx, GLenum internalFormat)
+
+gl_format
+_mesa_validate_texbuffer_format(const struct gl_context *ctx,
+                                GLenum internalFormat)
 {
    gl_format format = get_texbuffer_format(ctx, internalFormat);
    GLenum datatype;
@@ -4048,15 +4066,10 @@ validate_texbuffer_format(const struct gl_context *ctx, GLenum internalFormat)
    if (datatype == GL_HALF_FLOAT && !ctx->Extensions.ARB_half_float_pixel)
       return MESA_FORMAT_NONE;
 
-   /* The GL_ARB_texture_rg and GL_ARB_texture_buffer_object specs don't make
-    * any mention of R/RG formats, but they appear in the GL 3.1 core
-    * specification.
-    */
-   if (ctx->Version <= 30) {
+   if (!ctx->Extensions.ARB_texture_rg) {
       GLenum base_format = _mesa_get_format_base_format(format);
-
       if (base_format == GL_R || base_format == GL_RG)
-        return MESA_FORMAT_NONE;
+         return MESA_FORMAT_NONE;
    }
 
    if (!ctx->Extensions.ARB_texture_buffer_object_rgb32) {
@@ -4083,7 +4096,7 @@ texbufferrange(struct gl_context *ctx, GLenum target, GLenum internalFormat,
       return;
    }
 
-   format = validate_texbuffer_format(ctx, internalFormat);
+   format = _mesa_validate_texbuffer_format(ctx, internalFormat);
    if (format == MESA_FORMAT_NONE) {
       _mesa_error(ctx, GL_INVALID_ENUM, "glTexBuffer(internalFormat 0x%x)",
                   internalFormat);
@@ -4103,6 +4116,7 @@ texbufferrange(struct gl_context *ctx, GLenum target, GLenum internalFormat,
    _mesa_unlock_texture(ctx, texObj);
 }
 
+
 /** GL_ARB_texture_buffer_object */
 void GLAPIENTRY
 _mesa_TexBuffer(GLenum target, GLenum internalFormat, GLuint buffer)
@@ -4129,6 +4143,7 @@ _mesa_TexBuffer(GLenum target, GLenum internalFormat, GLuint buffer)
    texbufferrange(ctx, target, internalFormat, bufObj, 0, buffer ? -1 : 0);
 }
 
+
 /** GL_ARB_texture_buffer_range */
 void GLAPIENTRY
 _mesa_TexBufferRange(GLenum target, GLenum internalFormat, GLuint buffer,
@@ -4169,6 +4184,7 @@ _mesa_TexBufferRange(GLenum target, GLenum internalFormat, GLuint buffer,
    texbufferrange(ctx, target, internalFormat, bufObj, offset, size);
 }
 
+
 static GLboolean
 is_renderable_texture_format(struct gl_context *ctx, GLenum internalformat)
 {
@@ -4179,6 +4195,7 @@ is_renderable_texture_format(struct gl_context *ctx, GLenum internalformat)
    return baseFormat != 0 && baseFormat != GL_STENCIL_INDEX;
 }
 
+
 /** GL_ARB_texture_multisample */
 static GLboolean
 check_multisample_target(GLuint dims, GLenum target)
@@ -4197,6 +4214,7 @@ check_multisample_target(GLuint dims, GLenum target)
    }
 }
 
+
 static void
 teximagemultisample(GLuint dims, GLenum target, GLsizei samples,
                     GLint internalformat, GLsizei width, GLsizei height,
@@ -4314,7 +4332,6 @@ teximagemultisample(GLuint dims, GLenum target, GLsizei samples,
       texImage->FixedSampleLocations = fixedsamplelocations;
 
       if (width > 0 && height > 0 && depth > 0) {
-
          if (!ctx->Driver.AllocTextureStorage(ctx, texObj, 1,
                   width, height, depth)) {
             /* tidy up the texture image state. strictly speaking,
@@ -4327,27 +4344,36 @@ teximagemultisample(GLuint dims, GLenum target, GLsizei samples,
       }
 
       texObj->Immutable = immutable;
+
+      if (immutable) {
+         _mesa_set_texture_view_state(ctx, texObj, target, 1);
+      }
+
       _mesa_update_fbo_texture(ctx, texObj, 0, 0);
    }
 }
 
+
 void GLAPIENTRY
 _mesa_TexImage2DMultisample(GLenum target, GLsizei samples,
-                            GLint internalformat, GLsizei width,
+                            GLenum internalformat, GLsizei width,
                             GLsizei height, GLboolean fixedsamplelocations)
 {
    teximagemultisample(2, target, samples, internalformat,
-         width, height, 1, fixedsamplelocations, GL_FALSE, "glTexImage2DMultisample");
+                       width, height, 1, fixedsamplelocations, GL_FALSE,
+                       "glTexImage2DMultisample");
 }
 
+
 void GLAPIENTRY
 _mesa_TexImage3DMultisample(GLenum target, GLsizei samples,
-                            GLint internalformat, GLsizei width,
+                            GLenum internalformat, GLsizei width,
                             GLsizei height, GLsizei depth,
                             GLboolean fixedsamplelocations)
 {
    teximagemultisample(3, target, samples, internalformat,
-         width, height, depth, fixedsamplelocations, GL_FALSE, "glTexImage3DMultisample");
+                       width, height, depth, fixedsamplelocations, GL_FALSE,
+                       "glTexImage3DMultisample");
 }
 
 
@@ -4357,9 +4383,11 @@ _mesa_TexStorage2DMultisample(GLenum target, GLsizei samples,
                               GLsizei height, GLboolean fixedsamplelocations)
 {
    teximagemultisample(2, target, samples, internalformat,
-         width, height, 1, fixedsamplelocations, GL_TRUE, "glTexStorage2DMultisample");
+                       width, height, 1, fixedsamplelocations, GL_TRUE,
+                       "glTexStorage2DMultisample");
 }
 
+
 void GLAPIENTRY
 _mesa_TexStorage3DMultisample(GLenum target, GLsizei samples,
                               GLenum internalformat, GLsizei width,
@@ -4367,5 +4395,6 @@ _mesa_TexStorage3DMultisample(GLenum target, GLsizei samples,
                               GLboolean fixedsamplelocations)
 {
    teximagemultisample(3, target, samples, internalformat,
-         width, height, depth, fixedsamplelocations, GL_TRUE, "glTexStorage3DMultisample");
+                       width, height, depth, fixedsamplelocations, GL_TRUE,
+                       "glTexStorage3DMultisample");
 }