st/mesa: fix texture deallocation bug
authorBrian Paul <brianp@vmware.com>
Tue, 2 Feb 2010 02:04:16 +0000 (19:04 -0700)
committerBrian Paul <brianp@vmware.com>
Tue, 2 Feb 2010 02:04:16 +0000 (19:04 -0700)
This fixes a bug reported by Christoph Bumiller on mesa3d-dev.

When a texture is first created as RGBA, then re-defined with
glTexImage(internalFormat=GL_DEPTH_COMPONENT) we failed to deallocate
the original texture.  When this texture was bound as a FBO surface,
the depth/Z surface format was RGBA instead of Z.  Depending on the
driver this led to a failed assertion or FBO validation failure.

This patch does three things:

1. Remove ancient code that mysteriously tested if we were replacing
the smallest mipmap level and tested if the texture was not a cube map
texture.  I can't see any reason for those tests.

2. Move the width=height=depth=0 test to after the code which frees
texture data.  Calling glTexImage with width=height=depth=0 and data=NULL
is a way to free a single mipmap level.

3. Update the code comments.

There are no apparent conform, glean or piglit regressions from this change.

(cherry picked from commit 43e4b584227534e30e487e7fb7e99d6501cbcd85)

src/mesa/state_tracker/st_cb_texture.c

index cee2452eafee47e5164b610b5f34d00eae05dd76..0a7b222e85eecc24aca21e90e54bd801779e20cc 100644 (file)
@@ -543,22 +543,15 @@ st_TexImage(GLcontext * ctx,
       _mesa_align_free(texImage->Data);
    }
 
-   if (width == 0 || height == 0 || depth == 0) {
-      /* stop after freeing old image */
-      return;
-   }
-
-   /* If this is the only mipmap level in the texture, could call
-    * bmBufferData with NULL data to free the old block and avoid
-    * waiting on any outstanding fences.
+   /*
+    * See if the new image is somehow incompatible with the existing
+    * mipmap.  If so, free the old mipmap.
     */
    if (stObj->pt) {
       if (stObj->teximage_realloc ||
           level > (GLint) stObj->pt->last_level ||
-          (stObj->pt->last_level == level &&
-           stObj->pt->target != PIPE_TEXTURE_CUBE &&
-           !st_texture_match_image(stObj->pt, &stImage->base,
-                                   stImage->face, stImage->level))) {
+          !st_texture_match_image(stObj->pt, &stImage->base,
+                                  stImage->face, stImage->level)) {
          DBG("release it\n");
          pipe_texture_reference(&stObj->pt, NULL);
          assert(!stObj->pt);
@@ -566,6 +559,11 @@ st_TexImage(GLcontext * ctx,
       }
    }
 
+   if (width == 0 || height == 0 || depth == 0) {
+      /* stop after freeing old image */
+      return;
+   }
+
    if (!stObj->pt) {
       guess_and_alloc_texture(ctx->st, stObj, stImage);
       if (!stObj->pt) {