d1cfc27837b9ee5a4d6aaebcf4e6dd1d6923e58f
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 "util/imports.h"
32 #include "main/shaderobj.h"
33 #include "program/prog_cache.h"
34 #include "program/program.h"
35 #include "util/u_memory.h"
43 struct gl_program
*program
;
44 struct cache_item
*next
;
47 struct gl_program_cache
49 struct cache_item
**items
;
50 struct cache_item
*last
;
57 * Compute hash index from state key.
60 hash_key(const void *key
, GLuint key_size
)
62 const GLuint
*ikey
= (const GLuint
*) key
;
65 assert(key_size
>= 4);
67 /* Make a slightly better attempt at a hash function:
69 for (i
= 0; i
< key_size
/ sizeof(*ikey
); i
++)
81 * Rebuild/expand the hash table to accommodate more entries
84 rehash(struct gl_program_cache
*cache
)
86 struct cache_item
**items
;
87 struct cache_item
*c
, *next
;
92 size
= cache
->size
* 3;
93 items
= malloc(size
* sizeof(*items
));
94 memset(items
, 0, size
* sizeof(*items
));
96 for (i
= 0; i
< cache
->size
; i
++)
97 for (c
= cache
->items
[i
]; c
; c
= next
) {
99 c
->next
= items
[c
->hash
% size
];
100 items
[c
->hash
% size
] = c
;
104 cache
->items
= items
;
110 clear_cache(struct gl_context
*ctx
, struct gl_program_cache
*cache
,
113 struct cache_item
*c
, *next
;
118 for (i
= 0; i
< cache
->size
; i
++) {
119 for (c
= cache
->items
[i
]; c
; c
= next
) {
123 _mesa_reference_shader_program(ctx
,
124 (struct gl_shader_program
**)&c
->program
,
127 _mesa_reference_program(ctx
, &c
->program
, NULL
);
131 cache
->items
[i
] = NULL
;
140 struct gl_program_cache
*
141 _mesa_new_program_cache(void)
143 struct gl_program_cache
*cache
= CALLOC_STRUCT(gl_program_cache
);
147 calloc(cache
->size
, sizeof(struct cache_item
*));
158 _mesa_delete_program_cache(struct gl_context
*ctx
, struct gl_program_cache
*cache
)
160 clear_cache(ctx
, cache
, GL_FALSE
);
166 _mesa_delete_shader_cache(struct gl_context
*ctx
,
167 struct gl_program_cache
*cache
)
169 clear_cache(ctx
, cache
, GL_TRUE
);
176 _mesa_search_program_cache(struct gl_program_cache
*cache
,
177 const void *key
, GLuint keysize
)
180 cache
->last
->keysize
== keysize
&&
181 memcmp(cache
->last
->key
, key
, keysize
) == 0) {
182 return cache
->last
->program
;
185 const GLuint hash
= hash_key(key
, keysize
);
186 struct cache_item
*c
;
188 for (c
= cache
->items
[hash
% cache
->size
]; c
; c
= c
->next
) {
189 if (c
->hash
== hash
&&
190 c
->keysize
== keysize
&&
191 memcmp(c
->key
, key
, keysize
) == 0) {
204 _mesa_program_cache_insert(struct gl_context
*ctx
,
205 struct gl_program_cache
*cache
,
206 const void *key
, GLuint keysize
,
207 struct gl_program
*program
)
209 const GLuint hash
= hash_key(key
, keysize
);
210 struct cache_item
*c
= CALLOC_STRUCT(cache_item
);
214 c
->key
= malloc(keysize
);
215 memcpy(c
->key
, key
, keysize
);
216 c
->keysize
= keysize
;
218 c
->program
= program
; /* no refcount change */
220 if (cache
->n_items
> cache
->size
* 1.5) {
221 if (cache
->size
< 1000)
224 clear_cache(ctx
, cache
, GL_FALSE
);
228 c
->next
= cache
->items
[hash
% cache
->size
];
229 cache
->items
[hash
% cache
->size
] = c
;
233 _mesa_shader_cache_insert(struct gl_context
*ctx
,
234 struct gl_program_cache
*cache
,
235 const void *key
, GLuint keysize
,
236 struct gl_shader_program
*program
)
238 const GLuint hash
= hash_key(key
, keysize
);
239 struct cache_item
*c
= CALLOC_STRUCT(cache_item
);
243 c
->key
= malloc(keysize
);
244 memcpy(c
->key
, key
, keysize
);
245 c
->keysize
= keysize
;
247 c
->program
= (struct gl_program
*)program
; /* no refcount change */
249 if (cache
->n_items
> cache
->size
* 1.5) {
250 if (cache
->size
< 1000)
253 clear_cache(ctx
, cache
, GL_TRUE
);
257 c
->next
= cache
->items
[hash
% cache
->size
];
258 cache
->items
[hash
% cache
->size
] = c
;