Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | 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 "main/shaderobj.h"
  33. #include "program/prog_cache.h"
  34. #include "program/program.h"
  35.  
  36.  
  37. struct cache_item
  38. {
  39.    GLuint hash;
  40.    unsigned keysize;
  41.    void *key;
  42.    struct gl_program *program;
  43.    struct cache_item *next;
  44. };
  45.  
  46. struct gl_program_cache
  47. {
  48.    struct cache_item **items;
  49.    struct cache_item *last;
  50.    GLuint size, n_items;
  51. };
  52.  
  53.  
  54.  
  55. /**
  56.  * Compute hash index from state key.
  57.  */
  58. static GLuint
  59. hash_key(const void *key, GLuint key_size)
  60. {
  61.    const GLuint *ikey = (const GLuint *) key;
  62.    GLuint hash = 0, i;
  63.  
  64.    assert(key_size >= 4);
  65.  
  66.    /* Make a slightly better attempt at a hash function:
  67.     */
  68.    for (i = 0; i < key_size / sizeof(*ikey); i++)
  69.    {
  70.       hash += ikey[i];
  71.       hash += (hash << 10);
  72.       hash ^= (hash >> 6);
  73.    }
  74.  
  75.    return hash;
  76. }
  77.  
  78.  
  79. /**
  80.  * Rebuild/expand the hash table to accomodate more entries
  81.  */
  82. static void
  83. rehash(struct gl_program_cache *cache)
  84. {
  85.    struct cache_item **items;
  86.    struct cache_item *c, *next;
  87.    GLuint size, i;
  88.  
  89.    cache->last = NULL;
  90.  
  91.    size = cache->size * 3;
  92.    items = malloc(size * sizeof(*items));
  93.    memset(items, 0, size * sizeof(*items));
  94.  
  95.    for (i = 0; i < cache->size; i++)
  96.       for (c = cache->items[i]; c; c = next) {
  97.          next = c->next;
  98.          c->next = items[c->hash % size];
  99.          items[c->hash % size] = c;
  100.       }
  101.  
  102.    free(cache->items);
  103.    cache->items = items;
  104.    cache->size = size;
  105. }
  106.  
  107.  
  108. static void
  109. clear_cache(struct gl_context *ctx, struct gl_program_cache *cache,
  110.             GLboolean shader)
  111. {
  112.    struct cache_item *c, *next;
  113.    GLuint i;
  114.    
  115.    cache->last = NULL;
  116.  
  117.    for (i = 0; i < cache->size; i++) {
  118.       for (c = cache->items[i]; c; c = next) {
  119.          next = c->next;
  120.          free(c->key);
  121.          if (shader) {
  122.             _mesa_reference_shader_program(ctx,
  123.                                            (struct gl_shader_program **)&c->program,
  124.                                            NULL);
  125.          } else {
  126.             _mesa_reference_program(ctx, &c->program, NULL);
  127.          }
  128.          free(c);
  129.       }
  130.       cache->items[i] = NULL;
  131.    }
  132.  
  133.  
  134.    cache->n_items = 0;
  135. }
  136.  
  137.  
  138.  
  139. struct gl_program_cache *
  140. _mesa_new_program_cache(void)
  141. {
  142.    struct gl_program_cache *cache = CALLOC_STRUCT(gl_program_cache);
  143.    if (cache) {
  144.       cache->size = 17;
  145.       cache->items =
  146.          calloc(1, cache->size * sizeof(struct cache_item));
  147.       if (!cache->items) {
  148.          free(cache);
  149.          return NULL;
  150.       }
  151.    }
  152.    return cache;
  153. }
  154.  
  155.  
  156. void
  157. _mesa_delete_program_cache(struct gl_context *ctx, struct gl_program_cache *cache)
  158. {
  159.    clear_cache(ctx, cache, GL_FALSE);
  160.    free(cache->items);
  161.    free(cache);
  162. }
  163.  
  164. void
  165. _mesa_delete_shader_cache(struct gl_context *ctx,
  166.                           struct gl_program_cache *cache)
  167. {
  168.    clear_cache(ctx, cache, GL_TRUE);
  169.    free(cache->items);
  170.    free(cache);
  171. }
  172.  
  173.  
  174. struct gl_program *
  175. _mesa_search_program_cache(struct gl_program_cache *cache,
  176.                            const void *key, GLuint keysize)
  177. {
  178.    if (cache->last &&
  179.        cache->last->keysize == keysize &&
  180.        memcmp(cache->last->key, key, keysize) == 0) {
  181.       return cache->last->program;
  182.    }
  183.    else {
  184.       const GLuint hash = hash_key(key, keysize);
  185.       struct cache_item *c;
  186.  
  187.       for (c = cache->items[hash % cache->size]; c; c = c->next) {
  188.          if (c->hash == hash &&
  189.              c->keysize == keysize &&
  190.              memcmp(c->key, key, keysize) == 0) {
  191.  
  192.             cache->last = c;
  193.             return c->program;
  194.          }
  195.       }
  196.  
  197.       return NULL;
  198.    }
  199. }
  200.  
  201.  
  202. void
  203. _mesa_program_cache_insert(struct gl_context *ctx,
  204.                            struct gl_program_cache *cache,
  205.                            const void *key, GLuint keysize,
  206.                            struct gl_program *program)
  207. {
  208.    const GLuint hash = hash_key(key, keysize);
  209.    struct cache_item *c = CALLOC_STRUCT(cache_item);
  210.  
  211.    c->hash = hash;
  212.  
  213.    c->key = malloc(keysize);
  214.    memcpy(c->key, key, keysize);
  215.    c->keysize = keysize;
  216.  
  217.    c->program = program;  /* no refcount change */
  218.  
  219.    if (cache->n_items > cache->size * 1.5) {
  220.       if (cache->size < 1000)
  221.          rehash(cache);
  222.       else
  223.          clear_cache(ctx, cache, GL_FALSE);
  224.    }
  225.  
  226.    cache->n_items++;
  227.    c->next = cache->items[hash % cache->size];
  228.    cache->items[hash % cache->size] = c;
  229. }
  230.  
  231. void
  232. _mesa_shader_cache_insert(struct gl_context *ctx,
  233.                           struct gl_program_cache *cache,
  234.                           const void *key, GLuint keysize,
  235.                           struct gl_shader_program *program)
  236. {
  237.    const GLuint hash = hash_key(key, keysize);
  238.    struct cache_item *c = CALLOC_STRUCT(cache_item);
  239.  
  240.    c->hash = hash;
  241.  
  242.    c->key = malloc(keysize);
  243.    memcpy(c->key, key, keysize);
  244.    c->keysize = keysize;
  245.  
  246.    c->program = (struct gl_program *)program;  /* no refcount change */
  247.  
  248.    if (cache->n_items > cache->size * 1.5) {
  249.       if (cache->size < 1000)
  250.          rehash(cache);
  251.       else
  252.          clear_cache(ctx, cache, GL_TRUE);
  253.    }
  254.  
  255.    cache->n_items++;
  256.    c->next = cache->items[hash % cache->size];
  257.    cache->items[hash % cache->size] = c;
  258. }
  259.