d3dx9: Implement recording parameters to parameter block.

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-11-20 17:50:11 +01:00 committed by Alexandre Julliard
parent 9da70c0758
commit 7d512a1e0e
2 changed files with 204 additions and 75 deletions

View File

@ -36,6 +36,7 @@ static const char parameter_block_magic_string[4] = {'@', '!', '#', '\xFE'};
#define PARAMETER_FLAG_SHARED 1 #define PARAMETER_FLAG_SHARED 1
#define INITIAL_POOL_SIZE 16 #define INITIAL_POOL_SIZE 16
#define INITIAL_PARAM_BLOCK_SIZE 1024
WINE_DEFAULT_DEBUG_CHANNEL(d3dx); WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
@ -153,6 +154,15 @@ struct d3dx_parameter_block
{ {
char magic_string[ARRAY_SIZE(parameter_block_magic_string)]; char magic_string[ARRAY_SIZE(parameter_block_magic_string)];
struct list entry; struct list entry;
size_t size;
size_t offset;
BYTE *buffer;
};
struct d3dx_recorded_parameter
{
struct d3dx_parameter *param;
unsigned int bytes;
}; };
struct d3dx_effect struct d3dx_effect
@ -706,11 +716,27 @@ static void free_technique(struct d3dx_technique *technique)
technique->name = NULL; 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) static void free_parameter_block(struct d3dx_parameter_block *block)
{ {
struct d3dx_recorded_parameter *record;
if (!block) if (!block)
return; return;
record = (struct d3dx_recorded_parameter *)block->buffer;
while ((BYTE *)record < block->buffer + block->offset)
{
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->offset);
heap_free(block->buffer);
heap_free(block); 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; UINT i;
for (i = 0; i < param->columns; ++i) for (i = 0; i < param->columns; ++i)
{ set_number((FLOAT *)dst_data + i, param->type, (FLOAT *)vector + i, D3DXPT_FLOAT);
set_number((FLOAT *)param->data + i, param->type, (FLOAT *)vector + i, D3DXPT_FLOAT);
}
} }
static void get_matrix(struct d3dx_parameter *param, D3DXMATRIX *matrix, BOOL transpose) 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; UINT i, k;
if (param->type == D3DXPT_FLOAT) if (param->type == D3DXPT_FLOAT)
{ {
if (param->columns == 4) 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 else
{
for (i = 0; i < param->rows; ++i) 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; return;
} }
for (i = 0; i < param->rows; ++i) for (i = 0; i < param->rows; ++i)
{ {
for (k = 0; k < param->columns; ++k) for (k = 0; k < param->columns; ++k)
{ set_number((FLOAT *)dst_data + i * param->columns + k, param->type,
set_number((FLOAT *)param->data + i * param->columns + k, param->type,
&matrix->u.m[i][k], D3DXPT_FLOAT); &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; 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) 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); &matrix->u.m[k][i], D3DXPT_FLOAT);
} }
} }
@ -857,7 +883,8 @@ static HRESULT set_string(char **param_data, const char *string)
return D3D_OK; 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; unsigned int i, count;
@ -873,7 +900,7 @@ static HRESULT set_value(struct d3dx_parameter *param, const void *data, unsigne
case D3DXPT_TEXTURECUBE: case D3DXPT_TEXTURECUBE:
for (i = 0; i < count; ++i) 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]; IUnknown *new_texture = ((IUnknown **)data)[i];
if (new_texture == old_texture) 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_INT:
case D3DXPT_FLOAT: case D3DXPT_FLOAT:
TRACE("Copy %u bytes.\n", bytes); TRACE("Copy %u bytes.\n", bytes);
memcpy(param->data, data, bytes); memcpy(dst_data, data, bytes);
break; break;
case D3DXPT_STRING: case D3DXPT_STRING:
@ -898,7 +925,7 @@ static HRESULT set_value(struct d3dx_parameter *param, const void *data, unsigne
HRESULT hr; HRESULT hr;
for (i = 0; i < count; ++i) 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; return hr;
break; break;
} }
@ -1248,6 +1275,43 @@ static ULONG64 next_effect_update_version(struct d3dx_effect *effect)
return next_update_version(get_version_counter_ptr(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->offset + get_recorded_parameter_size(&new_record);
if (new_size > block->size)
{
BYTE *new_alloc;
alloc_size = max(block->size * 2, max(new_size, INITIAL_PARAM_BLOCK_SIZE));
if (block->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->size, 0, alloc_size - block->size);
block->size = alloc_size;
block->buffer = new_alloc;
}
record = (struct d3dx_recorded_parameter *)(block->buffer + block->offset);
*record = new_record;
block->offset = new_size;
return record + 1;
}
static void set_dirty(struct d3dx_parameter *param) static void set_dirty(struct d3dx_parameter *param)
{ {
struct d3dx_shared_data *shared_data; 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; top_param->update_version = new_update_version;
} }
static void *param_get_data_and_dirtify(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 void d3dx9_set_light_parameter(enum LIGHT_TYPE op, D3DLIGHT9 *light, void *value)
{ {
static const struct static const struct
@ -2364,10 +2439,7 @@ static HRESULT WINAPI d3dx_effect_SetValue(ID3DXEffect *iface, D3DXHANDLE parame
} }
if (data && param->bytes <= bytes) if (data && param->bytes <= bytes)
{ return set_value(param, data, bytes, param_get_data_and_dirtify(effect, param, param->bytes, TRUE));
set_dirty(param);
return set_value(param, data, bytes);
}
WARN("Invalid argument specified.\n"); 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) if (param && !param->element_count && param->rows == 1 && param->columns == 1)
{ {
set_number(param->data, param->type, &b, D3DXPT_BOOL); set_number(param_get_data_and_dirtify(effect, param, sizeof(int), TRUE),
set_dirty(param); param->type, &b, D3DXPT_BOOL);
return D3D_OK; 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_effect *effect = impl_from_ID3DXEffect(iface);
struct d3dx_parameter *param = get_valid_parameter(effect, parameter); struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
DWORD *data;
TRACE("iface %p, parameter %p, b %p, count %u.\n", iface, parameter, b, count); 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_SCALAR:
case D3DXPC_VECTOR: case D3DXPC_VECTOR:
case D3DXPC_MATRIX_ROWS: case D3DXPC_MATRIX_ROWS:
data = param_get_data_and_dirtify(effect, param, size * sizeof(int), TRUE);
for (i = 0; i < size; ++i) for (i = 0; i < size; ++i)
{ {
/* don't crop the input, use D3DXPT_INT instead of D3DXPT_BOOL */ /* 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(data + i, param->type, &b[i], D3DXPT_INT);
} }
set_dirty(param);
return D3D_OK; return D3D_OK;
case D3DXPC_OBJECT: case D3DXPC_OBJECT:
@ -2558,9 +2631,8 @@ static HRESULT WINAPI d3dx_effect_SetInt(ID3DXEffect *iface, D3DXHANDLE paramete
DWORD value; DWORD value;
set_number(&value, param->type, &n, D3DXPT_INT); set_number(&value, param->type, &n, D3DXPT_INT);
if (value != *(DWORD *)param->data) *(DWORD *)param_get_data_and_dirtify(effect, param, sizeof(int),
set_dirty(param); value != *(DWORD *)param->data) = value;
*(DWORD *)param->data = value;
return D3D_OK; 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_VECTOR && param->columns != 2)
|| (param->class == D3DXPC_MATRIX_ROWS && param->rows != 2 && param->columns == 1))) || (param->class == D3DXPC_MATRIX_ROWS && param->rows != 2 && param->columns == 1)))
{ {
float *data;
TRACE("Vector fixup.\n"); TRACE("Vector fixup.\n");
*(float *)param->data = ((n & 0xff0000) >> 16) * INT_FLOAT_MULTI_INVERSE; data = param_get_data_and_dirtify(effect, param,
((float *)param->data)[1] = ((n & 0xff00) >> 8) * INT_FLOAT_MULTI_INVERSE; min(4, param->rows * param->columns) * sizeof(float), TRUE);
((float *)param->data)[2] = (n & 0xff) * INT_FLOAT_MULTI_INVERSE;
data[0] = ((n & 0xff0000) >> 16) * INT_FLOAT_MULTI_INVERSE;
data[1] = ((n & 0xff00) >> 8) * INT_FLOAT_MULTI_INVERSE;
data[2] = (n & 0xff) * INT_FLOAT_MULTI_INVERSE;
if (param->rows * param->columns > 3) if (param->rows * param->columns > 3)
((float *)param->data)[3] = ((n & 0xff000000) >> 24) * INT_FLOAT_MULTI_INVERSE; data[3] = ((n & 0xff000000) >> 24) * INT_FLOAT_MULTI_INVERSE;
set_dirty(param);
return D3D_OK; 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_effect *effect = impl_from_ID3DXEffect(iface);
struct d3dx_parameter *param = get_valid_parameter(effect, parameter); struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
DWORD *data;
TRACE("iface %p, parameter %p, n %p, count %u.\n", iface, parameter, n, count); 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_SCALAR:
case D3DXPC_VECTOR: case D3DXPC_VECTOR:
case D3DXPC_MATRIX_ROWS: case D3DXPC_MATRIX_ROWS:
data = param_get_data_and_dirtify(effect, param, size * sizeof(int), TRUE);
for (i = 0; i < size; ++i) for (i = 0; i < size; ++i)
set_number((DWORD *)param->data + i, param->type, &n[i], D3DXPT_INT); set_number(data + i, param->type, &n[i], D3DXPT_INT);
set_dirty(param);
return D3D_OK; return D3D_OK;
case D3DXPC_OBJECT: case D3DXPC_OBJECT:
@ -2698,9 +2776,8 @@ static HRESULT WINAPI d3dx_effect_SetFloat(ID3DXEffect *iface, D3DXHANDLE parame
DWORD value; DWORD value;
set_number(&value, param->type, &f, D3DXPT_FLOAT); set_number(&value, param->type, &f, D3DXPT_FLOAT);
if (value != *(DWORD *)param->data) *(DWORD *)param_get_data_and_dirtify(effect, param, sizeof(float),
set_dirty(param); value != *(DWORD *)param->data) = value;
*(DWORD *)param->data = value;
return D3D_OK; 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_effect *effect = impl_from_ID3DXEffect(iface);
struct d3dx_parameter *param = get_valid_parameter(effect, parameter); struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
DWORD *data;
TRACE("iface %p, parameter %p, f %p, count %u.\n", iface, parameter, f, count); 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_SCALAR:
case D3DXPC_VECTOR: case D3DXPC_VECTOR:
case D3DXPC_MATRIX_ROWS: case D3DXPC_MATRIX_ROWS:
data = param_get_data_and_dirtify(effect, param, size * sizeof(float), TRUE);
for (i = 0; i < size; ++i) for (i = 0; i < size; ++i)
set_number((DWORD *)param->data + i, param->type, &f[i], D3DXPT_FLOAT); set_number(data + i, param->type, &f[i], D3DXPT_FLOAT);
set_dirty(param);
return D3D_OK; return D3D_OK;
case D3DXPC_OBJECT: case D3DXPC_OBJECT:
@ -2806,7 +2884,6 @@ static HRESULT WINAPI d3dx_effect_SetVector(ID3DXEffect *iface, D3DXHANDLE param
{ {
case D3DXPC_SCALAR: case D3DXPC_SCALAR:
case D3DXPC_VECTOR: case D3DXPC_VECTOR:
set_dirty(param);
if (param->type == D3DXPT_INT && param->bytes == 4) if (param->type == D3DXPT_INT && param->bytes == 4)
{ {
DWORD tmp; 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->x, 1.0f), 0.0f) * INT_FLOAT_MULTI)) << 16;
tmp += ((DWORD)(max(min(vector->w, 1.0f), 0.0f) * INT_FLOAT_MULTI)) << 24; tmp += ((DWORD)(max(min(vector->w, 1.0f), 0.0f) * INT_FLOAT_MULTI)) << 24;
*(int *)param->data = tmp; *(int *)param_get_data_and_dirtify(effect, param, sizeof(int), TRUE) = tmp;
return D3D_OK; return D3D_OK;
} }
if (param->type == D3DXPT_FLOAT) if (param->type == D3DXPT_FLOAT)
{ {
memcpy(param->data, vector, param->columns * sizeof(float)); memcpy(param_get_data_and_dirtify(effect, param, param->columns * sizeof(float), TRUE),
vector, param->columns * sizeof(float));
return D3D_OK; return D3D_OK;
} }
set_vector(param, vector); set_vector(param, vector, param_get_data_and_dirtify(effect, param, param->columns * sizeof(float), TRUE));
return D3D_OK; return D3D_OK;
case D3DXPC_MATRIX_ROWS: case D3DXPC_MATRIX_ROWS:
@ -2899,26 +2977,33 @@ static HRESULT WINAPI d3dx_effect_SetVectorArray(ID3DXEffect *iface, D3DXHANDLE
if (param && param->element_count && param->element_count >= count) if (param && param->element_count && param->element_count >= count)
{ {
unsigned int i; unsigned int i;
BYTE *data;
TRACE("Class %s.\n", debug_d3dxparameter_class(param->class)); TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
switch (param->class) switch (param->class)
{ {
case D3DXPC_VECTOR: case D3DXPC_VECTOR:
set_dirty(param); data = param_get_data_and_dirtify(effect, param, count * param->columns * sizeof(float), TRUE);
if (param->type == D3DXPT_FLOAT) if (param->type == D3DXPT_FLOAT)
{ {
if (param->columns == 4) if (param->columns == 4)
memcpy(param->data, vector, count * 4 * sizeof(float)); {
memcpy(data, vector, count * 4 * sizeof(float));
}
else else
{
for (i = 0; i < count; ++i) 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)); param->columns * sizeof(float));
}
return D3D_OK; return D3D_OK;
} }
for (i = 0; i < count; ++i) for (i = 0; i < count; ++i)
set_vector(&param->members[i], &vector[i]); set_vector(&param->members[i], &vector[i], data + i * param->columns * sizeof(float));
return D3D_OK; return D3D_OK;
case D3DXPC_SCALAR: case D3DXPC_SCALAR:
@ -2993,8 +3078,8 @@ static HRESULT WINAPI d3dx_effect_SetMatrix(ID3DXEffect *iface, D3DXHANDLE param
switch (param->class) switch (param->class)
{ {
case D3DXPC_MATRIX_ROWS: case D3DXPC_MATRIX_ROWS:
set_matrix(param, matrix); set_matrix(param, matrix, param_get_data_and_dirtify(effect, param,
set_dirty(param); param->rows * param->columns * sizeof(float), TRUE));
return D3D_OK; return D3D_OK;
case D3DXPC_SCALAR: case D3DXPC_SCALAR:
@ -3059,15 +3144,20 @@ static HRESULT WINAPI d3dx_effect_SetMatrixArray(ID3DXEffect *iface, D3DXHANDLE
if (param && param->element_count >= count) if (param && param->element_count >= count)
{ {
unsigned int i; unsigned int i;
BYTE *data;
TRACE("Class %s.\n", debug_d3dxparameter_class(param->class)); TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
switch (param->class) switch (param->class)
{ {
case D3DXPC_MATRIX_ROWS: case D3DXPC_MATRIX_ROWS:
set_dirty(param); data = param_get_data_and_dirtify(effect, param, count * param->rows
* param->columns * sizeof(float), TRUE);
for (i = 0; i < count; ++i) for (i = 0; i < count; ++i)
set_matrix(&param->members[i], &matrix[i]); set_matrix(&param->members[i], &matrix[i],
data + i * param->rows * param->columns * sizeof(float));
return D3D_OK; return D3D_OK;
case D3DXPC_SCALAR: case D3DXPC_SCALAR:
@ -3139,13 +3229,18 @@ static HRESULT WINAPI d3dx_effect_SetMatrixPointerArray(ID3DXEffect *iface, D3DX
if (param && count <= param->element_count) if (param && count <= param->element_count)
{ {
unsigned int i; unsigned int i;
BYTE *data;
switch (param->class) switch (param->class)
{ {
case D3DXPC_MATRIX_ROWS: case D3DXPC_MATRIX_ROWS:
set_dirty(param); data = param_get_data_and_dirtify(effect, param, count * param->rows
* param->columns * sizeof(float), TRUE);
for (i = 0; i < count; ++i) for (i = 0; i < count; ++i)
set_matrix(&param->members[i], matrix[i]); set_matrix(&param->members[i], matrix[i], data + i * param->rows
* param->columns * sizeof(float));
return D3D_OK; return D3D_OK;
case D3DXPC_SCALAR: case D3DXPC_SCALAR:
@ -3219,8 +3314,8 @@ static HRESULT WINAPI d3dx_effect_SetMatrixTranspose(ID3DXEffect *iface, D3DXHAN
switch (param->class) switch (param->class)
{ {
case D3DXPC_MATRIX_ROWS: case D3DXPC_MATRIX_ROWS:
set_dirty(param); set_matrix_transpose(param, matrix, param_get_data_and_dirtify(effect, param,
set_matrix_transpose(param, matrix); param->rows * param->columns * sizeof(float), TRUE));
return D3D_OK; return D3D_OK;
case D3DXPC_SCALAR: case D3DXPC_SCALAR:
@ -3289,15 +3384,20 @@ static HRESULT WINAPI d3dx_effect_SetMatrixTransposeArray(ID3DXEffect *iface, D3
if (param && param->element_count >= count) if (param && param->element_count >= count)
{ {
unsigned int i; unsigned int i;
BYTE *data;
TRACE("Class %s.\n", debug_d3dxparameter_class(param->class)); TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
switch (param->class) switch (param->class)
{ {
case D3DXPC_MATRIX_ROWS: case D3DXPC_MATRIX_ROWS:
set_dirty(param); data = param_get_data_and_dirtify(effect, param, count * param->rows
* param->columns * sizeof(float), TRUE);
for (i = 0; i < count; ++i) for (i = 0; i < count; ++i)
set_matrix_transpose(&param->members[i], &matrix[i]); set_matrix_transpose(&param->members[i], &matrix[i], data
+ i * param->rows * param->columns * sizeof(float));
return D3D_OK; return D3D_OK;
case D3DXPC_SCALAR: case D3DXPC_SCALAR:
@ -3369,13 +3469,18 @@ static HRESULT WINAPI d3dx_effect_SetMatrixTransposePointerArray(ID3DXEffect *if
if (param && count <= param->element_count) if (param && count <= param->element_count)
{ {
unsigned int i; unsigned int i;
BYTE *data;
switch (param->class) switch (param->class)
{ {
case D3DXPC_MATRIX_ROWS: case D3DXPC_MATRIX_ROWS:
set_dirty(param); data = param_get_data_and_dirtify(effect, param, count * param->rows
* param->columns * sizeof(float), TRUE);
for (i = 0; i < count; ++i) for (i = 0; i < count; ++i)
set_matrix_transpose(&param->members[i], matrix[i]); set_matrix_transpose(&param->members[i], matrix[i], data
+ i * param->rows * param->columns * sizeof(float));
return D3D_OK; return D3D_OK;
case D3DXPC_SCALAR: case D3DXPC_SCALAR:
@ -3442,10 +3547,7 @@ static HRESULT WINAPI d3dx_effect_SetString(ID3DXEffect *iface, D3DXHANDLE param
TRACE("iface %p, parameter %p, string %s.\n", iface, parameter, debugstr_a(string)); TRACE("iface %p, parameter %p, string %s.\n", iface, parameter, debugstr_a(string));
if (param && param->type == D3DXPT_STRING) if (param && param->type == D3DXPT_STRING)
{ return set_string(param_get_data_and_dirtify(effect, param, sizeof(void *), TRUE), string);
set_dirty(param);
return set_string(param->data, string);
}
WARN("Parameter not found.\n"); WARN("Parameter not found.\n");
@ -3484,7 +3586,11 @@ static HRESULT WINAPI d3dx_effect_SetTexture(ID3DXEffect *iface, D3DXHANDLE para
|| param->type == D3DXPT_TEXTURE2D || param->type == D3DXPT_TEXTURE3D || param->type == D3DXPT_TEXTURE2D || param->type == D3DXPT_TEXTURE3D
|| param->type == D3DXPT_TEXTURECUBE)) || param->type == D3DXPT_TEXTURECUBE))
{ {
IDirect3DBaseTexture9 *old_texture = *(IDirect3DBaseTexture9 **)param->data; IDirect3DBaseTexture9 **data = param_get_data_and_dirtify(effect, param,
sizeof(void *), texture != *(IDirect3DBaseTexture9 **)param->data);
IDirect3DBaseTexture9 *old_texture = *data;
*data = texture;
if (texture == old_texture) if (texture == old_texture)
return D3D_OK; return D3D_OK;
@ -3494,9 +3600,6 @@ static HRESULT WINAPI d3dx_effect_SetTexture(ID3DXEffect *iface, D3DXHANDLE para
if (old_texture) if (old_texture)
IDirect3DBaseTexture9_Release(old_texture); IDirect3DBaseTexture9_Release(old_texture);
*(IDirect3DBaseTexture9 **)param->data = texture;
set_dirty(param);
return D3D_OK; return D3D_OK;
} }
@ -4137,6 +4240,10 @@ static D3DXHANDLE WINAPI d3dx_effect_EndParameterBlock(ID3DXEffect *iface)
return NULL; return NULL;
} }
ret = effect->current_parameter_block; ret = effect->current_parameter_block;
ret->buffer = heap_realloc(ret->buffer, ret->offset);
ret->size = ret->offset;
effect->current_parameter_block = NULL; effect->current_parameter_block = NULL;
list_add_tail(&effect->parameter_block_list, &ret->entry); list_add_tail(&effect->parameter_block_list, &ret->entry);
return (D3DXHANDLE)ret; return (D3DXHANDLE)ret;

View File

@ -8020,12 +8020,12 @@ static void test_effect_parameter_block(void)
IDirect3DTexture9 *texture, *tex_test; IDirect3DTexture9 *texture, *tex_test;
D3DXHANDLE block, block2, handle; D3DXHANDLE block, block2, handle;
ID3DXEffect *effect, *effect2; ID3DXEffect *effect, *effect2;
D3DXMATRIX mat, mat_arr[2];
IDirect3DDevice9 *device; IDirect3DDevice9 *device;
ID3DXEffectPool *pool; ID3DXEffectPool *pool;
float float_array[4]; float float_array[4];
float float_value; float float_value;
IDirect3D9 *d3d; IDirect3D9 *d3d;
D3DXMATRIX mat;
ULONG refcount; ULONG refcount;
HWND window; HWND window;
HRESULT hr; HRESULT hr;
@ -8115,9 +8115,7 @@ static void test_effect_parameter_block(void)
ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
hr = effect->lpVtbl->GetTexture(effect, "tex1", (IDirect3DBaseTexture9 **)&tex_test); 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); 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 /* Child parameters and array members are recorded separately (the whole
* parameter is not updated when parameter block is applied). */ * 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); hr = effect->lpVtbl->SetFloat(effect, "ts1[0].fv", 28.0f);
ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
hr = effect->lpVtbl->GetFloat(effect, "ts1[0].fv", &float_value); 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; float_array[0] = -29.0f;
hr = effect->lpVtbl->SetFloatArray(effect, "ts1[0].v2", float_array, 1); hr = effect->lpVtbl->SetFloatArray(effect, "ts1[0].v2", float_array, 1);
ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
hr = effect->lpVtbl->GetFloatArray(effect, "ts1[0].v2", float_array, 1); 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]); hr, float_array[0]);
memset(&mat, 0, sizeof(mat)); 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); ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
hr = effect->lpVtbl->GetMatrix(effect, "m3x2row", &mat); hr = effect->lpVtbl->GetMatrix(effect, "m3x2row", &mat);
ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 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); hr = effect->lpVtbl->SetMatrix(effect, "m3x2column", &test_mat);
ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
hr = effect->lpVtbl->GetMatrix(effect, "m3x2column", &mat); hr = effect->lpVtbl->GetMatrix(effect, "m3x2column", &mat);
ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 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");
/* Setting shared parameter through effect2 is not recorded to effect /* Setting shared parameter through effect2 is not recorded to effect
* parameter block. */ * parameter block. */
@ -8321,6 +8319,30 @@ static void test_effect_parameter_block(void)
refcount = pool->lpVtbl->Release(pool); refcount = pool->lpVtbl->Release(pool);
ok(!refcount, "Got unexpected refcount %u.\n", refcount); 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); refcount = IDirect3DDevice9_Release(device);
ok(!refcount, "Device has %u references left.\n", refcount); ok(!refcount, "Device has %u references left.\n", refcount);
IDirect3D9_Release(d3d); IDirect3D9_Release(d3d);