u_tile: fix stencil texturing tests under softpipe
[mesa.git] / src / gallium / auxiliary / util / u_handle_table.c
index 2c40011923dccef9bf84c4072e87313afe5bbd15..85302f1e1942dc4374ddf43732848e8009d36957 100644 (file)
@@ -1,6 +1,6 @@
 /**************************************************************************
  *
- * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright 2008 VMware, Inc.
  * All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -18,7 +18,7 @@
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  * @file
  * Generic handle table implementation.
  *  
- * @author José Fonseca <jrfonseca@tungstengraphics.com>
+ * @author José Fonseca <jfonseca@vmware.com>
  */
 
 
 #include "pipe/p_compiler.h"
-#include "pipe/p_debug.h"
+#include "util/u_debug.h"
 
 #include "util/u_memory.h"
 #include "util/u_handle_table.h"
@@ -87,6 +87,8 @@ handle_table_set_destroy(struct handle_table *ht,
                          void (*destroy)(void *object))
 {
    assert(ht);
+   if (!ht)
+      return;
    ht->destroy = destroy;
 }
 
@@ -124,6 +126,28 @@ handle_table_resize(struct handle_table *ht,
 }
 
 
+static INLINE void
+handle_table_clear(struct handle_table *ht, 
+                   unsigned index)
+{
+   void *object;
+   
+   /* The order here is important so that the object being destroyed is not
+    * present in the table when seen by the destroy callback, because the 
+    * destroy callback may directly or indirectly call the other functions in 
+    * this module.
+    */
+
+   object = ht->objects[index];
+   if(object) {
+      ht->objects[index] = NULL;
+      
+      if(ht->destroy)
+         ht->destroy(object);
+   }   
+}
+
+
 unsigned
 handle_table_add(struct handle_table *ht, 
                  void *object)
@@ -133,7 +157,7 @@ handle_table_add(struct handle_table *ht,
    
    assert(ht);
    assert(object);
-   if(!object)
+   if(!object || !ht)
       return 0;
 
    /* linear search for an empty handle */
@@ -171,7 +195,7 @@ handle_table_set(struct handle_table *ht,
    
    assert(ht);
    assert(handle);
-   if(!handle)
+   if(!handle || !ht)
       return 0;
 
    assert(object);
@@ -184,9 +208,8 @@ handle_table_set(struct handle_table *ht,
    if(!handle_table_resize(ht, index))
       return 0;
 
-   if(ht->objects[index] && ht->destroy)
-      ht->destroy(ht->objects[index]);
-      
+   handle_table_clear(ht, index);
+
    ht->objects[index] = object;
    
    return handle;
@@ -201,7 +224,7 @@ handle_table_get(struct handle_table *ht,
    
    assert(ht);
    assert(handle);
-   if(!handle || handle > ht->size)
+   if(!handle || !ht || handle > ht->size)
       return NULL;
 
    object = ht->objects[handle - 1];
@@ -219,7 +242,7 @@ handle_table_remove(struct handle_table *ht,
    
    assert(ht);
    assert(handle);
-   if(!handle || handle > ht->size)
+   if(!handle || !ht || handle > ht->size)
       return;
 
    index = handle - 1;
@@ -227,10 +250,8 @@ handle_table_remove(struct handle_table *ht,
    if(!object)
       return;
    
-   if(ht->destroy)
-      ht->destroy(object);
+   handle_table_clear(ht, index);
 
-   ht->objects[index] = NULL;
    if(index < ht->filled)
       ht->filled = index;
 }
@@ -264,10 +285,12 @@ handle_table_destroy(struct handle_table *ht)
    unsigned index;
    assert(ht);
 
+   if (!ht)
+      return;
+
    if(ht->destroy)
       for(index = 0; index < ht->size; ++index)
-        if(ht->objects[index])
-           ht->destroy(ht->objects[index]);
+         handle_table_clear(ht, index);
    
    FREE(ht->objects);
    FREE(ht);