Repeatedly deleting a texture ID with glDeleteTextures() could lead to a crash.
authorBrian Paul <brian.paul@tungstengraphics.com>
Tue, 14 Sep 2004 20:40:55 +0000 (20:40 +0000)
committerBrian Paul <brian.paul@tungstengraphics.com>
Tue, 14 Sep 2004 20:40:55 +0000 (20:40 +0000)
Added a DeletePending flag to texture object struct to fix that.
Other misc clean-ups.

src/mesa/main/mtypes.h
src/mesa/main/texobj.c

index ba32faad7037bdf82d9ac506e90df399e1d57bb3..3e5c04415d2b4bafec1787b35e75e8bdadf3c856 100644 (file)
@@ -1147,6 +1147,7 @@ struct gl_texture_image {
 struct gl_texture_object {
    _glthread_Mutex Mutex;      /**< for thread safety */
    GLint RefCount;             /**< reference count */
+   GLboolean DeletePending;    /**< Has glDeleteTexture been called? */
    GLuint Name;                        /**< an unsigned integer */
    GLenum Target;               /**< GL_TEXTURE_1D, GL_TEXTURE_2D, etc. */
    GLfloat Priority;           /**< in [0,1] */
index 74a5fdc06e9f91615e022eb25ac353ec24f20336..5e02f3b04ca9bb7a92328e5a1a8dfa346175c08b 100644 (file)
@@ -5,7 +5,7 @@
 
 /*
  * Mesa 3-D graphics library
- * Version:  6.1
+ * Version:  6.2
  *
  * Copyright (C) 1999-2004  Brian Paul   All Rights Reserved.
  *
@@ -72,7 +72,7 @@ _mesa_new_texture_object( GLcontext *ctx, GLuint name, GLenum target )
 
 
 /**
- * Initialize a texture object to default values.
+ * Initialize a new texture object to default values.
  * \param obj  the texture object
  * \param name  the texture name
  * \param target  the texture target
@@ -88,9 +88,9 @@ _mesa_initialize_texture_object( struct gl_texture_object *obj,
           target == GL_TEXTURE_CUBE_MAP_ARB ||
           target == GL_TEXTURE_RECTANGLE_NV);
 
+   _mesa_bzero(obj, sizeof(*obj));
    /* init the non-zero fields */
    _glthread_INIT_MUTEX(obj->Mutex);
-   _mesa_bzero(obj, sizeof(*obj));
    obj->RefCount = 1;
    obj->Name = name;
    obj->Target = target;
@@ -138,8 +138,6 @@ _mesa_delete_texture_object( GLcontext *ctx, struct gl_texture_object *texObj )
 
    (void) ctx;
 
-   assert(texObj);
-
    _mesa_free_colortable_data(&texObj->Palette);
 
    /* free the texture images */
@@ -703,12 +701,16 @@ _mesa_DeleteTextures( GLsizei n, const GLuint *textures)
             }
             ctx->NewState |= _NEW_TEXTURE;
 
-            /* Decrement reference count and delete if zero */
-            delObj->RefCount--;
-            ASSERT(delObj->RefCount >= 0);
+            /* If user hasn't already tried to delete the texture... */
+            if (!delObj->DeletePending) {
+               delObj->DeletePending = GL_TRUE;
+               delObj->RefCount--;
+               ASSERT(delObj->RefCount >= 0);
+            }
 
+            /* See if we can really delete the texture now */
             if (delObj->RefCount == 0) {
-               ASSERT(delObj->Name != 0);
+               ASSERT(delObj->Name != 0); /* Never delete default tex objects */
                _mesa_remove_texture_object(ctx, delObj);
                ASSERT(ctx->Driver.DeleteTexture);
                (*ctx->Driver.DeleteTexture)(ctx, delObj);
@@ -718,6 +720,7 @@ _mesa_DeleteTextures( GLsizei n, const GLuint *textures)
    }
 }
 
+
 /**
  * Bind a named texture to a texturing target.
  * 
@@ -747,6 +750,9 @@ _mesa_BindTexture( GLenum target, GLuint texName )
       _mesa_debug(ctx, "glBindTexture %s %d\n",
                   _mesa_lookup_enum_by_nr(target), (GLint) texName);
 
+   /*
+    * Get pointer to currently bound texture object (oldTexObj)
+    */
    switch (target) {
       case GL_TEXTURE_1D:
          oldTexObj = texUnit->Current1D;
@@ -875,16 +881,21 @@ _mesa_BindTexture( GLenum target, GLuint texName )
    if (ctx->Driver.BindTexture)
       (*ctx->Driver.BindTexture)( ctx, target, newTexObj );
 
+   /* Decrement the reference count on the old texture and check if it's
+    * time to delete it.
+    */
    oldTexObj->RefCount--;
-   assert(oldTexObj->RefCount >= 0);
+   ASSERT(oldTexObj->RefCount >= 0);
    if (oldTexObj->RefCount == 0) {
-      assert(oldTexObj->Name != 0);
+      ASSERT(oldTexObj->Name != 0);
+      ASSERT(oldTexObj->DeletePending);
       _mesa_remove_texture_object(ctx, oldTexObj);
       ASSERT(ctx->Driver.DeleteTexture);
       (*ctx->Driver.DeleteTexture)( ctx, oldTexObj );
    }
 }
 
+
 /**
  * Set texture priorities.
  *