[PATCH] WineD3D: Use a hashmap to store the ffp shaders=0A=

Stefan Doesinger stefan at codeweavers.com
Tue Jul 29 10:51:52 CDT 2008


=0A=
---=0A=
 dlls/wined3d/ati_fragment_shader.c |   32 +++++++++--------=0A=
 dlls/wined3d/glsl_shader.c         |    2 +-=0A=
 dlls/wined3d/utils.c               |   64 =
++++++++++++++++++++++++++----------=0A=
 dlls/wined3d/wined3d_private.h     |    9 +++--=0A=
 4 files changed, 69 insertions(+), 38 deletions(-)=0A=
=0A=
diff --git a/dlls/wined3d/ati_fragment_shader.c =
b/dlls/wined3d/ati_fragment_shader.c=0A=
index 6dc0193..54b05b1 100644=0A=
--- a/dlls/wined3d/ati_fragment_shader.c=0A=
+++ b/dlls/wined3d/ati_fragment_shader.c=0A=
@@ -50,7 +50,7 @@ struct atifs_ffp_desc=0A=
 =0A=
 struct atifs_private_data=0A=
 {=0A=
-    struct list fragment_shaders; /* A linked list to track fragment =
pipeline replacement shaders */=0A=
+    hash_table_t *fragment_shaders; /* A hashtable to track fragment =
pipeline replacement shaders */=0A=
 =0A=
 };=0A=
 =0A=
@@ -786,7 +786,7 @@ static void set_tex_op_atifs(DWORD state, =
IWineD3DStateBlockImpl *stateblock, Wi=0A=
     unsigned int i;=0A=
 =0A=
     gen_ffp_op(stateblock, &settings, TRUE);=0A=
-    desc =3D (struct atifs_ffp_desc *) =
find_ffp_shader(&priv->fragment_shaders, &settings);=0A=
+    desc =3D (struct atifs_ffp_desc *) =
find_ffp_shader(priv->fragment_shaders, &settings);=0A=
     if(!desc) {=0A=
         desc =3D HeapAlloc(GetProcessHeap(), 0, sizeof(*desc));=0A=
         if(!desc) {=0A=
@@ -801,7 +801,7 @@ static void set_tex_op_atifs(DWORD state, =
IWineD3DStateBlockImpl *stateblock, Wi=0A=
 =0A=
         memcpy(&desc->parent.settings, &settings, sizeof(settings));=0A=
         desc->shader =3D gen_ati_shader(settings.op, &GLINFO_LOCATION);=0A=
-        add_ffp_shader(&priv->fragment_shaders, &desc->parent);=0A=
+        add_ffp_shader(priv->fragment_shaders, &desc->parent);=0A=
         TRACE("Allocated fixed function replacement shader descriptor =
%p\n", desc);=0A=
     }=0A=
 =0A=
@@ -1036,26 +1036,28 @@ static HRESULT atifs_alloc(IWineD3DDevice =
*iface) {=0A=
         return E_OUTOFMEMORY;=0A=
     }=0A=
     priv =3D (struct atifs_private_data *) This->fragment_priv;=0A=
-    list_init(&priv->fragment_shaders);=0A=
+    priv->fragment_shaders =3D hash_table_create(ffp_program_key_hash, =
ffp_program_key_compare);=0A=
     return WINED3D_OK;=0A=
 }=0A=
 =0A=
 #define GLINFO_LOCATION This->adapter->gl_info=0A=
+static void atifs_free_ffpshader(void *value, void *device) {=0A=
+    IWineD3DDeviceImpl *This =3D device;=0A=
+    struct atifs_ffp_desc *entry_ati =3D value;=0A=
+=0A=
+    ENTER_GL();=0A=
+    GL_EXTCALL(glDeleteFragmentShaderATI(entry_ati->shader));=0A=
+    checkGLcall("glDeleteFragmentShaderATI(entry->shader)");=0A=
+    HeapFree(GetProcessHeap(), 0, entry_ati);=0A=
+    LEAVE_GL();=0A=
+}=0A=
+=0A=
 static void atifs_free(IWineD3DDevice *iface) {=0A=
     IWineD3DDeviceImpl *This =3D (IWineD3DDeviceImpl *) iface;=0A=
     struct atifs_private_data *priv =3D (struct atifs_private_data *) =
This->fragment_priv;=0A=
-    struct ffp_desc *entry, *entry2;=0A=
-    struct atifs_ffp_desc *entry_ati;=0A=
 =0A=
-    ENTER_GL();=0A=
-    LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &priv->fragment_shaders, =
struct ffp_desc, entry) {=0A=
-        entry_ati =3D (struct atifs_ffp_desc *) entry;=0A=
-        GL_EXTCALL(glDeleteFragmentShaderATI(entry_ati->shader));=0A=
-        checkGLcall("glDeleteFragmentShaderATI(entry->shader)");=0A=
-        list_remove(&entry->entry);=0A=
-        HeapFree(GetProcessHeap(), 0, entry);=0A=
-    }=0A=
-    LEAVE_GL();=0A=
+    hash_table_destroy(priv->fragment_shaders, atifs_free_ffpshader, =
This);=0A=
+=0A=
     HeapFree(GetProcessHeap(), 0, priv);=0A=
     This->fragment_priv =3D NULL;=0A=
 }=0A=
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c=0A=
index ce84ea7..80c4411 100644=0A=
--- a/dlls/wined3d/glsl_shader.c=0A=
+++ b/dlls/wined3d/glsl_shader.c=0A=
@@ -3527,7 +3527,7 @@ static void shader_glsl_free(IWineD3DDevice =
*iface) {=0A=
         GL_EXTCALL(glDeleteObjectARB(priv->depth_blt_glsl_program_id));=0A=
     }=0A=
 =0A=
-    hash_table_destroy(priv->glsl_program_lookup);=0A=
+    hash_table_destroy(priv->glsl_program_lookup, NULL, NULL);=0A=
 =0A=
     HeapFree(GetProcessHeap(), 0, This->shader_priv);=0A=
     This->shader_priv =3D NULL;=0A=
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c=0A=
index 80de55c..e97a337 100644=0A=
--- a/dlls/wined3d/utils.c=0A=
+++ b/dlls/wined3d/utils.c=0A=
@@ -1576,12 +1576,15 @@ hash_table_t *hash_table_create(hash_function_t =
*hash_function, compare_function=0A=
     return table;=0A=
 }=0A=
 =0A=
-void hash_table_destroy(hash_table_t *table)=0A=
+void hash_table_destroy(hash_table_t *table, void (*free_value)(void =
*value, void *cb), void *cb)=0A=
 {=0A=
     unsigned int i =3D 0;=0A=
 =0A=
     for (i =3D 0; i < table->entry_count; ++i)=0A=
     {=0A=
+        if(free_value) {=0A=
+            free_value(table->entries[i].value, cb);=0A=
+        }=0A=
         HeapFree(GetProcessHeap(), 0, table->entries[i].key);=0A=
     }=0A=
 =0A=
@@ -1952,26 +1955,18 @@ void gen_ffp_op(IWineD3DStateBlockImpl =
*stateblock, struct ffp_settings *setting=0A=
 }=0A=
 #undef GLINFO_LOCATION=0A=
 =0A=
-struct ffp_desc *find_ffp_shader(struct list *shaders, struct =
ffp_settings *settings)=0A=
+struct ffp_desc *find_ffp_shader(hash_table_t *fragment_shaders, struct =
ffp_settings *settings)=0A=
 {=0A=
-    struct ffp_desc *entry;=0A=
+    return (struct ffp_desc *)hash_table_get(fragment_shaders, =
settings);}=0A=
 =0A=
-    /* TODO: Optimize this. Finding the shader can be optimized by e.g. =
sorting the list,=0A=
-     * or maybe consider using hashtables=0A=
+void add_ffp_shader(hash_table_t *shaders, struct ffp_desc *desc) {=0A=
+    struct ffp_settings *key =3D HeapAlloc(GetProcessHeap(), 0, =
sizeof(*key));=0A=
+    /* Note that the key is the implementation independent part of the =
ffp_desc structure,=0A=
+     * whereas desc points to an extended structure with implementation =
specific parts.=0A=
+     * Make a copy of the key because hash_table_put takes ownership of =
it=0A=
      */=0A=
-    LIST_FOR_EACH_ENTRY(entry, shaders, struct ffp_desc, entry) {=0A=
-        if(memcmp(settings, &entry->settings, sizeof(*settings)) =3D=3D =
0) {=0A=
-            TRACE("Found shader entry %p\n", entry);=0A=
-            return entry;=0A=
-        }=0A=
-    }=0A=
-=0A=
-    TRACE("Shader not found\n");=0A=
-    return NULL;=0A=
-}=0A=
-=0A=
-void add_ffp_shader(struct list *shaders, struct ffp_desc *desc) {=0A=
-    list_add_head(shaders, &desc->entry);=0A=
+    *key =3D desc->settings;=0A=
+    hash_table_put(shaders, key, desc);=0A=
 }=0A=
 =0A=
 /* Activates the texture dimension according to the bound D3D texture.=0A=
@@ -2068,3 +2063,36 @@ void sampler_texdim(DWORD state, =
IWineD3DStateBlockImpl *stateblock, WineD3DCont=0A=
     texture_activate_dimensions(sampler, stateblock, context);=0A=
 }=0A=
 #undef GLINFO_LOCATION=0A=
+=0A=
+unsigned int ffp_program_key_hash(void *key) {=0A=
+    struct ffp_settings *k =3D (struct ffp_settings *)key;=0A=
+    unsigned int hash =3D 0, i;=0A=
+    DWORD *blob;=0A=
+=0A=
+    /* This takes the texture op settings of stage 0 and 1 into account.=0A=
+     * how exactly depends on the memory laybout of the compiler, but it=0A=
+     * should not matter too much. Stages > 1 are used rarely, so =
there's=0A=
+     * no need to process them. Even if they're used it is likely that=0A=
+     * the ffp setup has distinct stage 0 and 1 settings.=0A=
+     */=0A=
+    for(i =3D 0; i < 2; i++) {=0A=
+        blob =3D (DWORD *) &k->op[i];=0A=
+        hash ^=3D blob[0] ^ blob[1];=0A=
+    }=0A=
+=0A=
+    hash +=3D ~(hash << 15);=0A=
+    hash ^=3D  (hash >> 10);=0A=
+    hash +=3D  (hash << 3);=0A=
+    hash ^=3D  (hash >> 6);=0A=
+    hash +=3D ~(hash << 11);=0A=
+    hash ^=3D  (hash >> 16);=0A=
+=0A=
+    return hash;=0A=
+}=0A=
+=0A=
+BOOL ffp_program_key_compare(void *keya, void *keyb) {=0A=
+    struct ffp_settings *ka =3D (struct ffp_settings *)keya;=0A=
+    struct ffp_settings *kb =3D (struct ffp_settings *)keyb;=0A=
+=0A=
+    return memcmp(ka, kb, sizeof(*ka)) =3D=3D 0;=0A=
+}=0A=
diff --git a/dlls/wined3d/wined3d_private.h =
b/dlls/wined3d/wined3d_private.h=0A=
index 66e5a32..5b19acc 100644=0A=
--- a/dlls/wined3d/wined3d_private.h=0A=
+++ b/dlls/wined3d/wined3d_private.h=0A=
@@ -68,7 +68,7 @@ typedef struct {=0A=
 } hash_table_t;=0A=
 =0A=
 hash_table_t *hash_table_create(hash_function_t *hash_function, =
compare_function_t *compare_function);=0A=
-void hash_table_destroy(hash_table_t *table);=0A=
+void hash_table_destroy(hash_table_t *table, void (*free_value)(void =
*value, void *cb), void *cb);=0A=
 void *hash_table_get(hash_table_t *table, void *key);=0A=
 void hash_table_put(hash_table_t *table, void *key, void *value);=0A=
 void hash_table_remove(hash_table_t *table, void *key);=0A=
@@ -761,12 +761,13 @@ struct ffp_settings {=0A=
 struct ffp_desc=0A=
 {=0A=
     struct ffp_settings         settings;=0A=
-    struct list                 entry;=0A=
 };=0A=
 =0A=
 void gen_ffp_op(IWineD3DStateBlockImpl *stateblock, struct ffp_settings =
*settings, BOOL ignore_textype);=0A=
-struct ffp_desc *find_ffp_shader(struct list *shaders, struct =
ffp_settings *settings);=0A=
-void add_ffp_shader(struct list *shaders, struct ffp_desc *desc);=0A=
+struct ffp_desc *find_ffp_shader(hash_table_t *fragment_shaders, struct =
ffp_settings *settings);=0A=
+void add_ffp_shader(hash_table_t *shaders, struct ffp_desc *desc);=0A=
+BOOL ffp_program_key_compare(void *keya, void *keyb);=0A=
+unsigned int ffp_program_key_hash(void *key);=0A=
 =0A=
 =
/************************************************************************=
*****=0A=
  * IWineD3D implementation structure=0A=
-- =0A=
1.5.4.5=0A=
=0A=

------=_NextPart_000_0005_01C8F16E.2F79D7F0--




More information about the wine-patches mailing list