Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
  4.  * All Rights Reserved.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the
  8.  * "Software"), to deal in the Software without restriction, including
  9.  * without limitation the rights to use, copy, modify, merge, publish,
  10.  * distribute, sub license, and/or sell copies of the Software, and to
  11.  * permit persons to whom the Software is furnished to do so, subject to
  12.  * the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice (including the
  15.  * next paragraph) shall be included in all copies or substantial portions
  16.  * of the Software.
  17.  *
  18.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  19.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  21.  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
  22.  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  23.  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  24.  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  *
  26.  **************************************************************************/
  27.  
  28.  
  29. #include "main/glheader.h"
  30. #include "main/mtypes.h"
  31. #include "main/imports.h"
  32. #include "program/prog_cache.h"
  33. #include "program/program.h"
  34.  
  35.  
  36. struct cache_item
  37. {
  38.    GLuint hash;
  39.    void *key;
  40.    struct gl_program *program;
  41.    struct cache_item *next;
  42. };
  43.  
  44. struct gl_program_cache
  45. {
  46.    struct cache_item **items;
  47.    struct cache_item *last;
  48.    GLuint size, n_items;
  49. };
  50.  
  51.  
  52.  
  53. /**
  54.  * Compute hash index from state key.
  55.  */
  56. static GLuint
  57. hash_key(const void *key, GLuint key_size)
  58. {
  59.    const GLuint *ikey = (const GLuint *) key;
  60.    GLuint hash = 0, i;
  61.  
  62.    assert(key_size >= 4);
  63.  
  64.    /* Make a slightly better attempt at a hash function:
  65.     */
  66.    for (i = 0; i < key_size / sizeof(*ikey); i++)
  67.    {
  68.       hash += ikey[i];
  69.       hash += (hash << 10);
  70.       hash ^= (hash >> 6);
  71.    }
  72.  
  73.    return hash;
  74. }
  75.  
  76.  
  77. /**
  78.  * Rebuild/expand the hash table to accomodate more entries
  79.  */
  80. static void
  81. rehash(struct gl_program_cache *cache)
  82. {
  83.    struct cache_item **items;
  84.    struct cache_item *c, *next;
  85.    GLuint size, i;
  86.  
  87.    cache->last = NULL;
  88.  
  89.    size = cache->size * 3;
  90.    items = (struct cache_item**) malloc(size * sizeof(*items));
  91.    memset(items, 0, size * sizeof(*items));
  92.  
  93.    for (i = 0; i < cache->size; i++)
  94.       for (c = cache->items[i]; c; c = next) {
  95.          next = c->next;
  96.          c->next = items[c->hash % size];
  97.          items[c->hash % size] = c;
  98.       }
  99.  
  100.    free(cache->items);
  101.    cache->items = items;
  102.    cache->size = size;
  103. }
  104.  
  105.  
  106. static void
  107. clear_cache(struct gl_context *ctx, struct gl_program_cache *cache)
  108. {
  109.    struct cache_item *c, *next;
  110.    GLuint i;
  111.    
  112.    cache->last = NULL;
  113.  
  114.    for (i = 0; i < cache->size; i++) {
  115.       for (c = cache->items[i]; c; c = next) {
  116.          next = c->next;
  117.          free(c->key);
  118.          _mesa_reference_program(ctx, &c->program, NULL);
  119.          free(c);
  120.       }
  121.       cache->items[i] = NULL;
  122.    }
  123.  
  124.  
  125.    cache->n_items = 0;
  126. }
  127.  
  128.  
  129.  
  130. struct gl_program_cache *
  131. _mesa_new_program_cache(void)
  132. {
  133.    struct gl_program_cache *cache = CALLOC_STRUCT(gl_program_cache);
  134.    if (cache) {
  135.       cache->size = 17;
  136.       cache->items = (struct cache_item **)
  137.          calloc(1, cache->size * sizeof(struct cache_item));
  138.       if (!cache->items) {
  139.          free(cache);
  140.          return NULL;
  141.       }
  142.    }
  143.    return cache;
  144. }
  145.  
  146.  
  147. void
  148. _mesa_delete_program_cache(struct gl_context *ctx, struct gl_program_cache *cache)
  149. {
  150.    clear_cache(ctx, cache);
  151.    free(cache->items);
  152.    free(cache);
  153. }
  154.  
  155.  
  156. struct gl_program *
  157. _mesa_search_program_cache(struct gl_program_cache *cache,
  158.                            const void *key, GLuint keysize)
  159. {
  160.    if (cache->last &&
  161.        memcmp(cache->last->key, key, keysize) == 0) {
  162.       return cache->last->program;
  163.    }
  164.    else {
  165.       const GLuint hash = hash_key(key, keysize);
  166.       struct cache_item *c;
  167.  
  168.       for (c = cache->items[hash % cache->size]; c; c = c->next) {
  169.          if (c->hash == hash && memcmp(c->key, key, keysize) == 0) {
  170.             cache->last = c;
  171.             return c->program;
  172.          }
  173.       }
  174.  
  175.       return NULL;
  176.    }
  177. }
  178.  
  179.  
  180. void
  181. _mesa_program_cache_insert(struct gl_context *ctx,
  182.                            struct gl_program_cache *cache,
  183.                            const void *key, GLuint keysize,
  184.                            struct gl_program *program)
  185. {
  186.    const GLuint hash = hash_key(key, keysize);
  187.    struct cache_item *c = CALLOC_STRUCT(cache_item);
  188.  
  189.    c->hash = hash;
  190.  
  191.    c->key = malloc(keysize);
  192.    memcpy(c->key, key, keysize);
  193.  
  194.    c->program = program;  /* no refcount change */
  195.  
  196.    if (cache->n_items > cache->size * 1.5) {
  197.       if (cache->size < 1000)
  198.          rehash(cache);
  199.       else
  200.          clear_cache(ctx, cache);
  201.    }
  202.  
  203.    cache->n_items++;
  204.    c->next = cache->items[hash % cache->size];
  205.    cache->items[hash % cache->size] = c;
  206. }
  207.