Signed-off-by: Paul Gofman gofmanp@gmail.com --- v2: - use heap_free() in modified functions.
I don't think strings have the same problem as samplers, as param->data is a pointer to string pointers, while samplers data is the direct pointer to sampler structure.
dlls/d3dx9_36/effect.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/dlls/d3dx9_36/effect.c b/dlls/d3dx9_36/effect.c index e69a1fd1f8..4eb1a2b042 100644 --- a/dlls/d3dx9_36/effect.c +++ b/dlls/d3dx9_36/effect.c @@ -516,8 +516,7 @@ static void free_sampler(struct d3dx_sampler *sampler) { free_state(&sampler->states[i]); } - HeapFree(GetProcessHeap(), 0, sampler->states); - HeapFree(GetProcessHeap(), 0, sampler); + heap_free(sampler->states); }
static void d3dx_pool_release_shared_parameter(struct d3dx_top_level_parameter *param); @@ -531,7 +530,7 @@ static void free_parameter_data(struct d3dx_parameter *param, BOOL child) switch (param->type) { case D3DXPT_STRING: - HeapFree(GetProcessHeap(), 0, *(char **)param->data); + heap_free(*(char **)param->data); break;
case D3DXPT_TEXTURE: @@ -557,8 +556,8 @@ static void free_parameter_data(struct d3dx_parameter *param, BOOL child) break; } } - if (!child) - HeapFree(GetProcessHeap(), 0, param->data); + if (!child || is_param_type_sampler(param->type)) + heap_free(param->data); }
static void free_parameter(struct d3dx_parameter *param, BOOL element, BOOL child)
Signed-off-by: Paul Gofman gofmanp@gmail.com --- v2: - remove double hr checks; - remove redundant 'if (refcount)' for releasing texture; - test if parameter values are changed when recording to state block (they do not); - modified comments accordingly.
I also briefly tested _SetArrayRange, and could not find any effect of that on recording parameters to parameter block so far. As docs suggest, it could influence something in setting effect parameters to device, but I could not detect any effect either (tested setting array range before applying changes updating shader constants). There is probably the room for further investigation of what may be influenced upon the function (e. g. various type of getting the parameter, or maybe it had some effect in earlier d3dx9 versions, but I did not go that far.
dlls/d3dx9_36/tests/effect.c | 244 +++++++++++++++++++++++++++++++++++ 1 file changed, 244 insertions(+)
diff --git a/dlls/d3dx9_36/tests/effect.c b/dlls/d3dx9_36/tests/effect.c index 5c4a3c5e77..3560696a1c 100644 --- a/dlls/d3dx9_36/tests/effect.c +++ b/dlls/d3dx9_36/tests/effect.c @@ -8001,6 +8001,249 @@ static void test_effect_find_next_valid_technique(void) DestroyWindow(window); }
+static void test_effect_parameter_block(void) +{ + static const D3DXMATRIX test_mat = + {{{ + -11.0f, -12.0f, 0.0f, 0.0f, + -21.0f, -22.0f, 0.0f, 0.0f, + -31.0f, -32.0f, 0.0f, 0.0f, + }}}; + static const D3DXMATRIX effect_orig_mat = + {{{ + 11.0f, 12.0f, 0.0f, 0.0f, + 21.0f, 22.0f, 0.0f, 0.0f, + 31.0f, 32.0f, 0.0f, 0.0f, + }}}; + D3DPRESENT_PARAMETERS present_parameters = {0}; + static const float float_array_zero[4]; + IDirect3DTexture9 *texture, *tex_test; + ID3DXEffect *effect, *effect2; + D3DXHANDLE block, handle; + IDirect3DDevice9 *device; + ID3DXEffectPool *pool; + float float_array[4]; + float float_value; + IDirect3D9 *d3d; + D3DXMATRIX mat; + ULONG refcount; + HWND window; + HRESULT hr; + + if (!(window = CreateWindowA("static", "d3dx9_test", WS_OVERLAPPEDWINDOW, 0, 0, + 640, 480, NULL, NULL, NULL, NULL))) + { + skip("Failed to create window.\n"); + return; + } + if (!(d3d = Direct3DCreate9(D3D_SDK_VERSION))) + { + skip("Failed to create IDirect3D9 object.\n"); + DestroyWindow(window); + return; + } + present_parameters.Windowed = TRUE; + present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD; + hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window, + D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device); + if (FAILED(hr)) + { + skip("Failed to create IDirect3DDevice9 object, hr %#x.\n", hr); + IDirect3D9_Release(d3d); + DestroyWindow(window); + return; + } + + hr = D3DXCreateEffectPool(&pool); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = D3DXCreateEffect(device, test_effect_preshader_effect_blob, sizeof(test_effect_preshader_effect_blob), + NULL, NULL, 0, pool, &effect, NULL); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = D3DXCreateEffect(device, test_effect_preshader_effect_blob, sizeof(test_effect_preshader_effect_blob), + NULL, NULL, 0, pool, &effect2, NULL); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + + hr = effect->lpVtbl->BeginParameterBlock(effect); + todo_wine ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = effect->lpVtbl->BeginParameterBlock(effect); + todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr); + block = effect->lpVtbl->EndParameterBlock(effect); + todo_wine ok(!!block, "Got unexpected block %p.\n", block); + handle = effect->lpVtbl->EndParameterBlock(effect); + ok(!handle, "Got unexpected handle %p.\n", handle); + + /* Block doesn't hold effect's reference. */ + effect->lpVtbl->AddRef(effect); + refcount = effect->lpVtbl->Release(effect); + ok(refcount == 1, "Got unexpected refcount %u.\n", refcount); + + hr = effect->lpVtbl->ApplyParameterBlock(effect, block); + todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr); + hr = effect->lpVtbl->DeleteParameterBlock(effect, block); + todo_wine ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->BeginParameterBlock(effect); + todo_wine ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = effect->lpVtbl->SetFloat(effect, "vec3[0]", 1001.0f); + ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr); + hr = effect->lpVtbl->SetFloat(effect, "arr1[0]", 91.0f); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + block = effect->lpVtbl->EndParameterBlock(effect); + todo_wine ok(!!block, "Got unexpected block %p.\n", block); + hr = effect->lpVtbl->ApplyParameterBlock(effect, block); + todo_wine ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + + hr = effect->lpVtbl->DeleteParameterBlock(effect2, block); + todo_wine ok(hr == D3DERR_INVALIDCALL, "Got result %#x.\n", hr); + hr = effect->lpVtbl->DeleteParameterBlock(effect, block); + todo_wine ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->ApplyParameterBlock(effect, "parameter_block"); + todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr); + + hr = D3DXCreateTexture(device, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, 0, D3DPOOL_DEFAULT, &texture); + ok(hr == D3D_OK, "Got result %#x, expected 0 (D3D_OK).\n", hr); + + hr = effect->lpVtbl->BeginParameterBlock(effect); + todo_wine ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + + hr = effect->lpVtbl->SetTexture(effect, "tex1", (IDirect3DBaseTexture9 *)texture); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + + hr = effect->lpVtbl->GetTexture(effect, "tex1", (IDirect3DBaseTexture9 **)&tex_test); + todo_wine ok(hr == D3D_OK && !tex_test, "Got unexpected hr %#x, tex_test %p.\n", hr, tex_test); + if (tex_test) + IDirect3DTexture9_Release(tex_test); + + /* Child parameters and array members are recorded separately (the whole parameter is not + * updated when parameter block is applied). + * The effect parameters are not updated during recording. + * Setting shared parameter through effect2 is not recorded to effect parameter block. + */ + hr = effect->lpVtbl->SetFloat(effect, "arr2[0]", 92.0f); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = effect->lpVtbl->SetFloat(effect, "ts1[0].fv", 28.0f); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = effect->lpVtbl->GetFloat(effect, "ts1[0].fv", &float_value); + todo_wine ok(hr == D3D_OK && float_value == 12.0, "Got unexpected hr %#x, float_value %g.\n", hr, float_value); + + float_array[0] = -29.0f; + hr = effect->lpVtbl->SetFloatArray(effect, "ts1[0].v2", float_array, 1); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = effect->lpVtbl->GetFloatArray(effect, "ts1[0].v2", float_array, 1); + todo_wine ok(hr == D3D_OK && float_array[0] == 13.0, "Got unexpected hr %#x, float_array[0] %g.\n", + hr, float_array[0]); + + memset(&mat, 0, sizeof(mat)); + hr = effect->lpVtbl->SetMatrix(effect, "m3x2row", &test_mat); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = effect->lpVtbl->GetMatrix(effect, "m3x2row", &mat); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + todo_wine ok(!memcmp(&mat, &effect_orig_mat, sizeof(mat)), "Got unexpected matrix.\n"); + + hr = effect->lpVtbl->SetMatrix(effect, "m3x2column", &test_mat); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = effect->lpVtbl->GetMatrix(effect, "m3x2column", &mat); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + todo_wine ok(!memcmp(&mat, &effect_orig_mat, sizeof(mat)), "Got unexpected matrix.\n"); + + hr = effect2->lpVtbl->SetFloat(effect2, "arr2[1]", -1.0f); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + /* Ensure that parameter is actually shared. */ + hr = effect->lpVtbl->GetFloat(effect, "arr2[1]", &float_value); + ok(float_value == -1.0f, "Unexpected value %g.\n", float_value); + + IDirect3DTexture9_AddRef(texture); + refcount = IDirect3DTexture9_Release(texture); + ok(refcount == 2, "Got unexpected refcount %u.\n", refcount); + + block = effect->lpVtbl->EndParameterBlock(effect); + todo_wine ok(!!block, "Got unexpected block %p.\n", block); + + IDirect3DTexture9_AddRef(texture); + refcount = IDirect3DTexture9_Release(texture); + ok(refcount == 2, "Got unexpected refcount %u.\n", refcount); + + hr = effect->lpVtbl->DeleteParameterBlock(effect2, block); + todo_wine ok(hr == D3DERR_INVALIDCALL, "Got result %#x.\n", hr); + + IDirect3DTexture9_AddRef(texture); + refcount = IDirect3DTexture9_Release(texture); + 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); + hr = effect->lpVtbl->SetFloat(effect, "arr2[1]", 0.0f); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = effect->lpVtbl->SetFloatArray(effect, "ts1[0].v1", float_array_zero, 3); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = effect->lpVtbl->SetFloat(effect, "ts1[0].fv", 0.0f); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = effect->lpVtbl->SetFloatArray(effect, "ts1[0].v2", float_array_zero, 4); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + memset(&mat, 0, sizeof(mat)); + hr = effect->lpVtbl->SetMatrix(effect, "m3x2row", &mat); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = effect->lpVtbl->SetMatrix(effect, "m3x2column", &mat); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + + hr = effect->lpVtbl->ApplyParameterBlock(effect, block); + todo_wine ok(hr == D3D_OK, "Got result %#x.\n", hr); + + IDirect3DTexture9_AddRef(texture); + refcount = IDirect3DTexture9_Release(texture); + todo_wine ok(refcount == 3, "Got unexpected refcount %u.\n", refcount); + + hr = effect->lpVtbl->GetFloat(effect, "arr2[0]", &float_value); + todo_wine ok(hr == D3D_OK && float_value == 92.0f, "Got unexpected hr %#x, float_value %g.\n", hr, float_value); + hr = effect->lpVtbl->GetFloat(effect, "arr2[1]", &float_value); + ok(hr == D3D_OK && float_value == 0.0f, "Got unexpected hr %#x, float_value %g.\n", hr, float_value); + + hr = effect->lpVtbl->GetFloatArray(effect, "ts1[0].v1", float_array, 3); + ok(hr == D3D_OK && !memcmp(float_array, float_array_zero, 3 * sizeof(*float_array)), + "Got unexpected hr %#x, ts1[0].v1 (%g, %g, %g).\n", hr, + float_array[0], float_array[1], float_array[2]); + + hr = effect->lpVtbl->GetMatrix(effect, "m3x2row", &mat); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + todo_wine ok(!memcmp(&mat, &test_mat, sizeof(mat)), "Got unexpected matrix.\n"); + hr = effect->lpVtbl->GetMatrix(effect, "m3x2column", &mat); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + todo_wine ok(!memcmp(&mat, &test_mat, sizeof(mat)), "Got unexpected matrix.\n"); + + hr = effect->lpVtbl->GetFloat(effect, "ts1[0].fv", &float_value); + todo_wine ok(hr == D3D_OK && float_value == 28.0f, "Got unexpected hr %#x, float_value %g.\n", hr, float_value); + + hr = effect->lpVtbl->GetFloatArray(effect, "ts1[0].v2", float_array, 4); + todo_wine ok(hr == D3D_OK && float_array[0] == -29.0f + && !memcmp(float_array + 1, float_array_zero, 3 * sizeof(*float_array)), + "Got unexpected hr %#x, ts1[0].v2 (%g, %g, %g, %g).\n", hr, + float_array[0], float_array[1], float_array[2], float_array[3]); + + hr = effect->lpVtbl->DeleteParameterBlock(effect, block); + todo_wine ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->SetTexture(effect, "tex1", NULL); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + refcount = IDirect3DTexture9_Release(texture); + ok(!refcount, "Got unexpected refcount %u.\n", refcount); + + refcount = effect->lpVtbl->Release(effect); + ok(!refcount, "Got unexpected refcount %u.\n", refcount); + + refcount = effect2->lpVtbl->Release(effect2); + ok(!refcount, "Got unexpected refcount %u.\n", refcount); + + refcount = pool->lpVtbl->Release(pool); + ok(!refcount, "Got unexpected refcount %u.\n", refcount); + + refcount = IDirect3DDevice9_Release(device); + ok(!refcount, "Device has %u references left.\n", refcount); + IDirect3D9_Release(d3d); + DestroyWindow(window); +} + START_TEST(effect) { IDirect3DDevice9 *device; @@ -8040,4 +8283,5 @@ START_TEST(effect) test_refcount(); test_create_effect_from_file(); test_effect_find_next_valid_technique(); + test_effect_parameter_block(); }
Signed-off-by: Paul Gofman gofmanp@gmail.com --- v2: - no changes.
dlls/d3dx9_36/effect.c | 34 +++++++++++++++++++++++++++++++--- dlls/d3dx9_36/tests/effect.c | 4 ++-- 2 files changed, 33 insertions(+), 5 deletions(-)
diff --git a/dlls/d3dx9_36/effect.c b/dlls/d3dx9_36/effect.c index 4eb1a2b042..25664194ea 100644 --- a/dlls/d3dx9_36/effect.c +++ b/dlls/d3dx9_36/effect.c @@ -30,6 +30,7 @@ #define INT_FLOAT_MULTI_INVERSE (1/INT_FLOAT_MULTI)
static const char parameter_magic_string[4] = {'@', '!', '#', '\xFF'}; +static const char parameter_block_magic_string[4] = {'@', '!', '#', '\xFE'};
#define PARAMETER_FLAG_SHARED 1
@@ -147,6 +148,11 @@ struct d3dx_technique struct IDirect3DStateBlock9 *saved_state; };
+struct d3dx_parameter_block +{ + char magic_string[ARRAY_SIZE(parameter_block_magic_string)]; +}; + struct d3dx_effect { ID3DXEffect ID3DXEffect_iface; @@ -177,6 +183,8 @@ struct d3dx_effect unsigned int light_updated; D3DMATERIAL9 current_material; BOOL material_updated; + + struct d3dx_parameter_block *current_parameter_block; };
#define INITIAL_SHARED_DATA_SIZE 4 @@ -670,6 +678,14 @@ static void free_technique(struct d3dx_technique *technique) technique->name = NULL; }
+static void free_parameter_block(struct d3dx_parameter_block *block) +{ + if (!block) + return; + + heap_free(block); +} + static void d3dx_effect_cleanup(struct d3dx_effect *effect) { ID3DXEffectPool *pool; @@ -677,6 +693,8 @@ static void d3dx_effect_cleanup(struct d3dx_effect *effect)
TRACE("effect %p.\n", effect);
+ free_parameter_block(effect->current_parameter_block); + heap_free(effect->full_name_tmp);
if (effect->parameters) @@ -4047,11 +4065,21 @@ static HRESULT WINAPI d3dx_effect_GetStateManager(ID3DXEffect *iface, ID3DXEffec
static HRESULT WINAPI d3dx_effect_BeginParameterBlock(ID3DXEffect *iface) { - struct d3dx_effect *This = impl_from_ID3DXEffect(iface); + struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
- FIXME("(%p)->(): stub\n", This); + TRACE("iface %p.\n", iface);
- return E_NOTIMPL; + if (effect->current_parameter_block) + { + WARN("Parameter block is already started.\n"); + return D3DERR_INVALIDCALL; + } + + effect->current_parameter_block = heap_alloc_zero(sizeof(*effect->current_parameter_block)); + memcpy(effect->current_parameter_block->magic_string, parameter_block_magic_string, + sizeof(parameter_block_magic_string)); + + return D3D_OK; }
static D3DXHANDLE WINAPI d3dx_effect_EndParameterBlock(ID3DXEffect *iface) diff --git a/dlls/d3dx9_36/tests/effect.c b/dlls/d3dx9_36/tests/effect.c index 3560696a1c..c643f9da7f 100644 --- a/dlls/d3dx9_36/tests/effect.c +++ b/dlls/d3dx9_36/tests/effect.c @@ -8065,9 +8065,9 @@ static void test_effect_parameter_block(void) ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
hr = effect->lpVtbl->BeginParameterBlock(effect); - todo_wine ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); hr = effect->lpVtbl->BeginParameterBlock(effect); - todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr); + ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr); block = effect->lpVtbl->EndParameterBlock(effect); todo_wine ok(!!block, "Got unexpected block %p.\n", block); handle = effect->lpVtbl->EndParameterBlock(effect);
Signed-off-by: Paul Gofman gofmanp@gmail.com --- v2: - no changes.
dlls/d3dx9_36/effect.c | 26 +++++++++++++++++++++++--- dlls/d3dx9_36/tests/effect.c | 10 +++++----- 2 files changed, 28 insertions(+), 8 deletions(-)
diff --git a/dlls/d3dx9_36/effect.c b/dlls/d3dx9_36/effect.c index 25664194ea..161a6c1746 100644 --- a/dlls/d3dx9_36/effect.c +++ b/dlls/d3dx9_36/effect.c @@ -24,6 +24,7 @@ #include "d3dx9_private.h" #include "d3dcompiler.h" #include "winternl.h" +#include "wine/list.h"
/* Constants for special INT/FLOAT conversation */ #define INT_FLOAT_MULTI 255.0f @@ -151,6 +152,7 @@ struct d3dx_technique struct d3dx_parameter_block { char magic_string[ARRAY_SIZE(parameter_block_magic_string)]; + struct list entry; };
struct d3dx_effect @@ -184,6 +186,7 @@ struct d3dx_effect D3DMATERIAL9 current_material; BOOL material_updated;
+ struct list parameter_block_list; struct d3dx_parameter_block *current_parameter_block; };
@@ -688,12 +691,18 @@ static void free_parameter_block(struct d3dx_parameter_block *block)
static void d3dx_effect_cleanup(struct d3dx_effect *effect) { + struct d3dx_parameter_block *block, *cursor; ID3DXEffectPool *pool; unsigned int i;
TRACE("effect %p.\n", effect);
free_parameter_block(effect->current_parameter_block); + LIST_FOR_EACH_ENTRY_SAFE(block, cursor, &effect->parameter_block_list, struct d3dx_parameter_block, entry) + { + list_remove(&block->entry); + free_parameter_block(block); + }
heap_free(effect->full_name_tmp);
@@ -4084,11 +4093,20 @@ static HRESULT WINAPI d3dx_effect_BeginParameterBlock(ID3DXEffect *iface)
static D3DXHANDLE WINAPI d3dx_effect_EndParameterBlock(ID3DXEffect *iface) { - struct d3dx_effect *This = impl_from_ID3DXEffect(iface); + struct d3dx_effect *effect = impl_from_ID3DXEffect(iface); + struct d3dx_parameter_block *ret;
- FIXME("(%p)->(): stub\n", This); + TRACE("iface %p.\n", iface);
- return NULL; + if (!effect->current_parameter_block) + { + WARN("No active parameter block.\n"); + return NULL; + } + ret = effect->current_parameter_block; + effect->current_parameter_block = NULL; + list_add_tail(&effect->parameter_block_list, &ret->entry); + return (D3DXHANDLE)ret; }
static HRESULT WINAPI d3dx_effect_ApplyParameterBlock(ID3DXEffect *iface, D3DXHANDLE parameter_block) @@ -6234,6 +6252,8 @@ static HRESULT d3dx9_effect_init(struct d3dx_effect *effect, struct IDirect3DDev
effect->flags = eflags;
+ list_init(&effect->parameter_block_list); + read_dword(&ptr, &tag); TRACE("Tag: %x\n", tag);
diff --git a/dlls/d3dx9_36/tests/effect.c b/dlls/d3dx9_36/tests/effect.c index c643f9da7f..71dc8ad226 100644 --- a/dlls/d3dx9_36/tests/effect.c +++ b/dlls/d3dx9_36/tests/effect.c @@ -8069,7 +8069,7 @@ static void test_effect_parameter_block(void) hr = effect->lpVtbl->BeginParameterBlock(effect); ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr); block = effect->lpVtbl->EndParameterBlock(effect); - todo_wine ok(!!block, "Got unexpected block %p.\n", block); + ok(!!block, "Got unexpected block %p.\n", block); handle = effect->lpVtbl->EndParameterBlock(effect); ok(!handle, "Got unexpected handle %p.\n", handle);
@@ -8084,13 +8084,13 @@ static void test_effect_parameter_block(void) todo_wine ok(hr == D3D_OK, "Got result %#x.\n", hr);
hr = effect->lpVtbl->BeginParameterBlock(effect); - todo_wine ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); hr = effect->lpVtbl->SetFloat(effect, "vec3[0]", 1001.0f); ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr); hr = effect->lpVtbl->SetFloat(effect, "arr1[0]", 91.0f); ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); block = effect->lpVtbl->EndParameterBlock(effect); - todo_wine ok(!!block, "Got unexpected block %p.\n", block); + ok(!!block, "Got unexpected block %p.\n", block); hr = effect->lpVtbl->ApplyParameterBlock(effect, block); todo_wine ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
@@ -8106,7 +8106,7 @@ static void test_effect_parameter_block(void) ok(hr == D3D_OK, "Got result %#x, expected 0 (D3D_OK).\n", hr);
hr = effect->lpVtbl->BeginParameterBlock(effect); - todo_wine ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
hr = effect->lpVtbl->SetTexture(effect, "tex1", (IDirect3DBaseTexture9 *)texture); ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); @@ -8159,7 +8159,7 @@ static void test_effect_parameter_block(void) ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
block = effect->lpVtbl->EndParameterBlock(effect); - todo_wine ok(!!block, "Got unexpected block %p.\n", block); + ok(!!block, "Got unexpected block %p.\n", block);
IDirect3DTexture9_AddRef(texture); refcount = IDirect3DTexture9_Release(texture);
Signed-off-by: Paul Gofman gofmanp@gmail.com --- v2: - no changes.
dlls/d3dx9_36/effect.c | 30 +++++++++++++++++++++++++++--- dlls/d3dx9_36/tests/effect.c | 10 +++++----- 2 files changed, 32 insertions(+), 8 deletions(-)
diff --git a/dlls/d3dx9_36/effect.c b/dlls/d3dx9_36/effect.c index 161a6c1746..9b97d8ae20 100644 --- a/dlls/d3dx9_36/effect.c +++ b/dlls/d3dx9_36/effect.c @@ -509,6 +509,14 @@ static struct d3dx_parameter *get_valid_parameter(struct d3dx_effect *effect, D3 return effect->flags & D3DXFX_LARGEADDRESSAWARE ? NULL : get_parameter_by_name(effect, NULL, parameter); }
+static struct d3dx_parameter_block *get_valid_parameter_block(D3DXHANDLE handle) +{ + struct d3dx_parameter_block *block = (struct d3dx_parameter_block *)handle; + + return block && !strncmp(block->magic_string, parameter_block_magic_string, + sizeof(parameter_block_magic_string)) ? block : NULL; +} + static void free_state(struct d3dx_state *state) { free_parameter(&state->parameter, FALSE, FALSE); @@ -4121,11 +4129,27 @@ static HRESULT WINAPI d3dx_effect_ApplyParameterBlock(ID3DXEffect *iface, D3DXHA #if D3DX_SDK_VERSION >= 26 static HRESULT WINAPI d3dx_effect_DeleteParameterBlock(ID3DXEffect *iface, D3DXHANDLE parameter_block) { - struct d3dx_effect *This = impl_from_ID3DXEffect(iface); + struct d3dx_parameter_block *block = get_valid_parameter_block(parameter_block); + struct d3dx_effect *effect = impl_from_ID3DXEffect(iface); + struct d3dx_parameter_block *b;
- FIXME("(%p)->(%p): stub\n", This, parameter_block); + TRACE("iface %p, parameter_block %p.\n", iface, parameter_block);
- return E_NOTIMPL; + if (!block) + return D3DERR_INVALIDCALL; + + LIST_FOR_EACH_ENTRY(b, &effect->parameter_block_list, struct d3dx_parameter_block, entry) + { + if (b == block) + { + list_remove(&b->entry); + free_parameter_block(b); + return D3D_OK; + } + } + + WARN("Block is not found in issued block list, not freeing memory.\n"); + return D3DERR_INVALIDCALL; } #endif
diff --git a/dlls/d3dx9_36/tests/effect.c b/dlls/d3dx9_36/tests/effect.c index 71dc8ad226..86cad3e0cf 100644 --- a/dlls/d3dx9_36/tests/effect.c +++ b/dlls/d3dx9_36/tests/effect.c @@ -8081,7 +8081,7 @@ static void test_effect_parameter_block(void) hr = effect->lpVtbl->ApplyParameterBlock(effect, block); todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr); hr = effect->lpVtbl->DeleteParameterBlock(effect, block); - todo_wine ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(hr == D3D_OK, "Got result %#x.\n", hr);
hr = effect->lpVtbl->BeginParameterBlock(effect); ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); @@ -8095,9 +8095,9 @@ static void test_effect_parameter_block(void) todo_wine ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
hr = effect->lpVtbl->DeleteParameterBlock(effect2, block); - todo_wine ok(hr == D3DERR_INVALIDCALL, "Got result %#x.\n", hr); + ok(hr == D3DERR_INVALIDCALL, "Got result %#x.\n", hr); hr = effect->lpVtbl->DeleteParameterBlock(effect, block); - todo_wine ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(hr == D3D_OK, "Got result %#x.\n", hr);
hr = effect->lpVtbl->ApplyParameterBlock(effect, "parameter_block"); todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr); @@ -8166,7 +8166,7 @@ static void test_effect_parameter_block(void) ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
hr = effect->lpVtbl->DeleteParameterBlock(effect2, block); - todo_wine ok(hr == D3DERR_INVALIDCALL, "Got result %#x.\n", hr); + ok(hr == D3DERR_INVALIDCALL, "Got result %#x.\n", hr);
IDirect3DTexture9_AddRef(texture); refcount = IDirect3DTexture9_Release(texture); @@ -8222,7 +8222,7 @@ static void test_effect_parameter_block(void) float_array[0], float_array[1], float_array[2], float_array[3]);
hr = effect->lpVtbl->DeleteParameterBlock(effect, block); - todo_wine ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(hr == D3D_OK, "Got result %#x.\n", hr);
hr = effect->lpVtbl->SetTexture(effect, "tex1", NULL); ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
Signed-off-by: Paul Gofman gofmanp@gmail.com --- v2: - use heap_alloc() / heap_free() in set_string().
dlls/d3dx9_36/effect.c | 130 ++++++++++++++++++++++------------------- 1 file changed, 69 insertions(+), 61 deletions(-)
diff --git a/dlls/d3dx9_36/effect.c b/dlls/d3dx9_36/effect.c index 9b97d8ae20..4ebcc32090 100644 --- a/dlls/d3dx9_36/effect.c +++ b/dlls/d3dx9_36/effect.c @@ -827,6 +827,73 @@ static void set_matrix_transpose(struct d3dx_parameter *param, const D3DXMATRIX } }
+static HRESULT set_string(char **param_data, const char *string) +{ + heap_free(*param_data); + *param_data = heap_alloc(strlen(string) + 1); + if (!*param_data) + { + ERR("Out of memory.\n"); + return E_OUTOFMEMORY; + } + strcpy(*param_data, string); + return D3D_OK; +} + +static HRESULT set_value(struct d3dx_parameter *param, const void *data, unsigned int bytes) +{ + unsigned int i, count; + + bytes = min(bytes, param->bytes); + count = min(param->element_count ? param->element_count : 1, bytes / sizeof(void *)); + + switch (param->type) + { + case D3DXPT_TEXTURE: + case D3DXPT_TEXTURE1D: + case D3DXPT_TEXTURE2D: + case D3DXPT_TEXTURE3D: + case D3DXPT_TEXTURECUBE: + for (i = 0; i < count; ++i) + { + IUnknown *old_texture = ((IUnknown **)param->data)[i]; + IUnknown *new_texture = ((IUnknown **)data)[i]; + + if (new_texture == old_texture) + continue; + + if (new_texture) + IUnknown_AddRef(new_texture); + if (old_texture) + IUnknown_Release(old_texture); + } + /* fallthrough */ + case D3DXPT_VOID: + case D3DXPT_BOOL: + case D3DXPT_INT: + case D3DXPT_FLOAT: + TRACE("Copy %u bytes.\n", bytes); + memcpy(param->data, data, bytes); + break; + + case D3DXPT_STRING: + { + HRESULT hr; + + for (i = 0; i < count; ++i) + if (FAILED(hr = set_string(&((char **)param->data)[i], ((const char **)data)[i]))) + return hr; + break; + } + + default: + FIXME("Unhandled type %s.\n", debug_d3dxparameter_type(param->type)); + break; + } + + return D3D_OK; +} + static struct d3dx_parameter *get_parameter_element_by_name(struct d3dx_effect *effect, struct d3dx_parameter *parameter, const char *name) { @@ -1176,19 +1243,6 @@ static void set_dirty(struct d3dx_parameter *param) top_param->update_version = new_update_version; }
-static HRESULT set_string(char **param_data, const char *string) -{ - HeapFree(GetProcessHeap(), 0, *param_data); - *param_data = HeapAlloc(GetProcessHeap(), 0, strlen(string) + 1); - if (!*param_data) - { - ERR("Out of memory.\n"); - return E_OUTOFMEMORY; - } - strcpy(*param_data, string); - return D3D_OK; -} - static void d3dx9_set_light_parameter(enum LIGHT_TYPE op, D3DLIGHT9 *light, void *value) { static const struct @@ -2278,7 +2332,6 @@ static HRESULT WINAPI d3dx_effect_SetValue(ID3DXEffect *iface, D3DXHANDLE parame { struct d3dx_effect *effect = impl_from_ID3DXEffect(iface); struct d3dx_parameter *param = get_valid_parameter(effect, parameter); - unsigned int i;
TRACE("iface %p, parameter %p, data %p, bytes %u.\n", iface, parameter, data, bytes);
@@ -2295,53 +2348,8 @@ static HRESULT WINAPI d3dx_effect_SetValue(ID3DXEffect *iface, D3DXHANDLE parame
if (data && param->bytes <= bytes) { - switch (param->type) - { - case D3DXPT_TEXTURE: - case D3DXPT_TEXTURE1D: - case D3DXPT_TEXTURE2D: - case D3DXPT_TEXTURE3D: - case D3DXPT_TEXTURECUBE: - for (i = 0; i < (param->element_count ? param->element_count : 1); ++i) - { - IUnknown *old_texture = ((IUnknown **)param->data)[i]; - IUnknown *new_texture = ((IUnknown **)data)[i]; - - if (new_texture == old_texture) - continue; - - if (new_texture) - IUnknown_AddRef(new_texture); - if (old_texture) - IUnknown_Release(old_texture); - } - /* fallthrough */ - case D3DXPT_VOID: - case D3DXPT_BOOL: - case D3DXPT_INT: - case D3DXPT_FLOAT: - TRACE("Copy %u bytes.\n", param->bytes); - memcpy(param->data, data, param->bytes); - set_dirty(param); - break; - - case D3DXPT_STRING: - { - HRESULT hr; - - set_dirty(param); - for (i = 0; i < (param->element_count ? param->element_count : 1); ++i) - if (FAILED(hr = set_string(&((char **)param->data)[i], ((const char **)data)[i]))) - return hr; - break; - } - - default: - FIXME("Unhandled type %s.\n", debug_d3dxparameter_type(param->type)); - break; - } - - return D3D_OK; + set_dirty(param); + return set_value(param, data, bytes); }
WARN("Invalid argument specified.\n");
Signed-off-by: Paul Gofman gofmanp@gmail.com --- v2: - no changes.
dlls/d3dx9_36/effect.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-)
diff --git a/dlls/d3dx9_36/effect.c b/dlls/d3dx9_36/effect.c index 4ebcc32090..8706a086ea 100644 --- a/dlls/d3dx9_36/effect.c +++ b/dlls/d3dx9_36/effect.c @@ -540,16 +540,21 @@ static void free_sampler(struct d3dx_sampler *sampler)
static void d3dx_pool_release_shared_parameter(struct d3dx_top_level_parameter *param);
-static void free_parameter_data(struct d3dx_parameter *param, BOOL child) +static void free_parameter_object_data(struct d3dx_parameter *param, const void *data, unsigned int bytes) { - if (!param->data) + unsigned int i, count; + + if (param->class != D3DXPC_OBJECT) return; - if (param->class == D3DXPC_OBJECT && !param->element_count) + + count = min(param->element_count ? param->element_count : 1, bytes / sizeof(void *)); + + for (i = 0; i < count; ++i) { switch (param->type) { case D3DXPT_STRING: - heap_free(*(char **)param->data); + heap_free(((char **)data)[i]); break;
case D3DXPT_TEXTURE: @@ -559,7 +564,8 @@ static void free_parameter_data(struct d3dx_parameter *param, BOOL child) case D3DXPT_TEXTURECUBE: case D3DXPT_PIXELSHADER: case D3DXPT_VERTEXSHADER: - if (*(IUnknown **)param->data) IUnknown_Release(*(IUnknown **)param->data); + if (*(IUnknown **)data) + IUnknown_Release(((IUnknown **)data)[i]); break;
case D3DXPT_SAMPLER: @@ -567,7 +573,8 @@ static void free_parameter_data(struct d3dx_parameter *param, BOOL child) case D3DXPT_SAMPLER2D: case D3DXPT_SAMPLER3D: case D3DXPT_SAMPLERCUBE: - free_sampler((struct d3dx_sampler *)param->data); + assert(count == 1); + free_sampler((struct d3dx_sampler *)data); return;
default: @@ -575,6 +582,16 @@ static void free_parameter_data(struct d3dx_parameter *param, BOOL child) break; } } +} + +static void free_parameter_data(struct d3dx_parameter *param, BOOL child) +{ + if (!param->data) + return; + + if (!param->element_count) + free_parameter_object_data(param, param->data, param->bytes); + if (!child || is_param_type_sampler(param->type)) heap_free(param->data); }
Signed-off-by: Paul Gofman gofmanp@gmail.com --- v2 (basically redid the whole thing): - get rid of separate set_dirty() calls; - do not update parameter data while recording blocks; - record string parameters update as well.
dlls/d3dx9_36/effect.c | 239 +++++++++++++++++++++++++---------- dlls/d3dx9_36/tests/effect.c | 38 ++++-- 2 files changed, 203 insertions(+), 74 deletions(-)
diff --git a/dlls/d3dx9_36/effect.c b/dlls/d3dx9_36/effect.c index 8706a086ea..746f1eb9ed 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); }
@@ -778,14 +804,12 @@ static void get_vector(struct d3dx_parameter *param, D3DXVECTOR4 *vector) } }
-static void set_vector(struct d3dx_parameter *param, const D3DXVECTOR4 *vector) +static void set_vector(struct d3dx_parameter *param, const D3DXVECTOR4 *vector, void *dst_data) { UINT i;
for (i = 0; i < param->columns; ++i) - { - set_number((FLOAT *)param->data + i, param->type, (FLOAT *)vector + i, D3DXPT_FLOAT); - } + set_number((FLOAT *)dst_data + i, param->type, (FLOAT *)vector + i, D3DXPT_FLOAT); }
static void get_matrix(struct d3dx_parameter *param, D3DXMATRIX *matrix, BOOL transpose) @@ -806,31 +830,33 @@ static void get_matrix(struct d3dx_parameter *param, D3DXMATRIX *matrix, BOOL tr } }
-static void set_matrix(struct d3dx_parameter *param, const D3DXMATRIX *matrix) +static void set_matrix(struct d3dx_parameter *param, const D3DXMATRIX *matrix, void *dst_data) { UINT i, k;
if (param->type == D3DXPT_FLOAT) { if (param->columns == 4) - memcpy(param->data, matrix->u.m, param->rows * 4 * sizeof(float)); + { + memcpy(dst_data, matrix->u.m, param->rows * 4 * sizeof(float)); + } else + { for (i = 0; i < param->rows; ++i) - memcpy((float *)param->data + i * param->columns, matrix->u.m + i, param->columns * sizeof(float)); + memcpy((float *)dst_data + i * param->columns, matrix->u.m + i, param->columns * sizeof(float)); + } return; }
for (i = 0; i < param->rows; ++i) { for (k = 0; k < param->columns; ++k) - { - set_number((FLOAT *)param->data + i * param->columns + k, param->type, + set_number((FLOAT *)dst_data + i * param->columns + k, param->type, &matrix->u.m[i][k], D3DXPT_FLOAT); - } } }
-static void set_matrix_transpose(struct d3dx_parameter *param, const D3DXMATRIX *matrix) +static void set_matrix_transpose(struct d3dx_parameter *param, const D3DXMATRIX *matrix, void *dst_data) { UINT i, k;
@@ -838,7 +864,7 @@ static void set_matrix_transpose(struct d3dx_parameter *param, const D3DXMATRIX { for (k = 0; k < param->columns; ++k) { - set_number((FLOAT *)param->data + i * param->columns + k, param->type, + set_number((FLOAT *)dst_data + i * param->columns + k, param->type, &matrix->u.m[k][i], D3DXPT_FLOAT); } } @@ -857,7 +883,8 @@ static HRESULT set_string(char **param_data, const char *string) return D3D_OK; }
-static HRESULT set_value(struct d3dx_parameter *param, const void *data, unsigned int bytes) +static HRESULT set_value(struct d3dx_parameter *param, const void *data, unsigned int bytes, + void *dst_data) { unsigned int i, count;
@@ -873,7 +900,7 @@ static HRESULT set_value(struct d3dx_parameter *param, const void *data, unsigne case D3DXPT_TEXTURECUBE: for (i = 0; i < count; ++i) { - IUnknown *old_texture = ((IUnknown **)param->data)[i]; + IUnknown *old_texture = ((IUnknown **)dst_data)[i]; IUnknown *new_texture = ((IUnknown **)data)[i];
if (new_texture == old_texture) @@ -890,7 +917,7 @@ static HRESULT set_value(struct d3dx_parameter *param, const void *data, unsigne case D3DXPT_INT: case D3DXPT_FLOAT: TRACE("Copy %u bytes.\n", bytes); - memcpy(param->data, data, bytes); + memcpy(dst_data, data, bytes); break;
case D3DXPT_STRING: @@ -898,7 +925,7 @@ static HRESULT set_value(struct d3dx_parameter *param, const void *data, unsigne HRESULT hr;
for (i = 0; i < count; ++i) - if (FAILED(hr = set_string(&((char **)param->data)[i], ((const char **)data)[i]))) + if (FAILED(hr = set_string(&((char **)dst_data)[i], ((const char **)data)[i]))) return hr; break; } @@ -1248,6 +1275,43 @@ 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, 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; + + 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 param->data; + } + /* Data update functions may want to free some references upon setting value. */ + memset(new_alloc + block->buffer_size, 0, alloc_size - block->buffer_size); + + block->buffer_size = alloc_size; + block->buffer = new_alloc; + } + record = (struct d3dx_recorded_parameter *)(block->buffer + block->current_size); + *record = new_record; + block->current_size = new_size; + return record + 1; +} + static void set_dirty(struct d3dx_parameter *param) { struct d3dx_shared_data *shared_data; @@ -1260,6 +1324,17 @@ static void set_dirty(struct d3dx_parameter *param) top_param->update_version = new_update_version; }
+static void *parameter_get_update_data(struct d3dx_effect *effect, struct d3dx_parameter *param, + unsigned int bytes, BOOL value_changed) +{ + assert(bytes <= param->bytes); + + if (value_changed && !effect->current_parameter_block) + set_dirty(param); + + return effect->current_parameter_block ? record_parameter(effect, param, bytes) : param->data; +} + static void d3dx9_set_light_parameter(enum LIGHT_TYPE op, D3DLIGHT9 *light, void *value) { static const struct @@ -2364,10 +2439,7 @@ static HRESULT WINAPI d3dx_effect_SetValue(ID3DXEffect *iface, D3DXHANDLE parame }
if (data && param->bytes <= bytes) - { - set_dirty(param); - return set_value(param, data, bytes); - } + return set_value(param, data, bytes, parameter_get_update_data(effect, param, param->bytes, TRUE));
WARN("Invalid argument specified.\n");
@@ -2448,8 +2520,8 @@ 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); - set_dirty(param); + set_number(parameter_get_update_data(effect, param, sizeof(int), TRUE), + param->type, &b, D3DXPT_BOOL); return D3D_OK; }
@@ -2481,6 +2553,7 @@ static HRESULT WINAPI d3dx_effect_SetBoolArray(ID3DXEffect *iface, D3DXHANDLE pa { struct d3dx_effect *effect = impl_from_ID3DXEffect(iface); struct d3dx_parameter *param = get_valid_parameter(effect, parameter); + void *data;
TRACE("iface %p, parameter %p, b %p, count %u.\n", iface, parameter, b, count);
@@ -2495,12 +2568,12 @@ static HRESULT WINAPI d3dx_effect_SetBoolArray(ID3DXEffect *iface, D3DXHANDLE pa case D3DXPC_SCALAR: case D3DXPC_VECTOR: case D3DXPC_MATRIX_ROWS: + data = parameter_get_update_data(effect, param, size * sizeof(int), TRUE); for (i = 0; i < size; ++i) { /* don't crop the input, use D3DXPT_INT instead of D3DXPT_BOOL */ - set_number((DWORD *)param->data + i, param->type, &b[i], D3DXPT_INT); + set_number((DWORD *)data + i, param->type, &b[i], D3DXPT_INT); } - set_dirty(param); return D3D_OK;
case D3DXPC_OBJECT: @@ -2558,9 +2631,8 @@ static HRESULT WINAPI d3dx_effect_SetInt(ID3DXEffect *iface, D3DXHANDLE paramete DWORD value;
set_number(&value, param->type, &n, D3DXPT_INT); - if (value != *(DWORD *)param->data) - set_dirty(param); - *(DWORD *)param->data = value; + *(DWORD *)parameter_get_update_data(effect, param, sizeof(int), + value != *(DWORD *)param->data) = value; return D3D_OK; }
@@ -2569,14 +2641,19 @@ static HRESULT WINAPI d3dx_effect_SetInt(ID3DXEffect *iface, D3DXHANDLE paramete && ((param->class == D3DXPC_VECTOR && param->columns != 2) || (param->class == D3DXPC_MATRIX_ROWS && param->rows != 2 && param->columns == 1))) { + void *data; + TRACE("Vector fixup.\n");
- *(float *)param->data = ((n & 0xff0000) >> 16) * INT_FLOAT_MULTI_INVERSE; - ((float *)param->data)[1] = ((n & 0xff00) >> 8) * INT_FLOAT_MULTI_INVERSE; - ((float *)param->data)[2] = (n & 0xff) * INT_FLOAT_MULTI_INVERSE; + data = parameter_get_update_data(effect, param, + min(4, param->rows * param->columns) * sizeof(float), TRUE); + + *(float *)data = ((n & 0xff0000) >> 16) * INT_FLOAT_MULTI_INVERSE; + ((float *)data)[1] = ((n & 0xff00) >> 8) * INT_FLOAT_MULTI_INVERSE; + ((float *)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; - set_dirty(param); + ((float *)data)[3] = ((n & 0xff000000) >> 24) * INT_FLOAT_MULTI_INVERSE; + return D3D_OK; } } @@ -2628,6 +2705,7 @@ static HRESULT WINAPI d3dx_effect_SetIntArray(ID3DXEffect *iface, D3DXHANDLE par { struct d3dx_effect *effect = impl_from_ID3DXEffect(iface); struct d3dx_parameter *param = get_valid_parameter(effect, parameter); + void *data;
TRACE("iface %p, parameter %p, n %p, count %u.\n", iface, parameter, n, count);
@@ -2642,9 +2720,9 @@ static HRESULT WINAPI d3dx_effect_SetIntArray(ID3DXEffect *iface, D3DXHANDLE par case D3DXPC_SCALAR: case D3DXPC_VECTOR: case D3DXPC_MATRIX_ROWS: + data = parameter_get_update_data(effect, param, size * sizeof(int), TRUE); for (i = 0; i < size; ++i) - set_number((DWORD *)param->data + i, param->type, &n[i], D3DXPT_INT); - set_dirty(param); + set_number((DWORD *)data + i, param->type, &n[i], D3DXPT_INT); return D3D_OK;
case D3DXPC_OBJECT: @@ -2698,9 +2776,8 @@ static HRESULT WINAPI d3dx_effect_SetFloat(ID3DXEffect *iface, D3DXHANDLE parame DWORD value;
set_number(&value, param->type, &f, D3DXPT_FLOAT); - if (value != *(DWORD *)param->data) - set_dirty(param); - *(DWORD *)param->data = value; + *(DWORD *)parameter_get_update_data(effect, param, sizeof(float), + value != *(DWORD *)param->data) = value; return D3D_OK; }
@@ -2733,6 +2810,7 @@ static HRESULT WINAPI d3dx_effect_SetFloatArray(ID3DXEffect *iface, D3DXHANDLE p { struct d3dx_effect *effect = impl_from_ID3DXEffect(iface); struct d3dx_parameter *param = get_valid_parameter(effect, parameter); + void *data;
TRACE("iface %p, parameter %p, f %p, count %u.\n", iface, parameter, f, count);
@@ -2747,9 +2825,9 @@ static HRESULT WINAPI d3dx_effect_SetFloatArray(ID3DXEffect *iface, D3DXHANDLE p case D3DXPC_SCALAR: case D3DXPC_VECTOR: case D3DXPC_MATRIX_ROWS: + data = parameter_get_update_data(effect, param, size * sizeof(float), TRUE); for (i = 0; i < size; ++i) - set_number((DWORD *)param->data + i, param->type, &f[i], D3DXPT_FLOAT); - set_dirty(param); + set_number((DWORD *)data + i, param->type, &f[i], D3DXPT_FLOAT); return D3D_OK;
case D3DXPC_OBJECT: @@ -2806,7 +2884,6 @@ static HRESULT WINAPI d3dx_effect_SetVector(ID3DXEffect *iface, D3DXHANDLE param { case D3DXPC_SCALAR: case D3DXPC_VECTOR: - set_dirty(param); if (param->type == D3DXPT_INT && param->bytes == 4) { DWORD tmp; @@ -2817,16 +2894,17 @@ static HRESULT WINAPI d3dx_effect_SetVector(ID3DXEffect *iface, D3DXHANDLE param tmp += ((DWORD)(max(min(vector->x, 1.0f), 0.0f) * INT_FLOAT_MULTI)) << 16; tmp += ((DWORD)(max(min(vector->w, 1.0f), 0.0f) * INT_FLOAT_MULTI)) << 24;
- *(int *)param->data = tmp; + *(int *)parameter_get_update_data(effect, param, sizeof(int), TRUE) = tmp; return D3D_OK; } if (param->type == D3DXPT_FLOAT) { - memcpy(param->data, vector, param->columns * sizeof(float)); + memcpy(parameter_get_update_data(effect, param, param->columns * sizeof(float), TRUE), + vector, param->columns * sizeof(float)); return D3D_OK; }
- set_vector(param, vector); + set_vector(param, vector, parameter_get_update_data(effect, param, param->columns * sizeof(float), TRUE)); return D3D_OK;
case D3DXPC_MATRIX_ROWS: @@ -2899,26 +2977,34 @@ static HRESULT WINAPI d3dx_effect_SetVectorArray(ID3DXEffect *iface, D3DXHANDLE if (param && param->element_count && param->element_count >= count) { unsigned int i; + BYTE *data;
TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
switch (param->class) { case D3DXPC_VECTOR: - set_dirty(param); + data = (BYTE *)parameter_get_update_data(effect, param, + count * param->columns * sizeof(float), TRUE); + if (param->type == D3DXPT_FLOAT) { if (param->columns == 4) - memcpy(param->data, vector, count * 4 * sizeof(float)); + { + memcpy(data, vector, count * 4 * sizeof(float)); + } else + { for (i = 0; i < count; ++i) - memcpy((float *)param->data + param->columns * i, vector + i, + memcpy((float *)data + param->columns * i, vector + i, param->columns * sizeof(float)); + } return D3D_OK; }
for (i = 0; i < count; ++i) - set_vector(¶m->members[i], &vector[i]); + set_vector(¶m->members[i], &vector[i], data + i * param->columns * sizeof(float)); + return D3D_OK;
case D3DXPC_SCALAR: @@ -2993,8 +3079,8 @@ static HRESULT WINAPI d3dx_effect_SetMatrix(ID3DXEffect *iface, D3DXHANDLE param switch (param->class) { case D3DXPC_MATRIX_ROWS: - set_matrix(param, matrix); - set_dirty(param); + set_matrix(param, matrix, parameter_get_update_data(effect, param, + param->rows * param->columns * sizeof(float), TRUE)); return D3D_OK;
case D3DXPC_SCALAR: @@ -3059,15 +3145,20 @@ static HRESULT WINAPI d3dx_effect_SetMatrixArray(ID3DXEffect *iface, D3DXHANDLE if (param && param->element_count >= count) { unsigned int i; + BYTE *data;
TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
switch (param->class) { case D3DXPC_MATRIX_ROWS: - set_dirty(param); + data = parameter_get_update_data(effect, param, count * param->rows + * param->columns * sizeof(float), TRUE); + for (i = 0; i < count; ++i) - set_matrix(¶m->members[i], &matrix[i]); + set_matrix(¶m->members[i], &matrix[i], + data + i * param->rows * param->columns * sizeof(float)); + return D3D_OK;
case D3DXPC_SCALAR: @@ -3139,13 +3230,18 @@ static HRESULT WINAPI d3dx_effect_SetMatrixPointerArray(ID3DXEffect *iface, D3DX if (param && count <= param->element_count) { unsigned int i; + BYTE *data;
switch (param->class) { case D3DXPC_MATRIX_ROWS: - set_dirty(param); + data = parameter_get_update_data(effect, param, count * param->rows + * param->columns * sizeof(float), TRUE); + for (i = 0; i < count; ++i) - set_matrix(¶m->members[i], matrix[i]); + set_matrix(¶m->members[i], matrix[i], data + i * param->rows + * param->columns * sizeof(float)); + return D3D_OK;
case D3DXPC_SCALAR: @@ -3219,8 +3315,8 @@ static HRESULT WINAPI d3dx_effect_SetMatrixTranspose(ID3DXEffect *iface, D3DXHAN switch (param->class) { case D3DXPC_MATRIX_ROWS: - set_dirty(param); - set_matrix_transpose(param, matrix); + set_matrix_transpose(param, matrix, parameter_get_update_data(effect, param, + param->rows * param->columns * sizeof(float), TRUE)); return D3D_OK;
case D3DXPC_SCALAR: @@ -3289,15 +3385,20 @@ static HRESULT WINAPI d3dx_effect_SetMatrixTransposeArray(ID3DXEffect *iface, D3 if (param && param->element_count >= count) { unsigned int i; + BYTE *data;
TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
switch (param->class) { case D3DXPC_MATRIX_ROWS: - set_dirty(param); + data = parameter_get_update_data(effect, param, count * param->rows + * param->columns * sizeof(float), TRUE); + for (i = 0; i < count; ++i) - set_matrix_transpose(¶m->members[i], &matrix[i]); + set_matrix_transpose(¶m->members[i], &matrix[i], data + + i * param->rows * param->columns * sizeof(float)); + return D3D_OK;
case D3DXPC_SCALAR: @@ -3369,13 +3470,18 @@ static HRESULT WINAPI d3dx_effect_SetMatrixTransposePointerArray(ID3DXEffect *if if (param && count <= param->element_count) { unsigned int i; + BYTE *data;
switch (param->class) { case D3DXPC_MATRIX_ROWS: - set_dirty(param); + data = parameter_get_update_data(effect, param, count * param->rows + * param->columns * sizeof(float), TRUE); + for (i = 0; i < count; ++i) - set_matrix_transpose(¶m->members[i], matrix[i]); + set_matrix_transpose(¶m->members[i], matrix[i], data + + i * param->rows * param->columns * sizeof(float)); + return D3D_OK;
case D3DXPC_SCALAR: @@ -3442,10 +3548,7 @@ static HRESULT WINAPI d3dx_effect_SetString(ID3DXEffect *iface, D3DXHANDLE param TRACE("iface %p, parameter %p, string %s.\n", iface, parameter, debugstr_a(string));
if (param && param->type == D3DXPT_STRING) - { - set_dirty(param); - return set_string(param->data, string); - } + return set_string(parameter_get_update_data(effect, param, sizeof(void *), TRUE), string);
WARN("Parameter not found.\n");
@@ -3486,6 +3589,9 @@ static HRESULT WINAPI d3dx_effect_SetTexture(ID3DXEffect *iface, D3DXHANDLE para { IDirect3DBaseTexture9 *old_texture = *(IDirect3DBaseTexture9 **)param->data;
+ *(IDirect3DBaseTexture9 **)parameter_get_update_data(effect, param, + sizeof(void *), texture != old_texture) = texture; + if (texture == old_texture) return D3D_OK;
@@ -3494,9 +3600,6 @@ static HRESULT WINAPI d3dx_effect_SetTexture(ID3DXEffect *iface, D3DXHANDLE para if (old_texture) IDirect3DBaseTexture9_Release(old_texture);
- *(IDirect3DBaseTexture9 **)param->data = texture; - set_dirty(param); - return D3D_OK; }
@@ -4137,6 +4240,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 86cad3e0cf..d86ae2acb5 100644 --- a/dlls/d3dx9_36/tests/effect.c +++ b/dlls/d3dx9_36/tests/effect.c @@ -8019,13 +8019,13 @@ static void test_effect_parameter_block(void) static const float float_array_zero[4]; IDirect3DTexture9 *texture, *tex_test; ID3DXEffect *effect, *effect2; + D3DXMATRIX mat, mat_arr[2]; D3DXHANDLE block, handle; IDirect3DDevice9 *device; ID3DXEffectPool *pool; float float_array[4]; float float_value; IDirect3D9 *d3d; - D3DXMATRIX mat; ULONG refcount; HWND window; HRESULT hr; @@ -8112,9 +8112,7 @@ static void test_effect_parameter_block(void) ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
hr = effect->lpVtbl->GetTexture(effect, "tex1", (IDirect3DBaseTexture9 **)&tex_test); - todo_wine ok(hr == D3D_OK && !tex_test, "Got unexpected hr %#x, tex_test %p.\n", hr, tex_test); - if (tex_test) - IDirect3DTexture9_Release(tex_test); + ok(hr == D3D_OK && !tex_test, "Got unexpected hr %#x, tex_test %p.\n", hr, tex_test);
/* Child parameters and array members are recorded separately (the whole parameter is not * updated when parameter block is applied). @@ -8126,13 +8124,13 @@ static void test_effect_parameter_block(void) hr = effect->lpVtbl->SetFloat(effect, "ts1[0].fv", 28.0f); ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); hr = effect->lpVtbl->GetFloat(effect, "ts1[0].fv", &float_value); - todo_wine ok(hr == D3D_OK && float_value == 12.0, "Got unexpected hr %#x, float_value %g.\n", hr, float_value); + ok(hr == D3D_OK && float_value == 12.0, "Got unexpected hr %#x, float_value %g.\n", hr, float_value);
float_array[0] = -29.0f; hr = effect->lpVtbl->SetFloatArray(effect, "ts1[0].v2", float_array, 1); ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); hr = effect->lpVtbl->GetFloatArray(effect, "ts1[0].v2", float_array, 1); - todo_wine ok(hr == D3D_OK && float_array[0] == 13.0, "Got unexpected hr %#x, float_array[0] %g.\n", + ok(hr == D3D_OK && float_array[0] == 13.0, "Got unexpected hr %#x, float_array[0] %g.\n", hr, float_array[0]);
memset(&mat, 0, sizeof(mat)); @@ -8140,13 +8138,13 @@ static void test_effect_parameter_block(void) ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); hr = effect->lpVtbl->GetMatrix(effect, "m3x2row", &mat); ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); - todo_wine ok(!memcmp(&mat, &effect_orig_mat, sizeof(mat)), "Got unexpected matrix.\n"); + ok(!memcmp(&mat, &effect_orig_mat, sizeof(mat)), "Got unexpected matrix.\n");
hr = effect->lpVtbl->SetMatrix(effect, "m3x2column", &test_mat); ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); hr = effect->lpVtbl->GetMatrix(effect, "m3x2column", &mat); ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); - todo_wine ok(!memcmp(&mat, &effect_orig_mat, sizeof(mat)), "Got unexpected matrix.\n"); + ok(!memcmp(&mat, &effect_orig_mat, sizeof(mat)), "Got unexpected matrix.\n");
hr = effect2->lpVtbl->SetFloat(effect2, "arr2[1]", -1.0f); ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); @@ -8238,6 +8236,30 @@ static void test_effect_parameter_block(void) refcount = pool->lpVtbl->Release(pool); ok(!refcount, "Got unexpected refcount %u.\n", refcount);
+ hr = D3DXCreateEffect(device, test_effect_parameter_value_blob_float, sizeof(test_effect_parameter_value_blob_float), + NULL, NULL, 0, NULL, &effect, NULL); + hr = effect->lpVtbl->BeginParameterBlock(effect); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + mat_arr[0] = mat_arr[1] = test_mat; + hr = effect->lpVtbl->SetMatrixArray(effect, "f33_2", mat_arr, 2); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + block = effect->lpVtbl->EndParameterBlock(effect); + ok(!!block, "Got unexpected block %p.\n", block); + + memset(mat_arr, 0, sizeof(mat_arr)); + hr = effect->lpVtbl->SetMatrixArray(effect, "f33_2", mat_arr, 2); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = effect->lpVtbl->ApplyParameterBlock(effect, block); + todo_wine ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->GetMatrixArray(effect, "f33_2", mat_arr, 2); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + todo_wine ok(!memcmp(&mat_arr[0], &test_mat, sizeof(test_mat)) + && !memcmp(&mat_arr[1], &test_mat, sizeof(test_mat)), "Got unexpected matrix array.\n"); + + refcount = effect->lpVtbl->Release(effect); + ok(!refcount, "Got unexpected refcount %u.\n", refcount); + refcount = IDirect3DDevice9_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); IDirect3D9_Release(d3d);
Signed-off-by: Paul Gofman gofmanp@gmail.com --- v2: - added test for applying block during recording; - also update current parameter on parameter block application.
dlls/d3dx9_36/effect.c | 25 ++++++++++++++-- dlls/d3dx9_36/tests/effect.c | 58 ++++++++++++++++++++++++++++-------- 2 files changed, 68 insertions(+), 15 deletions(-)
diff --git a/dlls/d3dx9_36/effect.c b/dlls/d3dx9_36/effect.c index 746f1eb9ed..fc43cdd918 100644 --- a/dlls/d3dx9_36/effect.c +++ b/dlls/d3dx9_36/effect.c @@ -153,6 +153,7 @@ struct d3dx_technique struct d3dx_parameter_block { char magic_string[ARRAY_SIZE(parameter_block_magic_string)]; + struct d3dx_effect *effect; struct list entry; size_t buffer_size; size_t current_size; @@ -4223,6 +4224,7 @@ static HRESULT WINAPI d3dx_effect_BeginParameterBlock(ID3DXEffect *iface) effect->current_parameter_block = heap_alloc_zero(sizeof(*effect->current_parameter_block)); memcpy(effect->current_parameter_block->magic_string, parameter_block_magic_string, sizeof(parameter_block_magic_string)); + effect->current_parameter_block->effect = effect;
return D3D_OK; } @@ -4251,11 +4253,28 @@ static D3DXHANDLE WINAPI d3dx_effect_EndParameterBlock(ID3DXEffect *iface)
static HRESULT WINAPI d3dx_effect_ApplyParameterBlock(ID3DXEffect *iface, D3DXHANDLE parameter_block) { - struct d3dx_effect *This = impl_from_ID3DXEffect(iface); + struct d3dx_parameter_block *block = get_valid_parameter_block(parameter_block); + struct d3dx_recorded_parameter *record;
- FIXME("(%p)->(%p): stub\n", This, parameter_block); + TRACE("iface %p, paramater_block %p.\n", iface, parameter_block);
- return E_NOTIMPL; + if (!block || !block->current_size) + return D3DERR_INVALIDCALL; + + record = (struct d3dx_recorded_parameter *)block->buffer; + while ((BYTE *)record < block->buffer + block->current_size) + { + set_value(record->param, record + 1, record->bytes, record->param->data); + if (block->effect->current_parameter_block) + set_value(record->param, record + 1, record->bytes, + record_parameter(block->effect, record->param, record->bytes)); + + set_dirty(record->param); + + record = (struct d3dx_recorded_parameter *)((BYTE *)record + get_recorded_parameter_size(record)); + } + assert((BYTE *)record == block->buffer + block->current_size); + return D3D_OK; }
#if D3DX_SDK_VERSION >= 26 diff --git a/dlls/d3dx9_36/tests/effect.c b/dlls/d3dx9_36/tests/effect.c index d86ae2acb5..316d874a69 100644 --- a/dlls/d3dx9_36/tests/effect.c +++ b/dlls/d3dx9_36/tests/effect.c @@ -8079,7 +8079,7 @@ static void test_effect_parameter_block(void) ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
hr = effect->lpVtbl->ApplyParameterBlock(effect, block); - todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr); + ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr); hr = effect->lpVtbl->DeleteParameterBlock(effect, block); ok(hr == D3D_OK, "Got result %#x.\n", hr);
@@ -8092,7 +8092,7 @@ static void test_effect_parameter_block(void) block = effect->lpVtbl->EndParameterBlock(effect); ok(!!block, "Got unexpected block %p.\n", block); hr = effect->lpVtbl->ApplyParameterBlock(effect, block); - todo_wine ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
hr = effect->lpVtbl->DeleteParameterBlock(effect2, block); ok(hr == D3DERR_INVALIDCALL, "Got result %#x.\n", hr); @@ -8100,7 +8100,7 @@ static void test_effect_parameter_block(void) ok(hr == D3D_OK, "Got result %#x.\n", hr);
hr = effect->lpVtbl->ApplyParameterBlock(effect, "parameter_block"); - todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr); + ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
hr = D3DXCreateTexture(device, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, 0, D3DPOOL_DEFAULT, &texture); ok(hr == D3D_OK, "Got result %#x, expected 0 (D3D_OK).\n", hr); @@ -8187,14 +8187,14 @@ static void test_effect_parameter_block(void) ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
hr = effect->lpVtbl->ApplyParameterBlock(effect, block); - todo_wine ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(hr == D3D_OK, "Got result %#x.\n", hr);
IDirect3DTexture9_AddRef(texture); refcount = IDirect3DTexture9_Release(texture); - todo_wine ok(refcount == 3, "Got unexpected refcount %u.\n", refcount); + ok(refcount == 3, "Got unexpected refcount %u.\n", refcount);
hr = effect->lpVtbl->GetFloat(effect, "arr2[0]", &float_value); - todo_wine ok(hr == D3D_OK && float_value == 92.0f, "Got unexpected hr %#x, float_value %g.\n", hr, float_value); + ok(hr == D3D_OK && float_value == 92.0f, "Got unexpected hr %#x, float_value %g.\n", hr, float_value); hr = effect->lpVtbl->GetFloat(effect, "arr2[1]", &float_value); ok(hr == D3D_OK && float_value == 0.0f, "Got unexpected hr %#x, float_value %g.\n", hr, float_value);
@@ -8205,16 +8205,16 @@ static void test_effect_parameter_block(void)
hr = effect->lpVtbl->GetMatrix(effect, "m3x2row", &mat); ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); - todo_wine ok(!memcmp(&mat, &test_mat, sizeof(mat)), "Got unexpected matrix.\n"); + ok(!memcmp(&mat, &test_mat, sizeof(mat)), "Got unexpected matrix.\n"); hr = effect->lpVtbl->GetMatrix(effect, "m3x2column", &mat); ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); - todo_wine ok(!memcmp(&mat, &test_mat, sizeof(mat)), "Got unexpected matrix.\n"); + ok(!memcmp(&mat, &test_mat, sizeof(mat)), "Got unexpected matrix.\n");
hr = effect->lpVtbl->GetFloat(effect, "ts1[0].fv", &float_value); - todo_wine ok(hr == D3D_OK && float_value == 28.0f, "Got unexpected hr %#x, float_value %g.\n", hr, float_value); + ok(hr == D3D_OK && float_value == 28.0f, "Got unexpected hr %#x, float_value %g.\n", hr, float_value);
hr = effect->lpVtbl->GetFloatArray(effect, "ts1[0].v2", float_array, 4); - todo_wine ok(hr == D3D_OK && float_array[0] == -29.0f + ok(hr == D3D_OK && float_array[0] == -29.0f && !memcmp(float_array + 1, float_array_zero, 3 * sizeof(*float_array)), "Got unexpected hr %#x, ts1[0].v2 (%g, %g, %g, %g).\n", hr, float_array[0], float_array[1], float_array[2], float_array[3]); @@ -8250,11 +8250,45 @@ static void test_effect_parameter_block(void) hr = effect->lpVtbl->SetMatrixArray(effect, "f33_2", mat_arr, 2); ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); hr = effect->lpVtbl->ApplyParameterBlock(effect, block); - todo_wine ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->GetMatrixArray(effect, "f33_2", mat_arr, 2); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + ok(!memcmp(&mat_arr[0], &test_mat, sizeof(test_mat)) + && !memcmp(&mat_arr[1], &test_mat, sizeof(test_mat)), "Got unexpected matrix array.\n"); + + hr = effect->lpVtbl->BeginParameterBlock(effect); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + + memset(mat_arr, 0, sizeof(mat_arr)); + hr = effect->lpVtbl->SetMatrixArray(effect, "f33_2", mat_arr, 2); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + + /* Applying a block while recording another one puts the data both + * to parameter and a new block. */ + hr = effect->lpVtbl->ApplyParameterBlock(effect, block); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->GetMatrixArray(effect, "f33_2", mat_arr, 2); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + ok(!memcmp(&mat_arr[0], &test_mat, sizeof(test_mat)) + && !memcmp(&mat_arr[1], &test_mat, sizeof(test_mat)), "Got unexpected matrix array.\n"); + + hr = effect->lpVtbl->DeleteParameterBlock(effect, block); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + block = effect->lpVtbl->EndParameterBlock(effect); + ok(!!block, "Got unexpected block %p.\n", block); + + memset(mat_arr, 0, sizeof(mat_arr)); + hr = effect->lpVtbl->SetMatrixArray(effect, "f33_2", mat_arr, 2); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + + hr = effect->lpVtbl->ApplyParameterBlock(effect, block); + ok(hr == D3D_OK, "Got result %#x.\n", hr);
hr = effect->lpVtbl->GetMatrixArray(effect, "f33_2", mat_arr, 2); ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); - todo_wine ok(!memcmp(&mat_arr[0], &test_mat, sizeof(test_mat)) + ok(!memcmp(&mat_arr[0], &test_mat, sizeof(test_mat)) && !memcmp(&mat_arr[1], &test_mat, sizeof(test_mat)), "Got unexpected matrix array.\n");
refcount = effect->lpVtbl->Release(effect);