diff --git a/dlls/d3dx9_36/effect.c b/dlls/d3dx9_36/effect.c index b7abe2434d6..9a8f7277218 100644 --- a/dlls/d3dx9_36/effect.c +++ b/dlls/d3dx9_36/effect.c @@ -32,6 +32,8 @@ #define INT_FLOAT_MULTI 255.0f #define INT_FLOAT_MULTI_INVERSE (1/INT_FLOAT_MULTI) +#define INITIAL_PARAM_TABLE_SIZE 16 + WINE_DEFAULT_DEBUG_CHANNEL(d3dx); enum STATE_CLASS @@ -112,6 +114,8 @@ struct d3dx_parameter UINT bytes; DWORD object_id; + D3DXHANDLE handle; + struct d3dx_parameter *annotations; struct d3dx_parameter *members; }; @@ -157,6 +161,12 @@ struct d3dx_technique struct d3dx_pass *passes; }; +struct param_table +{ + struct d3dx_parameter **table; + unsigned int count, size; +}; + struct d3dx9_base_effect { struct ID3DXEffectImpl *effect; @@ -168,6 +178,8 @@ struct d3dx9_base_effect struct d3dx_parameter *parameters; struct d3dx_technique *techniques; struct d3dx_object *objects; + + struct param_table param_table; }; struct ID3DXEffectImpl @@ -198,8 +210,8 @@ static struct d3dx_parameter *get_parameter_by_name(struct d3dx9_base_effect *ba struct d3dx_parameter *parameter, const char *name); static struct d3dx_parameter *get_annotation_by_name(UINT count, struct d3dx_parameter *parameters, const char *name); -static HRESULT d3dx9_parse_state(struct d3dx_state *state, const char *data, const char **ptr, - struct d3dx_object *objects); +static HRESULT d3dx9_parse_state(struct d3dx9_base_effect *base, struct d3dx_state *state, + const char *data, const char **ptr, struct d3dx_object *objects); static void free_parameter(struct d3dx_parameter *param, BOOL element, BOOL child); static const struct @@ -426,7 +438,7 @@ static void skip_dword_unknown(const char **ptr, unsigned int count) static inline D3DXHANDLE get_parameter_handle(struct d3dx_parameter *parameter) { - return (D3DXHANDLE) parameter; + return parameter ? parameter->handle : NULL; } static inline D3DXHANDLE get_technique_handle(struct d3dx_technique *technique) @@ -485,74 +497,12 @@ static struct d3dx_pass *get_valid_pass(struct d3dx9_base_effect *base, D3DXHAND return NULL; } -static struct d3dx_parameter *get_valid_sub_parameter(struct d3dx_parameter *param, D3DXHANDLE parameter) -{ - unsigned int i, count; - struct d3dx_parameter *p; - - for (i = 0; i < param->annotation_count; ++i) - { - if (get_parameter_handle(¶m->annotations[i]) == parameter) - return ¶m->annotations[i]; - - p = get_valid_sub_parameter(¶m->annotations[i], parameter); - if (p) return p; - } - - count = param->element_count ? param->element_count : param->member_count; - for (i = 0; i < count; ++i) - { - if (get_parameter_handle(¶m->members[i]) == parameter) - return ¶m->members[i]; - - p = get_valid_sub_parameter(¶m->members[i], parameter); - if (p) return p; - } - - return NULL; -} - static struct d3dx_parameter *get_valid_parameter(struct d3dx9_base_effect *base, D3DXHANDLE parameter) { - unsigned int i, k, m; - struct d3dx_parameter *p; + struct d3dx_parameter **handle_param = (struct d3dx_parameter **)parameter; - for (i = 0; i < base->parameter_count; ++i) - { - if (get_parameter_handle(&base->parameters[i]) == parameter) - return &base->parameters[i]; - - p = get_valid_sub_parameter(&base->parameters[i], parameter); - if (p) return p; - } - - for (i = 0; i < base->technique_count; ++i) - { - struct d3dx_technique *technique = &base->techniques[i]; - - for (k = 0; k < technique->pass_count; ++k) - { - struct d3dx_pass *pass = &technique->passes[k]; - - for (m = 0; m < pass->annotation_count; ++m) - { - if (get_parameter_handle(&pass->annotations[m]) == parameter) - return &pass->annotations[m]; - - p = get_valid_sub_parameter(&pass->annotations[m], parameter); - if (p) return p; - } - } - - for (k = 0; k < technique->annotation_count; ++k) - { - if (get_parameter_handle(&technique->annotations[k]) == parameter) - return &technique->annotations[k]; - - p = get_valid_sub_parameter(&technique->annotations[k], parameter); - if (p) return p; - } - } + if (handle_param >= base->param_table.table && handle_param < base->param_table.table + base->param_table.count) + return *handle_param; return get_parameter_by_name(base, NULL, parameter); } @@ -714,6 +664,8 @@ static void d3dx9_base_effect_cleanup(struct d3dx9_base_effect *base) TRACE("base %p.\n", base); + HeapFree(GetProcessHeap(), 0, base->param_table.table); + if (base->parameters) { for (i = 0; i < base->parameter_count; ++i) @@ -4147,8 +4099,8 @@ static const struct ID3DXEffectCompilerVtbl ID3DXEffectCompiler_Vtbl = ID3DXEffectCompilerImpl_CompileShader, }; -static HRESULT d3dx9_parse_sampler(struct d3dx_sampler *sampler, const char *data, const char **ptr, - struct d3dx_object *objects) +static HRESULT d3dx9_parse_sampler(struct d3dx9_base_effect *base, struct d3dx_sampler *sampler, + const char *data, const char **ptr, struct d3dx_object *objects) { HRESULT hr; UINT i; @@ -4165,7 +4117,7 @@ static HRESULT d3dx9_parse_sampler(struct d3dx_sampler *sampler, const char *dat for (i = 0; i < sampler->state_count; ++i) { - hr = d3dx9_parse_state(&sampler->states[i], data, ptr, objects); + hr = d3dx9_parse_state(base, &sampler->states[i], data, ptr, objects); if (hr != D3D_OK) { WARN("Failed to parse state %u\n", i); @@ -4187,8 +4139,8 @@ err_out: return hr; } -static HRESULT d3dx9_parse_value(struct d3dx_parameter *param, void *value, const char *data, - const char **ptr, struct d3dx_object *objects) +static HRESULT d3dx9_parse_value(struct d3dx9_base_effect *base, struct d3dx_parameter *param, + void *value, const char *data, const char **ptr, struct d3dx_object *objects) { unsigned int i; HRESULT hr; @@ -4202,7 +4154,7 @@ static HRESULT d3dx9_parse_value(struct d3dx_parameter *param, void *value, cons { struct d3dx_parameter *member = ¶m->members[i]; - hr = d3dx9_parse_value(member, value ? (char *)value + old_size : NULL, data, ptr, objects); + hr = d3dx9_parse_value(base, member, value ? (char *)value + old_size : NULL, data, ptr, objects); if (hr != D3D_OK) { WARN("Failed to parse value %u\n", i); @@ -4231,7 +4183,7 @@ static HRESULT d3dx9_parse_value(struct d3dx_parameter *param, void *value, cons { struct d3dx_parameter *member = ¶m->members[i]; - hr = d3dx9_parse_value(member, (char *)value + old_size, data, ptr, objects); + hr = d3dx9_parse_value(base, member, (char *)value + old_size, data, ptr, objects); if (hr != D3D_OK) { WARN("Failed to parse value %u\n", i); @@ -4271,7 +4223,7 @@ static HRESULT d3dx9_parse_value(struct d3dx_parameter *param, void *value, cons if (!sampler) return E_OUTOFMEMORY; - hr = d3dx9_parse_sampler(sampler, data, ptr, objects); + hr = d3dx9_parse_sampler(base, sampler, data, ptr, objects); if (hr != D3D_OK) { HeapFree(GetProcessHeap(), 0, sampler); @@ -4297,8 +4249,8 @@ static HRESULT d3dx9_parse_value(struct d3dx_parameter *param, void *value, cons return D3D_OK; } -static HRESULT d3dx9_parse_init_value(struct d3dx_parameter *param, const char *data, const char *ptr, - struct d3dx_object *objects) +static HRESULT d3dx9_parse_init_value(struct d3dx9_base_effect *base, struct d3dx_parameter *param, + const char *data, const char *ptr, struct d3dx_object *objects) { UINT size = param->bytes; HRESULT hr; @@ -4335,7 +4287,7 @@ static HRESULT d3dx9_parse_init_value(struct d3dx_parameter *param, const char * } } - hr = d3dx9_parse_value(param, value, data, &ptr, objects); + hr = d3dx9_parse_value(base, param, value, data, &ptr, objects); if (hr != D3D_OK) { WARN("Failed to parse value\n"); @@ -4394,8 +4346,63 @@ static HRESULT d3dx9_copy_data(struct d3dx_object *object, const char **ptr) return D3D_OK; } -static HRESULT d3dx9_parse_effect_typedef(struct d3dx_parameter *param, const char *data, const char **ptr, - struct d3dx_parameter *parent, UINT flags) +static void add_param_to_table(struct d3dx9_base_effect *base, struct d3dx_parameter *param) +{ + struct param_table *table = &base->param_table; + + if (table->count >= table->size) + { + unsigned int new_size; + struct d3dx_parameter **new_alloc; + + if (!table->size) + { + new_size = INITIAL_PARAM_TABLE_SIZE; + new_alloc = HeapAlloc(GetProcessHeap(), 0, sizeof(*table->table) * new_size); + if (!new_alloc) + { + ERR("Out of memory.\n"); + return; + } + } + else + { + new_size = table->size * 2; + new_alloc = HeapReAlloc(GetProcessHeap(), 0, table->table, sizeof(*table->table) * new_size); + if (!new_alloc) + { + ERR("Out of memory.\n"); + return; + } + } + table->table = new_alloc; + table->size = new_size; + } + + table->table[table->count++] = param; +} + +static void sync_param_handles(struct d3dx9_base_effect *base) +{ + struct param_table *table = &base->param_table; + struct d3dx_parameter **new_alloc; + unsigned int i; + + if (table->count) + { + new_alloc = HeapReAlloc(GetProcessHeap(), 0, table->table, sizeof(*table->table) * table->count); + if (new_alloc) + table->table = new_alloc; + else + ERR("Out of memory.\n"); + } + + for (i = 0; i < table->count; ++i) + table->table[i]->handle = (D3DXHANDLE)&table->table[i]; +} + +static HRESULT d3dx9_parse_effect_typedef(struct d3dx9_base_effect *base, struct d3dx_parameter *param, + const char *data, const char **ptr, struct d3dx_parameter *parent, UINT flags) { DWORD offset; HRESULT hr; @@ -4528,7 +4535,8 @@ static HRESULT d3dx9_parse_effect_typedef(struct d3dx_parameter *param, const ch { *ptr = save_ptr; - hr = d3dx9_parse_effect_typedef(¶m->members[i], data, ptr, param, flags); + add_param_to_table(base, ¶m->members[i]); + hr = d3dx9_parse_effect_typedef(base, ¶m->members[i], data, ptr, param, flags); if (hr != D3D_OK) { WARN("Failed to parse member %u\n", i); @@ -4552,7 +4560,8 @@ static HRESULT d3dx9_parse_effect_typedef(struct d3dx_parameter *param, const ch for (i = 0; i < param->member_count; ++i) { - hr = d3dx9_parse_effect_typedef(¶m->members[i], data, ptr, NULL, flags); + add_param_to_table(base, ¶m->members[i]); + hr = d3dx9_parse_effect_typedef(base, ¶m->members[i], data, ptr, NULL, flags); if (hr != D3D_OK) { WARN("Failed to parse member %u\n", i); @@ -4587,8 +4596,8 @@ err_out: return hr; } -static HRESULT d3dx9_parse_effect_annotation(struct d3dx_parameter *anno, const char *data, - const char **ptr, struct d3dx_object *objects) +static HRESULT d3dx9_parse_effect_annotation(struct d3dx9_base_effect *base, struct d3dx_parameter *anno, + const char *data, const char **ptr, struct d3dx_object *objects) { DWORD offset; const char *ptr2; @@ -4599,7 +4608,7 @@ static HRESULT d3dx9_parse_effect_annotation(struct d3dx_parameter *anno, const read_dword(ptr, &offset); TRACE("Typedef offset: %#x\n", offset); ptr2 = data + offset; - hr = d3dx9_parse_effect_typedef(anno, data, &ptr2, NULL, D3DX_PARAMETER_ANNOTATION); + hr = d3dx9_parse_effect_typedef(base, anno, data, &ptr2, NULL, D3DX_PARAMETER_ANNOTATION); if (hr != D3D_OK) { WARN("Failed to parse type definition\n"); @@ -4608,7 +4617,7 @@ static HRESULT d3dx9_parse_effect_annotation(struct d3dx_parameter *anno, const read_dword(ptr, &offset); TRACE("Value offset: %#x\n", offset); - hr = d3dx9_parse_init_value(anno, data, data + offset, objects); + hr = d3dx9_parse_init_value(base, anno, data, data + offset, objects); if (hr != D3D_OK) { WARN("Failed to parse value\n"); @@ -4618,8 +4627,8 @@ static HRESULT d3dx9_parse_effect_annotation(struct d3dx_parameter *anno, const return D3D_OK; } -static HRESULT d3dx9_parse_state(struct d3dx_state *state, const char *data, const char **ptr, - struct d3dx_object *objects) +static HRESULT d3dx9_parse_state(struct d3dx9_base_effect *base, struct d3dx_state *state, + const char *data, const char **ptr, struct d3dx_object *objects) { DWORD offset; const char *ptr2; @@ -4636,7 +4645,7 @@ static HRESULT d3dx9_parse_state(struct d3dx_state *state, const char *data, con read_dword(ptr, &offset); TRACE("Typedef offset: %#x\n", offset); ptr2 = data + offset; - hr = d3dx9_parse_effect_typedef(&state->parameter, data, &ptr2, NULL, 0); + hr = d3dx9_parse_effect_typedef(base, &state->parameter, data, &ptr2, NULL, 0); if (hr != D3D_OK) { WARN("Failed to parse type definition\n"); @@ -4645,7 +4654,7 @@ static HRESULT d3dx9_parse_state(struct d3dx_state *state, const char *data, con read_dword(ptr, &offset); TRACE("Value offset: %#x\n", offset); - hr = d3dx9_parse_init_value(&state->parameter, data, data + offset, objects); + hr = d3dx9_parse_init_value(base, &state->parameter, data, data + offset, objects); if (hr != D3D_OK) { WARN("Failed to parse value\n"); @@ -4661,8 +4670,8 @@ err_out: return hr; } -static HRESULT d3dx9_parse_effect_parameter(struct d3dx_parameter *param, const char *data, - const char **ptr, struct d3dx_object *objects) +static HRESULT d3dx9_parse_effect_parameter(struct d3dx9_base_effect *base, struct d3dx_parameter *param, + const char *data, const char **ptr, struct d3dx_object *objects) { DWORD offset; HRESULT hr; @@ -4682,14 +4691,14 @@ static HRESULT d3dx9_parse_effect_parameter(struct d3dx_parameter *param, const read_dword(ptr, ¶m->annotation_count); TRACE("Annotation count: %u\n", param->annotation_count); - hr = d3dx9_parse_effect_typedef(param, data, &ptr2, NULL, param->flags); + hr = d3dx9_parse_effect_typedef(base, param, data, &ptr2, NULL, param->flags); if (hr != D3D_OK) { WARN("Failed to parse type definition\n"); return hr; } - hr = d3dx9_parse_init_value(param, data, data + offset, objects); + hr = d3dx9_parse_init_value(base, param, data, data + offset, objects); if (hr != D3D_OK) { WARN("Failed to parse value\n"); @@ -4709,7 +4718,8 @@ static HRESULT d3dx9_parse_effect_parameter(struct d3dx_parameter *param, const for (i = 0; i < param->annotation_count; ++i) { - hr = d3dx9_parse_effect_annotation(¶m->annotations[i], data, ptr, objects); + add_param_to_table(base, ¶m->annotations[i]); + hr = d3dx9_parse_effect_annotation(base, ¶m->annotations[i], data, ptr, objects); if (hr != D3D_OK) { WARN("Failed to parse annotation\n"); @@ -4733,8 +4743,8 @@ err_out: return hr; } -static HRESULT d3dx9_parse_effect_pass(struct d3dx_pass *pass, const char *data, const char **ptr, - struct d3dx_object *objects) +static HRESULT d3dx9_parse_effect_pass(struct d3dx9_base_effect *base, struct d3dx_pass *pass, + const char *data, const char **ptr, struct d3dx_object *objects) { DWORD offset; HRESULT hr; @@ -4770,7 +4780,8 @@ static HRESULT d3dx9_parse_effect_pass(struct d3dx_pass *pass, const char *data, for (i = 0; i < pass->annotation_count; ++i) { - hr = d3dx9_parse_effect_annotation(&pass->annotations[i], data, ptr, objects); + add_param_to_table(base, &pass->annotations[i]); + hr = d3dx9_parse_effect_annotation(base, &pass->annotations[i], data, ptr, objects); if (hr != D3D_OK) { WARN("Failed to parse annotation %u\n", i); @@ -4791,7 +4802,7 @@ static HRESULT d3dx9_parse_effect_pass(struct d3dx_pass *pass, const char *data, for (i = 0; i < pass->state_count; ++i) { - hr = d3dx9_parse_state(&states[i], data, ptr, objects); + hr = d3dx9_parse_state(base, &states[i], data, ptr, objects); if (hr != D3D_OK) { WARN("Failed to parse annotation %u\n", i); @@ -4829,8 +4840,8 @@ err_out: return hr; } -static HRESULT d3dx9_parse_effect_technique(struct d3dx_technique *technique, const char *data, - const char **ptr, struct d3dx_object *objects) +static HRESULT d3dx9_parse_effect_technique(struct d3dx9_base_effect *base, struct d3dx_technique *technique, + const char *data, const char **ptr, struct d3dx_object *objects) { DWORD offset; HRESULT hr; @@ -4865,7 +4876,8 @@ static HRESULT d3dx9_parse_effect_technique(struct d3dx_technique *technique, co for (i = 0; i < technique->annotation_count; ++i) { - hr = d3dx9_parse_effect_annotation(&technique->annotations[i], data, ptr, objects); + add_param_to_table(base, &technique->annotations[i]); + hr = d3dx9_parse_effect_annotation(base, &technique->annotations[i], data, ptr, objects); if (hr != D3D_OK) { WARN("Failed to parse annotation %u\n", i); @@ -4887,7 +4899,7 @@ static HRESULT d3dx9_parse_effect_technique(struct d3dx_technique *technique, co for (i = 0; i < technique->pass_count; ++i) { - hr = d3dx9_parse_effect_pass(&technique->passes[i], data, ptr, objects); + hr = d3dx9_parse_effect_pass(base, &technique->passes[i], data, ptr, objects); if (hr != D3D_OK) { WARN("Failed to parse pass %u\n", i); @@ -5089,7 +5101,8 @@ static HRESULT d3dx9_parse_effect(struct d3dx9_base_effect *base, const char *da for (i = 0; i < base->parameter_count; ++i) { - hr = d3dx9_parse_effect_parameter(&base->parameters[i], data, &ptr, base->objects); + add_param_to_table(base, &base->parameters[i]); + hr = d3dx9_parse_effect_parameter(base, &base->parameters[i], data, &ptr, base->objects); if (hr != D3D_OK) { WARN("Failed to parse parameter %u\n", i); @@ -5111,7 +5124,8 @@ static HRESULT d3dx9_parse_effect(struct d3dx9_base_effect *base, const char *da for (i = 0; i < base->technique_count; ++i) { - hr = d3dx9_parse_effect_technique(&base->techniques[i], data, &ptr, base->objects); + TRACE("Parsing technique %u.\n", i); + hr = d3dx9_parse_effect_technique(base, &base->techniques[i], data, &ptr, base->objects); if (hr != D3D_OK) { WARN("Failed to parse technique %u\n", i); @@ -5120,6 +5134,8 @@ static HRESULT d3dx9_parse_effect(struct d3dx9_base_effect *base, const char *da } } + sync_param_handles(base); + read_dword(&ptr, &stringcount); TRACE("String count: %u\n", stringcount);