Signed-off-by: Paul Gofman gofmanp@gmail.com --- dlls/d3dx9_36/effect.c | 111 +++++++++++++++++++++++++++++++++++ dlls/d3dx9_36/tests/effect.c | 6 +- 2 files changed, 114 insertions(+), 3 deletions(-)
diff --git a/dlls/d3dx9_36/effect.c b/dlls/d3dx9_36/effect.c index 4739b0cc0e..7a7fc336e1 100644 --- a/dlls/d3dx9_36/effect.c +++ b/dlls/d3dx9_36/effect.c @@ -36,6 +36,7 @@ static const char parameter_block_magic_string[4] = {'@', '!', '#', '\xFE'}; #define PARAMETER_FLAG_SHARED 1
#define INITIAL_POOL_SIZE 16 +#define INITIAL_PARAM_BLOCK_SIZE 1024
WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
@@ -153,6 +154,15 @@ struct d3dx_parameter_block { char magic_string[ARRAY_SIZE(parameter_block_magic_string)]; struct list entry; + size_t buffer_size; + size_t current_size; + BYTE *buffer; +}; + +struct d3dx_recorded_parameter +{ + struct d3dx_parameter *param; + unsigned int bytes; };
struct d3dx_effect @@ -706,11 +716,27 @@ static void free_technique(struct d3dx_technique *technique) technique->name = NULL; }
+static unsigned int get_recorded_parameter_size(const struct d3dx_recorded_parameter *record) +{ + return sizeof(*record) + record->bytes; +} + static void free_parameter_block(struct d3dx_parameter_block *block) { + struct d3dx_recorded_parameter *record; + if (!block) return;
+ record = (struct d3dx_recorded_parameter *)block->buffer; + while ((BYTE *)record < block->buffer + block->current_size) + { + free_parameter_object_data(record->param, record + 1, record->bytes); + record = (struct d3dx_recorded_parameter *)((BYTE *)record + get_recorded_parameter_size(record)); + } + assert((BYTE *)record == block->buffer + block->current_size); + + heap_free(block->buffer); heap_free(block); }
@@ -1293,6 +1319,46 @@ static ULONG64 next_effect_update_version(struct d3dx_effect *effect) return next_update_version(get_version_counter_ptr(effect)); }
+static void record_parameter(struct d3dx_effect *effect, struct d3dx_parameter *param, const void *data, + unsigned int bytes) +{ + struct d3dx_parameter_block *block = effect->current_parameter_block; + struct d3dx_recorded_parameter new_record, *record; + unsigned int new_size, alloc_size; + + if (!block) + return; + + assert(bytes <= param->bytes); + + new_record.param = param; + new_record.bytes = bytes; + new_size = block->current_size + get_recorded_parameter_size(&new_record); + + if (new_size > block->buffer_size) + { + BYTE *new_alloc; + + alloc_size = max(block->buffer_size * 2, max(new_size, INITIAL_PARAM_BLOCK_SIZE)); + if (block->buffer_size) + new_alloc = heap_realloc(block->buffer, alloc_size); + else + new_alloc = heap_alloc(alloc_size); + + if (!new_alloc) + { + ERR("Out of memory.\n"); + return; + } + block->buffer_size = alloc_size; + block->buffer = new_alloc; + } + record = (struct d3dx_recorded_parameter *)(block->buffer + block->current_size); + *record = new_record; + get_value(param, record + 1, data, bytes); + block->current_size = new_size; +} + static void set_dirty(struct d3dx_parameter *param) { struct d3dx_shared_data *shared_data; @@ -2411,6 +2477,7 @@ static HRESULT WINAPI d3dx_effect_SetValue(ID3DXEffect *iface, D3DXHANDLE parame if (data && param->bytes <= bytes) { set_dirty(param); + record_parameter(effect, param, data, param->bytes); return set_value(param, data, bytes); }
@@ -2460,6 +2527,7 @@ static HRESULT WINAPI d3dx_effect_SetBool(ID3DXEffect *iface, D3DXHANDLE paramet if (param && !param->element_count && param->rows == 1 && param->columns == 1) { set_number(param->data, param->type, &b, D3DXPT_BOOL); + record_parameter(effect, param, NULL, sizeof(int)); set_dirty(param); return D3D_OK; } @@ -2511,6 +2579,7 @@ static HRESULT WINAPI d3dx_effect_SetBoolArray(ID3DXEffect *iface, D3DXHANDLE pa /* don't crop the input, use D3DXPT_INT instead of D3DXPT_BOOL */ set_number((DWORD *)param->data + i, param->type, &b[i], D3DXPT_INT); } + record_parameter(effect, param, NULL, count * sizeof(int)); set_dirty(param); return D3D_OK;
@@ -2571,6 +2640,7 @@ static HRESULT WINAPI d3dx_effect_SetInt(ID3DXEffect *iface, D3DXHANDLE paramete set_number(&value, param->type, &n, D3DXPT_INT); if (value != *(DWORD *)param->data) set_dirty(param); + record_parameter(effect, param, &value, sizeof(int)); *(DWORD *)param->data = value; return D3D_OK; } @@ -2587,6 +2657,7 @@ static HRESULT WINAPI d3dx_effect_SetInt(ID3DXEffect *iface, D3DXHANDLE paramete ((float *)param->data)[2] = (n & 0xff) * INT_FLOAT_MULTI_INVERSE; if (param->rows * param->columns > 3) ((float *)param->data)[3] = ((n & 0xff000000) >> 24) * INT_FLOAT_MULTI_INVERSE; + record_parameter(effect, param, NULL, 4 * sizeof(float)); set_dirty(param); return D3D_OK; } @@ -2655,6 +2726,7 @@ static HRESULT WINAPI d3dx_effect_SetIntArray(ID3DXEffect *iface, D3DXHANDLE par case D3DXPC_MATRIX_ROWS: for (i = 0; i < size; ++i) set_number((DWORD *)param->data + i, param->type, &n[i], D3DXPT_INT); + record_parameter(effect, param, NULL, size * sizeof(int)); set_dirty(param); return D3D_OK;
@@ -2712,6 +2784,7 @@ static HRESULT WINAPI d3dx_effect_SetFloat(ID3DXEffect *iface, D3DXHANDLE parame if (value != *(DWORD *)param->data) set_dirty(param); *(DWORD *)param->data = value; + record_parameter(effect, param, NULL, sizeof(float)); return D3D_OK; }
@@ -2760,6 +2833,7 @@ static HRESULT WINAPI d3dx_effect_SetFloatArray(ID3DXEffect *iface, D3DXHANDLE p case D3DXPC_MATRIX_ROWS: for (i = 0; i < size; ++i) set_number((DWORD *)param->data + i, param->type, &f[i], D3DXPT_FLOAT); + record_parameter(effect, param, NULL, size * sizeof(float)); set_dirty(param); return D3D_OK;
@@ -2829,15 +2903,18 @@ static HRESULT WINAPI d3dx_effect_SetVector(ID3DXEffect *iface, D3DXHANDLE param tmp += ((DWORD)(max(min(vector->w, 1.0f), 0.0f) * INT_FLOAT_MULTI)) << 24;
*(int *)param->data = tmp; + record_parameter(effect, param, NULL, sizeof(int)); return D3D_OK; } if (param->type == D3DXPT_FLOAT) { memcpy(param->data, vector, param->columns * sizeof(float)); + record_parameter(effect, param, NULL, param->columns * sizeof(float)); return D3D_OK; }
set_vector(param, vector); + record_parameter(effect, param, NULL, param->columns * sizeof(float)); return D3D_OK;
case D3DXPC_MATRIX_ROWS: @@ -2920,16 +2997,23 @@ static HRESULT WINAPI d3dx_effect_SetVectorArray(ID3DXEffect *iface, D3DXHANDLE if (param->type == D3DXPT_FLOAT) { if (param->columns == 4) + { memcpy(param->data, vector, count * 4 * sizeof(float)); + record_parameter(effect, param, NULL, count * 4 * sizeof(float)); + } else + { for (i = 0; i < count; ++i) memcpy((float *)param->data + param->columns * i, vector + i, param->columns * sizeof(float)); + record_parameter(effect, param, NULL, count * param->columns * sizeof(float)); + } return D3D_OK; }
for (i = 0; i < count; ++i) set_vector(¶m->members[i], &vector[i]); + record_parameter(effect, param, NULL, count * param->columns * sizeof(float)); return D3D_OK;
case D3DXPC_SCALAR: @@ -3005,6 +3089,7 @@ static HRESULT WINAPI d3dx_effect_SetMatrix(ID3DXEffect *iface, D3DXHANDLE param { case D3DXPC_MATRIX_ROWS: set_matrix(param, matrix); + record_parameter(effect, param, NULL, param->rows * param->columns * sizeof(float)); set_dirty(param); return D3D_OK;
@@ -3078,7 +3163,11 @@ static HRESULT WINAPI d3dx_effect_SetMatrixArray(ID3DXEffect *iface, D3DXHANDLE case D3DXPC_MATRIX_ROWS: set_dirty(param); for (i = 0; i < count; ++i) + { set_matrix(¶m->members[i], &matrix[i]); + record_parameter(effect, ¶m->members[i], NULL, param->members[i].rows + * param->members[i].columns * sizeof(float)); + } return D3D_OK;
case D3DXPC_SCALAR: @@ -3156,7 +3245,11 @@ static HRESULT WINAPI d3dx_effect_SetMatrixPointerArray(ID3DXEffect *iface, D3DX case D3DXPC_MATRIX_ROWS: set_dirty(param); for (i = 0; i < count; ++i) + { set_matrix(¶m->members[i], matrix[i]); + record_parameter(effect, ¶m->members[i], NULL, param->members[i].rows + * param->members[i].columns * sizeof(float)); + } return D3D_OK;
case D3DXPC_SCALAR: @@ -3232,6 +3325,7 @@ static HRESULT WINAPI d3dx_effect_SetMatrixTranspose(ID3DXEffect *iface, D3DXHAN case D3DXPC_MATRIX_ROWS: set_dirty(param); set_matrix_transpose(param, matrix); + record_parameter(effect, param, NULL, param->rows * param->columns * sizeof(float)); return D3D_OK;
case D3DXPC_SCALAR: @@ -3308,7 +3402,11 @@ static HRESULT WINAPI d3dx_effect_SetMatrixTransposeArray(ID3DXEffect *iface, D3 case D3DXPC_MATRIX_ROWS: set_dirty(param); for (i = 0; i < count; ++i) + { set_matrix_transpose(¶m->members[i], &matrix[i]); + record_parameter(effect, ¶m->members[i], NULL, param->members[i].rows + * param->members[i].columns * sizeof(float)); + } return D3D_OK;
case D3DXPC_SCALAR: @@ -3386,7 +3484,11 @@ static HRESULT WINAPI d3dx_effect_SetMatrixTransposePointerArray(ID3DXEffect *if case D3DXPC_MATRIX_ROWS: set_dirty(param); for (i = 0; i < count; ++i) + { set_matrix_transpose(¶m->members[i], matrix[i]); + record_parameter(effect, ¶m->members[i], NULL, param->members[i].rows + * param->members[i].columns * sizeof(float)); + } return D3D_OK;
case D3DXPC_SCALAR: @@ -3455,6 +3557,10 @@ static HRESULT WINAPI d3dx_effect_SetString(ID3DXEffect *iface, D3DXHANDLE param if (param && param->type == D3DXPT_STRING) { set_dirty(param); + + if (effect->current_parameter_block) + FIXME("Recording string parameters not supported.\n"); + return set_string(param->data, string); }
@@ -3507,6 +3613,7 @@ static HRESULT WINAPI d3dx_effect_SetTexture(ID3DXEffect *iface, D3DXHANDLE para
*(IDirect3DBaseTexture9 **)param->data = texture; set_dirty(param); + record_parameter(effect, param, NULL, sizeof(void *));
return D3D_OK; } @@ -4148,6 +4255,10 @@ static D3DXHANDLE WINAPI d3dx_effect_EndParameterBlock(ID3DXEffect *iface) return NULL; } ret = effect->current_parameter_block; + + ret->buffer = heap_realloc(ret->buffer, ret->current_size); + ret->buffer_size = ret->current_size; + effect->current_parameter_block = NULL; list_add_tail(&effect->parameter_block_list, &ret->entry); return (D3DXHANDLE)ret; diff --git a/dlls/d3dx9_36/tests/effect.c b/dlls/d3dx9_36/tests/effect.c index 1732a77541..d24e04a753 100644 --- a/dlls/d3dx9_36/tests/effect.c +++ b/dlls/d3dx9_36/tests/effect.c @@ -8134,21 +8134,21 @@ static void test_effect_parameter_block(void) * Maybe native d3dx is using some copy on write strategy. */ IDirect3DTexture9_AddRef(texture); refcount = IDirect3DTexture9_Release(texture); - ok(refcount == 2, "Got unexpected refcount %u.\n", refcount); + todo_wine ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
block = effect->lpVtbl->EndParameterBlock(effect); ok(!!block, "Got unexpected block %p.\n", block);
IDirect3DTexture9_AddRef(texture); refcount = IDirect3DTexture9_Release(texture); - ok(refcount == 2, "Got unexpected refcount %u.\n", refcount); + todo_wine ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
hr = effect->lpVtbl->SetTexture(effect, "tex1", NULL); ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
IDirect3DTexture9_AddRef(texture); refcount = IDirect3DTexture9_Release(texture); - todo_wine ok(refcount == 2, "Got unexpected refcount %u.\n", refcount); + ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
hr = effect->lpVtbl->SetFloat(effect, "arr2[0]", 0.0f); ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);