u_tile: fix stencil texturing tests under softpipe
[mesa.git] / src / gallium / auxiliary / util / u_handle_table.c
index ab427ee371da0f010f16ea38998379a023e2aa9d..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 "pipe/p_util.h"
+#include "util/u_debug.h"
 
-#include "u_handle_table.h"
+#include "util/u_memory.h"
+#include "util/u_handle_table.h"
 
 
 #define HANDLE_TABLE_INITIAL_SIZE 16  
@@ -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 */
@@ -170,18 +194,22 @@ handle_table_set(struct handle_table *ht,
    unsigned index;
    
    assert(ht);
-   assert(handle > 0);
-   assert(handle <= ht->size);
-   if(!handle || handle > ht->size)
+   assert(handle);
+   if(!handle || !ht)
       return 0;
 
+   assert(object);
+   if(!object)
+      return 0;
+   
    index = handle - 1;
 
    /* grow the table if necessary */
    if(!handle_table_resize(ht, index))
       return 0;
 
-   assert(!ht->objects[index]);
+   handle_table_clear(ht, index);
+
    ht->objects[index] = object;
    
    return handle;
@@ -195,13 +223,11 @@ handle_table_get(struct handle_table *ht,
    void *object;
    
    assert(ht);
-   assert(handle > 0);
-   assert(handle <= ht->size);
-   if(!handle || handle > ht->size)
+   assert(handle);
+   if(!handle || !ht || handle > ht->size)
       return NULL;
 
    object = ht->objects[handle - 1];
-   assert(object);
    
    return object;
 }
@@ -215,34 +241,56 @@ handle_table_remove(struct handle_table *ht,
    unsigned index;
    
    assert(ht);
-   assert(handle > 0);
-   assert(handle <= ht->size);
-   if(!handle || handle > ht->size)
+   assert(handle);
+   if(!handle || !ht || handle > ht->size)
       return;
 
    index = handle - 1;
    object = ht->objects[index];
-   assert(object);
+   if(!object)
+      return;
    
-   if(object && ht->destroy)
-      ht->destroy(object);
+   handle_table_clear(ht, index);
 
-   ht->objects[index] = NULL;
    if(index < ht->filled)
       ht->filled = index;
 }
 
 
+unsigned
+handle_table_get_next_handle(struct handle_table *ht, 
+                             unsigned handle)
+{
+   unsigned index;
+   
+   for(index = handle; index < ht->size; ++index) {
+      if(ht->objects[index])
+        return index + 1;
+   }
+
+   return 0;
+}
+
+
+unsigned
+handle_table_get_first_handle(struct handle_table *ht)
+{
+   return handle_table_get_next_handle(ht, 0);
+}
+
+
 void
 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);