}
+/**
+ * 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
*/
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);
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 {
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);
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 {
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);
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 {
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);
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);
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);
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);
}
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);
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);
}
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);
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);
}