2 Copyright (C) Intel Corp. 2006. All Rights Reserved.
3 Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
4 develop this 3D driver.
6 Permission is hereby granted, free of charge, to any person obtaining
7 a 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, sublicense, 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
16 portions of the Software.
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **********************************************************************/
29 * Keith Whitwell <keith@tungstengraphics.com>
33 #include "brw_state.h"
41 #include "util/u_memory.h"
45 /***********************************************************************
46 * Check cache for uploaded version of struct, else upload new one.
47 * Fail when memory is exhausted.
49 * XXX: FIXME: Currently search is so slow it would be quicker to
50 * regenerate the data every time...
53 static unsigned hash_key( const void *key
, unsigned key_size
)
55 unsigned *ikey
= (unsigned *)key
;
58 assert(key_size
% 4 == 0);
60 /* I'm sure this can be improved on:
62 for (i
= 0; i
< key_size
/4; i
++)
68 static struct brw_cache_item
*search_cache( struct brw_cache
*cache
,
73 struct brw_cache_item
*c
;
75 for (c
= cache
->items
[hash
% cache
->size
]; c
; c
= c
->next
) {
76 if (c
->hash
== hash
&&
77 c
->key_size
== key_size
&&
78 memcmp(c
->key
, key
, key_size
) == 0)
86 static void rehash( struct brw_cache
*cache
)
88 struct brw_cache_item
**items
;
89 struct brw_cache_item
*c
, *next
;
92 size
= cache
->size
* 3;
93 items
= (struct brw_cache_item
**) 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
;
109 boolean
brw_search_cache( struct brw_cache
*cache
,
113 unsigned *offset_return
)
115 struct brw_cache_item
*item
;
117 unsigned hash
= hash_key(key
, key_size
);
119 item
= search_cache(cache
, hash
, key
, key_size
);
123 *(void **)aux_return
= (void *)((char *)item
->key
+ item
->key_size
);
125 *offset_return
= addr
= item
->offset
;
128 if (item
== NULL
|| addr
!= cache
->last_addr
) {
129 cache
->brw
->state
.dirty
.cache
|= 1<<cache
->id
;
130 cache
->last_addr
= addr
;
136 unsigned brw_upload_cache( struct brw_cache
*cache
,
145 struct brw_cache_item
*item
= CALLOC_STRUCT(brw_cache_item
);
146 unsigned hash
= hash_key(key
, key_size
);
147 void *tmp
= MALLOC(key_size
+ cache
->aux_size
);
149 if (!brw_pool_alloc(cache
->pool
, data_size
, 1 << 6, &offset
)) {
150 /* Should not be possible:
152 debug_printf("brw_pool_alloc failed\n");
156 memcpy(tmp
, key
, key_size
);
159 memcpy(tmp
+key_size
, aux
, cache
->aux_size
);
163 item
->key_size
= key_size
;
164 item
->offset
= offset
;
165 item
->data_size
= data_size
;
167 if (++cache
->n_items
> cache
->size
* 1.5)
171 item
->next
= cache
->items
[hash
];
172 cache
->items
[hash
] = item
;
175 assert(cache
->aux_size
);
176 *(void **)aux_return
= (void *)((char *)item
->key
+ item
->key_size
);
179 if (BRW_DEBUG
& DEBUG_STATE
)
180 debug_printf("upload %s: %d bytes to pool buffer %p offset %x\n",
183 (void*)cache
->pool
->buffer
,
186 /* Copy data to the buffer:
188 cache
->brw
->winsys
->buffer_subdata_typed(cache
->brw
->winsys
,
195 cache
->brw
->state
.dirty
.cache
|= 1<<cache
->id
;
196 cache
->last_addr
= offset
;
201 /* This doesn't really work with aux data. Use search/upload instead
203 unsigned brw_cache_data_sz(struct brw_cache
*cache
,
209 if (!brw_search_cache(cache
, data
, data_size
, NULL
, &addr
)) {
210 addr
= brw_upload_cache(cache
,
219 unsigned brw_cache_data(struct brw_cache
*cache
,
222 return brw_cache_data_sz(cache
, data
, cache
->key_size
);
230 static void brw_init_cache( struct brw_context
*brw
,
235 enum pool_type pool_type
)
237 struct brw_cache
*cache
= &brw
->cache
[id
];
245 cache
->items
= (struct brw_cache_item
**)
246 CALLOC(cache
->size
, sizeof(struct brw_cache_item
));
249 cache
->key_size
= key_size
;
250 cache
->aux_size
= aux_size
;
252 case DW_GENERAL_STATE
: cache
->pool
= &brw
->pool
[BRW_GS_POOL
]; break;
253 case DW_SURFACE_STATE
: cache
->pool
= &brw
->pool
[BRW_SS_POOL
]; break;
254 default: assert(0); break;
258 void brw_init_caches( struct brw_context
*brw
)
264 sizeof(struct brw_cc_viewport
),
271 sizeof(struct brw_cc_unit_state
),
278 sizeof(struct brw_wm_prog_key
),
279 sizeof(struct brw_wm_prog_data
),
283 "SAMPLER_DEFAULT_COLOR",
284 BRW_SAMPLER_DEFAULT_COLOR
,
285 sizeof(struct brw_sampler_default_color
),
292 0, /* variable key/data size */
299 sizeof(struct brw_wm_unit_state
),
306 sizeof(struct brw_sf_prog_key
),
307 sizeof(struct brw_sf_prog_data
),
313 sizeof(struct brw_sf_viewport
),
320 sizeof(struct brw_sf_unit_state
),
327 sizeof(struct brw_vs_unit_state
),
334 sizeof(struct brw_vs_prog_key
),
335 sizeof(struct brw_vs_prog_data
),
341 sizeof(struct brw_clip_unit_state
),
348 sizeof(struct brw_clip_prog_key
),
349 sizeof(struct brw_clip_prog_data
),
355 sizeof(struct brw_gs_unit_state
),
362 sizeof(struct brw_gs_prog_key
),
363 sizeof(struct brw_gs_prog_data
),
369 sizeof(struct brw_surface_state
),
376 sizeof(struct brw_surface_binding_table
),
382 /* When we lose hardware context, need to invalidate the surface cache
383 * as these structs must be explicitly re-uploaded. They are subject
384 * to fixup by the memory manager as they contain absolute agp
385 * offsets, so we need to ensure there is a fresh version of the
386 * struct available to receive the fixup.
388 * XXX: Need to ensure that there aren't two versions of a surface or
389 * bufferobj with different backing data active in the same buffer at
390 * once? Otherwise the cache could confuse them. Maybe better not to
393 * --> Isn't this the same as saying need to ensure batch is flushed
394 * before new data is uploaded to an existing buffer? We
395 * already try to make sure of that.
397 static void clear_cache( struct brw_cache
*cache
)
399 struct brw_cache_item
*c
, *next
;
402 for (i
= 0; i
< cache
->size
; i
++) {
403 for (c
= cache
->items
[i
]; c
; c
= next
) {
405 free((void *)c
->key
);
408 cache
->items
[i
] = NULL
;
414 void brw_clear_all_caches( struct brw_context
*brw
)
418 if (BRW_DEBUG
& DEBUG_STATE
)
419 debug_printf("%s\n", __FUNCTION__
);
421 for (i
= 0; i
< BRW_MAX_CACHE
; i
++)
422 clear_cache(&brw
->cache
[i
]);
424 if (brw
->curbe
.last_buf
) {
425 FREE(brw
->curbe
.last_buf
);
426 brw
->curbe
.last_buf
= NULL
;
429 brw
->state
.dirty
.brw
|= ~0;
430 brw
->state
.dirty
.cache
|= ~0;
437 void brw_destroy_caches( struct brw_context
*brw
)
441 for (i
= 0; i
< BRW_MAX_CACHE
; i
++)
442 clear_cache(&brw
->cache
[i
]);