gallium: bypass u_vbuf if it's not needed (no fallbacks and no user VBOs)
[mesa.git] / src / gallium / auxiliary / cso_cache / cso_hash.c
index b40217c524be6fe20ef9cf0530efb45146b981f2..4d3e261a741f24a96d295d881383923018becb3c 100644 (file)
@@ -1,6 +1,6 @@
 /**************************************************************************
  *
- * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright 2007 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.
 
  /*
   * Authors:
-  *   Zack Rusin <zack@tungstengraphics.com>
+  *   Zack Rusin <zackr@vmware.com>
   */
 
-#include "cso_hash.h"
+#include "util/u_debug.h"
+#include "util/u_memory.h"
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
+#include "cso_hash.h"
 
+#ifndef MAX
 #define MAX(a, b) ((a > b) ? (a) : (b))
+#endif
 
 static const int MinNumBits = 4;
 
@@ -73,12 +73,6 @@ static int countBits(int hint)
    return numBits;
 }
 
-struct cso_node {
-   struct cso_node *next;
-   unsigned key;
-   void *value;
-};
-
 struct cso_hash_data {
    struct cso_node *fakeNext;
    struct cso_node **buckets;
@@ -89,28 +83,14 @@ struct cso_hash_data {
    int numBuckets;
 };
 
-struct cso_hash {
-   union {
-      struct cso_hash_data *d;
-      struct cso_node      *e;
-   } data;
-};
-
 static void *cso_data_allocate_node(struct cso_hash_data *hash)
 {
-   return malloc(hash->nodeSize);
+   return MALLOC(hash->nodeSize);
 }
 
-static void cso_data_free_node(struct cso_node *node)
+static void cso_free_node(struct cso_node *node)
 {
-   /* XXX still a leak here.
-    * Need to cast value ptr to original cso type, then free the
-    * driver-specific data hanging off of it.  For example:
-   struct cso_sampler *csamp = (struct cso_sampler *) node->value;
-   free(csamp->data);
-   */
-   free(node->value);
-   free(node);
+   FREE(node);
 }
 
 static struct cso_node *
@@ -119,6 +99,10 @@ cso_hash_create_node(struct cso_hash *hash,
                       struct cso_node **anextNode)
 {
    struct cso_node *node = cso_data_allocate_node(hash->data.d);
+
+   if (!node)
+      return NULL;
+
    node->key = akey;
    node->value = avalue;
 
@@ -134,7 +118,7 @@ static void cso_data_rehash(struct cso_hash_data *hash, int hint)
       hint = countBits(-hint);
       if (hint < MinNumBits)
          hint = MinNumBits;
-      hash->userNumBits = hint;
+      hash->userNumBits = (short)hint;
       while (primeForNumBits(hint) < (hash->size >> 1))
          ++hint;
    } else if (hint < MinNumBits) {
@@ -147,9 +131,9 @@ static void cso_data_rehash(struct cso_hash_data *hash, int hint)
       int oldNumBuckets = hash->numBuckets;
       int  i = 0;
 
-      hash->numBits = hint;
+      hash->numBits = (short)hint;
       hash->numBuckets = primeForNumBits(hint);
-      hash->buckets = malloc(sizeof(struct cso_node*) * hash->numBuckets);
+      hash->buckets = MALLOC(sizeof(struct cso_node*) * hash->numBuckets);
       for (i = 0; i < hash->numBuckets; ++i)
          hash->buckets[i] = e;
 
@@ -173,7 +157,7 @@ static void cso_data_rehash(struct cso_hash_data *hash, int hint)
             firstNode = afterLastNode;
          }
       }
-      free(oldBuckets);
+      FREE(oldBuckets);
    }
 }
 
@@ -228,20 +212,35 @@ struct cso_hash_iter cso_hash_insert(struct cso_hash *hash,
    {
       struct cso_node **nextNode = cso_hash_find_node(hash, key);
       struct cso_node *node = cso_hash_create_node(hash, key, data, nextNode);
-      struct cso_hash_iter iter = {hash, node};
-      return iter;
+      if (!node) {
+         struct cso_hash_iter null_iter = {hash, 0};
+         return null_iter;
+      }
+
+      {
+         struct cso_hash_iter iter = {hash, node};
+         return iter;
+      }
    }
 }
 
 struct cso_hash * cso_hash_create(void)
 {
-   struct cso_hash *hash = malloc(sizeof(struct cso_hash));
-   hash->data.d = malloc(sizeof(struct cso_hash_data));
+   struct cso_hash *hash = MALLOC_STRUCT(cso_hash);
+   if (!hash)
+      return NULL;
+
+   hash->data.d = MALLOC_STRUCT(cso_hash_data);
+   if (!hash->data.d) {
+      FREE(hash);
+      return NULL;
+   }
+
    hash->data.d->fakeNext = 0;
    hash->data.d->buckets = 0;
    hash->data.d->size = 0;
    hash->data.d->nodeSize = sizeof(struct cso_node);
-   hash->data.d->userNumBits = MinNumBits;
+   hash->data.d->userNumBits = (short)MinNumBits;
    hash->data.d->numBits = 0;
    hash->data.d->numBuckets = 0;
 
@@ -257,13 +256,13 @@ void cso_hash_delete(struct cso_hash *hash)
       struct cso_node *cur = *bucket++;
       while (cur != e_for_x) {
          struct cso_node *next = cur->next;
-         cso_data_free_node(cur);
+         cso_free_node(cur);
          cur = next;
       }
    }
-   free(hash->data.d->buckets);
-   free(hash->data.d);
-   free(hash);
+   FREE(hash->data.d->buckets);
+   FREE(hash->data.d);
+   FREE(hash);
 }
 
 struct cso_hash_iter cso_hash_find(struct cso_hash *hash,
@@ -281,13 +280,6 @@ unsigned cso_hash_iter_key(struct cso_hash_iter iter)
    return iter.node->key;
 }
 
-void * cso_hash_iter_data(struct cso_hash_iter iter)
-{
-   if (!iter.node || iter.hash->data.e == iter.node)
-      return 0;
-   return iter.node->value;
-}
-
 static struct cso_node *cso_hash_data_next(struct cso_node *node)
 {
    union {
@@ -301,7 +293,7 @@ static struct cso_node *cso_hash_data_next(struct cso_node *node)
 
    a.next = node->next;
    if (!a.next) {
-      fprintf(stderr, "iterating beyond the last element\n");
+      debug_printf("iterating beyond the last element\n");
       return 0;
    }
    if (a.next->next)
@@ -352,7 +344,7 @@ static struct cso_node *cso_hash_data_prev(struct cso_node *node)
       --bucket;
       --start;
    }
-   fprintf(stderr, "iterating backward beyond first element\n");
+   debug_printf("iterating backward beyond first element\n");
    return a.e;
 }
 
@@ -362,13 +354,6 @@ struct cso_hash_iter cso_hash_iter_next(struct cso_hash_iter iter)
    return next;
 }
 
-int cso_hash_iter_is_null(struct cso_hash_iter iter)
-{
-   if (!iter.node || iter.node == iter.hash->data.e)
-      return 1;
-   return 0;
-}
-
 void * cso_hash_take(struct cso_hash *hash,
                       unsigned akey)
 {
@@ -376,7 +361,7 @@ void * cso_hash_take(struct cso_hash *hash,
    if (*node != hash->data.e) {
       void *t = (*node)->value;
       struct cso_node *next = (*node)->next;
-      cso_data_free_node(*node);
+      cso_free_node(*node);
       *node = next;
       --hash->data.d->size;
       cso_data_has_shrunk(hash->data.d);
@@ -397,3 +382,33 @@ struct cso_hash_iter cso_hash_first_node(struct cso_hash *hash)
    struct cso_hash_iter iter = {hash, cso_data_first_node(hash->data.d)};
    return iter;
 }
+
+int cso_hash_size(struct cso_hash *hash)
+{
+   return hash->data.d->size;
+}
+
+struct cso_hash_iter cso_hash_erase(struct cso_hash *hash, struct cso_hash_iter iter)
+{
+   struct cso_hash_iter ret = iter;
+   struct cso_node *node = iter.node;
+   struct cso_node **node_ptr;
+
+   if (node == hash->data.e)
+      return iter;
+
+   ret = cso_hash_iter_next(ret);
+   node_ptr = (struct cso_node**)(&hash->data.d->buckets[node->key % hash->data.d->numBuckets]);
+   while (*node_ptr != node)
+      node_ptr = &(*node_ptr)->next;
+   *node_ptr = node->next;
+   cso_free_node(node);
+   --hash->data.d->size;
+   return ret;
+}
+
+boolean cso_hash_contains(struct cso_hash *hash, unsigned key)
+{
+   struct cso_node **node = cso_hash_find_node(hash, key);
+   return (*node != hash->data.e);
+}