[Mesa-dev] [PATCH] meta: rework dest image allocation in mipmap generation code
Brian Paul
brianp at vmware.com
Sat Dec 10 11:00:27 PST 2011
This fixes two things:
1. If the texture object was created with glTexStorage2D, the call
to _mesa_TexImage2D() would generate INVALID_OPERATION since the
texture is marked as immutable.
2. _mesa_TexImage2D() always frees any existing texture image memory
before allocating new memory. That's inefficient since the existing
image is usually the right size already.
---
src/mesa/drivers/common/meta.c | 114 +++++++++++++++++++++++++++------------
1 files changed, 79 insertions(+), 35 deletions(-)
diff --git a/src/mesa/drivers/common/meta.c b/src/mesa/drivers/common/meta.c
index 259041f..3ec8828 100644
--- a/src/mesa/drivers/common/meta.c
+++ b/src/mesa/drivers/common/meta.c
@@ -2789,6 +2789,75 @@ setup_texture_coords(GLenum faceTarget,
/**
+ * Helper function for mipmap generation.
+ * Make sure the specified destination mipmap level is the right size/format
+ * for mipmap generation. If not, (re) allocate it.
+ * \return GL_TRUE if successful, GL_FALSE if mipmap generation should stop
+ */
+static GLboolean
+prepare_dest_image(struct gl_context *ctx,
+ struct gl_texture_object *texObj, GLuint level,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLsizei border, GLenum intFormat, gl_format format)
+{
+ const GLuint numFaces = texObj->Target == GL_TEXTURE_CUBE_MAP ? 6 : 1;
+ GLuint face;
+
+ if (texObj->Immutable) {
+ /* The texture was created with glTexStorage() so the number/size of
+ * mipmap levels is fixed and the storage for all images is already
+ * allocated.
+ */
+ if (!texObj->Image[0][level]) {
+ /* No more levels to create - we're done */
+ return GL_FALSE;
+ }
+ else {
+ /* Nothing to do - the texture memory must have already been
+ * allocated to the right size so we're all set.
+ */
+ return GL_TRUE;
+ }
+ }
+
+ for (face = 0; face < numFaces; face++) {
+ struct gl_texture_image *dstImage;
+ GLenum target;
+
+ if (numFaces == 1)
+ target = texObj->Target;
+ else
+ target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;
+
+ dstImage = _mesa_get_tex_image(ctx, texObj, target, level);
+ if (!dstImage) {
+ /* out of memory */
+ return GL_FALSE;
+ }
+
+ if (dstImage->Width != width ||
+ dstImage->Height != height ||
+ dstImage->Depth != depth ||
+ dstImage->Border != border ||
+ dstImage->InternalFormat != intFormat ||
+ dstImage->TexFormat != format) {
+ /* need to (re)allocate image */
+ ctx->Driver.FreeTextureImageBuffer(ctx, dstImage);
+
+ _mesa_init_teximage_fields(ctx, target, dstImage,
+ width, height, depth,
+ border, intFormat, format);
+
+ ctx->Driver.AllocTextureImageBuffer(ctx, dstImage,
+ format, width, height, depth);
+ }
+ }
+
+ return GL_TRUE;
+}
+
+
+/**
* Called via ctx->Driver.GenerateMipmap()
* Note: We don't yet support 3D textures, 1D/2D array textures or texture
* borders.
@@ -2943,43 +3012,18 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target,
break;
}
- /* Set MaxLevel large enough to hold the new level when we allocate it */
+ /* Allocate storage for the destination mipmap image(s) */
+
+ /* Set MaxLevel large enough to hold the new level when we allocate it */
_mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, dstLevel);
- /* Create empty dest image */
- if (target == GL_TEXTURE_1D) {
- _mesa_TexImage1D(target, dstLevel, srcImage->InternalFormat,
- dstWidth, border,
- GL_RGBA, GL_UNSIGNED_BYTE, NULL);
- }
- else if (target == GL_TEXTURE_3D) {
- _mesa_TexImage3D(target, dstLevel, srcImage->InternalFormat,
- dstWidth, dstHeight, dstDepth, border,
- GL_RGBA, GL_UNSIGNED_BYTE, NULL);
- }
- else {
- /* 2D or cube */
- _mesa_TexImage2D(faceTarget, dstLevel, srcImage->InternalFormat,
- dstWidth, dstHeight, border,
- GL_RGBA, GL_UNSIGNED_BYTE, NULL);
-
- if (target == GL_TEXTURE_CUBE_MAP) {
- /* If texturing from a cube, we need to make sure all src faces
- * have been defined (even if we're not sampling from them.)
- * Otherwise the texture object will be 'incomplete' and
- * texturing from it will not be allowed.
- */
- GLuint face;
- for (face = 0; face < 6; face++) {
- if (!texObj->Image[face][srcLevel] ||
- texObj->Image[face][srcLevel]->Width != srcWidth) {
- _mesa_TexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face,
- srcLevel, srcImage->InternalFormat,
- srcWidth, srcHeight, border,
- GL_RGBA, GL_UNSIGNED_BYTE, NULL);
- }
- }
- }
+ if (!prepare_dest_image(ctx, texObj, dstLevel,
+ dstWidth, dstHeight, dstDepth, srcImage->Border,
+ srcImage->InternalFormat, srcImage->TexFormat)) {
+ /* All done. We either ran out of memory or we would go beyond the
+ * last valid level of an immutable texture if we continued.
+ */
+ break;
}
/* limit minification to src level */
--
1.7.3.4
More information about the mesa-dev
mailing list