d3dx9: Handle short parameter in d3dx_set_shader_const_state().

The issue is spotted in https://bugs.winehq.org/show_bug.cgi?id=46553,
while fixing it alone is reported not to affect the bug.

Signed-off-by: Paul Gofman <gofmanp@gmail.com>
Signed-off-by: Matteo Bruni <mbruni@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Paul Gofman 2019-02-13 21:03:40 +03:00 committed by Alexandre Julliard
parent 6fe2728b21
commit b3e91c3408
2 changed files with 54 additions and 15 deletions

View File

@ -21,6 +21,7 @@
#include "wine/port.h"
#include <stdio.h>
#include <assert.h>
#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,

View File

@ -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);