summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/mesa/main/config.h17
-rw-r--r--src/mesa/main/context.c1
-rw-r--r--src/mesa/main/mtypes.h1
-rw-r--r--src/mesa/main/teximage.c308
4 files changed, 213 insertions, 114 deletions
diff --git a/src/mesa/main/config.h b/src/mesa/main/config.h
index 0f2d1a8f8da..ff77bd0dfe3 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 e2c91c3e400..f42a566c302 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 82495714f21..1c549a8e247 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -2567,6 +2567,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 060f34b7f97..8c5bc775a0a 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);
}