diff --git a/src/mesa/main/config.h b/src/mesa/main/config.h
index 0f2d1a8..ff77bd0 100644
--- a/src/mesa/main/config.h
+++ b/src/mesa/main/config.h
@@ -97,17 +97,20 @@
 /** Max texture palette / color table size */
 #define MAX_COLOR_TABLE_SIZE 256
 
+/** Max memory to allow for a single texture image (in megabytes) */
+#define MAX_TEXTURE_MBYTES 1024
+
 /** Number of 1D/2D texture mipmap levels */
-#define MAX_TEXTURE_LEVELS 13
+#define MAX_TEXTURE_LEVELS 15
 
 /** Number of 3D texture mipmap levels */
-#define MAX_3D_TEXTURE_LEVELS 9
+#define MAX_3D_TEXTURE_LEVELS 15
 
 /** Number of cube texture mipmap levels - GL_ARB_texture_cube_map */
-#define MAX_CUBE_TEXTURE_LEVELS 13
+#define MAX_CUBE_TEXTURE_LEVELS 15
 
 /** Maximum rectangular texture size - GL_NV_texture_rectangle */
-#define MAX_TEXTURE_RECT_SIZE 4096
+#define MAX_TEXTURE_RECT_SIZE 16384
 
 /** Maximum number of layers in a 1D or 2D array texture - GL_MESA_texture_array */
 #define MAX_ARRAY_TEXTURE_LAYERS 64
@@ -140,11 +143,11 @@
  */
 
 #ifndef MAX_WIDTH
-#   define MAX_WIDTH 4096
+#   define MAX_WIDTH 16384
 #endif
 /** Maximum viewport/image height */
 #ifndef MAX_HEIGHT
-#   define MAX_HEIGHT 4096
+#   define MAX_HEIGHT 16384
 #endif
 
 /** Maxmimum size for CVA.  May be overridden by the drivers.  */
@@ -168,7 +171,7 @@
 #define MAX_TEXTURE_MAX_ANISOTROPY 16.0
 
 /** For GL_EXT_texture_lod_bias (typically MAX_TEXTURE_LEVELS - 1) */
-#define MAX_TEXTURE_LOD_BIAS 12.0
+#define MAX_TEXTURE_LOD_BIAS 14.0
 
 /** For any program target/extension */
 /*@{*/
diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c
index e2c91c3..f42a566 100644
--- a/src/mesa/main/context.c
+++ b/src/mesa/main/context.c
@@ -535,6 +535,7 @@ _mesa_init_constants(struct gl_context *ctx)
    assert(ctx);
 
    /* Constants, may be overriden (usually only reduced) by device drivers */
+   ctx->Const.MaxTextureMbytes = MAX_TEXTURE_MBYTES;
    ctx->Const.MaxTextureLevels = MAX_TEXTURE_LEVELS;
    ctx->Const.Max3DTextureLevels = MAX_3D_TEXTURE_LEVELS;
    ctx->Const.MaxCubeTextureLevels = MAX_CUBE_TEXTURE_LEVELS;
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 80c20e0..e95c56f 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -2566,6 +2566,7 @@ struct gl_program_constants
  */
 struct gl_constants
 {
+   GLint MaxTextureMbytes;      /**< Max memory per image, in MB */
    GLint MaxTextureLevels;      /**< Max mipmap levels. */ 
    GLint Max3DTextureLevels;    /**< Max mipmap levels for 3D textures */
    GLint MaxCubeTextureLevels;  /**< Max mipmap levels for cube textures */
diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c
index 060f34b..8c5bc77 100644
--- a/src/mesa/main/teximage.c
+++ b/src/mesa/main/teximage.c
@@ -1274,6 +1274,24 @@ _mesa_test_proxy_teximage(struct gl_context *ctx, GLenum target, GLint level,
 
 
 /**
+ * Check if the memory used by the texture would exceed the driver's limit.
+ * This lets us support a max 3D texture size of 8K (for example) but
+ * prevents allocating a full 8K x 8K x 8K texture.
+ * XXX this could be rolled into the proxy texture size test (above) but
+ * we don't have the actual texture internal format at that point.
+ */
+static GLboolean
+legal_texture_size(struct gl_context *ctx, gl_format format,
+                   GLint width, GLint height, GLint depth)
+{
+   uint64_t bytes = _mesa_format_image_size64(format, width, height, depth);
+   uint64_t mbytes = bytes / (1024 * 1024); /* convert to MB */
+   return mbytes <= (uint64_t) ctx->Const.MaxTextureMbytes;
+}
+
+
+
+/**
  * Helper function to determine whether a target supports compressed textures
  */
 static GLboolean
@@ -2392,24 +2410,29 @@ _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
                                                     internalFormat, format,
                                                     type);
 
-            _mesa_init_teximage_fields(ctx, target, texImage,
-                                       width, 1, 1,
-                                       border, internalFormat,
-                                       texFormat);
+            if (legal_texture_size(ctx, texFormat, width, 1, 1)) {
+               _mesa_init_teximage_fields(ctx, target, texImage,
+                                          width, 1, 1,
+                                          border, internalFormat,
+                                          texFormat);
 
-            /* Give the texture to the driver.  <pixels> may be null. */
-            ASSERT(ctx->Driver.TexImage1D);
-            ctx->Driver.TexImage1D(ctx, target, level, internalFormat,
-                                   width, border, format, type, pixels,
-                                   &ctx->Unpack, texObj, texImage);
+               /* Give the texture to the driver.  <pixels> may be null. */
+               ASSERT(ctx->Driver.TexImage1D);
+               ctx->Driver.TexImage1D(ctx, target, level, internalFormat,
+                                      width, border, format, type, pixels,
+                                      &ctx->Unpack, texObj, texImage);
 
-            check_gen_mipmap(ctx, target, texObj, level);
+               check_gen_mipmap(ctx, target, texObj, level);
 
-            update_fbo_texture(ctx, texObj, face, level);
+               update_fbo_texture(ctx, texObj, face, level);
 
-            /* state update */
-            texObj->_Complete = GL_FALSE;
-            ctx->NewState |= _NEW_TEXTURE;
+               /* state update */
+               texObj->_Complete = GL_FALSE;
+               ctx->NewState |= _NEW_TEXTURE;
+            }
+            else {
+               _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
+            }
          }
       }
       _mesa_unlock_texture(ctx, texObj);
@@ -2432,8 +2455,13 @@ _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
                                                            level,
                                                            internalFormat,
                                                            format, type);
-         _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
-                                    border, internalFormat, texFormat);
+         if (legal_texture_size(ctx, texFormat, width, 1, 1)) {
+            _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
+                                       border, internalFormat, texFormat);
+         }
+         else if (texImage) {
+            clear_teximage_fields(texImage);
+         }
       }
    }
    else {
@@ -2502,22 +2530,28 @@ _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
                                                     internalFormat, format,
                                                     type);
 
-            _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
-                                       border, internalFormat, texFormat);
+            if (legal_texture_size(ctx, texFormat, width, height, 1)) {
+               _mesa_init_teximage_fields(ctx, target, texImage, width,
+                                          height, 1, border, internalFormat,
+                                          texFormat);
 
-            /* Give the texture to the driver.  <pixels> may be null. */
-            ASSERT(ctx->Driver.TexImage2D);
-            ctx->Driver.TexImage2D(ctx, target, level, internalFormat,
-                                   width, height, border, format, type,
-                                   pixels, &ctx->Unpack, texObj, texImage);
+               /* Give the texture to the driver.  <pixels> may be null. */
+               ASSERT(ctx->Driver.TexImage2D);
+               ctx->Driver.TexImage2D(ctx, target, level, internalFormat,
+                                      width, height, border, format, type,
+                                      pixels, &ctx->Unpack, texObj, texImage);
 
-            check_gen_mipmap(ctx, target, texObj, level);
+               check_gen_mipmap(ctx, target, texObj, level);
 
-            update_fbo_texture(ctx, texObj, face, level);
+               update_fbo_texture(ctx, texObj, face, level);
 
-            /* state update */
-            texObj->_Complete = GL_FALSE;
-            ctx->NewState |= _NEW_TEXTURE;
+               /* state update */
+               texObj->_Complete = GL_FALSE;
+               ctx->NewState |= _NEW_TEXTURE;
+            }
+            else {
+               _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
+            }
          }
       }
       _mesa_unlock_texture(ctx, texObj);
@@ -2546,8 +2580,13 @@ _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
                                                            target, level,
                                                            internalFormat,
                                                            format, type);
-         _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
-                                    border, internalFormat, texFormat);
+         if (legal_texture_size(ctx, texFormat, width, 1, 1)) {
+            _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
+                                       border, internalFormat, texFormat);
+         }
+         else if (texImage) {
+            clear_teximage_fields(texImage);
+         }
       }
    }
    else {
@@ -2613,23 +2652,30 @@ _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
             texFormat = _mesa_choose_texture_format(ctx, texObj, target, level,
                                                     internalFormat, format,
                                                     type);
-            _mesa_init_teximage_fields(ctx, target, texImage,
-                                       width, height, depth,
-                                       border, internalFormat, texFormat);
 
-            /* Give the texture to the driver.  <pixels> may be null. */
-            ASSERT(ctx->Driver.TexImage3D);
-            ctx->Driver.TexImage3D(ctx, target, level, internalFormat,
-                                   width, height, depth, border, format, type,
-                                   pixels, &ctx->Unpack, texObj, texImage);
+            if (legal_texture_size(ctx, texFormat, width, height, depth)) {
+               _mesa_init_teximage_fields(ctx, target, texImage,
+                                          width, height, depth,
+                                          border, internalFormat, texFormat);
 
-            check_gen_mipmap(ctx, target, texObj, level);
+               /* Give the texture to the driver.  <pixels> may be null. */
+               ASSERT(ctx->Driver.TexImage3D);
+               ctx->Driver.TexImage3D(ctx, target, level, internalFormat,
+                                      width, height, depth, border, format,
+                                      type, pixels, &ctx->Unpack, texObj,
+                                      texImage);
 
-            update_fbo_texture(ctx, texObj, face, level);
+               check_gen_mipmap(ctx, target, texObj, level);
 
-            /* state update */
-            texObj->_Complete = GL_FALSE;
-            ctx->NewState |= _NEW_TEXTURE;
+               update_fbo_texture(ctx, texObj, face, level);
+
+               /* state update */
+               texObj->_Complete = GL_FALSE;
+               ctx->NewState |= _NEW_TEXTURE;
+            }
+            else {
+               _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
+            }
          }
       }
       _mesa_unlock_texture(ctx, texObj);
@@ -2654,8 +2700,14 @@ _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
                                                            target, level,
                                                            internalFormat,
                                                            format, type);
-         _mesa_init_teximage_fields(ctx, target, texImage, width, height,
-                                    depth, border, internalFormat, texFormat);
+         if (legal_texture_size(ctx, texFormat, width, height, depth)) {
+            _mesa_init_teximage_fields(ctx, target, texImage, width, height,
+                                       depth, border, internalFormat,
+                                       texFormat);
+         }
+         else if (texImage) {
+            clear_teximage_fields(texImage);
+         }
       }
    }
    else {
@@ -2944,20 +2996,25 @@ _mesa_CopyTexImage1D( GLenum target, GLint level,
                                                  internalFormat, GL_NONE,
                                                  GL_NONE);
 
-         _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
-                                    border, internalFormat, texFormat);
+         if (legal_texture_size(ctx, texFormat, width, 1, 1)) {
+            _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
+                                       border, internalFormat, texFormat);
 
-         ASSERT(ctx->Driver.CopyTexImage1D);
-         ctx->Driver.CopyTexImage1D(ctx, target, level, internalFormat,
-                                    x, y, width, border);
+            ASSERT(ctx->Driver.CopyTexImage1D);
+            ctx->Driver.CopyTexImage1D(ctx, target, level, internalFormat,
+                                       x, y, width, border);
 
-         check_gen_mipmap(ctx, target, texObj, level);
+            check_gen_mipmap(ctx, target, texObj, level);
 
-         update_fbo_texture(ctx, texObj, face, level);
+            update_fbo_texture(ctx, texObj, face, level);
 
-         /* state update */
-         texObj->_Complete = GL_FALSE;
-         ctx->NewState |= _NEW_TEXTURE;
+            /* state update */
+            texObj->_Complete = GL_FALSE;
+            ctx->NewState |= _NEW_TEXTURE;
+         }
+         else {
+            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
+         }
       }
    }
    _mesa_unlock_texture(ctx, texObj);
@@ -3011,20 +3068,25 @@ _mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
                                                  internalFormat, GL_NONE,
                                                  GL_NONE);
 
-         _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
-                                    border, internalFormat, texFormat);
+         if (legal_texture_size(ctx, texFormat, width, height, 1)) {
+            _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
+                                       border, internalFormat, texFormat);
 
-         ASSERT(ctx->Driver.CopyTexImage2D);
-         ctx->Driver.CopyTexImage2D(ctx, target, level, internalFormat,
-                                    x, y, width, height, border);
+            ASSERT(ctx->Driver.CopyTexImage2D);
+            ctx->Driver.CopyTexImage2D(ctx, target, level, internalFormat,
+                                       x, y, width, height, border);
 
-         check_gen_mipmap(ctx, target, texObj, level);
+            check_gen_mipmap(ctx, target, texObj, level);
 
-         update_fbo_texture(ctx, texObj, face, level);
+            update_fbo_texture(ctx, texObj, face, level);
 
-         /* state update */
-         texObj->_Complete = GL_FALSE;
-         ctx->NewState |= _NEW_TEXTURE;
+            /* state update */
+            texObj->_Complete = GL_FALSE;
+            ctx->NewState |= _NEW_TEXTURE;
+         }
+         else {
+            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
+         }
       }
    }
    _mesa_unlock_texture(ctx, texObj);
@@ -3510,20 +3572,25 @@ _mesa_CompressedTexImage1DARB(GLenum target, GLint level,
                                                     internalFormat, GL_NONE,
                                                     GL_NONE);
 
-            _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
-                                       border, internalFormat, texFormat);
+            if (legal_texture_size(ctx, texFormat, width, 1, 1)) {
+               _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
+                                          border, internalFormat, texFormat);
 
-            ASSERT(ctx->Driver.CompressedTexImage1D);
-            ctx->Driver.CompressedTexImage1D(ctx, target, level,
-                                             internalFormat, width, border,
-                                             imageSize, data,
-                                             texObj, texImage);
+               ASSERT(ctx->Driver.CompressedTexImage1D);
+               ctx->Driver.CompressedTexImage1D(ctx, target, level,
+                                                internalFormat, width, border,
+                                                imageSize, data,
+                                                texObj, texImage);
 
-            check_gen_mipmap(ctx, target, texObj, level);
+               check_gen_mipmap(ctx, target, texObj, level);
 
-            /* state update */
-            texObj->_Complete = GL_FALSE;
-            ctx->NewState |= _NEW_TEXTURE;
+               /* state update */
+               texObj->_Complete = GL_FALSE;
+               ctx->NewState |= _NEW_TEXTURE;
+            }
+            else {
+               _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1D");
+            }
          }
       }
       _mesa_unlock_texture(ctx, texObj);
@@ -3559,8 +3626,13 @@ _mesa_CompressedTexImage1DARB(GLenum target, GLint level,
             texFormat = _mesa_choose_texture_format(ctx, texObj, target, level,
                                                     internalFormat, GL_NONE,
                                                     GL_NONE);
-	    _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
-				       border, internalFormat, texFormat);
+            if (legal_texture_size(ctx, texFormat, width, 1, 1)) {
+               _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
+                                          border, internalFormat, texFormat);
+            }
+            else if (texImage) {
+               clear_teximage_fields(texImage);
+            }
 	 }
 	 _mesa_unlock_texture(ctx, texObj);
       }
@@ -3639,20 +3711,26 @@ _mesa_CompressedTexImage2DARB(GLenum target, GLint level,
                                                     internalFormat, GL_NONE,
                                                     GL_NONE);
 
-            _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
-                                       border, internalFormat, texFormat);
+            if (legal_texture_size(ctx, texFormat, width, 1, 1)) {
+               _mesa_init_teximage_fields(ctx, target, texImage, width,
+                                          height, 1, border, internalFormat,
+                                          texFormat);
 
-            ASSERT(ctx->Driver.CompressedTexImage2D);
-            ctx->Driver.CompressedTexImage2D(ctx, target, level,
-                                             internalFormat, width, height,
-                                             border, imageSize, data,
-                                             texObj, texImage);
+               ASSERT(ctx->Driver.CompressedTexImage2D);
+               ctx->Driver.CompressedTexImage2D(ctx, target, level,
+                                                internalFormat, width, height,
+                                                border, imageSize, data,
+                                                texObj, texImage);
 
-            check_gen_mipmap(ctx, target, texObj, level);
+               check_gen_mipmap(ctx, target, texObj, level);
 
-            /* state update */
-            texObj->_Complete = GL_FALSE;
-            ctx->NewState |= _NEW_TEXTURE;
+               /* state update */
+               texObj->_Complete = GL_FALSE;
+               ctx->NewState |= _NEW_TEXTURE;
+            }
+            else {
+               _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
+            }
          }
       }
       _mesa_unlock_texture(ctx, texObj);
@@ -3690,8 +3768,14 @@ _mesa_CompressedTexImage2DARB(GLenum target, GLint level,
             texFormat = _mesa_choose_texture_format(ctx, texObj, target, level,
                                                     internalFormat, GL_NONE,
                                                     GL_NONE);
-	    _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
-				       border, internalFormat, texFormat);
+            if (legal_texture_size(ctx, texFormat, width, height, 1)) {
+               _mesa_init_teximage_fields(ctx, target, texImage, width,
+                                          height, 1, border, internalFormat,
+                                          texFormat);
+            }
+            else {
+               _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
+            }
 	 }
 	 _mesa_unlock_texture(ctx, texObj);
       }
@@ -3749,22 +3833,27 @@ _mesa_CompressedTexImage3DARB(GLenum target, GLint level,
                                                     internalFormat, GL_NONE,
                                                     GL_NONE);
 
-            _mesa_init_teximage_fields(ctx, target, texImage,
-                                       width, height, depth,
-                                       border, internalFormat, texFormat);
+            if (legal_texture_size(ctx, texFormat, width, height, depth)) {
+               _mesa_init_teximage_fields(ctx, target, texImage,
+                                          width, height, depth,
+                                          border, internalFormat, texFormat);
 
-            ASSERT(ctx->Driver.CompressedTexImage3D);
-            ctx->Driver.CompressedTexImage3D(ctx, target, level,
-                                             internalFormat,
-                                             width, height, depth,
-                                             border, imageSize, data,
-                                             texObj, texImage);
+               ASSERT(ctx->Driver.CompressedTexImage3D);
+               ctx->Driver.CompressedTexImage3D(ctx, target, level,
+                                                internalFormat,
+                                                width, height, depth,
+                                                border, imageSize, data,
+                                                texObj, texImage);
 
-            check_gen_mipmap(ctx, target, texObj, level);
+               check_gen_mipmap(ctx, target, texObj, level);
 
-            /* state update */
-            texObj->_Complete = GL_FALSE;
-            ctx->NewState |= _NEW_TEXTURE;
+               /* state update */
+               texObj->_Complete = GL_FALSE;
+               ctx->NewState |= _NEW_TEXTURE;
+            }
+            else {
+               _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3D");
+            }
          }
       }
       _mesa_unlock_texture(ctx, texObj);
@@ -3800,9 +3889,14 @@ _mesa_CompressedTexImage3DARB(GLenum target, GLint level,
             texFormat = _mesa_choose_texture_format(ctx, texObj, target, level,
                                                     internalFormat, GL_NONE,
                                                     GL_NONE);
-	    _mesa_init_teximage_fields(ctx, target, texImage, width, height,
-				       depth, border, internalFormat,
-                                       texFormat);
+            if (legal_texture_size(ctx, texFormat, width, height, depth)) {
+               _mesa_init_teximage_fields(ctx, target, texImage, width, height,
+                                          depth, border, internalFormat,
+                                          texFormat);
+            }
+            else if (texImage) {
+               clear_teximage_fields(texImage);
+            }
 	 }
 	 _mesa_unlock_texture(ctx, texObj);
       }