Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
November 2021
- 83 participants
- 2620 messages
[v3 PATCH] d3d10/effect: Add initial support for indexing expressions.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
v3: some rework based on received feedback
For now for simplicity I removed destination index from property update, with additional
test for property type when parsing.
dlls/d3d10/effect.c | 577 +++++++++++++++++++++++++++++++++++++-
dlls/d3d10/tests/effect.c | 114 ++++++++
2 files changed, 683 insertions(+), 8 deletions(-)
diff --git a/dlls/d3d10/effect.c b/dlls/d3d10/effect.c
index 78a3d0c386a..1be16771921 100644
--- a/dlls/d3d10/effect.c
+++ b/dlls/d3d10/effect.c
@@ -30,6 +30,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d10);
((DWORD)(ch2) << 16) | ((DWORD)(ch3) << 24 ))
#define TAG_DXBC MAKE_TAG('D', 'X', 'B', 'C')
#define TAG_FX10 MAKE_TAG('F', 'X', '1', '0')
+#define TAG_FXLC MAKE_TAG('F', 'X', 'L', 'C')
+#define TAG_CLI4 MAKE_TAG('C', 'L', 'I', '4')
+#define TAG_CTAB MAKE_TAG('C', 'T', 'A', 'B')
#define D3D10_FX10_TYPE_COLUMN_SHIFT 11
#define D3D10_FX10_TYPE_COLUMN_MASK (0x7 << D3D10_FX10_TYPE_COLUMN_SHIFT)
@@ -180,6 +183,96 @@ static enum d3d10_effect_container_type get_var_container_type(const struct d3d1
}
}
+struct preshader_instr
+{
+ unsigned int comp_count : 16;
+ unsigned int reserved : 4;
+ unsigned int opcode : 11;
+ unsigned int scalar : 1;
+};
+
+typedef float (*pres_op_func)(float **args, unsigned int n);
+
+static float pres_ftou(float **args, unsigned int n)
+{
+ unsigned int u = *args[0];
+ return *(float *)&u;
+}
+
+static float pres_add(float **args, unsigned int n)
+{
+ return *args[0] + *args[1];
+}
+
+struct preshader_op_info
+{
+ int opcode;
+ char name[8];
+ pres_op_func func;
+};
+
+static const struct preshader_op_info preshader_ops[] =
+{
+ { 0x133, "ftou", pres_ftou },
+ { 0x204, "add", pres_add },
+};
+
+static int __cdecl preshader_op_compare(const void *a, const void *b)
+{
+ int opcode = *(int *)a;
+ const struct preshader_op_info *op_info = b;
+ return opcode - op_info->opcode;
+}
+
+static const struct preshader_op_info * d3d10_effect_get_op_info(int opcode)
+{
+ return bsearch(&opcode, preshader_ops, ARRAY_SIZE(preshader_ops), sizeof(*preshader_ops),
+ preshader_op_compare);
+}
+
+struct d3d10_ctab_var
+{
+ struct d3d10_effect_variable *v;
+ unsigned int offset;
+ unsigned int length;
+};
+
+struct d3d10_reg_table
+{
+ union
+ {
+ float *f;
+ DWORD *dword;
+ };
+ unsigned int count;
+};
+
+enum d3d10_reg_table_type
+{
+ D3D10_REG_TABLE_CONSTANTS = 1,
+ D3D10_REG_TABLE_CB = 2,
+ D3D10_REG_TABLE_RESULT = 4,
+ D3D10_REG_TABLE_TEMP = 7,
+ D3D10_REG_TABLE_COUNT,
+};
+
+struct d3d10_effect_preshader
+{
+ struct d3d10_reg_table reg_tables[D3D10_REG_TABLE_COUNT];
+ ID3D10Blob *code;
+
+ struct d3d10_ctab_var *vars;
+ unsigned int vars_count;
+};
+
+struct d3d10_preshader_parse_context
+{
+ struct d3d10_effect_preshader *preshader;
+ struct d3d10_effect *effect;
+ unsigned int result_count;
+ unsigned int temp_count;
+};
+
struct d3d10_effect_prop_dependency
{
unsigned int id;
@@ -192,11 +285,115 @@ struct d3d10_effect_prop_dependency
struct d3d10_effect_variable *v;
unsigned int offset;
} var;
- } u;
+ struct
+ {
+ struct d3d10_effect_variable *v;
+ struct d3d10_effect_preshader index;
+ } index_expr;
+ };
};
+static HRESULT d3d10_reg_table_allocate(struct d3d10_reg_table *table, unsigned int count)
+{
+ if (!(table->f = heap_calloc(count, sizeof(*table->f))))
+ return E_OUTOFMEMORY;
+ table->count = count;
+ return S_OK;
+}
+
+static void d3d10_effect_preshader_clear(struct d3d10_effect_preshader *p)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(p->reg_tables); ++i)
+ heap_free(&p->reg_tables[i].f);
+ if (p->code)
+ ID3D10Blob_Release(p->code);
+ heap_free(p->vars);
+ memset(p, 0, sizeof(*p));
+}
+
+static float * d3d10_effect_preshader_get_reg_ptr(const struct d3d10_effect_preshader *p,
+ enum d3d10_reg_table_type regt, unsigned int offset)
+{
+ switch (regt)
+ {
+ case D3D10_REG_TABLE_CONSTANTS:
+ case D3D10_REG_TABLE_CB:
+ case D3D10_REG_TABLE_RESULT:
+ case D3D10_REG_TABLE_TEMP:
+ return p->reg_tables[regt].f + offset;
+ default:
+ return NULL;
+ }
+}
+
+static HRESULT d3d10_effect_preshader_eval(struct d3d10_effect_preshader *p)
+{
+ unsigned int i, j, regt, offset, instr_count, input_count;
+ const DWORD *ip = ID3D10Blob_GetBufferPointer(p->code);
+ float *dst, *args[4], *retval;
+ struct preshader_instr ins;
+
+ dst = d3d10_effect_preshader_get_reg_ptr(p, D3D10_REG_TABLE_RESULT, 0);
+ memset(dst, 0, sizeof(float) * p->reg_tables[D3D10_REG_TABLE_RESULT].count);
+
+ /* Update constant buffer */
+ dst = d3d10_effect_preshader_get_reg_ptr(p, D3D10_REG_TABLE_CB, 0);
+ for (i = 0; i < p->vars_count; ++i)
+ {
+ struct d3d10_ctab_var *v = &p->vars[i];
+ memcpy(dst + v->offset, v->v->buffer->u.buffer.local_buffer, v->length * sizeof(*dst));
+ }
+
+ instr_count = *ip++;
+
+ for (i = 0; i < instr_count; ++i)
+ {
+ *(DWORD *)&ins = *ip++;
+ input_count = *ip++;
+
+ if (input_count > ARRAY_SIZE(args))
+ {
+ FIXME("Unexpected argument count %u.\n", input_count);
+ return E_FAIL;
+ }
+
+ /* Arguments */
+ for (j = 0; j < input_count; ++j)
+ {
+ ip++; /* TODO: argument register flags are currently ignored */
+ regt = *ip++;
+ offset = *ip++;
+
+ args[j] = d3d10_effect_preshader_get_reg_ptr(p, regt, offset);
+ }
+
+ ip++; /* TODO: result register flags are currently ignored */
+ regt = *ip++;
+ offset = *ip++;
+ retval = d3d10_effect_preshader_get_reg_ptr(p, regt, offset);
+
+ *retval = d3d10_effect_get_op_info(ins.opcode)->func(args, input_count);
+ }
+
+ return S_OK;
+}
+
static void d3d10_effect_clear_prop_dependencies(struct d3d10_effect_prop_dependencies *d)
{
+ unsigned int i;
+
+ for (i = 0; i < d->count; ++i)
+ {
+ struct d3d10_effect_prop_dependency *dep = &d->entries[i];
+ switch (dep->operation)
+ {
+ case D3D10_EOO_INDEX_EXPRESSION:
+ d3d10_effect_preshader_clear(&dep->index_expr.index);
+ break;
+ }
+ }
heap_free(d->entries);
memset(d, 0, sizeof(*d));
}
@@ -516,9 +713,11 @@ static void d3d10_effect_update_dependent_props(struct d3d10_effect_prop_depende
{
const struct d3d10_effect_state_property_info *property_info;
struct d3d10_effect_prop_dependency *d;
+ unsigned int i, j, count, variable_idx;
struct d3d10_effect_variable *v;
- unsigned int i, j, count;
+ unsigned int *dst_index;
uint32_t value;
+ HRESULT hr;
void *dst;
for (i = 0; i < deps->count; ++i)
@@ -528,24 +727,58 @@ static void d3d10_effect_update_dependent_props(struct d3d10_effect_prop_depende
property_info = &property_infos[d->id];
dst = (char *)container + property_info->offset;
+ dst_index = (unsigned int *)((char *)container + property_info->index_offset);
switch (d->operation)
{
case D3D10_EOO_VAR:
case D3D10_EOO_CONST_INDEX:
- v = d->u.var.v;
+ v = d->var.v;
count = v->type->type_class == D3D10_SVC_VECTOR ? 4 : 1;
for (j = 0; j < count; ++j)
{
- d3d10_effect_variable_get_raw_value(v, &value, d->u.var.offset + j * sizeof(value), sizeof(value));
+ d3d10_effect_variable_get_raw_value(v, &value, d->var.offset + j * sizeof(value), sizeof(value));
d3d10_effect_read_numeric_value(value, v->type->basetype, property_info->type, dst, j);
}
break;
+ case D3D10_EOO_INDEX_EXPRESSION:
+
+ v = d->index_expr.v;
+
+ if (FAILED(hr = d3d10_effect_preshader_eval(&d->index_expr.index)))
+ {
+ WARN("Failed to evaluate index expression, hr %#x.\n", hr);
+ return;
+ }
+
+ variable_idx = *d->index_expr.index.reg_tables[D3D10_REG_TABLE_RESULT].dword;
+
+ if (variable_idx >= v->type->element_count)
+ {
+ WARN("Expression evaluated to invalid index value %u, array %s of size %u.\n",
+ variable_idx, debugstr_a(v->name), v->type->element_count);
+ return;
+ }
+
+ /* Ignoring destination index here, there are no object typed array properties. */
+ switch (property_info->type)
+ {
+ case D3D10_SVT_VERTEXSHADER:
+ case D3D10_SVT_PIXELSHADER:
+ case D3D10_SVT_GEOMETRYSHADER:
+ *(void **)dst = v;
+ *dst_index = variable_idx;
+ break;
+ default:
+ *(void **)dst = &v->elements[variable_idx];
+ }
+ break;
+
default:
FIXME("Unsupported property update for %u.\n", d->operation);
}
@@ -1856,6 +2089,266 @@ static BOOL is_object_property_type_matching(const struct d3d10_effect_state_pro
}
}
+static HRESULT parse_fx10_preshader_instr(struct d3d10_preshader_parse_context *context,
+ unsigned int *offset, const char **ptr, unsigned int data_size)
+{
+ const struct preshader_op_info *op_info;
+ unsigned int i, param_count;
+ struct preshader_instr ins;
+ uint32_t input_count;
+
+ if (!require_space(*offset, 2, sizeof(uint32_t), data_size))
+ {
+ WARN("Malformed FXLC table, size %u.\n", data_size);
+ return E_FAIL;
+ }
+
+ read_dword(ptr, (uint32_t *)&ins);
+ read_dword(ptr, &input_count);
+ *offset += 2 * sizeof(uint32_t);
+
+ if (!(op_info = d3d10_effect_get_op_info(ins.opcode)))
+ {
+ FIXME("Unrecognized opcode %#x.\n", ins.opcode);
+ return E_FAIL;
+ }
+
+ TRACE("Opcode %#x (%s), input count %u.\n", ins.opcode, op_info->name, input_count);
+
+ /* Inputs + one output */
+ param_count = input_count + 1;
+
+ if (!require_space(*offset, 3 * param_count, sizeof(uint32_t), data_size))
+ {
+ WARN("Malformed FXLC table, opcode %#x.\n", ins.opcode);
+ return E_FAIL;
+ }
+ *offset += 3 * param_count * sizeof(uint32_t);
+
+ for (i = 0; i < param_count; ++i)
+ {
+ uint32_t flags, regt, param_offset;
+
+ read_dword(ptr, &flags);
+ if (flags)
+ {
+ FIXME("Arguments flags are not supported %#x.\n", flags);
+ return E_UNEXPECTED;
+ }
+
+ read_dword(ptr, ®t);
+ read_dword(ptr, ¶m_offset);
+
+ switch (regt)
+ {
+ case D3D10_REG_TABLE_RESULT:
+ context->result_count = max(context->result_count, param_offset + 1);
+ break;
+ case D3D10_REG_TABLE_TEMP:
+ context->temp_count = max(context->temp_count, param_offset + 1);
+ break;
+ default:
+ break;
+ }
+ }
+
+ return S_OK;
+}
+
+static HRESULT parse_fx10_fxlc(void *ctx, const char *data, unsigned int data_size)
+{
+ struct d3d10_preshader_parse_context *context = ctx;
+ struct d3d10_effect_preshader *p = context->preshader;
+ unsigned int i, offset = 4;
+ uint32_t ins_count;
+ const char *ptr;
+ HRESULT hr;
+
+ if (data_size % sizeof(uint32_t))
+ {
+ WARN("FXLC size misaligned %u.\n", data_size);
+ return E_FAIL;
+ }
+
+ /* Parse through bytecode copy, so we can patch opcodes. */
+ if (FAILED(hr = D3DCreateBlob(data_size, &p->code)))
+ return hr;
+ memcpy(ID3D10Blob_GetBufferPointer(p->code), data, data_size);
+
+ ptr = data;
+ read_dword(&ptr, &ins_count);
+ TRACE("%u instructions.\n", ins_count);
+
+ for (i = 0; i < ins_count; ++i)
+ {
+ if (FAILED(hr = parse_fx10_preshader_instr(context, &offset, &ptr, data_size)))
+ {
+ WARN("Failed to parse instruction %u.\n", i);
+ return hr;
+ }
+ }
+
+ if (FAILED(hr = d3d10_reg_table_allocate(&p->reg_tables[D3D10_REG_TABLE_RESULT],
+ context->result_count))) return hr;
+ if (FAILED(hr = d3d10_reg_table_allocate(&p->reg_tables[D3D10_REG_TABLE_TEMP],
+ context->temp_count))) return hr;
+
+ return S_OK;
+}
+
+static HRESULT parse_fx10_cli4(void *ctx, const char *data, unsigned int data_size)
+{
+ struct d3d10_preshader_parse_context *context = ctx;
+ struct d3d10_effect_preshader *p = context->preshader;
+ struct d3d10_reg_table *table = &p->reg_tables[D3D10_REG_TABLE_CONSTANTS];
+ const char *ptr = data;
+ uint32_t count;
+ HRESULT hr;
+
+ if (data_size < sizeof(DWORD))
+ {
+ WARN("Invalid CLI4 chunk size %u.\n", data_size);
+ return E_FAIL;
+ }
+
+ read_dword(&ptr, &count);
+
+ TRACE("%u literal constants.\n", count);
+
+ if (!require_space(4, count, sizeof(float), data_size))
+ {
+ WARN("Invalid constant table size %u.\n", data_size);
+ return E_FAIL;
+ }
+
+ if (FAILED(hr = d3d10_reg_table_allocate(table, count)))
+ return hr;
+
+ memcpy(table->f, ptr, table->count * sizeof(*table->f));
+
+ return S_OK;
+}
+
+static HRESULT parse_fx10_ctab(void *ctx, const char *data, unsigned int data_size)
+{
+ struct d3d10_preshader_parse_context *context = ctx;
+ struct d3d10_effect_preshader *p = context->preshader;
+ struct ctab_header
+ {
+ DWORD size;
+ DWORD creator;
+ DWORD version;
+ DWORD constants;
+ DWORD constantinfo;
+ DWORD flags;
+ DWORD target;
+ } header;
+ struct ctab_const_info
+ {
+ DWORD name;
+ WORD register_set;
+ WORD register_index;
+ WORD register_count;
+ WORD reserved;
+ DWORD typeinfo;
+ DWORD default_value;
+ } *info;
+ unsigned int i, cb_reg_count = 0;
+ const char *ptr = data;
+ const char *name;
+ size_t name_len;
+ HRESULT hr;
+
+ if (data_size < sizeof(header))
+ {
+ WARN("Invalid constant table size %u.\n", data_size);
+ return E_FAIL;
+ }
+
+ read_dword(&ptr, &header.size);
+ read_dword(&ptr, &header.creator);
+ read_dword(&ptr, &header.version);
+ read_dword(&ptr, &header.constants);
+ read_dword(&ptr, &header.constantinfo);
+ read_dword(&ptr, &header.flags);
+ read_dword(&ptr, &header.target);
+
+ if (!require_space(header.constantinfo, header.constants, sizeof(*info), data_size))
+ {
+ WARN("Invalid constant info section offset %#x.\n", header.constantinfo);
+ return E_FAIL;
+ }
+
+ p->vars_count = header.constants;
+
+ TRACE("Variable count %u.\n", p->vars_count);
+
+ if (!(p->vars = heap_calloc(p->vars_count, sizeof(*p->vars))))
+ return E_OUTOFMEMORY;
+
+ /* Collect variables used in expression. */
+ info = (struct ctab_const_info *)(data + header.constantinfo);
+ for (i = 0; i < p->vars_count; ++i, ++info)
+ {
+ if (!fx10_get_string(data, data_size, info->name, &name, &name_len))
+ return E_FAIL;
+
+ if (!(p->vars[i].v = d3d10_effect_get_variable_by_name(context->effect, name)))
+ {
+ WARN("Couldn't find variable %s.\n", debugstr_a(name));
+ return E_FAIL;
+ }
+
+ /* 4 components per register */
+ p->vars[i].offset = info->register_index * 4;
+ p->vars[i].length = info->register_count * 4;
+
+ cb_reg_count = max(cb_reg_count, info->register_index + info->register_count);
+ }
+
+ /* Allocate contiguous "constant buffer" for all referenced variables. */
+ if (FAILED(hr = d3d10_reg_table_allocate(&p->reg_tables[D3D10_REG_TABLE_CB], cb_reg_count * 4)))
+ {
+ WARN("Failed to allocate variables buffer.\n");
+ return hr;
+ }
+
+ return S_OK;
+}
+
+static HRESULT fxlvm_chunk_handler(const char *data, DWORD data_size, DWORD tag, void *ctx)
+{
+ TRACE("Chunk tag: %s, size: %u.\n", debugstr_an((const char *)&tag, 4), data_size);
+
+ switch (tag)
+ {
+ case TAG_FXLC:
+ return parse_fx10_fxlc(ctx, data, data_size);
+
+ case TAG_CLI4:
+ return parse_fx10_cli4(ctx, data, data_size);
+
+ case TAG_CTAB:
+ return parse_fx10_ctab(ctx, data, data_size);
+
+ default:
+ FIXME("Unhandled chunk %s.\n", debugstr_an((const char *)&tag, 4));
+ return S_OK;
+ }
+}
+
+static HRESULT parse_fx10_preshader(const char *data, size_t data_size,
+ struct d3d10_effect *effect, struct d3d10_effect_preshader *preshader)
+{
+ struct d3d10_preshader_parse_context context;
+
+ memset(preshader, 0, sizeof(*preshader));
+ context.preshader = preshader;
+ context.effect = effect;
+
+ return parse_dxbc(data, data_size, fxlvm_chunk_handler, &context);
+}
+
static HRESULT d3d10_effect_add_prop_dependency(struct d3d10_effect_prop_dependencies *d,
const struct d3d10_effect_prop_dependency *dep)
{
@@ -1875,6 +2368,7 @@ static HRESULT parse_fx10_property_assignment(const char *data, size_t data_size
const struct d3d10_effect_state_property_info *property_info;
struct d3d10_effect_prop_dependency dep;
struct d3d10_effect_variable *variable;
+ uint32_t code_offset, blob_size;
const char *data_ptr, *name;
unsigned int *dst_index;
size_t name_len;
@@ -1974,8 +2468,8 @@ static HRESULT parse_fx10_property_assignment(const char *data, size_t data_size
dep.id = id;
dep.idx = idx;
dep.operation = operation;
- dep.u.var.v = variable;
- dep.u.var.offset = 0;
+ dep.var.v = variable;
+ dep.var.offset = 0;
return d3d10_effect_add_prop_dependency(d, &dep);
}
@@ -2051,14 +2545,75 @@ static HRESULT parse_fx10_property_assignment(const char *data, size_t data_size
dep.id = id;
dep.idx = idx;
dep.operation = operation;
- dep.u.var.v = variable;
- dep.u.var.offset = offset;
+ dep.var.v = variable;
+ dep.var.offset = offset;
return d3d10_effect_add_prop_dependency(d, &dep);
}
break;
+ case D3D10_EOO_INDEX_EXPRESSION:
+
+ /* Variable, and an expression for its index. */
+ if (value_offset >= data_size || !require_space(value_offset, 2, sizeof(DWORD), data_size))
+ {
+ WARN("Invalid offset %#x (data size %#lx).\n", value_offset, (long)data_size);
+ return E_FAIL;
+ }
+
+ data_ptr = data + value_offset;
+ read_dword(&data_ptr, &value_offset);
+ read_dword(&data_ptr, &code_offset);
+
+ if (!fx10_get_string(data, data_size, value_offset, &name, &name_len))
+ {
+ WARN("Failed to get variable name.\n");
+ return E_FAIL;
+ }
+
+ TRACE("Variable name %s[<expr>].\n", debugstr_a(name));
+
+ if (!(variable = d3d10_effect_get_variable_by_name(effect, name)))
+ {
+ WARN("Couldn't find variable %s.\n", debugstr_a(name));
+ return E_FAIL;
+ }
+
+ /* Has to be an array */
+ if (!variable->type->element_count)
+ {
+ WARN("Expected array variable.\n");
+ return E_FAIL;
+ }
+
+ if (!is_object_property(property_info))
+ {
+ WARN("Expected object type property used with indexed expression.\n");
+ return E_FAIL;
+ }
+
+ if (code_offset >= data_size || !require_space(code_offset, 1, sizeof(DWORD), data_size))
+ {
+ WARN("Invalid offset %#x (data size %#lx).\n", value_offset, (long)data_size);
+ return E_FAIL;
+ }
+
+ data_ptr = data + code_offset;
+ read_dword(&data_ptr, &blob_size);
+
+ dep.id = id;
+ dep.idx = idx;
+ dep.operation = operation;
+ dep.index_expr.v = variable;
+ if (FAILED(hr = parse_fx10_preshader(data_ptr, blob_size, effect, &dep.index_expr.index)))
+ {
+ WARN("Failed to parse preshader, hr %#x.\n", hr);
+ return hr;
+ }
+
+ return d3d10_effect_add_prop_dependency(d, &dep);
+
case D3D10_EOO_ANONYMOUS_SHADER:
/* Anonymous shader */
@@ -4004,6 +4559,8 @@ static HRESULT STDMETHODCALLTYPE d3d10_effect_pass_GetVertexShaderDesc(ID3D10Eff
return E_INVALIDARG;
}
+ d3d10_effect_update_dependent_props(&pass->dependencies, pass);
+
desc->pShaderVariable = (ID3D10EffectShaderVariable *)&pass->vs.shader->ID3D10EffectVariable_iface;
desc->ShaderIndex = pass->vs.index;
@@ -4029,6 +4586,8 @@ static HRESULT STDMETHODCALLTYPE d3d10_effect_pass_GetGeometryShaderDesc(ID3D10E
return E_INVALIDARG;
}
+ d3d10_effect_update_dependent_props(&pass->dependencies, pass);
+
desc->pShaderVariable = (ID3D10EffectShaderVariable *)&pass->gs.shader->ID3D10EffectVariable_iface;
desc->ShaderIndex = pass->gs.index;
@@ -4054,6 +4613,8 @@ static HRESULT STDMETHODCALLTYPE d3d10_effect_pass_GetPixelShaderDesc(ID3D10Effe
return E_INVALIDARG;
}
+ d3d10_effect_update_dependent_props(&pass->dependencies, pass);
+
desc->pShaderVariable = (ID3D10EffectShaderVariable *)&pass->ps.shader->ID3D10EffectVariable_iface;
desc->ShaderIndex = pass->ps.index;
diff --git a/dlls/d3d10/tests/effect.c b/dlls/d3d10/tests/effect.c
index da644d8d9db..f3e93fe34f4 100644
--- a/dlls/d3d10/tests/effect.c
+++ b/dlls/d3d10/tests/effect.c
@@ -7801,6 +7801,119 @@ static void test_effect_dynamic_numeric_field(void)
ok(!refcount, "Device has %u references left.\n", refcount);
}
+#if 0
+float4 g_var;
+PixelShader ps_array[2];
+VertexShader vs_array[2];
+technique10 tech
+{
+ pass p0
+ {
+ SetPixelShader( ps_array[g_var.z] );
+ SetVertexShader( vs_array[g_var.x + 0.1f] );
+ }
+}
+#endif
+static DWORD fx_test_index_expression[] =
+{
+ 0x43425844, 0x83787296, 0xf866b7a9, 0x7b56930c, 0xdc9d061a, 0x00000001, 0x000003e9, 0x00000001,
+ 0x00000024, 0x30315846, 0x000003bd, 0xfeff1001, 0x00000001, 0x00000001, 0x00000002, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000001, 0x000002cd, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000004, 0x00000000, 0x00000000, 0x6f6c4724,
+ 0x736c6162, 0x6f6c6600, 0x00347461, 0x0000000d, 0x00000001, 0x00000000, 0x00000010, 0x00000010,
+ 0x00000010, 0x0000210a, 0x61765f67, 0x69500072, 0x536c6578, 0x65646168, 0x00360072, 0x00020000,
+ 0x00020000, 0x00000000, 0x00000000, 0x00000000, 0x00050000, 0x73700000, 0x7272615f, 0x56007961,
+ 0x65747265, 0x61685378, 0x00726564, 0x00000067, 0x00000002, 0x00000002, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000006, 0x615f7376, 0x79617272, 0x63657400, 0x30700068, 0x0000ec00, 0x42584400,
+ 0x990a9743, 0xd17834e6, 0x40de477e, 0xf476a79f, 0x00000101, 0x0000ec00, 0x00000300, 0x00002c00,
+ 0x0000a800, 0x0000b400, 0x41544300, 0x00007442, 0x00001c00, 0x00004b00, 0x58040000, 0x00000146,
+ 0x00001c00, 0x00010000, 0x00004800, 0x00003000, 0x00000200, 0x00000100, 0x00003800, 0x00000000,
+ 0x765f6700, 0xab007261, 0x030001ab, 0x04000100, 0x00000100, 0x00000000, 0x00787400, 0x7263694d,
+ 0x666f736f, 0x52282074, 0x4c482029, 0x53204c53, 0x65646168, 0x6f432072, 0x6c69706d, 0x31207265,
+ 0x00312e30, 0x494c43ab, 0x00000434, 0x00000000, 0x4c584600, 0x00003043, 0x00000100, 0x30000100,
+ 0x00000113, 0x00000000, 0x00000200, 0x00000200, 0x00000000, 0x00000400, 0x00000000, 0xf0f0f000,
+ 0x0f0f0ff0, 0x00ffff0f, 0x00005e00, 0x0000a100, 0x00012800, 0x42584400, 0x78de2e43, 0x31414e7a,
+ 0xf69158cd, 0x416c97b6, 0x00000192, 0x00012800, 0x00000300, 0x00002c00, 0x0000a800, 0x0000c400,
+ 0x41544300, 0x00007442, 0x00001c00, 0x00004b00, 0x58040000, 0x00000146, 0x00001c00, 0x00010000,
+ 0x00004800, 0x00003000, 0x00000200, 0x00000100, 0x00003800, 0x00000000, 0x765f6700, 0xab007261,
+ 0x030001ab, 0x04000100, 0x00000100, 0x00000000, 0x00787400, 0x7263694d, 0x666f736f, 0x52282074,
+ 0x4c482029, 0x53204c53, 0x65646168, 0x6f432072, 0x6c69706d, 0x31207265, 0x00312e30, 0x494c43ab,
+ 0x00001434, 0x00000400, 0xcccccd00, 0x0000003d, 0x00000000, 0x00000000, 0x4c584600, 0x00005c43,
+ 0x00000200, 0x40000100, 0x00000220, 0x00000000, 0x00000200, 0x00000000, 0x00000000, 0x00000100,
+ 0x00000000, 0x00000000, 0x00000700, 0x00000000, 0x30000100, 0x00000113, 0x00000000, 0x00000700,
+ 0x00000000, 0x00000000, 0x00000400, 0x00000000, 0xf0f0f000, 0x0f0f0ff0, 0x00ffff0f, 0x00009000,
+ 0x00019900, 0x00000400, 0x00001000, 0x00000000, 0x00000100, 0xffffff00, 0x000000ff, 0x00003000,
+ 0x00001400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00005e00, 0x00004200,
+ 0x00000000, 0xffffff00, 0x000000ff, 0x00000000, 0x00000000, 0x00009000, 0x00007400, 0x00000000,
+ 0xffffff00, 0x000000ff, 0x00000000, 0x00000000, 0x00009900, 0x00000100, 0x00000000, 0x00009e00,
+ 0x00000200, 0x00000000, 0x00000700, 0x00000000, 0x00000500, 0x00019100, 0x00000600, 0x00000000,
+ 0x00000500, 0x0002c500, 0x00000000,
+};
+
+static void test_effect_index_expression(void)
+{
+ D3D10_PASS_SHADER_DESC shader_desc;
+ ID3D10EffectVectorVariable *vector;
+ ID3D10EffectTechnique *tech;
+ ID3D10EffectVariable *v;
+ ID3D10EffectPass *pass;
+ ID3D10Effect *effect;
+ ID3D10Device *device;
+ ULONG refcount;
+ float val[4];
+ HRESULT hr;
+
+ if (!(device = create_device()))
+ {
+ skip("Failed to create device, skipping tests.\n");
+ return;
+ }
+
+ hr = create_effect(fx_test_index_expression, 0, device, NULL, &effect);
+ ok(SUCCEEDED(hr), "Failed to create an effect, hr %#x.\n", hr);
+
+ /* Initial index */
+ tech = effect->lpVtbl->GetTechniqueByIndex(effect, 0);
+ pass = tech->lpVtbl->GetPassByIndex(tech, 0);
+ hr = pass->lpVtbl->GetPixelShaderDesc(pass, &shader_desc);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ ok(!shader_desc.ShaderIndex, "Unexpected shader index.\n");
+
+ v = effect->lpVtbl->GetVariableByName(effect, "g_var");
+ vector = v->lpVtbl->AsVector(v);
+
+ val[0] = 0.0f;
+ val[1] = 0.0f;
+ val[2] = 1.0f;
+ val[3] = 0.0f;
+ hr = vector->lpVtbl->SetFloatVector(vector, val);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ hr = pass->lpVtbl->GetPixelShaderDesc(pass, &shader_desc);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ ok(shader_desc.ShaderIndex == 1, "Unexpected shader index %#x.\n", shader_desc.ShaderIndex);
+
+ hr = pass->lpVtbl->GetVertexShaderDesc(pass, &shader_desc);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ ok(!shader_desc.ShaderIndex, "Unexpected shader index %#x.\n", shader_desc.ShaderIndex);
+
+ val[0] = 0.9f;
+ val[1] = 0.0f;
+ val[2] = 1.0f;
+ val[3] = 0.0f;
+ hr = vector->lpVtbl->SetFloatVector(vector, val);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ hr = pass->lpVtbl->GetVertexShaderDesc(pass, &shader_desc);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ ok(shader_desc.ShaderIndex == 1, "Unexpected shader index %#x.\n", shader_desc.ShaderIndex);
+
+ effect->lpVtbl->Release(effect);
+
+ refcount = ID3D10Device_Release(device);
+ ok(!refcount, "Device has %u references left.\n", refcount);
+}
+
START_TEST(effect)
{
test_effect_constant_buffer_type();
@@ -7825,4 +7938,5 @@ START_TEST(effect)
test_effect_default_variable_value();
test_effect_raw_value();
test_effect_dynamic_numeric_field();
+ test_effect_index_expression();
}
--
2.33.0
Nov. 8, 2021
[PATCH 4/4] evr/presenter: Add missing break in get_FramesDrawn() (Coverity).
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/evr/presenter.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/dlls/evr/presenter.c b/dlls/evr/presenter.c
index 5f70d173c0b..fd02404b7af 100644
--- a/dlls/evr/presenter.c
+++ b/dlls/evr/presenter.c
@@ -1754,6 +1754,7 @@ static HRESULT WINAPI video_presenter_qualprop_get_FramesDrawn(IQualProp *iface,
case PRESENTER_STATE_PAUSED:
if (frames) *frames = presenter->frame_stats.presented;
else hr = E_POINTER;
+ break;
default:
hr = E_NOTIMPL;
}
--
2.33.0
Nov. 8, 2021
[PATCH 3/4] evr/presenter: Remove logic related to picture aspect ratio adjustment.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/evr/presenter.c | 35 +----------------------------------
1 file changed, 1 insertion(+), 34 deletions(-)
diff --git a/dlls/evr/presenter.c b/dlls/evr/presenter.c
index 0381cb3e593..5f70d173c0b 100644
--- a/dlls/evr/presenter.c
+++ b/dlls/evr/presenter.c
@@ -483,8 +483,6 @@ static void video_presenter_sample_present(struct video_presenter *presenter, IM
{
IDirect3DSurface9 *surface, *backbuffer;
IDirect3DDevice9 *device;
- D3DSURFACE_DESC desc;
- RECT dst, src;
HRESULT hr;
if (!presenter->swapchain)
@@ -506,38 +504,7 @@ static void video_presenter_sample_present(struct video_presenter *presenter, IM
IDirect3DSwapChain9_GetDevice(presenter->swapchain, &device);
IDirect3DDevice9_StretchRect(device, surface, NULL, backbuffer, NULL, D3DTEXF_POINT);
- IDirect3DSurface9_GetDesc(surface, &desc);
- SetRect(&src, 0, 0, desc.Width, desc.Height);
-
- IDirect3DSurface9_GetDesc(backbuffer, &desc);
- SetRect(&dst, 0, 0, desc.Width, desc.Height);
-
- if (presenter->ar_mode & MFVideoARMode_PreservePicture)
- {
- unsigned int src_width = src.right - src.left, src_height = src.bottom - src.top;
- unsigned int dst_width = dst.right - dst.left, dst_height = dst.bottom - dst.top;
-
- if (src_width * dst_height > dst_width * src_height)
- {
- /* src is "wider" than dst. */
- unsigned int dst_center = (dst.top + dst.bottom) / 2;
- unsigned int scaled_height = src_height * dst_width / src_width;
-
- dst.top = dst_center - scaled_height / 2;
- dst.bottom = dst.top + scaled_height;
- }
- else if (src_width * dst_height < dst_width * src_height)
- {
- /* src is "taller" than dst. */
- unsigned int dst_center = (dst.left + dst.right) / 2;
- unsigned int scaled_width = src_width * dst_height / src_height;
-
- dst.left = dst_center - scaled_width / 2;
- dst.right = dst.left + scaled_width;
- }
- }
-
- IDirect3DSwapChain9_Present(presenter->swapchain, &src, &dst, NULL, NULL, 0);
+ IDirect3DSwapChain9_Present(presenter->swapchain, NULL, NULL, NULL, NULL, 0);
presenter->frame_stats.presented++;
IDirect3DDevice9_Release(device);
--
2.33.0
Nov. 8, 2021
[PATCH 2/4] evr/mixer: Preserve frame aspect ratio when rendering.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/evr/mixer.c | 109 +++++++++++++++++++++++++----------------------
1 file changed, 57 insertions(+), 52 deletions(-)
diff --git a/dlls/evr/mixer.c b/dlls/evr/mixer.c
index b6b4d148f90..4f5837a49a4 100644
--- a/dlls/evr/mixer.c
+++ b/dlls/evr/mixer.c
@@ -45,6 +45,7 @@ struct input_stream
IMFMediaType *media_type;
MFVideoNormalizedRect rect;
unsigned int zorder;
+ SIZE frame_size;
IMFSample *sample;
unsigned int sample_requested : 1;
};
@@ -100,6 +101,7 @@ struct video_mixer
COLORREF rgba;
DXVA2_AYUVSample16 ayuv;
} bkgnd_color;
+ MFVideoArea aperture;
LONGLONG lower_bound;
LONGLONG upper_bound;
CRITICAL_SECTION cs;
@@ -864,6 +866,8 @@ static HRESULT WINAPI video_mixer_transform_SetInputType(IMFTransform *iface, DW
if (mixer->inputs[0].media_type)
IMFMediaType_Release(mixer->inputs[0].media_type);
mixer->inputs[0].media_type = media_type;
+ mixer->inputs[0].frame_size.cx = video_desc.SampleWidth;
+ mixer->inputs[0].frame_size.cy = video_desc.SampleHeight;
IMFMediaType_AddRef(mixer->inputs[0].media_type);
}
CoTaskMemFree(guids);
@@ -939,6 +943,11 @@ static HRESULT WINAPI video_mixer_transform_SetOutputType(IMFTransform *iface, D
if (SUCCEEDED(hr = IDirectXVideoProcessorService_CreateVideoProcessor(service, &mixer->output.rt_formats[i].device,
&video_desc, rt_format, MAX_MIXER_INPUT_SUBSTREAMS, &mixer->processor)))
{
+ if (FAILED(IMFMediaType_GetBlob(type, &MF_MT_GEOMETRIC_APERTURE, (UINT8 *)&mixer->aperture,
+ sizeof(mixer->aperture), NULL)))
+ {
+ memset(&mixer->aperture, 0, sizeof(mixer->aperture));
+ }
if (mixer->output.media_type)
IMFMediaType_Release(mixer->output.media_type);
mixer->output.media_type = type;
@@ -1234,46 +1243,60 @@ static HRESULT video_mixer_get_d3d_device(struct video_mixer *mixer, IDirect3DDe
return hr;
}
+static BOOL video_mixer_rect_needs_scaling(const MFVideoNormalizedRect *scale)
+{
+ return scale->left != 0.0f || scale->top != 0.0f || scale->right != 1.0f || scale->bottom != 1.0f;
+}
+
static void video_mixer_scale_rect(RECT *rect, unsigned int width, unsigned int height,
const MFVideoNormalizedRect *scale)
{
- if (scale->left == 0.0f && scale->top == 0.0f && scale->right == 1.0f && scale->bottom == 1.0f)
- {
- SetRect(rect, 0, 0, width, height);
- }
- else
+ if (video_mixer_rect_needs_scaling(scale))
{
rect->left = width * scale->left;
rect->right = width * scale->right;
rect->top = height * scale->top;
rect->bottom = height * scale->bottom;
}
+ else
+ SetRect(rect, 0, 0, width, height);
}
-static void video_mixer_normalize_rect(const RECT *full, const RECT *part, MFVideoNormalizedRect *ret)
+static void video_mixer_correct_aspect_ratio(const RECT *src, RECT *dst)
{
- float width = full->right - full->left;
- float height = full->bottom - full->top;
+ unsigned int src_width = src->right - src->left, src_height = src->bottom - src->top;
+ unsigned int dst_width = dst->right - dst->left, dst_height = dst->bottom - dst->top;
- ret->left = (part->left - full->left) / width;
- ret->right = (part->right - full->left) / width;
- ret->bottom = (part->bottom - full->top) / height;
- ret->top = (part->top - full->top) / height;
+ if (src_width * dst_height > dst_width * src_height)
+ {
+ /* src is "wider" than dst. */
+ unsigned int dst_center = (dst->top + dst->bottom) / 2;
+ unsigned int scaled_height = src_height * dst_width / src_width;
+
+ dst->top = dst_center - scaled_height / 2;
+ dst->bottom = dst->top + scaled_height;
+ }
+ else if (src_width * dst_height < dst_width * src_height)
+ {
+ /* src is "taller" than dst. */
+ unsigned int dst_center = (dst->left + dst->right) / 2;
+ unsigned int scaled_width = src_width * dst_height / src_height;
+
+ dst->left = dst_center - scaled_width / 2;
+ dst->right = dst->left + scaled_width;
+ }
}
static void video_mixer_render(struct video_mixer *mixer, IDirect3DSurface9 *rt)
{
DXVA2_VideoSample samples[MAX_MIXER_INPUT_STREAMS] = {{ 0 }};
DXVA2_VideoProcessBltParams params = { 0 };
- MFVideoNormalizedRect zoom_rect, norm;
- unsigned int i, sample_count = 0;
- D3DSURFACE_DESC desc, rt_desc;
+ MFVideoNormalizedRect zoom_rect;
struct input_stream *stream;
HRESULT hr = S_OK;
+ unsigned int i;
RECT dst;
- IDirect3DSurface9_GetDesc(rt, &rt_desc);
-
if (FAILED(IMFAttributes_GetBlob(mixer->attributes, &VIDEO_ZOOM_RECT, (UINT8 *)&zoom_rect,
sizeof(zoom_rect), NULL)))
{
@@ -1281,12 +1304,12 @@ static void video_mixer_render(struct video_mixer *mixer, IDirect3DSurface9 *rt)
zoom_rect.right = zoom_rect.bottom = 1.0f;
}
- video_mixer_scale_rect(&dst, rt_desc.Width, rt_desc.Height, &zoom_rect);
+ SetRect(&dst, 0, 0, mixer->aperture.Area.cx, mixer->aperture.Area.cy);
+ OffsetRect(&dst, mixer->aperture.OffsetX.value, mixer->aperture.OffsetY.value);
for (i = 0; i < mixer->input_count; ++i)
{
- RECT stream_dst, stream_vis;
-
+ DXVA2_VideoSample *sample = &samples[i];
IDirect3DSurface9 *surface;
stream = mixer->zorder[i];
@@ -1297,54 +1320,36 @@ static void video_mixer_render(struct video_mixer *mixer, IDirect3DSurface9 *rt)
break;
}
- IDirect3DSurface9_GetDesc(surface, &desc);
-
- /* In order to compute source/destination rectangles for each stream:
-
- * per-stream rectangle is used to get destination rectangle in target coordinates;
- * destination per-stream rectangle is clipped with zoom rectangle, applied to target coordinates;
- * visible rectangle is scaled back to get source area of the stream that would be visible;
- * visible rectangle is scaled back to get destination area in target coordinates for given steam.
+ /* Full input frame corrected to full destination rectangle. */
- */
+ video_mixer_scale_rect(&sample->SrcRect, stream->frame_size.cx, stream->frame_size.cy, &zoom_rect);
+ CopyRect(&sample->DstRect, &dst);
+ video_mixer_correct_aspect_ratio(&sample->SrcRect, &sample->DstRect);
- video_mixer_scale_rect(&stream_dst, rt_desc.Width, rt_desc.Height, &stream->rect);
+ if (video_mixer_rect_needs_scaling(&stream->rect))
+ WARN("Ignoring stream %u rectangle %s.\n", stream->id, debugstr_normalized_rect(&stream->rect));
- /* Part of the stream that's visible after zooming. */
- if (!IntersectRect(&stream_vis, &stream_dst, &dst))
- {
- IDirect3DSurface9_Release(surface);
- continue;
- }
-
- samples[sample_count].SampleFormat.SampleFormat = stream->id == 0 ?
- DXVA2_SampleProgressiveFrame : DXVA2_SampleSubStream;
- samples[sample_count].SrcSurface = surface;
-
- video_mixer_normalize_rect(&stream_dst, &stream_vis, &norm);
- video_mixer_scale_rect(&samples[sample_count].SrcRect, desc.Width, desc.Height, &norm);
-
- video_mixer_normalize_rect(&dst, &stream_vis, &norm);
- video_mixer_scale_rect(&samples[sample_count].DstRect, rt_desc.Width, rt_desc.Height, &norm);
- samples[sample_count].PlanarAlpha = DXVA2_Fixed32OpaqueAlpha();
-
- sample_count++;
+ sample->SampleFormat.SampleFormat = stream->id == 0 ? DXVA2_SampleProgressiveFrame : DXVA2_SampleSubStream;
+ sample->SrcSurface = surface;
+ sample->PlanarAlpha = DXVA2_Fixed32OpaqueAlpha();
}
if (SUCCEEDED(hr))
{
- SetRect(¶ms.TargetRect, 0, 0, rt_desc.Width, rt_desc.Height);
+ SetRect(¶ms.TargetRect, 0, 0, mixer->aperture.Area.cx, mixer->aperture.Area.cy);
+ OffsetRect(¶ms.TargetRect, mixer->aperture.OffsetX.value, mixer->aperture.OffsetY.value);
+
params.BackgroundColor = mixer->bkgnd_color.ayuv;
params.Alpha = DXVA2_Fixed32OpaqueAlpha();
if (FAILED(hr = IDirectXVideoProcessor_VideoProcessBlt(mixer->processor, rt, ¶ms, samples,
- sample_count, NULL)))
+ mixer->input_count, NULL)))
{
WARN("Failed to process samples, hr %#x.\n", hr);
}
}
- for (i = 0; i < sample_count; ++i)
+ for (i = 0; i < mixer->input_count; ++i)
{
if (samples[i].SrcSurface)
IDirect3DSurface9_Release(samples[i].SrcSurface);
--
2.33.0
Nov. 8, 2021
[PATCH 1/4] evr/mixer: Fix rectangle scaling helper argument check (Coverity).
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/evr/mixer.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/evr/mixer.c b/dlls/evr/mixer.c
index bb3f938cb64..b6b4d148f90 100644
--- a/dlls/evr/mixer.c
+++ b/dlls/evr/mixer.c
@@ -1237,7 +1237,7 @@ static HRESULT video_mixer_get_d3d_device(struct video_mixer *mixer, IDirect3DDe
static void video_mixer_scale_rect(RECT *rect, unsigned int width, unsigned int height,
const MFVideoNormalizedRect *scale)
{
- if (rect->left == 0.0f && rect->top == 0.0f && rect->right == 1.0f && rect->bottom == 1.0f)
+ if (scale->left == 0.0f && scale->top == 0.0f && scale->right == 1.0f && scale->bottom == 1.0f)
{
SetRect(rect, 0, 0, width, height);
}
--
2.33.0
Nov. 8, 2021
Re: [PATCH] ucrtbase: Later printf width specifiers should override earlier ones
by Marvin
Hi,
While running your changed tests, I think I found new failures.
Being a bot and all I'm not very good at pattern recognition, so I might be
wrong, but could you please double-check?
Full results can be found at:
https://testbot.winehq.org/JobDetails.pl?Key=101426
Your paranoid android.
=== build (build log) ===
error: patch failed: dlls/msvcrt/printf.h:1050
Task: Patch failed to apply
=== debiant2 (build log) ===
error: patch failed: dlls/msvcrt/printf.h:1050
Task: Patch failed to apply
=== debiant2 (build log) ===
error: patch failed: dlls/msvcrt/printf.h:1050
Task: Patch failed to apply
Nov. 8, 2021
[PATCH] ucrtbase: Later printf width specifiers should override earlier ones
by David Gow
In ucrtbase (but not in msvcrt), when a printf format specifier has two
width specifiers (both a '*' and an explicit number), only the latter
should take effect. (In msvcrt, the width of one is combined with the
other).
This patch builds on the prior patch which implements the msvcrt
behaviour, and needs to be applied on top of it:
msvcrt: The '*' character should be interpreted as the beginning of the width specification[1,2]
It also supercedes the previous (incorrect) patch which used the
ucrtbase behaviour on msvcrt as well:
msvcrt: printf: Later width specifiers should override earlier ones[3]
For further details, see [4], [5], and [6].
[1]: https://source.winehq.org/patches/data/218904
[2]: https://www.winehq.org/pipermail/wine-devel/2021-November/200009.html
[3]: https://www.winehq.org/pipermail/wine-devel/2021-November/200040.html
[4]: https://www.winehq.org/pipermail/wine-devel/2021-November/200039.html
[5]: https://github.com/ValveSoftware/Proton/issues/5258#issuecomment-962423092
[6]: https://www.winehq.org/pipermail/wine-devel/2021-November/200063.html
Signed-off-by: David Gow <david(a)davidgow.net>
---
dlls/msvcrt/printf.h | 6 ++++++
dlls/ucrtbase/tests/printf.c | 30 ++++++++++++++++++++++++++++++
2 files changed, 36 insertions(+)
diff --git a/dlls/msvcrt/printf.h b/dlls/msvcrt/printf.h
index 40a8a13d861..52dec97f8bc 100644
--- a/dlls/msvcrt/printf.h
+++ b/dlls/msvcrt/printf.h
@@ -1050,6 +1050,12 @@ int FUNC_NAME(pf_printf)(FUNC_NAME(puts_clbk) pf_puts, void *puts_ctx, const API
flags.LeftAlign = TRUE;
flags.FieldLength = -flags.FieldLength;
}
+
+ /* On ucrtbase, we ignore all but the last specifier. */
+#if _MSVCR_VER >= 140
+ if (*p >= '0' && *p <= '9')
+ flags.FieldLength = 0;
+#endif
}
while (*p >= '0' && *p <= '9') {
diff --git a/dlls/ucrtbase/tests/printf.c b/dlls/ucrtbase/tests/printf.c
index 4f20ccff9a4..328300d7827 100644
--- a/dlls/ucrtbase/tests/printf.c
+++ b/dlls/ucrtbase/tests/printf.c
@@ -845,6 +845,35 @@ static void test_printf_fp(void)
}
}
+static void test_printf_width_specifiers(void)
+{
+ char buf[150];
+ int r;
+
+ /* In msvcrt, multiple width specifiers will 'stack', producing
+ * a longer width. In ucrtbase, only the last width specifier will
+ * take effect. */
+ r = vsprintf_wrapper(0, buf, sizeof(buf), "%0*02d", 1, 0);
+ ok(r==2, "r = %d\n", r);
+ ok(!strcmp(buf, "00"), "failed: \"%s\"\n", buf);
+
+ r = vsprintf_wrapper(0, buf, sizeof(buf), "%0*02d", 2, 17);
+ ok(r==2, "r = %d\n", r);
+ ok(!strcmp(buf, "17"), "failed: \"%s\"\n", buf);
+
+ r = vsprintf_wrapper(0, buf, sizeof(buf), "%*1d", 1, 3);
+ ok(r==1, "r = %d\n", r);
+ ok(!strcmp(buf, "3"), "failed: \"%s\"\n", buf);
+
+ r = vsprintf_wrapper(0, buf, sizeof(buf), "%0*0d", 1, 2);
+ ok(r==1, "r = %d\n", r);
+ ok(!strcmp(buf, "2"), "failed: \"%s\"\n", buf);
+
+ r = vsprintf_wrapper(0, buf, sizeof(buf), "% *2d", 0, 7);
+ ok(r==2, "r = %d\n", r);
+ ok(!strcmp(buf, " 7"), "failed: \"%s\"\n", buf);
+}
+
START_TEST(printf)
{
ok(_set_invalid_parameter_handler(test_invalid_parameter_handler) == NULL,
@@ -862,4 +891,5 @@ START_TEST(printf)
test_printf_c99();
test_printf_natural_string();
test_printf_fp();
+ test_printf_width_specifiers();
}
--
2.32.0
Nov. 8, 2021
Re: [PATCH v5 1/2] nsiproxy: Fill the reply with exact ICMP_ECHO_REPLY in the output buffer.
by Huw Davies
On Mon, Oct 25, 2021 at 07:26:47PM +0300, Gabriel Ivăncescu wrote:
> @@ -372,9 +384,23 @@ static void handle_queued_send_echo( IRP *irp )
> irp->IoStatus.Status = status;
> if (status == STATUS_SUCCESS)
> {
> - memset( reply, 0, sizeof(*reply) );
> - reply->status = params.ip_status;
> - irp->IoStatus.Information = sizeof(*reply);
> + if (family == AF_INET)
> + {
> + if (bits == 32)
> + {
> + struct icmp_echo_reply_32 *reply = out;
> + memset( reply, 0, sizeof(*reply) );
> + reply->status = params.ip_status;
> + irp->IoStatus.Information = sizeof(*reply);
> + }
> + else
> + {
> + struct icmp_echo_reply_64 *reply = out;
> + memset( reply, 0, sizeof(*reply) );
> + reply->status = params.ip_status;
> + irp->IoStatus.Information = sizeof(*reply);
> + }
> + }
Given that this has increased in complexity, I think it would now make
sense to do this on the unix-side (it was a bit of a toss-up even
before this change). Obviously you'd now need to pass "out" and
"bits" to the syscall. Additionally this patch could be split. For
example, one could add the new ops before changing any functionality.
Huw.
Nov. 8, 2021
[PATCH v3 6/6] msdasql: Fix use after free (Coverity)
by Alistair Leslie-Hughes
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
---
dlls/msdasql/tests/provider.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/msdasql/tests/provider.c b/dlls/msdasql/tests/provider.c
index d093c3c2087..9b75f40a741 100644
--- a/dlls/msdasql/tests/provider.c
+++ b/dlls/msdasql/tests/provider.c
@@ -130,8 +130,8 @@ static void test_Properties(void)
hr = IDBProperties_GetProperties(props, 1, &propidlist, &propcnt, &propset);
ok(hr == S_OK, "got 0x%08x\n", hr);
- ok(propidlist.cPropertyIDs == 14, "got %d\n", propinfoset->cPropertyInfos);
- ok(propset->cProperties == 14, "got %d\n", propinfoset->cPropertyInfos);
+ ok(propidlist.cPropertyIDs == 14, "got %d\n", propidlist.cPropertyIDs);
+ ok(propset->cProperties == 14, "got %d\n", propset->cProperties);
for (i = 0; i < propidlist.cPropertyIDs; i++)
{
--
2.33.0
Nov. 8, 2021
[PATCH v3 5/6] msdasql: Correct default dialect logic
by Alistair Leslie-Hughes
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
---
dlls/msdasql/session.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/msdasql/session.c b/dlls/msdasql/session.c
index 98a1fc50220..e52e8cd18d8 100644
--- a/dlls/msdasql/session.c
+++ b/dlls/msdasql/session.c
@@ -847,7 +847,7 @@ static HRESULT WINAPI command_SetCommandText(ICommandText *iface, REFGUID dialec
struct command *command = impl_from_ICommandText( iface );
TRACE("%p, %s, %s\n", command, debugstr_guid(dialect), debugstr_w(commandstr));
- if (IsEqualGUID(&DBGUID_DEFAULT, dialect))
+ if (!IsEqualGUID(&DBGUID_DEFAULT, dialect))
FIXME("Currently non Default Dialect isn't supported\n");
heap_free(command->query);
--
2.33.0
Nov. 8, 2021