diff --git a/dlls/d3dx9_36/effect.c b/dlls/d3dx9_36/effect.c index 15683dfe78..fec95be502 100644 --- a/dlls/d3dx9_36/effect.c +++ b/dlls/d3dx9_36/effect.c @@ -32,6 +32,9 @@ typedef struct ID3DXEffectImpl { ID3DXEffect ID3DXEffect_iface; LONG ref; + LPDIRECT3DDEVICE9 device; + LPD3DXEFFECTPOOL pool; + UINT parameter_count; UINT technique_count; } ID3DXEffectImpl; @@ -55,6 +58,18 @@ static void skip_dword_unknown(const char **ptr, unsigned int count) } } +static void free_effect(struct ID3DXEffectImpl *effect) +{ + TRACE("Free effect %p\n", effect); + + if (effect->pool) + { + effect->pool->lpVtbl->Release(effect->pool); + } + + IDirect3DDevice9_Release(effect->device); +} + static inline DWORD d3dx9_effect_version(DWORD major, DWORD minor) { return (0xfeff0000 | ((major) << 8) | (minor)); @@ -103,7 +118,10 @@ static ULONG WINAPI ID3DXEffectImpl_Release(ID3DXEffect* iface) TRACE("(%p)->(): Release from %u\n", This, ref + 1); if (!ref) + { + free_effect(This); HeapFree(GetProcessHeap(), 0, This); + } return ref; } @@ -899,15 +917,24 @@ static HRESULT d3dx9_parse_effect(ID3DXEffectImpl *effect, const char *data, UIN return S_OK; } -static HRESULT d3dx9_effect_init(ID3DXEffectImpl *effect, const char *data, SIZE_T data_size) +static HRESULT d3dx9_effect_init(ID3DXEffectImpl *effect, LPDIRECT3DDEVICE9 device, + const char *data, SIZE_T data_size, LPD3DXEFFECTPOOL pool) { DWORD tag, offset; const char *ptr = data; HRESULT hr; + TRACE("effect %p, device %p, data %p, data_size %lu, pool %p\n", effect, device, data, data_size, pool); + effect->ID3DXEffect_iface.lpVtbl = &ID3DXEffect_Vtbl; effect->ref = 1; + if (pool) pool->lpVtbl->AddRef(pool); + effect->pool = pool; + + IDirect3DDevice9_AddRef(device); + effect->device = device; + read_dword(&ptr, &tag); TRACE("Tag: %x\n", tag); @@ -928,11 +955,17 @@ static HRESULT d3dx9_effect_init(ID3DXEffectImpl *effect, const char *data, SIZE if (hr != S_OK) { FIXME("Failed to parse effect.\n"); - return hr; + goto err_out; } } return S_OK; + +err_out: + + free_effect(effect); + + return hr; } HRESULT WINAPI D3DXCreateEffectEx(LPDIRECT3DDEVICE9 device, @@ -969,7 +1002,7 @@ HRESULT WINAPI D3DXCreateEffectEx(LPDIRECT3DDEVICE9 device, return E_OUTOFMEMORY; } - hr = d3dx9_effect_init(object, srcdata, srcdatalen); + hr = d3dx9_effect_init(object, device, srcdata, srcdatalen, pool); if (FAILED(hr)) { WARN("Failed to initialize shader reflection\n"); diff --git a/dlls/d3dx9_36/tests/effect.c b/dlls/d3dx9_36/tests/effect.c index 8b23536a2e..f4e0f9a1ca 100644 --- a/dlls/d3dx9_36/tests/effect.c +++ b/dlls/d3dx9_36/tests/effect.c @@ -16,6 +16,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#define COBJMACROS +#include "initguid.h" #include "wine/test.h" #include "d3dx9.h" @@ -24,10 +26,11 @@ static const char effect_desc[] = "{\n" "}\n"; -static void test_create_effect(IDirect3DDevice9* device) +static void test_create_effect(IDirect3DDevice9 *device) { HRESULT hr; - ID3DXEffect* effect; + ID3DXEffect *effect; + ULONG count; hr = D3DXCreateEffect(NULL, effect_desc, sizeof(effect_desc), NULL, NULL, 0, NULL, NULL, NULL); ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3D_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); @@ -44,13 +47,16 @@ static void test_create_effect(IDirect3DDevice9* device) hr = D3DXCreateEffect(device, effect_desc, sizeof(effect_desc), NULL, NULL, 0, NULL, &effect, NULL); ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); - effect->lpVtbl->Release(effect); + count = effect->lpVtbl->Release(effect); + ok(count == 0, "Release failed %u\n", count); } -static void test_create_effect_pool(void) +static void test_create_effect_pool(IDirect3DDevice9 *device) { HRESULT hr; - ID3DXEffectPool* pool; + ID3DXEffectPool *pool, *pool2; + ULONG count; + IDirect3DDevice9 *device2; hr = D3DXCreateEffectPool(NULL); ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3D_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); @@ -58,7 +64,29 @@ static void test_create_effect_pool(void) hr = D3DXCreateEffectPool(&pool); ok(hr == S_OK, "Got result %x, expected 0 (S_OK)\n", hr); - pool->lpVtbl->Release(pool); + count = pool->lpVtbl->Release(pool); + ok(count == 0, "Release failed %u\n", count); + + hr = D3DXCreateEffectPool(&pool); + ok(hr == S_OK, "Got result %x, expected 0 (S_OK)\n", hr); + + hr = D3DXCreateEffect(device, effect_desc, sizeof(effect_desc), NULL, NULL, 0, pool, NULL, NULL); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + + hr = pool->lpVtbl->QueryInterface(pool, &IID_ID3DXEffectPool, (void **)&pool2); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + + count = pool2->lpVtbl->Release(pool2); + ok(count == 1, "Release failed, got %u, expected 1\n", count); + + hr = device->lpVtbl->QueryInterface(device, &IID_IDirect3DDevice9, (void **)&device2); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + + count = device2->lpVtbl->Release(device2); + ok(count == 1, "Release failed, got %u, expected 1\n", count); + + count = pool->lpVtbl->Release(pool); + ok(count == 0, "Release failed %u\n", count); } START_TEST(effect) @@ -93,7 +121,7 @@ START_TEST(effect) } test_create_effect(device); - test_create_effect_pool(); + test_create_effect_pool(device); IDirect3DDevice9_Release(device); IDirect3D9_Release(d3d);