summaryrefslogtreecommitdiffstats
path: root/src/mesa/main/teximage.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/main/teximage.c')
-rw-r--r--src/mesa/main/teximage.c308
1 files changed, 201 insertions, 107 deletions
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);
}