1 /**************************************************************************
3 * Copyright 2003 VMware, Inc.
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 VMWARE 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"
42 struct gl_program
*program
;
43 struct cache_item
*next
;
46 struct gl_program_cache
48 struct cache_item
**items
;
49 struct cache_item
*last
;
56 * Compute hash index from state key.
59 hash_key(const void *key
, GLuint key_size
)
61 const GLuint
*ikey
= (const GLuint
*) key
;
64 assert(key_size
>= 4);
66 /* Make a slightly better attempt at a hash function:
68 for (i
= 0; i
< key_size
/ sizeof(*ikey
); i
++)
80 * Rebuild/expand the hash table to accommodate more entries
83 rehash(struct gl_program_cache
*cache
)
85 struct cache_item
**items
;
86 struct cache_item
*c
, *next
;
91 size
= cache
->size
* 3;
92 items
= malloc(size
* sizeof(*items
));
93 memset(items
, 0, size
* sizeof(*items
));
95 for (i
= 0; i
< cache
->size
; i
++)
96 for (c
= cache
->items
[i
]; c
; c
= next
) {
98 c
->next
= items
[c
->hash
% size
];
99 items
[c
->hash
% size
] = c
;
103 cache
->items
= items
;
109 clear_cache(struct gl_context
*ctx
, struct gl_program_cache
*cache
,
112 struct cache_item
*c
, *next
;
117 for (i
= 0; i
< cache
->size
; i
++) {
118 for (c
= cache
->items
[i
]; c
; c
= next
) {
122 _mesa_reference_shader_program(ctx
,
123 (struct gl_shader_program
**)&c
->program
,
126 _mesa_reference_program(ctx
, &c
->program
, NULL
);
130 cache
->items
[i
] = NULL
;
139 struct gl_program_cache
*
140 _mesa_new_program_cache(void)
142 struct gl_program_cache
*cache
= CALLOC_STRUCT(gl_program_cache
);
146 calloc(cache
->size
, sizeof(struct cache_item
*));
157 _mesa_delete_program_cache(struct gl_context
*ctx
, struct gl_program_cache
*cache
)
159 clear_cache(ctx
, cache
, GL_FALSE
);
165 _mesa_delete_shader_cache(struct gl_context
*ctx
,
166 struct gl_program_cache
*cache
)
168 clear_cache(ctx
, cache
, GL_TRUE
);
175 _mesa_search_program_cache(struct gl_program_cache
*cache
,
176 const void *key
, GLuint keysize
)
179 cache
->last
->keysize
== keysize
&&
180 memcmp(cache
->last
->key
, key
, keysize
) == 0) {
181 return cache
->last
->program
;
184 const GLuint hash
= hash_key(key
, keysize
);
185 struct cache_item
*c
;
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) {
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
)
208 const GLuint hash
= hash_key(key
, keysize
);
209 struct cache_item
*c
= CALLOC_STRUCT(cache_item
);
213 c
->key
= malloc(keysize
);
214 memcpy(c
->key
, key
, keysize
);
215 c
->keysize
= keysize
;
217 c
->program
= program
; /* no refcount change */
219 if (cache
->n_items
> cache
->size
* 1.5) {
220 if (cache
->size
< 1000)
223 clear_cache(ctx
, cache
, GL_FALSE
);
227 c
->next
= cache
->items
[hash
% cache
->size
];
228 cache
->items
[hash
% cache
->size
] = c
;
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
)
237 const GLuint hash
= hash_key(key
, keysize
);
238 struct cache_item
*c
= CALLOC_STRUCT(cache_item
);
242 c
->key
= malloc(keysize
);
243 memcpy(c
->key
, key
, keysize
);
244 c
->keysize
= keysize
;
246 c
->program
= (struct gl_program
*)program
; /* no refcount change */
248 if (cache
->n_items
> cache
->size
* 1.5) {
249 if (cache
->size
< 1000)
252 clear_cache(ctx
, cache
, GL_TRUE
);
256 c
->next
= cache
->items
[hash
% cache
->size
];
257 cache
->items
[hash
% cache
->size
] = c
;