diff options
-rw-r--r-- | src/mesa/main/config.h | 17 | ||||
-rw-r--r-- | src/mesa/main/context.c | 1 | ||||
-rw-r--r-- | src/mesa/main/mtypes.h | 1 | ||||
-rw-r--r-- | src/mesa/main/teximage.c | 308 |
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); } |