wined3d: Replace the wined3d hash table with the generic red-black tree.
This commit is contained in:
parent
484cde1327
commit
ad6279de9f
|
@ -80,7 +80,7 @@ struct shader_arb_priv {
|
|||
GLuint depth_blt_vprogram_id;
|
||||
GLuint depth_blt_fprogram_id[tex_type_count];
|
||||
BOOL use_arbfp_fixed_func;
|
||||
struct hash_table_t *fragment_shaders;
|
||||
struct wine_rb_tree fragment_shaders;
|
||||
};
|
||||
|
||||
struct if_frame {
|
||||
|
@ -3090,14 +3090,20 @@ static HRESULT arbfp_alloc(IWineD3DDevice *iface) {
|
|||
if(!This->fragment_priv) return E_OUTOFMEMORY;
|
||||
}
|
||||
priv = This->fragment_priv;
|
||||
priv->fragment_shaders = hash_table_create(ffp_frag_program_key_hash, ffp_frag_program_key_compare);
|
||||
if (wine_rb_init(&priv->fragment_shaders, &wined3d_ffp_frag_program_rb_functions) == -1)
|
||||
{
|
||||
ERR("Failed to initialize rbtree.\n");
|
||||
HeapFree(GetProcessHeap(), 0, This->fragment_priv);
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
priv->use_arbfp_fixed_func = TRUE;
|
||||
return WINED3D_OK;
|
||||
}
|
||||
|
||||
static void arbfp_free_ffpshader(void *value, void *gli) {
|
||||
const WineD3D_GL_Info *gl_info = gli;
|
||||
struct arbfp_ffp_desc *entry_arb = value;
|
||||
static void arbfp_free_ffpshader(struct wine_rb_entry *entry, void *context)
|
||||
{
|
||||
const WineD3D_GL_Info *gl_info = context;
|
||||
struct arbfp_ffp_desc *entry_arb = WINE_RB_ENTRY_VALUE(entry, struct arbfp_ffp_desc, parent.entry);
|
||||
|
||||
ENTER_GL();
|
||||
GL_EXTCALL(glDeleteProgramsARB(1, &entry_arb->shader));
|
||||
|
@ -3110,7 +3116,7 @@ static void arbfp_free(IWineD3DDevice *iface) {
|
|||
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
|
||||
struct shader_arb_priv *priv = This->fragment_priv;
|
||||
|
||||
hash_table_destroy(priv->fragment_shaders, arbfp_free_ffpshader, &This->adapter->gl_info);
|
||||
wine_rb_destroy(&priv->fragment_shaders, arbfp_free_ffpshader, &This->adapter->gl_info);
|
||||
priv->use_arbfp_fixed_func = FALSE;
|
||||
|
||||
if(This->shader_backend != &arb_program_shader_backend) {
|
||||
|
@ -3766,7 +3772,7 @@ static void fragment_prog_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock,
|
|||
if(!use_pshader) {
|
||||
/* Find or create a shader implementing the fixed function pipeline settings, then activate it */
|
||||
gen_ffp_frag_op(stateblock, &settings, FALSE);
|
||||
desc = (const struct arbfp_ffp_desc *)find_ffp_frag_shader(priv->fragment_shaders, &settings);
|
||||
desc = (const struct arbfp_ffp_desc *)find_ffp_frag_shader(&priv->fragment_shaders, &settings);
|
||||
if(!desc) {
|
||||
struct arbfp_ffp_desc *new_desc = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_desc));
|
||||
if (!new_desc)
|
||||
|
@ -3782,7 +3788,7 @@ static void fragment_prog_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock,
|
|||
|
||||
memcpy(&new_desc->parent.settings, &settings, sizeof(settings));
|
||||
new_desc->shader = gen_arbfp_ffp_shader(&settings, stateblock);
|
||||
add_ffp_frag_shader(priv->fragment_shaders, &new_desc->parent);
|
||||
add_ffp_frag_shader(&priv->fragment_shaders, &new_desc->parent);
|
||||
TRACE("Allocated fixed function replacement shader descriptor %p\n", new_desc);
|
||||
desc = new_desc;
|
||||
}
|
||||
|
|
|
@ -53,8 +53,7 @@ struct atifs_ffp_desc
|
|||
|
||||
struct atifs_private_data
|
||||
{
|
||||
struct hash_table_t *fragment_shaders; /* A hashtable to track fragment pipeline replacement shaders */
|
||||
|
||||
struct wine_rb_tree fragment_shaders; /* A rb-tree to track fragment pipeline replacement shaders */
|
||||
};
|
||||
|
||||
static const char *debug_dstmod(GLuint mod) {
|
||||
|
@ -810,7 +809,7 @@ static void set_tex_op_atifs(DWORD state, IWineD3DStateBlockImpl *stateblock, Wi
|
|||
unsigned int i;
|
||||
|
||||
gen_ffp_frag_op(stateblock, &settings, TRUE);
|
||||
desc = (const struct atifs_ffp_desc *)find_ffp_frag_shader(priv->fragment_shaders, &settings);
|
||||
desc = (const struct atifs_ffp_desc *)find_ffp_frag_shader(&priv->fragment_shaders, &settings);
|
||||
if(!desc) {
|
||||
struct atifs_ffp_desc *new_desc = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_desc));
|
||||
if (!new_desc)
|
||||
|
@ -826,7 +825,7 @@ static void set_tex_op_atifs(DWORD state, IWineD3DStateBlockImpl *stateblock, Wi
|
|||
|
||||
memcpy(&new_desc->parent.settings, &settings, sizeof(settings));
|
||||
new_desc->shader = gen_ati_shader(settings.op, &GLINFO_LOCATION);
|
||||
add_ffp_frag_shader(priv->fragment_shaders, &new_desc->parent);
|
||||
add_ffp_frag_shader(&priv->fragment_shaders, &new_desc->parent);
|
||||
TRACE("Allocated fixed function replacement shader descriptor %p\n", new_desc);
|
||||
desc = new_desc;
|
||||
}
|
||||
|
@ -1114,14 +1113,20 @@ static HRESULT atifs_alloc(IWineD3DDevice *iface) {
|
|||
return E_OUTOFMEMORY;
|
||||
}
|
||||
priv = This->fragment_priv;
|
||||
priv->fragment_shaders = hash_table_create(ffp_frag_program_key_hash, ffp_frag_program_key_compare);
|
||||
if (wine_rb_init(&priv->fragment_shaders, &wined3d_ffp_frag_program_rb_functions) == -1)
|
||||
{
|
||||
ERR("Failed to initialize rbtree.\n");
|
||||
HeapFree(GetProcessHeap(), 0, This->fragment_priv);
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
return WINED3D_OK;
|
||||
}
|
||||
|
||||
#define GLINFO_LOCATION This->adapter->gl_info
|
||||
static void atifs_free_ffpshader(void *value, void *device) {
|
||||
IWineD3DDeviceImpl *This = device;
|
||||
struct atifs_ffp_desc *entry_ati = value;
|
||||
static void atifs_free_ffpshader(struct wine_rb_entry *entry, void *context)
|
||||
{
|
||||
IWineD3DDeviceImpl *This = context;
|
||||
struct atifs_ffp_desc *entry_ati = WINE_RB_ENTRY_VALUE(entry, struct atifs_ffp_desc, parent.entry);
|
||||
|
||||
ENTER_GL();
|
||||
GL_EXTCALL(glDeleteFragmentShaderATI(entry_ati->shader));
|
||||
|
@ -1134,7 +1139,7 @@ static void atifs_free(IWineD3DDevice *iface) {
|
|||
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
|
||||
struct atifs_private_data *priv = This->fragment_priv;
|
||||
|
||||
hash_table_destroy(priv->fragment_shaders, atifs_free_ffpshader, This);
|
||||
wine_rb_destroy(&priv->fragment_shaders, atifs_free_ffpshader, This);
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, priv);
|
||||
This->fragment_priv = NULL;
|
||||
|
|
|
@ -83,7 +83,7 @@ struct constant_heap
|
|||
|
||||
/* GLSL shader private data */
|
||||
struct shader_glsl_priv {
|
||||
struct hash_table_t *glsl_program_lookup;
|
||||
struct wine_rb_tree program_lookup;
|
||||
struct glsl_shader_prog_link *glsl_program;
|
||||
struct constant_heap vconst_heap;
|
||||
struct constant_heap pconst_heap;
|
||||
|
@ -94,6 +94,7 @@ struct shader_glsl_priv {
|
|||
|
||||
/* Struct to maintain data about a linked GLSL program */
|
||||
struct glsl_shader_prog_link {
|
||||
struct wine_rb_entry program_lookup_entry;
|
||||
struct list vshader_entry;
|
||||
struct list pshader_entry;
|
||||
GLhandleARB programId;
|
||||
|
@ -543,10 +544,9 @@ static void shader_glsl_load_constantsB(IWineD3DBaseShaderImpl *This, const Wine
|
|||
}
|
||||
}
|
||||
|
||||
static void reset_program_constant_version(void *value, void *context)
|
||||
static void reset_program_constant_version(struct wine_rb_entry *entry, void *context)
|
||||
{
|
||||
struct glsl_shader_prog_link *entry = value;
|
||||
entry->constant_version = 0;
|
||||
WINE_RB_ENTRY_VALUE(entry, struct glsl_shader_prog_link, program_lookup_entry)->constant_version = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -696,7 +696,7 @@ static void shader_glsl_load_constants(
|
|||
if (priv->next_constant_version == UINT_MAX)
|
||||
{
|
||||
TRACE("Max constant version reached, resetting to 0.\n");
|
||||
hash_table_for_each_entry(priv->glsl_program_lookup, reset_program_constant_version, NULL);
|
||||
wine_rb_for_each_entry(&priv->program_lookup, reset_program_constant_version, NULL);
|
||||
priv->next_constant_version = 1;
|
||||
}
|
||||
else
|
||||
|
@ -3261,15 +3261,17 @@ static void pshader_glsl_input_pack(IWineD3DPixelShader *iface, SHADER_BUFFER *b
|
|||
********************************************/
|
||||
|
||||
static void add_glsl_program_entry(struct shader_glsl_priv *priv, struct glsl_shader_prog_link *entry) {
|
||||
glsl_program_key_t *key;
|
||||
glsl_program_key_t key;
|
||||
|
||||
key = HeapAlloc(GetProcessHeap(), 0, sizeof(glsl_program_key_t));
|
||||
key->vshader = entry->vshader;
|
||||
key->pshader = entry->pshader;
|
||||
key->vs_args = entry->vs_args;
|
||||
key->ps_args = entry->ps_args;
|
||||
key.vshader = entry->vshader;
|
||||
key.pshader = entry->pshader;
|
||||
key.vs_args = entry->vs_args;
|
||||
key.ps_args = entry->ps_args;
|
||||
|
||||
hash_table_put(priv->glsl_program_lookup, key, entry);
|
||||
if (wine_rb_put(&priv->program_lookup, &key, &entry->program_lookup_entry) == -1)
|
||||
{
|
||||
ERR("Failed to insert program entry.\n");
|
||||
}
|
||||
}
|
||||
|
||||
static struct glsl_shader_prog_link *get_glsl_program_entry(struct shader_glsl_priv *priv,
|
||||
|
@ -3282,21 +3284,21 @@ static struct glsl_shader_prog_link *get_glsl_program_entry(struct shader_glsl_p
|
|||
key.vs_args = *vs_args;
|
||||
key.ps_args = *ps_args;
|
||||
|
||||
return hash_table_get(priv->glsl_program_lookup, &key);
|
||||
return WINE_RB_ENTRY_VALUE(wine_rb_get(&priv->program_lookup, &key),
|
||||
struct glsl_shader_prog_link, program_lookup_entry);
|
||||
}
|
||||
|
||||
/* GL locking is done by the caller */
|
||||
static void delete_glsl_program_entry(struct shader_glsl_priv *priv, const WineD3D_GL_Info *gl_info,
|
||||
struct glsl_shader_prog_link *entry)
|
||||
{
|
||||
glsl_program_key_t *key;
|
||||
glsl_program_key_t key;
|
||||
|
||||
key = HeapAlloc(GetProcessHeap(), 0, sizeof(glsl_program_key_t));
|
||||
key->vshader = entry->vshader;
|
||||
key->pshader = entry->pshader;
|
||||
key->vs_args = entry->vs_args;
|
||||
key->ps_args = entry->ps_args;
|
||||
hash_table_remove(priv->glsl_program_lookup, key);
|
||||
key.vshader = entry->vshader;
|
||||
key.pshader = entry->pshader;
|
||||
key.vs_args = entry->vs_args;
|
||||
key.ps_args = entry->ps_args;
|
||||
wine_rb_remove(&priv->program_lookup, &key);
|
||||
|
||||
GL_EXTCALL(glDeleteObjectARB(entry->programId));
|
||||
if (entry->vshader) list_remove(&entry->vshader_entry);
|
||||
|
@ -4383,29 +4385,24 @@ static void shader_glsl_destroy(IWineD3DBaseShader *iface) {
|
|||
}
|
||||
}
|
||||
|
||||
static unsigned int glsl_program_key_hash(const void *key)
|
||||
static int glsl_program_key_compare(const void *key, const struct wine_rb_entry *entry)
|
||||
{
|
||||
const glsl_program_key_t *k = key;
|
||||
const struct glsl_shader_prog_link *prog = WINE_RB_ENTRY_VALUE(entry,
|
||||
const struct glsl_shader_prog_link, program_lookup_entry);
|
||||
int cmp;
|
||||
|
||||
unsigned int hash = ((DWORD_PTR) k->vshader) | ((DWORD_PTR) k->pshader) << 16;
|
||||
hash += ~(hash << 15);
|
||||
hash ^= (hash >> 10);
|
||||
hash += (hash << 3);
|
||||
hash ^= (hash >> 6);
|
||||
hash += ~(hash << 11);
|
||||
hash ^= (hash >> 16);
|
||||
if (k->vshader > prog->vshader) return 1;
|
||||
else if (k->vshader < prog->vshader) return -1;
|
||||
|
||||
return hash;
|
||||
}
|
||||
if (k->pshader > prog->pshader) return 1;
|
||||
else if (k->pshader < prog->pshader) return -1;
|
||||
|
||||
static BOOL glsl_program_key_compare(const void *keya, const void *keyb)
|
||||
{
|
||||
const glsl_program_key_t *ka = keya;
|
||||
const glsl_program_key_t *kb = keyb;
|
||||
cmp = memcmp(&k->vs_args, &prog->vs_args, sizeof(prog->vs_args));
|
||||
if (cmp) return cmp;
|
||||
|
||||
return ka->vshader == kb->vshader && ka->pshader == kb->pshader &&
|
||||
(memcmp(&ka->ps_args, &kb->ps_args, sizeof(kb->ps_args)) == 0) &&
|
||||
(memcmp(&ka->vs_args, &kb->vs_args, sizeof(kb->vs_args)) == 0);
|
||||
cmp = memcmp(&k->ps_args, &prog->ps_args, sizeof(prog->ps_args));
|
||||
return cmp;
|
||||
}
|
||||
|
||||
static BOOL constant_heap_init(struct constant_heap *heap, unsigned int constant_count)
|
||||
|
@ -4432,6 +4429,14 @@ static void constant_heap_free(struct constant_heap *heap)
|
|||
HeapFree(GetProcessHeap(), 0, heap->entries);
|
||||
}
|
||||
|
||||
static const struct wine_rb_functions wined3d_glsl_program_rb_functions =
|
||||
{
|
||||
wined3d_rb_alloc,
|
||||
wined3d_rb_realloc,
|
||||
wined3d_rb_free,
|
||||
glsl_program_key_compare,
|
||||
};
|
||||
|
||||
static HRESULT shader_glsl_alloc(IWineD3DDevice *iface) {
|
||||
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
|
||||
const WineD3D_GL_Info *gl_info = &This->adapter->gl_info;
|
||||
|
@ -4463,7 +4468,16 @@ static HRESULT shader_glsl_alloc(IWineD3DDevice *iface) {
|
|||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
priv->glsl_program_lookup = hash_table_create(glsl_program_key_hash, glsl_program_key_compare);
|
||||
if (wine_rb_init(&priv->program_lookup, &wined3d_glsl_program_rb_functions) == -1)
|
||||
{
|
||||
ERR("Failed to initialize rbtree.\n");
|
||||
constant_heap_free(&priv->pconst_heap);
|
||||
constant_heap_free(&priv->vconst_heap);
|
||||
HeapFree(GetProcessHeap(), 0, priv->stack);
|
||||
HeapFree(GetProcessHeap(), 0, priv);
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
priv->next_constant_version = 1;
|
||||
|
||||
This->shader_priv = priv;
|
||||
|
@ -4486,7 +4500,7 @@ static void shader_glsl_free(IWineD3DDevice *iface) {
|
|||
}
|
||||
LEAVE_GL();
|
||||
|
||||
hash_table_destroy(priv->glsl_program_lookup, NULL, NULL);
|
||||
wine_rb_destroy(&priv->program_lookup, NULL, NULL);
|
||||
constant_heap_free(&priv->pconst_heap);
|
||||
constant_heap_free(&priv->vconst_heap);
|
||||
|
||||
|
|
|
@ -1901,238 +1901,6 @@ BOOL CalculateTexRect(IWineD3DSurfaceImpl *This, RECT *Rect, float glTexCoord[4]
|
|||
}
|
||||
#undef GLINFO_LOCATION
|
||||
|
||||
/* Hash table functions */
|
||||
|
||||
struct hash_table_t *hash_table_create(hash_function_t *hash_function, compare_function_t *compare_function)
|
||||
{
|
||||
struct hash_table_t *table;
|
||||
unsigned int initial_size = 8;
|
||||
|
||||
table = HeapAlloc(GetProcessHeap(), 0, sizeof(struct hash_table_t) + (initial_size * sizeof(struct list)));
|
||||
if (!table)
|
||||
{
|
||||
ERR("Failed to allocate table, returning NULL.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
table->hash_function = hash_function;
|
||||
table->compare_function = compare_function;
|
||||
|
||||
table->grow_size = initial_size - (initial_size >> 2);
|
||||
table->shrink_size = 0;
|
||||
|
||||
table->buckets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, initial_size * sizeof(struct list));
|
||||
if (!table->buckets)
|
||||
{
|
||||
ERR("Failed to allocate table buckets, returning NULL.\n");
|
||||
HeapFree(GetProcessHeap(), 0, table);
|
||||
return NULL;
|
||||
}
|
||||
table->bucket_count = initial_size;
|
||||
|
||||
table->entries = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, table->grow_size * sizeof(struct hash_table_entry_t));
|
||||
if (!table->entries)
|
||||
{
|
||||
ERR("Failed to allocate table entries, returning NULL.\n");
|
||||
HeapFree(GetProcessHeap(), 0, table->buckets);
|
||||
HeapFree(GetProcessHeap(), 0, table);
|
||||
return NULL;
|
||||
}
|
||||
table->entry_count = 0;
|
||||
|
||||
list_init(&table->free_entries);
|
||||
table->count = 0;
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
void hash_table_destroy(struct hash_table_t *table, void (*free_value)(void *value, void *cb), void *cb)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
|
||||
for (i = 0; i < table->entry_count; ++i)
|
||||
{
|
||||
if(free_value) {
|
||||
free_value(table->entries[i].value, cb);
|
||||
}
|
||||
HeapFree(GetProcessHeap(), 0, table->entries[i].key);
|
||||
}
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, table->entries);
|
||||
HeapFree(GetProcessHeap(), 0, table->buckets);
|
||||
HeapFree(GetProcessHeap(), 0, table);
|
||||
}
|
||||
|
||||
void hash_table_for_each_entry(struct hash_table_t *table, void (*callback)(void *value, void *context), void *context)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
|
||||
for (i = 0; i < table->entry_count; ++i)
|
||||
{
|
||||
callback(table->entries[i].value, context);
|
||||
}
|
||||
}
|
||||
|
||||
static inline struct hash_table_entry_t *hash_table_get_by_idx(const struct hash_table_t *table, const void *key,
|
||||
unsigned int idx)
|
||||
{
|
||||
struct hash_table_entry_t *entry;
|
||||
|
||||
if (table->buckets[idx].next)
|
||||
LIST_FOR_EACH_ENTRY(entry, &(table->buckets[idx]), struct hash_table_entry_t, entry)
|
||||
if (table->compare_function(entry->key, key)) return entry;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static BOOL hash_table_resize(struct hash_table_t *table, unsigned int new_bucket_count)
|
||||
{
|
||||
unsigned int new_entry_count = 0;
|
||||
struct hash_table_entry_t *new_entries;
|
||||
struct list *new_buckets;
|
||||
unsigned int grow_size = new_bucket_count - (new_bucket_count >> 2);
|
||||
unsigned int i;
|
||||
|
||||
new_buckets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, new_bucket_count * sizeof(struct list));
|
||||
if (!new_buckets)
|
||||
{
|
||||
ERR("Failed to allocate new buckets, returning FALSE.\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
new_entries = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, grow_size * sizeof(struct hash_table_entry_t));
|
||||
if (!new_entries)
|
||||
{
|
||||
ERR("Failed to allocate new entries, returning FALSE.\n");
|
||||
HeapFree(GetProcessHeap(), 0, new_buckets);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (i = 0; i < table->bucket_count; ++i)
|
||||
{
|
||||
if (table->buckets[i].next)
|
||||
{
|
||||
struct hash_table_entry_t *entry, *entry2;
|
||||
|
||||
LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &table->buckets[i], struct hash_table_entry_t, entry)
|
||||
{
|
||||
int j;
|
||||
struct hash_table_entry_t *new_entry = new_entries + (new_entry_count++);
|
||||
*new_entry = *entry;
|
||||
|
||||
j = new_entry->hash & (new_bucket_count - 1);
|
||||
|
||||
if (!new_buckets[j].next) list_init(&new_buckets[j]);
|
||||
list_add_head(&new_buckets[j], &new_entry->entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, table->buckets);
|
||||
table->buckets = new_buckets;
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, table->entries);
|
||||
table->entries = new_entries;
|
||||
|
||||
table->entry_count = new_entry_count;
|
||||
list_init(&table->free_entries);
|
||||
|
||||
table->bucket_count = new_bucket_count;
|
||||
table->grow_size = grow_size;
|
||||
table->shrink_size = new_bucket_count > 8 ? new_bucket_count >> 2 : 0;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void hash_table_put(struct hash_table_t *table, void *key, void *value)
|
||||
{
|
||||
unsigned int idx;
|
||||
unsigned int hash;
|
||||
struct hash_table_entry_t *entry;
|
||||
|
||||
hash = table->hash_function(key);
|
||||
idx = hash & (table->bucket_count - 1);
|
||||
entry = hash_table_get_by_idx(table, key, idx);
|
||||
|
||||
if (entry)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, key);
|
||||
entry->value = value;
|
||||
|
||||
if (!value)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, entry->key);
|
||||
entry->key = NULL;
|
||||
|
||||
/* Remove the entry */
|
||||
list_remove(&entry->entry);
|
||||
list_add_head(&table->free_entries, &entry->entry);
|
||||
|
||||
--table->count;
|
||||
|
||||
/* Shrink if necessary */
|
||||
if (table->count < table->shrink_size) {
|
||||
if (!hash_table_resize(table, table->bucket_count >> 1))
|
||||
{
|
||||
ERR("Failed to shrink the table...\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!value) return;
|
||||
|
||||
/* Grow if necessary */
|
||||
if (table->count >= table->grow_size)
|
||||
{
|
||||
if (!hash_table_resize(table, table->bucket_count << 1))
|
||||
{
|
||||
ERR("Failed to grow the table, returning.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
idx = hash & (table->bucket_count - 1);
|
||||
}
|
||||
|
||||
/* Find an entry to insert */
|
||||
if (!list_empty(&table->free_entries))
|
||||
{
|
||||
struct list *elem = list_head(&table->free_entries);
|
||||
|
||||
list_remove(elem);
|
||||
entry = LIST_ENTRY(elem, struct hash_table_entry_t, entry);
|
||||
} else {
|
||||
entry = table->entries + (table->entry_count++);
|
||||
}
|
||||
|
||||
/* Insert the entry */
|
||||
entry->key = key;
|
||||
entry->value = value;
|
||||
entry->hash = hash;
|
||||
if (!table->buckets[idx].next) list_init(&table->buckets[idx]);
|
||||
list_add_head(&table->buckets[idx], &entry->entry);
|
||||
|
||||
++table->count;
|
||||
}
|
||||
|
||||
void hash_table_remove(struct hash_table_t *table, void *key)
|
||||
{
|
||||
hash_table_put(table, key, NULL);
|
||||
}
|
||||
|
||||
void *hash_table_get(const struct hash_table_t *table, const void *key)
|
||||
{
|
||||
unsigned int idx;
|
||||
struct hash_table_entry_t *entry;
|
||||
|
||||
idx = table->hash_function(key) & (table->bucket_count - 1);
|
||||
entry = hash_table_get_by_idx(table, key, idx);
|
||||
|
||||
return entry ? entry->value : NULL;
|
||||
}
|
||||
|
||||
#define GLINFO_LOCATION stateblock->wineD3DDevice->adapter->gl_info
|
||||
void gen_ffp_frag_op(IWineD3DStateBlockImpl *stateblock, struct ffp_frag_settings *settings, BOOL ignore_textype) {
|
||||
#define ARG1 0x01
|
||||
|
@ -2366,20 +2134,20 @@ void gen_ffp_frag_op(IWineD3DStateBlockImpl *stateblock, struct ffp_frag_setting
|
|||
}
|
||||
#undef GLINFO_LOCATION
|
||||
|
||||
const struct ffp_frag_desc *find_ffp_frag_shader(const struct hash_table_t *fragment_shaders,
|
||||
const struct ffp_frag_desc *find_ffp_frag_shader(const struct wine_rb_tree *fragment_shaders,
|
||||
const struct ffp_frag_settings *settings)
|
||||
{
|
||||
return hash_table_get(fragment_shaders, settings);
|
||||
return WINE_RB_ENTRY_VALUE(wine_rb_get(fragment_shaders, settings), struct ffp_frag_desc, entry);
|
||||
}
|
||||
|
||||
void add_ffp_frag_shader(struct hash_table_t *shaders, struct ffp_frag_desc *desc) {
|
||||
struct ffp_frag_settings *key = HeapAlloc(GetProcessHeap(), 0, sizeof(*key));
|
||||
void add_ffp_frag_shader(struct wine_rb_tree *shaders, struct ffp_frag_desc *desc)
|
||||
{
|
||||
/* Note that the key is the implementation independent part of the ffp_frag_desc structure,
|
||||
* whereas desc points to an extended structure with implementation specific parts.
|
||||
* Make a copy of the key because hash_table_put takes ownership of it
|
||||
*/
|
||||
*key = desc->settings;
|
||||
hash_table_put(shaders, key, desc);
|
||||
* whereas desc points to an extended structure with implementation specific parts. */
|
||||
if (wine_rb_put(shaders, &desc->settings, &desc->entry) == -1)
|
||||
{
|
||||
ERR("Failed to insert ffp frag shader.\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Activates the texture dimension according to the bound D3D texture.
|
||||
|
@ -2478,41 +2246,37 @@ void sampler_texdim(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCont
|
|||
}
|
||||
#undef GLINFO_LOCATION
|
||||
|
||||
unsigned int ffp_frag_program_key_hash(const void *key)
|
||||
void *wined3d_rb_alloc(size_t size)
|
||||
{
|
||||
const struct ffp_frag_settings *k = key;
|
||||
unsigned int hash = 0, i;
|
||||
const DWORD *blob;
|
||||
|
||||
/* This takes the texture op settings of stage 0 and 1 into account.
|
||||
* how exactly depends on the memory laybout of the compiler, but it
|
||||
* should not matter too much. Stages > 1 are used rarely, so there's
|
||||
* no need to process them. Even if they're used it is likely that
|
||||
* the ffp setup has distinct stage 0 and 1 settings.
|
||||
*/
|
||||
for(i = 0; i < 2; i++) {
|
||||
blob = (const DWORD *)&k->op[i];
|
||||
hash ^= blob[0] ^ blob[1];
|
||||
}
|
||||
|
||||
hash += ~(hash << 15);
|
||||
hash ^= (hash >> 10);
|
||||
hash += (hash << 3);
|
||||
hash ^= (hash >> 6);
|
||||
hash += ~(hash << 11);
|
||||
hash ^= (hash >> 16);
|
||||
|
||||
return hash;
|
||||
return HeapAlloc(GetProcessHeap(), 0, size);
|
||||
}
|
||||
|
||||
BOOL ffp_frag_program_key_compare(const void *keya, const void *keyb)
|
||||
void *wined3d_rb_realloc(void *ptr, size_t size)
|
||||
{
|
||||
const struct ffp_frag_settings *ka = keya;
|
||||
const struct ffp_frag_settings *kb = keyb;
|
||||
|
||||
return memcmp(ka, kb, sizeof(*ka)) == 0;
|
||||
return HeapReAlloc(GetProcessHeap(), 0, ptr, size);
|
||||
}
|
||||
|
||||
void wined3d_rb_free(void *ptr)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, ptr);
|
||||
}
|
||||
|
||||
static int ffp_frag_program_key_compare(const void *key, const struct wine_rb_entry *entry)
|
||||
{
|
||||
const struct ffp_frag_settings *ka = key;
|
||||
const struct ffp_frag_settings *kb = &WINE_RB_ENTRY_VALUE(entry, const struct ffp_frag_desc, entry)->settings;
|
||||
|
||||
return memcmp(ka, kb, sizeof(*ka));
|
||||
}
|
||||
|
||||
const struct wine_rb_functions wined3d_ffp_frag_program_rb_functions =
|
||||
{
|
||||
wined3d_rb_alloc,
|
||||
wined3d_rb_realloc,
|
||||
wined3d_rb_free,
|
||||
ffp_frag_program_key_compare,
|
||||
};
|
||||
|
||||
UINT wined3d_log2i(UINT32 x)
|
||||
{
|
||||
static const BYTE l[] =
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "wine/wined3d.h"
|
||||
#include "wined3d_gl.h"
|
||||
#include "wine/list.h"
|
||||
#include "wine/rbtree.h"
|
||||
|
||||
/* Texture format fixups */
|
||||
|
||||
|
@ -126,36 +127,9 @@ static inline enum yuv_fixup get_yuv_fixup(struct color_fixup_desc fixup)
|
|||
return yuv_fixup;
|
||||
}
|
||||
|
||||
/* Hash table functions */
|
||||
typedef unsigned int (hash_function_t)(const void *key);
|
||||
typedef BOOL (compare_function_t)(const void *keya, const void *keyb);
|
||||
|
||||
struct hash_table_entry_t {
|
||||
void *key;
|
||||
void *value;
|
||||
unsigned int hash;
|
||||
struct list entry;
|
||||
};
|
||||
|
||||
struct hash_table_t {
|
||||
hash_function_t *hash_function;
|
||||
compare_function_t *compare_function;
|
||||
struct list *buckets;
|
||||
unsigned int bucket_count;
|
||||
struct hash_table_entry_t *entries;
|
||||
unsigned int entry_count;
|
||||
struct list free_entries;
|
||||
unsigned int count;
|
||||
unsigned int grow_size;
|
||||
unsigned int shrink_size;
|
||||
};
|
||||
|
||||
struct hash_table_t *hash_table_create(hash_function_t *hash_function, compare_function_t *compare_function);
|
||||
void hash_table_destroy(struct hash_table_t *table, void (*free_value)(void *value, void *cb), void *cb);
|
||||
void hash_table_for_each_entry(struct hash_table_t *table, void (*callback)(void *value, void *context), void *context);
|
||||
void *hash_table_get(const struct hash_table_t *table, const void *key);
|
||||
void hash_table_put(struct hash_table_t *table, void *key, void *value);
|
||||
void hash_table_remove(struct hash_table_t *table, void *key);
|
||||
void *wined3d_rb_alloc(size_t size);
|
||||
void *wined3d_rb_realloc(void *ptr, size_t size);
|
||||
void wined3d_rb_free(void *ptr);
|
||||
|
||||
/* Device caps */
|
||||
#define MAX_PALETTES 65536
|
||||
|
@ -1384,15 +1358,16 @@ struct ffp_frag_settings {
|
|||
|
||||
struct ffp_frag_desc
|
||||
{
|
||||
struct wine_rb_entry entry;
|
||||
struct ffp_frag_settings settings;
|
||||
};
|
||||
|
||||
extern const struct wine_rb_functions wined3d_ffp_frag_program_rb_functions;
|
||||
|
||||
void gen_ffp_frag_op(IWineD3DStateBlockImpl *stateblock, struct ffp_frag_settings *settings, BOOL ignore_textype);
|
||||
const struct ffp_frag_desc *find_ffp_frag_shader(const struct hash_table_t *fragment_shaders,
|
||||
const struct ffp_frag_desc *find_ffp_frag_shader(const struct wine_rb_tree *fragment_shaders,
|
||||
const struct ffp_frag_settings *settings);
|
||||
void add_ffp_frag_shader(struct hash_table_t *shaders, struct ffp_frag_desc *desc);
|
||||
BOOL ffp_frag_program_key_compare(const void *keya, const void *keyb);
|
||||
unsigned int ffp_frag_program_key_hash(const void *key);
|
||||
void add_ffp_frag_shader(struct wine_rb_tree *shaders, struct ffp_frag_desc *desc);
|
||||
|
||||
/*****************************************************************************
|
||||
* IWineD3D implementation structure
|
||||
|
|
Loading…
Reference in New Issue