From c1487eee3ebbca16be17acf6cfd956d50aaf64e2 Mon Sep 17 00:00:00 2001 From: Paul Gofman Date: Thu, 3 Mar 2016 15:22:14 +0300 Subject: [PATCH] d3dx9: Implement state save and restore in effect. Signed-off-by: Paul Gofman Signed-off-by: Matteo Bruni Signed-off-by: Alexandre Julliard --- dlls/d3dx9_36/effect.c | 56 +++++++++++++++++++++++++++++------- dlls/d3dx9_36/tests/effect.c | 22 +++++++++++--- 2 files changed, 63 insertions(+), 15 deletions(-) diff --git a/dlls/d3dx9_36/effect.c b/dlls/d3dx9_36/effect.c index 6813c7914b7..ca5c46b837a 100644 --- a/dlls/d3dx9_36/effect.c +++ b/dlls/d3dx9_36/effect.c @@ -162,6 +162,8 @@ struct d3dx_technique struct d3dx_parameter *annotations; struct d3dx_pass *passes; + + struct IDirect3DStateBlock9 *saved_state; }; struct param_table @@ -642,6 +644,12 @@ static void free_technique(struct d3dx_technique *technique) if (!technique) return; + if (technique->saved_state) + { + IDirect3DStateBlock9_Release(technique->saved_state); + technique->saved_state = NULL; + } + if (technique->annotations) { for (i = 0; i < technique->annotation_count; ++i) @@ -3483,8 +3491,8 @@ static BOOL WINAPI ID3DXEffectImpl_IsParameterUsed(ID3DXEffect* iface, D3DXHANDL static HRESULT WINAPI ID3DXEffectImpl_Begin(ID3DXEffect *iface, UINT *passes, DWORD flags) { - struct ID3DXEffectImpl *This = impl_from_ID3DXEffect(iface); - struct d3dx_technique *technique = This->active_technique; + struct ID3DXEffectImpl *effect = impl_from_ID3DXEffect(iface); + struct d3dx_technique *technique = effect->active_technique; TRACE("iface %p, passes %p, flags %#x.\n", iface, passes, flags); @@ -3493,18 +3501,34 @@ static HRESULT WINAPI ID3DXEffectImpl_Begin(ID3DXEffect *iface, UINT *passes, DW if (flags & ~(D3DXFX_DONOTSAVESTATE | D3DXFX_DONOTSAVESAMPLERSTATE | D3DXFX_DONOTSAVESHADERSTATE)) WARN("Invalid flags (%#x) specified.\n", flags); - if (This->manager || flags & D3DXFX_DONOTSAVESTATE) + if (effect->manager || flags & D3DXFX_DONOTSAVESTATE) { TRACE("State capturing disabled.\n"); } else { - FIXME("State capturing not supported, yet!\n"); + HRESULT hr; + unsigned int i; + + if (!technique->saved_state) + { + hr = IDirect3DDevice9_BeginStateBlock(effect->device); + if (FAILED(hr)) + ERR("BeginStateBlock failed, hr %#x.\n", hr); + for (i = 0; i < technique->pass_count; i++) + d3dx9_apply_pass_states(effect, &technique->passes[i]); + hr = IDirect3DDevice9_EndStateBlock(effect->device, &technique->saved_state); + if (FAILED(hr)) + ERR("EndStateBlock failed, hr %#x.\n", hr); + } + hr = IDirect3DStateBlock9_Capture(technique->saved_state); + if (FAILED(hr)) + ERR("StateBlock Capture failed, hr %#x.\n", hr); } *passes = technique->pass_count; - This->started = TRUE; - This->flags = flags; + effect->started = TRUE; + effect->flags = flags; return D3D_OK; } @@ -3566,23 +3590,33 @@ static HRESULT WINAPI ID3DXEffectImpl_EndPass(ID3DXEffect *iface) static HRESULT WINAPI ID3DXEffectImpl_End(ID3DXEffect *iface) { - struct ID3DXEffectImpl *This = impl_from_ID3DXEffect(iface); + struct ID3DXEffectImpl *effect = impl_from_ID3DXEffect(iface); + struct d3dx_technique *technique = effect->active_technique; TRACE("iface %p.\n", iface); - if (!This->started) + if (!effect->started) return D3D_OK; - if (This->manager || This->flags & D3DXFX_DONOTSAVESTATE) + if (effect->manager || effect->flags & D3DXFX_DONOTSAVESTATE) { TRACE("State restoring disabled.\n"); } else { - FIXME("State restoring not supported, yet!\n"); + HRESULT hr; + + if (technique && technique->saved_state) + { + hr = IDirect3DStateBlock9_Apply(technique->saved_state); + if (FAILED(hr)) + ERR("State block apply failed, hr %#x.\n", hr); + } + else + ERR("No saved state.\n"); } - This->started = FALSE; + effect->started = FALSE; return D3D_OK; } diff --git a/dlls/d3dx9_36/tests/effect.c b/dlls/d3dx9_36/tests/effect.c index 916f69a2e63..de7d1e9e884 100644 --- a/dlls/d3dx9_36/tests/effect.c +++ b/dlls/d3dx9_36/tests/effect.c @@ -2853,7 +2853,7 @@ static void test_effect_states(IDirect3DDevice9 *device) hr = IDirect3DDevice9_GetRenderState(device, D3DRS_BLENDOP, &value); ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); - todo_wine ok(value == 1, "Got result %u, expected %u.\n", value, 1); + ok(value == 1, "Got result %u, expected %u.\n", value, 1); hr = IDirect3DDevice9_GetRenderState(device, D3DRS_ALPHAFUNC, &value); ok(value == 2, "Got result %u, expected %u.\n", value, 2); @@ -2865,7 +2865,7 @@ static void test_effect_states(IDirect3DDevice9 *device) ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); hr = IDirect3DDevice9_GetLightEnable(device, 2, &bval); - todo_wine ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); if (hr == D3D_OK) ok(!bval, "Got result %u, expected 0.", bval); @@ -2947,15 +2947,29 @@ static void test_effect_states(IDirect3DDevice9 *device) hr = IDirect3DDevice9_GetTransform(device, D3DTS_WORLDMATRIX(1), &mat); ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); - todo_wine ok(!memcmp(mat.m, test_mat.m, sizeof(mat)), "World matrix not restored.\n"); + ok(!memcmp(mat.m, test_mat.m, sizeof(mat)), "World matrix not restored.\n"); hr = IDirect3DDevice9_GetLightEnable(device, 2, &bval); ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); if (hr == D3D_OK) - todo_wine ok(!bval, "Got result %u, expected 0.\n", bval); + ok(!bval, "Got result %u, expected 0.\n", bval); + + /* State is not restored if effect is released without End call */ + hr = IDirect3DDevice9_SetRenderState(device, D3DRS_BLENDOP, 1); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + + hr = effect->lpVtbl->Begin(effect, &npasses, 0); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + + hr = IDirect3DDevice9_SetRenderState(device, D3DRS_BLENDOP, 3); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); if (effect) effect->lpVtbl->Release(effect); + + hr = IDirect3DDevice9_GetRenderState(device, D3DRS_BLENDOP, &value); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + ok(value == 3, "Got result %u, expected %u.\n", value, 1); } START_TEST(effect)