1 /**************************************************************************
3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
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"
41 struct gl_program
*program
;
42 struct cache_item
*next
;
45 struct gl_program_cache
47 struct cache_item
**items
;
48 struct cache_item
*last
;
55 * Compute hash index from state key.
58 hash_key(const void *key
, GLuint key_size
)
60 const GLuint
*ikey
= (const GLuint
*) key
;
63 assert(key_size
>= 4);
65 /* Make a slightly better attempt at a hash function:
67 for (i
= 0; i
< key_size
/ sizeof(*ikey
); i
++)
79 * Rebuild/expand the hash table to accomodate more entries
82 rehash(struct gl_program_cache
*cache
)
84 struct cache_item
**items
;
85 struct cache_item
*c
, *next
;
90 size
= cache
->size
* 3;
91 items
= (struct cache_item
**) malloc(size
* sizeof(*items
));
92 memset(items
, 0, size
* sizeof(*items
));
94 for (i
= 0; i
< cache
->size
; i
++)
95 for (c
= cache
->items
[i
]; c
; c
= next
) {
97 c
->next
= items
[c
->hash
% size
];
98 items
[c
->hash
% size
] = c
;
102 cache
->items
= items
;
108 clear_cache(struct gl_context
*ctx
, struct gl_program_cache
*cache
,
111 struct cache_item
*c
, *next
;
116 for (i
= 0; i
< cache
->size
; i
++) {
117 for (c
= cache
->items
[i
]; c
; c
= next
) {
121 _mesa_reference_shader_program(ctx
,
122 (struct gl_shader_program
**)&c
->program
,
125 _mesa_reference_program(ctx
, &c
->program
, NULL
);
129 cache
->items
[i
] = NULL
;
138 struct gl_program_cache
*
139 _mesa_new_program_cache(void)
141 struct gl_program_cache
*cache
= CALLOC_STRUCT(gl_program_cache
);
144 cache
->items
= (struct cache_item
**)
145 calloc(1, cache
->size
* sizeof(struct cache_item
));
156 _mesa_delete_program_cache(struct gl_context
*ctx
, struct gl_program_cache
*cache
)
158 clear_cache(ctx
, cache
, GL_FALSE
);
164 _mesa_delete_shader_cache(struct gl_context
*ctx
,
165 struct gl_program_cache
*cache
)
167 clear_cache(ctx
, cache
, GL_TRUE
);
174 _mesa_search_program_cache(struct gl_program_cache
*cache
,
175 const void *key
, GLuint keysize
)
178 memcmp(cache
->last
->key
, key
, keysize
) == 0) {
179 return cache
->last
->program
;
182 const GLuint hash
= hash_key(key
, keysize
);
183 struct cache_item
*c
;
185 for (c
= cache
->items
[hash
% cache
->size
]; c
; c
= c
->next
) {
186 if (c
->hash
== hash
&& memcmp(c
->key
, key
, keysize
) == 0) {
198 _mesa_program_cache_insert(struct gl_context
*ctx
,
199 struct gl_program_cache
*cache
,
200 const void *key
, GLuint keysize
,
201 struct gl_program
*program
)
203 const GLuint hash
= hash_key(key
, keysize
);
204 struct cache_item
*c
= CALLOC_STRUCT(cache_item
);
208 c
->key
= malloc(keysize
);
209 memcpy(c
->key
, key
, keysize
);
211 c
->program
= program
; /* no refcount change */
213 if (cache
->n_items
> cache
->size
* 1.5) {
214 if (cache
->size
< 1000)
217 clear_cache(ctx
, cache
, GL_FALSE
);
221 c
->next
= cache
->items
[hash
% cache
->size
];
222 cache
->items
[hash
% cache
->size
] = c
;
226 _mesa_shader_cache_insert(struct gl_context
*ctx
,
227 struct gl_program_cache
*cache
,
228 const void *key
, GLuint keysize
,
229 struct gl_shader_program
*program
)
231 const GLuint hash
= hash_key(key
, keysize
);
232 struct cache_item
*c
= CALLOC_STRUCT(cache_item
);
236 c
->key
= malloc(keysize
);
237 memcpy(c
->key
, key
, keysize
);
239 c
->program
= (struct gl_program
*)program
; /* no refcount change */
241 if (cache
->n_items
> cache
->size
* 1.5) {
242 if (cache
->size
< 1000)
245 clear_cache(ctx
, cache
, GL_TRUE
);
249 c
->next
= cache
->items
[hash
% cache
->size
];
250 cache
->items
[hash
% cache
->size
] = c
;