diff --git a/dlls/d3dx9_36/effect.c b/dlls/d3dx9_36/effect.c index 33197de9bd1..497c9c99f07 100644 --- a/dlls/d3dx9_36/effect.c +++ b/dlls/d3dx9_36/effect.c @@ -21,6 +21,7 @@ #include "wine/port.h" #include +#include #include "d3dx9_private.h" #include "d3dcompiler.h" @@ -2913,7 +2914,12 @@ static HRESULT d3dx_set_shader_const_state(struct ID3DXEffectImpl *effect, enum {D3DXPT_BOOL, sizeof(BOOL), "SCT_PSBOOL"}, {D3DXPT_INT, sizeof(int) * 4, "SCT_PSINT"}, }; + + BOOL is_heap_buffer = FALSE; unsigned int element_count; + void *buffer = value_ptr; + D3DXVECTOR4 value; + HRESULT ret; if (op < 0 || op > SCT_PSINT) { @@ -2927,28 +2933,61 @@ static HRESULT d3dx_set_shader_const_state(struct ID3DXEffectImpl *effect, enum FIXME("Unexpected param type %u.\n", param->type); return D3DERR_INVALIDCALL; } - if (param->bytes % const_tbl[op].elem_size != 0) + + if (param->bytes % const_tbl[op].elem_size) { - FIXME("Unexpected param size %u, rows %u, cols %u.\n", param->bytes, param->rows, param->columns); - return D3DERR_INVALIDCALL; + TRACE("Parameter size %u, rows %u, cols %u.\n", param->bytes, param->rows, param->columns); + + if (++element_count > 1) + { + WARN("Setting %u elements.\n", element_count); + buffer = HeapAlloc(GetProcessHeap(), 0, const_tbl[op].elem_size * element_count); + if (!buffer) + { + ERR("Out of memory.\n"); + return E_OUTOFMEMORY; + } + is_heap_buffer = TRUE; + } + else + { + assert(const_tbl[op].elem_size <= sizeof(value)); + buffer = &value; + } + memcpy(buffer, value_ptr, param->bytes); + memset((unsigned char *)buffer + param->bytes, 0, + const_tbl[op].elem_size * element_count - param->bytes); } switch (op) { case SCT_VSFLOAT: - return SET_D3D_STATE(effect, SetVertexShaderConstantF, index, (const float *)value_ptr, element_count); + ret = SET_D3D_STATE(effect, SetVertexShaderConstantF, index, (const float *)buffer, element_count); + break; case SCT_VSBOOL: - return SET_D3D_STATE(effect, SetVertexShaderConstantB, index, (const BOOL *)value_ptr, element_count); + ret = SET_D3D_STATE(effect, SetVertexShaderConstantB, index, (const BOOL *)buffer, element_count); + break; case SCT_VSINT: - return SET_D3D_STATE(effect, SetVertexShaderConstantI, index, (const int *)value_ptr, element_count); + ret = SET_D3D_STATE(effect, SetVertexShaderConstantI, index, (const int *)buffer, element_count); + break; case SCT_PSFLOAT: - return SET_D3D_STATE(effect, SetPixelShaderConstantF, index, (const float *)value_ptr, element_count); + ret = SET_D3D_STATE(effect, SetPixelShaderConstantF, index, (const float *)buffer, element_count); + break; case SCT_PSBOOL: - return SET_D3D_STATE(effect, SetPixelShaderConstantB, index, (const BOOL *)value_ptr, element_count); + ret = SET_D3D_STATE(effect, SetPixelShaderConstantB, index, (const BOOL *)buffer, element_count); + break; case SCT_PSINT: - return SET_D3D_STATE(effect, SetPixelShaderConstantI, index, (const int *)value_ptr, element_count); + ret = SET_D3D_STATE(effect, SetPixelShaderConstantI, index, (const int *)buffer, element_count); + break; + default: + ret = D3DERR_INVALIDCALL; + break; } - return D3D_OK; + + if (is_heap_buffer) + HeapFree(GetProcessHeap(), 0, buffer); + + return ret; } static HRESULT d3dx9_apply_state(struct ID3DXEffectImpl *effect, struct d3dx_pass *pass, diff --git a/dlls/d3dx9_36/tests/effect.c b/dlls/d3dx9_36/tests/effect.c index 88d0a420f1e..b0e78c029ad 100644 --- a/dlls/d3dx9_36/tests/effect.c +++ b/dlls/d3dx9_36/tests/effect.c @@ -3113,7 +3113,7 @@ static void test_effect_states(IDirect3DDevice9 *device) test_effect_clear_vconsts(device); hr = effect->lpVtbl->BeginPass(effect, 0); - 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); hr = IDirect3DDevice9_GetTransform(device, D3DTS_WORLDMATRIX(1), &mat); ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); @@ -3158,11 +3158,11 @@ static void test_effect_states(IDirect3DDevice9 *device) * contain garbage data on native. */ hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 1, &fvect.x, 1); ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); - todo_wine ok(fvect.x == 3.0f, "Got unexpected vertex shader constant (%.8e, %.8e, %.8e, %.8e).\n", + ok(fvect.x == 3.0f, "Got unexpected vertex shader constant (%.8e, %.8e, %.8e, %.8e).\n", fvect.x, fvect.y, fvect.z, fvect.w); hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 2, &fvect.x, 1); ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); - todo_wine ok(fvect.x == 1.0f, "Got unexpected vertex shader constant (%.8e, %.8e, %.8e, %.8e).\n", + ok(fvect.x == 1.0f, "Got unexpected vertex shader constant (%.8e, %.8e, %.8e, %.8e).\n", fvect.x, fvect.y, fvect.z, fvect.w); hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 3, &fvect.x, 1); @@ -3173,7 +3173,7 @@ static void test_effect_states(IDirect3DDevice9 *device) hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 4, &fvect.x, 1); ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); - todo_wine ok(fvect.x == 4.0f && fvect.y == 4.0f && fvect.z == 4.0f && fvect.w == 4.0f, + ok(fvect.x == 4.0f && fvect.y == 4.0f && fvect.z == 4.0f && fvect.w == 4.0f, "Got unexpected vertex shader constant (%.8e, %.8e, %.8e, %.8e).\n", fvect.x, fvect.y, fvect.z, fvect.w); hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 5, &fvect.x, 1); @@ -3193,7 +3193,7 @@ static void test_effect_states(IDirect3DDevice9 *device) fvect.x, fvect.y, fvect.z, fvect.w); hr = effect->lpVtbl->EndPass(effect); - 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); hr = IDirect3DDevice9_GetRenderState(device, D3DRS_BLENDOP, &value); ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); ok(value == 2, "Got result %u, expected %u\n", value, 2);