st/nir: Rework fixup_varying_slots
[mesa.git] / src / mesa / program / prog_cache.c
index 56ca59890de0ded4d83eafa3b4b4378960e7fb3a..aee61f90f47136361fe3e5f0b9cff67015835195 100644 (file)
@@ -1,8 +1,8 @@
 /**************************************************************************
- * 
- * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ *
+ * Copyright 2003 VMware, Inc.
  * All Rights Reserved.
- * 
+ *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the
  * "Software"), to deal in the Software without restriction, including
  * distribute, sub license, and/or sell copies of the Software, and to
  * permit persons to whom the Software is furnished to do so, subject to
  * the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice (including the
  * next paragraph) shall be included in all copies or substantial portions
  * of the Software.
- * 
+ *
  * 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.
- * 
+ *
  **************************************************************************/
 
 
 #include "main/glheader.h"
 #include "main/mtypes.h"
-#include "main/imports.h"
+
+#include "main/shaderobj.h"
 #include "program/prog_cache.h"
 #include "program/program.h"
+#include "util/u_memory.h"
 
 
 struct cache_item
 {
    GLuint hash;
+   unsigned keysize;
    void *key;
    struct gl_program *program;
    struct cache_item *next;
@@ -75,7 +78,7 @@ hash_key(const void *key, GLuint key_size)
 
 
 /**
- * Rebuild/expand the hash table to accomodate more entries
+ * Rebuild/expand the hash table to accommodate more entries
  */
 static void
 rehash(struct gl_program_cache *cache)
@@ -87,7 +90,7 @@ rehash(struct gl_program_cache *cache)
    cache->last = NULL;
 
    size = cache->size * 3;
-   items = (struct cache_item**) malloc(size * sizeof(*items));
+   items = malloc(size * sizeof(*items));
    memset(items, 0, size * sizeof(*items));
 
    for (i = 0; i < cache->size; i++)
@@ -104,18 +107,25 @@ rehash(struct gl_program_cache *cache)
 
 
 static void
-clear_cache(struct gl_context *ctx, struct gl_program_cache *cache)
+clear_cache(struct gl_context *ctx, struct gl_program_cache *cache,
+           GLboolean shader)
 {
    struct cache_item *c, *next;
    GLuint i;
-   
+
    cache->last = NULL;
 
    for (i = 0; i < cache->size; i++) {
       for (c = cache->items[i]; c; c = next) {
         next = c->next;
         free(c->key);
-         _mesa_reference_program(ctx, &c->program, NULL);
+        if (shader) {
+           _mesa_reference_shader_program(ctx,
+                                          (struct gl_shader_program **)&c->program,
+                                          NULL);
+        } else {
+           _mesa_reference_program(ctx, &c->program, NULL);
+        }
         free(c);
       }
       cache->items[i] = NULL;
@@ -133,8 +143,8 @@ _mesa_new_program_cache(void)
    struct gl_program_cache *cache = CALLOC_STRUCT(gl_program_cache);
    if (cache) {
       cache->size = 17;
-      cache->items = (struct cache_item **)
-         calloc(1, cache->size * sizeof(struct cache_item));
+      cache->items =
+         calloc(cache->size, sizeof(struct cache_item *));
       if (!cache->items) {
          free(cache);
          return NULL;
@@ -147,7 +157,16 @@ _mesa_new_program_cache(void)
 void
 _mesa_delete_program_cache(struct gl_context *ctx, struct gl_program_cache *cache)
 {
-   clear_cache(ctx, cache);
+   clear_cache(ctx, cache, GL_FALSE);
+   free(cache->items);
+   free(cache);
+}
+
+void
+_mesa_delete_shader_cache(struct gl_context *ctx,
+                         struct gl_program_cache *cache)
+{
+   clear_cache(ctx, cache, GL_TRUE);
    free(cache->items);
    free(cache);
 }
@@ -157,7 +176,8 @@ struct gl_program *
 _mesa_search_program_cache(struct gl_program_cache *cache,
                            const void *key, GLuint keysize)
 {
-   if (cache->last && 
+   if (cache->last &&
+       cache->last->keysize == keysize &&
        memcmp(cache->last->key, key, keysize) == 0) {
       return cache->last->program;
    }
@@ -166,7 +186,10 @@ _mesa_search_program_cache(struct gl_program_cache *cache,
       struct cache_item *c;
 
       for (c = cache->items[hash % cache->size]; c; c = c->next) {
-         if (c->hash == hash && memcmp(c->key, key, keysize) == 0) {
+         if (c->hash == hash &&
+             c->keysize == keysize &&
+             memcmp(c->key, key, keysize) == 0) {
+
             cache->last = c;
             return c->program;
          }
@@ -190,14 +213,44 @@ _mesa_program_cache_insert(struct gl_context *ctx,
 
    c->key = malloc(keysize);
    memcpy(c->key, key, keysize);
+   c->keysize = keysize;
 
    c->program = program;  /* no refcount change */
 
    if (cache->n_items > cache->size * 1.5) {
       if (cache->size < 1000)
         rehash(cache);
-      else 
-        clear_cache(ctx, cache);
+      else
+        clear_cache(ctx, cache, GL_FALSE);
+   }
+
+   cache->n_items++;
+   c->next = cache->items[hash % cache->size];
+   cache->items[hash % cache->size] = c;
+}
+
+void
+_mesa_shader_cache_insert(struct gl_context *ctx,
+                         struct gl_program_cache *cache,
+                         const void *key, GLuint keysize,
+                         struct gl_shader_program *program)
+{
+   const GLuint hash = hash_key(key, keysize);
+   struct cache_item *c = CALLOC_STRUCT(cache_item);
+
+   c->hash = hash;
+
+   c->key = malloc(keysize);
+   memcpy(c->key, key, keysize);
+   c->keysize = keysize;
+
+   c->program = (struct gl_program *)program;  /* no refcount change */
+
+   if (cache->n_items > cache->size * 1.5) {
+      if (cache->size < 1000)
+        rehash(cache);
+      else
+        clear_cache(ctx, cache, GL_TRUE);
    }
 
    cache->n_items++;