Commit ad6279de authored by Henri Verbeet's avatar Henri Verbeet Committed by Alexandre Julliard

wined3d: Replace the wined3d hash table with the generic red-black tree.

parent 484cde13
......@@ -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);
......
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment