Wine-Devel
Threads by month
- ----- 2026 -----
- 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
- 16 participants
- 84524 discussions
[PATCH 2/3] msdasql: Add ICommandWithParameters to command interface
by Alistair Leslie-Hughes Nov. 16, 2021
by Alistair Leslie-Hughes Nov. 16, 2021
Nov. 16, 2021
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
---
dlls/msdasql/session.c | 62 +++++++++++++++++++++++++++++++++++
dlls/msdasql/tests/provider.c | 5 +++
2 files changed, 67 insertions(+)
diff --git a/dlls/msdasql/session.c b/dlls/msdasql/session.c
index 82693115b8a..3829f8f946f 100644
--- a/dlls/msdasql/session.c
+++ b/dlls/msdasql/session.c
@@ -426,6 +426,7 @@ struct msdasql_rowset
IColumnsInfo IColumnsInfo_iface;
IAccessor IAccessor_iface;
IColumnsRowset IColumnsRowset_iface;
+ ICommandWithParameters ICommandWithParameters_iface;
IUnknown *caller;
LONG refs;
};
@@ -455,6 +456,11 @@ static inline struct msdasql_rowset *impl_from_IColumnsRowset ( IColumnsRowset *
return CONTAINING_RECORD( iface, struct msdasql_rowset, IColumnsRowset_iface );
}
+static inline struct msdasql_rowset *impl_from_ICommandWithParameters( ICommandWithParameters *iface )
+{
+ return CONTAINING_RECORD( iface, struct msdasql_rowset, ICommandWithParameters_iface );
+}
+
static HRESULT WINAPI msdasql_rowset_QueryInterface(IRowset *iface, REFIID riid, void **ppv)
{
struct msdasql_rowset *rowset = impl_from_IRowset( iface );
@@ -483,6 +489,10 @@ static HRESULT WINAPI msdasql_rowset_QueryInterface(IRowset *iface, REFIID riid,
{
*ppv = &rowset->IColumnsRowset_iface;
}
+ else if(IsEqualGUID(&IID_ICommandWithParameters, riid))
+ {
+ *ppv = &rowset->ICommandWithParameters_iface;
+ }
else if (IsEqualGUID(&IID_IRowsetChange, riid))
{
TRACE("IID_IRowsetChange not supported\n");
@@ -791,6 +801,57 @@ struct IColumnsRowsetVtbl columnrs_rs_vtbl =
column_rs_GetColumnsRowset
};
+static HRESULT WINAPI cmd_with_params_QueryInterface(ICommandWithParameters *iface, REFIID riid, void **out)
+{
+ struct msdasql_rowset *rowset = impl_from_ICommandWithParameters( iface );
+ return IRowset_QueryInterface(&rowset->IRowset_iface, riid, out);
+}
+
+static ULONG WINAPI cmd_with_params_AddRef(ICommandWithParameters *iface)
+{
+ struct msdasql_rowset *rowset = impl_from_ICommandWithParameters( iface );
+ return IRowset_AddRef(&rowset->IRowset_iface);
+}
+
+static ULONG WINAPI cmd_with_params_Release(ICommandWithParameters *iface)
+{
+ struct msdasql_rowset *rowset = impl_from_ICommandWithParameters( iface );
+ return IRowset_Release(&rowset->IRowset_iface);
+}
+
+static HRESULT WINAPI cmd_with_params_GetParameterInfo(ICommandWithParameters *iface, DB_UPARAMS *uparams,
+ DBPARAMINFO **info, OLECHAR **buffer)
+{
+ struct msdasql_rowset *rowset = impl_from_ICommandWithParameters( iface );
+ FIXME("%p, %p, %p, %p\n", rowset, uparams, info, buffer);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI cmd_with_params_MapParameterNames(ICommandWithParameters *iface, DB_UPARAMS uparams,
+ LPCWSTR names[], DB_LPARAMS ordinals[])
+{
+ struct msdasql_rowset *rowset = impl_from_ICommandWithParameters( iface );
+ FIXME("%p, %ld, %p, %p\n", rowset, uparams, names, ordinals);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI cmd_with_params_SetParameterInfo(ICommandWithParameters *iface, DB_UPARAMS uparams,
+ const DB_UPARAMS ordinals[], const DBPARAMBINDINFO bindinfo[])
+{
+ struct msdasql_rowset *rowset = impl_from_ICommandWithParameters( iface );
+ FIXME("%p, %ld, %p, %p\n", rowset, uparams, ordinals, bindinfo);
+ return E_NOTIMPL;
+}
+
+struct ICommandWithParametersVtbl command_with_params_vtbl =
+{
+ cmd_with_params_QueryInterface,
+ cmd_with_params_AddRef,
+ cmd_with_params_Release,
+ cmd_with_params_GetParameterInfo,
+ cmd_with_params_MapParameterNames,
+ cmd_with_params_SetParameterInfo
+};
static HRESULT WINAPI command_Execute(ICommandText *iface, IUnknown *outer, REFIID riid,
DBPARAMS *params, DBROWCOUNT *affected, IUnknown **rowset)
@@ -810,6 +871,7 @@ static HRESULT WINAPI command_Execute(ICommandText *iface, IUnknown *outer, REFI
msrowset->IColumnsInfo_iface.lpVtbl = &rowset_columninfo_vtbll;
msrowset->IAccessor_iface.lpVtbl = &accessor_vtbl;
msrowset->IColumnsRowset_iface.lpVtbl = &columnrs_rs_vtbl;
+ msrowset->ICommandWithParameters_iface.lpVtbl = &command_with_params_vtbl;
msrowset->refs = 1;
ICommandText_QueryInterface(iface, &IID_IUnknown, (void**)&msrowset->caller);
diff --git a/dlls/msdasql/tests/provider.c b/dlls/msdasql/tests/provider.c
index b0e13b72589..37230be04cb 100644
--- a/dlls/msdasql/tests/provider.c
+++ b/dlls/msdasql/tests/provider.c
@@ -193,12 +193,17 @@ static void test_command_interfaces(IUnknown *cmd)
ICommandStream *commandstream;
IColumnsInfo *colinfo;
IMultipleResults *multiple;
+ ICommandWithParameters *cmdwithparams;
IUnknown *unk;
hr = IUnknown_QueryInterface(cmd, &IID_ICommandProperties, (void**)&commandProp);
ok(hr == S_OK, "got 0x%08x\n", hr);
ICommandProperties_Release(commandProp);
+ hr = IUnknown_QueryInterface(cmd, &IID_ICommandWithParameters, (void**)&cmdwithparams);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ ICommandWithParameters_Release(cmdwithparams);
+
hr = IUnknown_QueryInterface(cmd, &IID_ICommandText, (void**)&comand_text);
ok(hr == S_OK, "got 0x%08x\n", hr);
ICommandText_Release(comand_text);
--
2.33.0
1
0
Nov. 16, 2021
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
---
include/dbs.idl | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/include/dbs.idl b/include/dbs.idl
index cbdb89d23b2..d5b903138d6 100644
--- a/include/dbs.idl
+++ b/include/dbs.idl
@@ -569,6 +569,15 @@ cpp_quote("#define DBPROPVAL_OS_CLIENTCURSOR __MSABI_LONG(0x00000004)"
cpp_quote("#define DBPROPVAL_OS_ENABLEALL __MSABI_LONG(0xffffffff)")
cpp_quote("#define DBPROPVAL_BI_CROSSROWSET __MSABI_LONG(0x00000001)")
+cpp_quote("#define DBPROPVAL_RT_FREETHREAD __MSABI_LONG(0x00000001)")
+cpp_quote("#define DBPROPVAL_RT_APTMTTHREAD __MSABI_LONG(0x00000002)")
+cpp_quote("#define DBPROPVAL_RT_SINGLETHREAD __MSABI_LONG(0x00000004)")
+
+cpp_quote("#define DBPROPVAL_LM_NONE __MSABI_LONG(0x00000001)")
+cpp_quote("#define DBPROPVAL_LM_READ __MSABI_LONG(0x00000002)")
+cpp_quote("#define DBPROPVAL_LM_INTENT __MSABI_LONG(0x00000004)")
+cpp_quote("#define DBPROPVAL_LM_RITE __MSABI_LONG(0x00000008)")
+
cpp_quote("#define DB_MODE_READ 0x01")
cpp_quote("#define DB_MODE_WRITE 0x02")
cpp_quote("#define DB_MODE_READWRITE 0x03")
--
2.33.0
1
0
[PATCH 1/8] dinput8/tests: Make sure SetCooperativeLevel window is foreground.
by Rémi Bernon Nov. 16, 2021
by Rémi Bernon Nov. 16, 2021
Nov. 16, 2021
This should prevent spurious failures on Windows.
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/dinput8/tests/hid.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c
index 007f81688cc..9ec9d147dd1 100644
--- a/dlls/dinput8/tests/hid.c
+++ b/dlls/dinput8/tests/hid.c
@@ -4267,6 +4267,7 @@ static void test_simple_joystick(void)
hwnd = CreateWindowW( L"static", L"dinput", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 10, 10, 200, 200,
NULL, NULL, NULL, NULL );
+ SetForegroundWindow( hwnd );
hr = IDirectInputDevice8_SetCooperativeLevel( device, hwnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE );
ok( hr == DI_OK, "SetCooperativeLevel returned: %#x\n", hr );
--
2.33.1
2
8
Nov. 16, 2021
Signed-off-by: Serge Gautherie <winehq-git_serge_180711(a)gautherie.fr>
---
Like the other release_font_cache() calls.
Addendum to wine-4.14-26-g6f1cc1f.
ReactOS-Bug: https://jira.reactos.org/browse/CORE-17843
---
dlls/riched20/style.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/riched20/style.c b/dlls/riched20/style.c
index 917a5bd..266bb93 100644
--- a/dlls/riched20/style.c
+++ b/dlls/riched20/style.c
@@ -429,7 +429,7 @@ void select_style( ME_Context *c, ME_Style *s )
c->orig_font = NULL;
}
- if (c->current_style)
+ if (c->current_style && c->current_style->font_cache)
{
release_font_cache( c->current_style->font_cache );
c->current_style->font_cache = NULL;
--
2.10.0.windows.1
2
1
[v4 PATCH] d3d10/effect: Add initial support for indexing expressions.
by Nikolay Sivov Nov. 15, 2021
by Nikolay Sivov Nov. 15, 2021
Nov. 15, 2021
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/d3d10/effect.c | 595 +++++++++++++++++++++++++++++++++++++-
dlls/d3d10/tests/effect.c | 147 ++++++++++
2 files changed, 734 insertions(+), 8 deletions(-)
diff --git a/dlls/d3d10/effect.c b/dlls/d3d10/effect.c
index 78a3d0c386a..3f35e9cc28a 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,95 @@ 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 table_sizes[D3D10_REG_TABLE_COUNT];
+};
+
struct d3d10_effect_prop_dependency
{
unsigned int id;
@@ -192,11 +284,116 @@ 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->v->buffer_offset,
+ 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,285 @@ 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_CONSTANTS:
+ case D3D10_REG_TABLE_CB:
+ case D3D10_REG_TABLE_RESULT:
+ case D3D10_REG_TABLE_TEMP:
+ context->table_sizes[regt] = max(context->table_sizes[regt], param_offset + 1);
+ break;
+ default:
+ FIXME("Unexpected register table index %u.\n", regt);
+ 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;
+ }
+
+ 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->table_sizes[D3D10_REG_TABLE_RESULT]))) return hr;
+ if (FAILED(hr = d3d10_reg_table_allocate(&p->reg_tables[D3D10_REG_TABLE_TEMP],
+ context->table_sizes[D3D10_REG_TABLE_TEMP]))) 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;
+
+ 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;
+ HRESULT hr;
+
+ memset(preshader, 0, sizeof(*preshader));
+ memset(&context, 0, sizeof(context));
+ context.preshader = preshader;
+ context.effect = effect;
+
+ if (FAILED(hr = parse_dxbc(data, data_size, fxlvm_chunk_handler, &context))) return hr;
+
+ /* Constant buffer and literal constants are preallocated, validate here that expression
+ has no invalid accesses for those. */
+
+ if (context.table_sizes[D3D10_REG_TABLE_CONSTANTS] >
+ preshader->reg_tables[D3D10_REG_TABLE_CONSTANTS].count)
+ {
+ WARN("Expression references out of bounds literal constant.\n");
+ return E_FAIL;
+ }
+
+ if (context.table_sizes[D3D10_REG_TABLE_CB] > preshader->reg_tables[D3D10_REG_TABLE_CB].count)
+ {
+ WARN("Expression references out of bounds variable.\n");
+ return E_FAIL;
+ }
+
+ return S_OK;
+}
+
static HRESULT d3d10_effect_add_prop_dependency(struct d3d10_effect_prop_dependencies *d,
const struct d3d10_effect_prop_dependency *dep)
{
@@ -1875,6 +2387,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 +2487,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 +2564,74 @@ 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;
+ }
+
+ 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 +4577,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 +4604,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 +4631,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..7c2bba6d818 100644
--- a/dlls/d3d10/tests/effect.c
+++ b/dlls/d3d10/tests/effect.c
@@ -7801,6 +7801,152 @@ static void test_effect_dynamic_numeric_field(void)
ok(!refcount, "Device has %u references left.\n", refcount);
}
+#if 0
+float4 g_var;
+float4 g_var2;
+PixelShader ps_array[2];
+VertexShader vs_array[2];
+GeometryShader gs_array[2];
+technique10 tech
+{
+ pass p0
+ {
+ SetPixelShader( ps_array[g_var.z] );
+ SetVertexShader( vs_array[g_var.x + 0.1f] );
+ SetGeometryShader( gs_array[g_var2.y] );
+ }
+}
+#endif
+static DWORD fx_test_index_expression[] =
+{
+ 0x43425844, 0xef7cea81, 0x5103f059, 0x9011e9d4, 0xa8ed3607, 0x00000001, 0x00000564, 0x00000001,
+ 0x00000024, 0x30315846, 0x00000538, 0xfeff1001, 0x00000001, 0x00000002, 0x00000003, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000001, 0x00000400, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000006, 0x00000000, 0x00000000, 0x6f6c4724,
+ 0x736c6162, 0x6f6c6600, 0x00347461, 0x0000000d, 0x00000001, 0x00000000, 0x00000010, 0x00000010,
+ 0x00000010, 0x0000210a, 0x61765f67, 0x5f670072, 0x32726176, 0x78695000, 0x68536c65, 0x72656461,
+ 0x00003d00, 0x00000200, 0x00000200, 0x00000000, 0x00000000, 0x00000000, 0x00000500, 0x5f737000,
+ 0x61727261, 0x65560079, 0x78657472, 0x64616853, 0x6e007265, 0x02000000, 0x02000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x06000000, 0x76000000, 0x72615f73, 0x00796172, 0x6d6f6547, 0x79727465,
+ 0x64616853, 0xa0007265, 0x02000000, 0x02000000, 0x00000000, 0x00000000, 0x00000000, 0x07000000,
+ 0x67000000, 0x72615f73, 0x00796172, 0x68636574, 0x00307000, 0x000000ec, 0x43425844, 0xe6990a97,
+ 0x7ed17834, 0x9f40de47, 0x01f476a7, 0x00000001, 0x000000ec, 0x00000003, 0x0000002c, 0x000000a8,
+ 0x000000b4, 0x42415443, 0x00000074, 0x0000001c, 0x0000004b, 0x46580400, 0x00000001, 0x0000001c,
+ 0x00000100, 0x00000048, 0x00000030, 0x00000002, 0x00000001, 0x00000038, 0x00000000, 0x61765f67,
+ 0xabab0072, 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x4d007874, 0x6f726369, 0x74666f73,
+ 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x30312072, 0xab00312e,
+ 0x34494c43, 0x00000004, 0x00000000, 0x434c5846, 0x00000030, 0x00000001, 0x13300001, 0x00000001,
+ 0x00000000, 0x00000002, 0x00000002, 0x00000000, 0x00000004, 0x00000000, 0xf0f0f0f0, 0x0f0f0f0f,
+ 0x0000ffff, 0x00000065, 0x000000dc, 0x00000128, 0x43425844, 0x7a78de2e, 0xcd31414e, 0xb6f69158,
+ 0x92416c97, 0x00000001, 0x00000128, 0x00000003, 0x0000002c, 0x000000a8, 0x000000c4, 0x42415443,
+ 0x00000074, 0x0000001c, 0x0000004b, 0x46580400, 0x00000001, 0x0000001c, 0x00000100, 0x00000048,
+ 0x00000030, 0x00000002, 0x00000001, 0x00000038, 0x00000000, 0x61765f67, 0xabab0072, 0x00030001,
+ 0x00040001, 0x00000001, 0x00000000, 0x4d007874, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820,
+ 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x30312072, 0xab00312e, 0x34494c43, 0x00000014,
+ 0x00000004, 0x3dcccccd, 0x00000000, 0x00000000, 0x00000000, 0x434c5846, 0x0000005c, 0x00000002,
+ 0x20400001, 0x00000002, 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000001, 0x00000000,
+ 0x00000000, 0x00000007, 0x00000000, 0x13300001, 0x00000001, 0x00000000, 0x00000007, 0x00000000,
+ 0x00000000, 0x00000004, 0x00000000, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, 0x00000097, 0x000001d4,
+ 0x000000ec, 0x43425844, 0x90e93368, 0x6c8d5166, 0x276e99ab, 0x25ccef44, 0x00000001, 0x000000ec,
+ 0x00000003, 0x0000002c, 0x000000a8, 0x000000b4, 0x42415443, 0x00000074, 0x0000001c, 0x0000004b,
+ 0x46580400, 0x00000001, 0x0000001c, 0x00000100, 0x00000048, 0x00000030, 0x00000002, 0x00000001,
+ 0x00000038, 0x00000000, 0x61765f67, 0xab003272, 0x00030001, 0x00040001, 0x00000001, 0x00000000,
+ 0x4d007874, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320,
+ 0x656c6970, 0x30312072, 0xab00312e, 0x34494c43, 0x00000004, 0x00000000, 0x434c5846, 0x00000030,
+ 0x00000001, 0x13300001, 0x00000001, 0x00000000, 0x00000002, 0x00000001, 0x00000000, 0x00000004,
+ 0x00000000, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, 0x000000cb, 0x00000308, 0x00000004, 0x00000020,
+ 0x00000000, 0x00000002, 0xffffffff, 0x00000000, 0x00000030, 0x00000014, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000036, 0x00000014, 0x00000000, 0x00000010, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000065, 0x00000049, 0x00000000, 0xffffffff, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000097, 0x0000007b, 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
+ 0x000000cb, 0x000000af, 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x000000d4,
+ 0x00000001, 0x00000000, 0x000000d9, 0x00000003, 0x00000000, 0x00000007, 0x00000000, 0x00000005,
+ 0x000001cc, 0x00000006, 0x00000000, 0x00000005, 0x00000300, 0x00000008, 0x00000000, 0x00000005,
+ 0x000003f8,
+};
+
+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);
+
+ v = effect->lpVtbl->GetVariableByName(effect, "g_var2");
+ vector = v->lpVtbl->AsVector(v);
+
+ hr = pass->lpVtbl->GetGeometryShaderDesc(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.0f;
+ val[1] = 1.0f;
+ val[2] = 0.0f;
+ val[3] = 0.0f;
+ hr = vector->lpVtbl->SetFloatVector(vector, val);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ hr = pass->lpVtbl->GetGeometryShaderDesc(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 +7971,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
3
2
[PATCH vkd3d v2] vkd3d-shader/hlsl: Explicitly specify the swizzle type for sm4 source registers.
by Francisco Casas Nov. 15, 2021
by Francisco Casas Nov. 15, 2021
Nov. 15, 2021
Some register types do not use a consistent swizzle type, so the
sm4_swizzle_type() function is removed.
The swizzle type now must be specified using the swizzle_type field.
Signed-off-by: Francisco Casas <fcasas(a)codeweavers.com>
---
libs/vkd3d-shader/hlsl_sm4.c | 69 ++++++++++++++++--------------------
1 file changed, 31 insertions(+), 38 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl_sm4.c b/libs/vkd3d-shader/hlsl_sm4.c
index e597425a..2ec8d7d9 100644
--- a/libs/vkd3d-shader/hlsl_sm4.c
+++ b/libs/vkd3d-shader/hlsl_sm4.c
@@ -748,6 +748,7 @@ struct sm4_instruction
struct
{
struct sm4_register reg;
+ enum vkd3d_sm4_swizzle_type swizzle_type;
unsigned int swizzle;
} srcs[2];
unsigned int src_count;
@@ -756,27 +757,9 @@ struct sm4_instruction
unsigned int idx_count;
};
-static unsigned int sm4_swizzle_type(enum vkd3d_sm4_register_type type)
-{
- switch (type)
- {
- case VKD3D_SM4_RT_IMMCONST:
- return VKD3D_SM4_SWIZZLE_NONE;
-
- case VKD3D_SM4_RT_CONSTBUFFER:
- case VKD3D_SM4_RT_INPUT:
- case VKD3D_SM4_RT_RESOURCE:
- case VKD3D_SM4_RT_TEMP:
- return VKD3D_SM4_SWIZZLE_VEC4;
-
- default:
- FIXME("Unhandled register type %#x.\n", type);
- return VKD3D_SM4_SWIZZLE_VEC4;
- }
-}
-
static void sm4_register_from_deref(struct hlsl_ctx *ctx, struct sm4_register *reg,
- unsigned int *writemask, const struct hlsl_deref *deref, const struct hlsl_type *data_type)
+ unsigned int *writemask, enum vkd3d_sm4_swizzle_type *swizzle_type,
+ const struct hlsl_deref *deref, const struct hlsl_type *data_type)
{
const struct hlsl_ir_var *var = deref->var;
@@ -797,6 +780,7 @@ static void sm4_register_from_deref(struct hlsl_ctx *ctx, struct sm4_register *r
assert(data_type->type <= HLSL_CLASS_VECTOR);
reg->type = VKD3D_SM4_RT_CONSTBUFFER;
reg->dim = VKD3D_SM4_DIMENSION_VEC4;
+ if(swizzle_type) *swizzle_type = VKD3D_SM4_SWIZZLE_VEC4;
reg->idx[0] = var->buffer->reg.id;
reg->idx[1] = offset / 4;
reg->idx_count = 2;
@@ -825,6 +809,7 @@ static void sm4_register_from_deref(struct hlsl_ctx *ctx, struct sm4_register *r
assert(hlsl_reg.allocated);
reg->type = VKD3D_SM4_RT_INPUT;
reg->dim = VKD3D_SM4_DIMENSION_VEC4;
+ if(swizzle_type) *swizzle_type = VKD3D_SM4_SWIZZLE_VEC4;
reg->idx[0] = hlsl_reg.id;
reg->idx_count = 1;
*writemask = hlsl_reg.writemask;
@@ -867,17 +852,20 @@ static void sm4_register_from_deref(struct hlsl_ctx *ctx, struct sm4_register *r
assert(hlsl_reg.allocated);
reg->type = VKD3D_SM4_RT_TEMP;
reg->dim = VKD3D_SM4_DIMENSION_VEC4;
+ if(swizzle_type) *swizzle_type = VKD3D_SM4_SWIZZLE_VEC4;
reg->idx[0] = hlsl_reg.id;
reg->idx_count = 1;
*writemask = hlsl_reg.writemask;
}
}
-static void sm4_register_from_node(struct sm4_register *reg, unsigned int *writemask, const struct hlsl_ir_node *instr)
+static void sm4_register_from_node(struct sm4_register *reg, unsigned int *writemask,
+ enum vkd3d_sm4_swizzle_type *swizzle_type, const struct hlsl_ir_node *instr)
{
assert(instr->reg.allocated);
reg->type = VKD3D_SM4_RT_TEMP;
reg->dim = VKD3D_SM4_DIMENSION_VEC4;
+ if(swizzle_type) *swizzle_type = VKD3D_SM4_SWIZZLE_VEC4;
reg->idx[0] = instr->reg.id;
reg->idx_count = 1;
*writemask = instr->reg.writemask;
@@ -929,7 +917,7 @@ static void write_sm4_instruction(struct vkd3d_bytecode_buffer *buffer, const st
for (i = 0; i < instr->src_count; ++i)
{
token = sm4_encode_register(&instr->srcs[i].reg);
- token |= sm4_swizzle_type(instr->srcs[i].reg.type) << VKD3D_SM4_SWIZZLE_TYPE_SHIFT;
+ token |= (uint32_t)instr->srcs[i].swizzle_type << VKD3D_SM4_SWIZZLE_TYPE_SHIFT;
token |= instr->srcs[i].swizzle << VKD3D_SM4_SWIZZLE_SHIFT;
if (instr->srcs[i].reg.mod)
token |= VKD3D_SM4_EXTENDED_OPERAND;
@@ -968,6 +956,7 @@ static void write_sm4_dcl_constant_buffer(struct vkd3d_bytecode_buffer *buffer,
.srcs[0].reg.type = VKD3D_SM4_RT_CONSTBUFFER,
.srcs[0].reg.idx = {cbuffer->reg.id, (cbuffer->used_size + 3) / 4},
.srcs[0].reg.idx_count = 2,
+ .srcs[0].swizzle_type = VKD3D_SM4_SWIZZLE_VEC4,
.srcs[0].swizzle = HLSL_SWIZZLE(X, Y, Z, W),
.src_count = 1,
};
@@ -1129,10 +1118,10 @@ static void write_sm4_unary_op(struct vkd3d_bytecode_buffer *buffer, enum vkd3d_
memset(&instr, 0, sizeof(instr));
instr.opcode = opcode;
- sm4_register_from_node(&instr.dsts[0].reg, &instr.dsts[0].writemask, dst);
+ sm4_register_from_node(&instr.dsts[0].reg, &instr.dsts[0].writemask, NULL, dst);
instr.dst_count = 1;
- sm4_register_from_node(&instr.srcs[0].reg, &writemask, src);
+ sm4_register_from_node(&instr.srcs[0].reg, &writemask, &instr.srcs[0].swizzle_type, src);
instr.srcs[0].swizzle = hlsl_map_swizzle(hlsl_swizzle_from_writemask(writemask), instr.dsts[0].writemask);
instr.srcs[0].reg.mod = src_mod;
instr.src_count = 1;
@@ -1149,12 +1138,12 @@ static void write_sm4_binary_op(struct vkd3d_bytecode_buffer *buffer, enum vkd3d
memset(&instr, 0, sizeof(instr));
instr.opcode = opcode;
- sm4_register_from_node(&instr.dsts[0].reg, &instr.dsts[0].writemask, dst);
+ sm4_register_from_node(&instr.dsts[0].reg, &instr.dsts[0].writemask, NULL, dst);
instr.dst_count = 1;
- sm4_register_from_node(&instr.srcs[0].reg, &writemask, src1);
+ sm4_register_from_node(&instr.srcs[0].reg, &writemask, &instr.srcs[0].swizzle_type, src1);
instr.srcs[0].swizzle = hlsl_map_swizzle(hlsl_swizzle_from_writemask(writemask), instr.dsts[0].writemask);
- sm4_register_from_node(&instr.srcs[1].reg, &writemask, src2);
+ sm4_register_from_node(&instr.srcs[1].reg, &writemask, &instr.srcs[1].swizzle_type, src2);
instr.srcs[1].swizzle = hlsl_map_swizzle(hlsl_swizzle_from_writemask(writemask), instr.dsts[0].writemask);
instr.src_count = 2;
@@ -1171,11 +1160,13 @@ static void write_sm4_constant(struct hlsl_ctx *ctx,
memset(&instr, 0, sizeof(instr));
instr.opcode = VKD3D_SM4_OP_MOV;
- sm4_register_from_node(&instr.dsts[0].reg, &instr.dsts[0].writemask, &constant->node);
+ sm4_register_from_node(&instr.dsts[0].reg, &instr.dsts[0].writemask, NULL, &constant->node);
instr.dst_count = 1;
instr.srcs[0].reg.dim = (dimx > 1) ? VKD3D_SM4_DIMENSION_VEC4 : VKD3D_SM4_DIMENSION_SCALAR;
instr.srcs[0].reg.type = VKD3D_SM4_RT_IMMCONST;
+ instr.srcs[0].swizzle_type = VKD3D_SM4_SWIZZLE_NONE;
+
for (i = 0; i < dimx; ++i)
instr.srcs[0].reg.immconst_uint[i] = constant->value[i].u;
instr.src_count = 1,
@@ -1193,10 +1184,10 @@ static void write_sm4_ld(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buf
memset(&instr, 0, sizeof(instr));
instr.opcode = VKD3D_SM4_OP_LD;
- sm4_register_from_node(&instr.dsts[0].reg, &instr.dsts[0].writemask, dst);
+ sm4_register_from_node(&instr.dsts[0].reg, &instr.dsts[0].writemask, NULL, dst);
instr.dst_count = 1;
- sm4_register_from_node(&instr.srcs[0].reg, &writemask, coords);
+ sm4_register_from_node(&instr.srcs[0].reg, &writemask, &instr.srcs[0].swizzle_type, coords);
instr.srcs[0].swizzle = hlsl_swizzle_from_writemask(writemask);
/* Mipmap level is in the last component in the IR, but needs to be in the W
@@ -1219,7 +1210,8 @@ static void write_sm4_ld(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buf
assert(0);
}
- sm4_register_from_deref(ctx, &instr.srcs[1].reg, &writemask, resource, resource_type);
+ sm4_register_from_deref(ctx, &instr.srcs[1].reg, &writemask, &instr.srcs[1].swizzle_type,
+ resource, resource_type);
instr.srcs[1].swizzle = hlsl_map_swizzle(hlsl_swizzle_from_writemask(writemask), instr.dsts[0].writemask);
instr.src_count = 2;
@@ -1440,7 +1432,7 @@ static void write_sm4_if(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buf
assert(iff->condition.node->data_type->dimx == 1);
- sm4_register_from_node(&instr.srcs[0].reg, &writemask, iff->condition.node);
+ sm4_register_from_node(&instr.srcs[0].reg, &writemask, &instr.srcs[0].swizzle_type, iff->condition.node);
instr.srcs[0].swizzle = hlsl_swizzle_from_writemask(writemask);
write_sm4_instruction(buffer, &instr);
@@ -1465,10 +1457,11 @@ static void write_sm4_load(struct hlsl_ctx *ctx,
memset(&instr, 0, sizeof(instr));
instr.opcode = VKD3D_SM4_OP_MOV;
- sm4_register_from_node(&instr.dsts[0].reg, &instr.dsts[0].writemask, &load->node);
+ sm4_register_from_node(&instr.dsts[0].reg, &instr.dsts[0].writemask, NULL, &load->node);
instr.dst_count = 1;
- sm4_register_from_deref(ctx, &instr.srcs[0].reg, &writemask, &load->src, load->node.data_type);
+ sm4_register_from_deref(ctx, &instr.srcs[0].reg, &writemask, &instr.srcs[0].swizzle_type,
+ &load->src, load->node.data_type);
instr.srcs[0].swizzle = hlsl_map_swizzle(hlsl_swizzle_from_writemask(writemask), instr.dsts[0].writemask);
instr.src_count = 1;
@@ -1531,11 +1524,11 @@ static void write_sm4_store(struct hlsl_ctx *ctx,
memset(&instr, 0, sizeof(instr));
instr.opcode = VKD3D_SM4_OP_MOV;
- sm4_register_from_deref(ctx, &instr.dsts[0].reg, &writemask, &store->lhs, rhs->data_type);
+ sm4_register_from_deref(ctx, &instr.dsts[0].reg, &writemask, NULL, &store->lhs, rhs->data_type);
instr.dsts[0].writemask = hlsl_combine_writemasks(writemask, store->writemask);
instr.dst_count = 1;
- sm4_register_from_node(&instr.srcs[0].reg, &writemask, rhs);
+ sm4_register_from_node(&instr.srcs[0].reg, &writemask, &instr.srcs[0].swizzle_type, rhs);
instr.srcs[0].swizzle = hlsl_map_swizzle(hlsl_swizzle_from_writemask(writemask), instr.dsts[0].writemask);
instr.src_count = 1;
@@ -1551,10 +1544,10 @@ static void write_sm4_swizzle(struct hlsl_ctx *ctx,
memset(&instr, 0, sizeof(instr));
instr.opcode = VKD3D_SM4_OP_MOV;
- sm4_register_from_node(&instr.dsts[0].reg, &instr.dsts[0].writemask, &swizzle->node);
+ sm4_register_from_node(&instr.dsts[0].reg, &instr.dsts[0].writemask, NULL, &swizzle->node);
instr.dst_count = 1;
- sm4_register_from_node(&instr.srcs[0].reg, &writemask, swizzle->val.node);
+ sm4_register_from_node(&instr.srcs[0].reg, &writemask, &instr.srcs[0].swizzle_type, swizzle->val.node);
instr.srcs[0].swizzle = hlsl_map_swizzle(hlsl_combine_swizzles(hlsl_swizzle_from_writemask(writemask),
swizzle->swizzle, swizzle->node.data_type->dimx), instr.dsts[0].writemask);
instr.src_count = 1;
--
2.25.1
2
1
Nov. 15, 2021
fixes BZ #42030
Signed-off-by: Eric Pouech <eric.pouech(a)gmail.com>
---
programs/winedbg/winedbg.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/programs/winedbg/winedbg.c b/programs/winedbg/winedbg.c
index 4cd2979dce3..45a7edfb309 100644
--- a/programs/winedbg/winedbg.c
+++ b/programs/winedbg/winedbg.c
@@ -675,7 +675,7 @@ int main(int argc, char** argv)
/* parse options */
while (argc > 0 && argv[0][0] == '-')
{
- if (!strcmp(argv[0], "--command"))
+ if (!strcmp(argv[0], "--command") && argc > 1)
{
argc--; argv++;
hFile = parser_generate_command_file(argv[0], NULL);
@@ -687,7 +687,7 @@ int main(int argc, char** argv)
argc--; argv++;
continue;
}
- if (!strcmp(argv[0], "--file"))
+ if (!strcmp(argv[0], "--file") && argc > 1)
{
argc--; argv++;
hFile = CreateFileA(argv[0], GENERIC_READ|DELETE, 0,
1
8
Nov. 15, 2021
In PE builds of wine, there's no unwind info (as LLVM hasn't
implemented generating SEH unwind info for ARM yet).
On startup of wine, an exception of the type RPC_S_SERVER_UNAVAILABLE
is raised. In a PE build of Wine, the unwind would get stuck in
an infinite loop.
This still loops for a short while; after returning the error
STATUS_INVALID_DISPOSITION, KiUserExceptionDispatcher ends up
calling RtlRaiseStatus with this status, which then tries to
unwind again, getting stuck similarly. However by recursively
trying to unwind multiple times, the process crashes fairly soon
after running out of stack.
Signed-off-by: Martin Storsjö <martin(a)martin.st>
---
Alternatively, should this case use a different error code, and
abort the process directly in KiUserExceptionDispatcher when we
know RtlRaiseStatus will get stuck in the same way?
---
dlls/ntdll/unix/signal_arm.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/dlls/ntdll/unix/signal_arm.c b/dlls/ntdll/unix/signal_arm.c
index fc37f917219..2017cf150db 100644
--- a/dlls/ntdll/unix/signal_arm.c
+++ b/dlls/ntdll/unix/signal_arm.c
@@ -255,13 +255,16 @@ NTSTATUS CDECL unwind_builtin_dll( ULONG type, struct _DISPATCHER_CONTEXT *dispa
}
if (rc == -UNW_ENOINFO || ip < info.start_ip || ip > info.end_ip)
{
- TRACE( "no info found for %x ip %x-%x, assuming leaf function\n",
- ip, info.start_ip, info.end_ip );
+ NTSTATUS status = context->Pc != context->Lr ?
+ STATUS_SUCCESS : STATUS_INVALID_DISPOSITION;
+ TRACE( "no info found for %x ip %x-%x, %s\n",
+ ip, info.start_ip, info.end_ip, status == STATUS_SUCCESS ?
+ "assuming leaf function" : "error, stuck" );
dispatch->LanguageHandler = NULL;
dispatch->EstablisherFrame = context->Sp;
context->Pc = context->Lr;
context->ContextFlags |= CONTEXT_UNWOUND_TO_CALL;
- return STATUS_SUCCESS;
+ return status;
}
TRACE( "ip %#x function %#lx-%#lx personality %#lx lsda %#lx fde %#lx\n",
--
2.25.1
1
1
[PATCH 1/5] wined3d: Acquire references to blend states in deferred contexts.
by Jan Sikorski Nov. 15, 2021
by Jan Sikorski Nov. 15, 2021
Nov. 15, 2021
Signed-off-by: Jan Sikorski <jsikorski(a)codeweavers.com>
---
dlls/wined3d/cs.c | 48 ++++++++++++++++++++++++++++++++++
dlls/wined3d/wined3d_private.h | 1 +
2 files changed, 49 insertions(+)
diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c
index f161b63be3c..063e8bd0a04 100644
--- a/dlls/wined3d/cs.c
+++ b/dlls/wined3d/cs.c
@@ -64,6 +64,9 @@ struct wined3d_command_list
SIZE_T query_count;
struct wined3d_deferred_query_issue *queries;
+
+ SIZE_T blend_state_count;
+ struct wined3d_blend_state **blend_states;
};
static void wined3d_command_list_destroy_object(void *object)
@@ -107,6 +110,8 @@ ULONG CDECL wined3d_command_list_decref(struct wined3d_command_list *list)
wined3d_resource_decref(list->uploads[i].resource);
for (i = 0; i < list->query_count; ++i)
wined3d_query_decref(list->queries[i].query);
+ for (i = 0; i < list->blend_state_count; ++i)
+ wined3d_blend_state_decref(list->blend_states[i]);
wined3d_mutex_lock();
wined3d_cs_destroy_object(device->cs, wined3d_command_list_destroy_object, list);
@@ -589,6 +594,12 @@ static inline void wined3d_device_context_acquire_resource(struct wined3d_device
context->ops->acquire_resource(context, resource);
}
+static inline void wined3d_device_context_acquire_blend_state(struct wined3d_device_context *context,
+ struct wined3d_blend_state *blend_state)
+{
+ context->ops->acquire_blend_state(context, blend_state);
+}
+
static struct wined3d_cs *wined3d_cs_from_context(struct wined3d_device_context *context)
{
return CONTAINING_RECORD(context, struct wined3d_cs, c);
@@ -1831,6 +1842,8 @@ void wined3d_device_context_emit_set_blend_state(struct wined3d_device_context *
op->factor = *blend_factor;
op->sample_mask = sample_mask;
+ if (state)
+ wined3d_device_context_acquire_blend_state(context, state);
wined3d_device_context_submit(context, WINED3D_CS_QUEUE_DEFAULT);
}
@@ -2957,6 +2970,11 @@ static void wined3d_cs_acquire_resource(struct wined3d_device_context *context,
wined3d_resource_acquire(resource);
}
+static void wined3d_cs_acquire_blend_state(struct wined3d_device_context *context,
+ struct wined3d_blend_state *blend_state)
+{
+}
+
static void wined3d_cs_exec_execute_command_list(struct wined3d_cs *cs, const void *data);
static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) =
@@ -3196,6 +3214,7 @@ static const struct wined3d_device_context_ops wined3d_cs_st_ops =
wined3d_cs_flush,
wined3d_cs_acquire_resource,
wined3d_cs_acquire_command_list,
+ wined3d_cs_acquire_blend_state,
};
static BOOL wined3d_cs_queue_is_empty(const struct wined3d_cs *cs, const struct wined3d_cs_queue *queue)
@@ -3323,6 +3342,7 @@ static const struct wined3d_device_context_ops wined3d_cs_mt_ops =
wined3d_cs_flush,
wined3d_cs_acquire_resource,
wined3d_cs_acquire_command_list,
+ wined3d_cs_acquire_blend_state,
};
static void poll_queries(struct wined3d_cs *cs)
@@ -3549,6 +3569,9 @@ struct wined3d_deferred_context
SIZE_T query_count, queries_capacity;
struct wined3d_deferred_query_issue *queries;
+
+ SIZE_T blend_state_count, blend_states_capacity;
+ struct wined3d_blend_state **blend_states;
};
static struct wined3d_deferred_context *wined3d_deferred_context_from_context(struct wined3d_device_context *context)
@@ -3747,6 +3770,18 @@ static void wined3d_deferred_context_acquire_command_list(struct wined3d_device_
wined3d_command_list_incref(deferred->command_lists[deferred->command_list_count++] = list);
}
+static void wined3d_deferred_context_acquire_blend_state(struct wined3d_device_context *context,
+ struct wined3d_blend_state *blend_state)
+{
+ struct wined3d_deferred_context *deferred = wined3d_deferred_context_from_context(context);
+ if (!wined3d_array_reserve((void **)&deferred->blend_states, &deferred->blend_states_capacity,
+ deferred->blend_state_count + 1, sizeof(*deferred->blend_states)))
+ return;
+
+ deferred->blend_states[deferred->blend_state_count++] = blend_state;
+ wined3d_blend_state_incref(blend_state);
+}
+
static const struct wined3d_device_context_ops wined3d_deferred_context_ops =
{
wined3d_deferred_context_require_space,
@@ -3759,6 +3794,7 @@ static const struct wined3d_device_context_ops wined3d_deferred_context_ops =
wined3d_deferred_context_flush,
wined3d_deferred_context_acquire_resource,
wined3d_deferred_context_acquire_command_list,
+ wined3d_deferred_context_acquire_blend_state,
};
HRESULT CDECL wined3d_deferred_context_create(struct wined3d_device *device, struct wined3d_device_context **context)
@@ -3816,6 +3852,10 @@ void CDECL wined3d_deferred_context_destroy(struct wined3d_device_context *conte
wined3d_query_decref(deferred->queries[i].query);
heap_free(deferred->queries);
+ for (i = 0; i < deferred->blend_state_count; ++i)
+ wined3d_blend_state_decref(deferred->blend_states[i]);
+ heap_free(deferred->blend_states);
+
wined3d_state_destroy(deferred->c.state);
heap_free(deferred->data);
heap_free(deferred);
@@ -3835,6 +3875,7 @@ HRESULT CDECL wined3d_deferred_context_record_command_list(struct wined3d_device
+ deferred->upload_count * sizeof(*object->uploads)
+ deferred->command_list_count * sizeof(*object->command_lists)
+ deferred->query_count * sizeof(*object->queries)
+ + deferred->blend_state_count * sizeof(*object->blend_states)
+ deferred->data_size);
if (!memory)
@@ -3874,6 +3915,12 @@ HRESULT CDECL wined3d_deferred_context_record_command_list(struct wined3d_device
memcpy(object->queries, deferred->queries, deferred->query_count * sizeof(*object->queries));
/* Transfer our references to the queries to the command list. */
+ object->blend_states = memory;
+ memory = &object->blend_states[deferred->blend_state_count];
+ object->blend_state_count = deferred->blend_state_count;
+ memcpy(object->blend_states, deferred->blend_states, deferred->blend_state_count * sizeof(*object->blend_states));
+ /* Transfer our references to the blend states to the command list. */
+
object->data = memory;
object->data_size = deferred->data_size;
memcpy(object->data, deferred->data, deferred->data_size);
@@ -3883,6 +3930,7 @@ HRESULT CDECL wined3d_deferred_context_record_command_list(struct wined3d_device
deferred->upload_count = 0;
deferred->command_list_count = 0;
deferred->query_count = 0;
+ deferred->blend_state_count = 0;
/* This is in fact recorded into a subsequent command list. */
if (restore)
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 0c5f7dda228..3a4df301dcb 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -4847,6 +4847,7 @@ struct wined3d_device_context_ops
void (*flush)(struct wined3d_device_context *context);
void (*acquire_resource)(struct wined3d_device_context *context, struct wined3d_resource *resource);
void (*acquire_command_list)(struct wined3d_device_context *context, struct wined3d_command_list *list);
+ void (*acquire_blend_state)(struct wined3d_device_context *context, struct wined3d_blend_state *blend_state);
};
struct wined3d_device_context
--
2.32.0
2
9
Nov. 15, 2021
Signed-off-by: Stefan Dösinger <stefan(a)codeweavers.com>
---
Supersedes 219242.
Version 3: It is color keying, not culling that is randomly applied by old
WARP versions.
---
dlls/ddraw/tests/ddraw1.c | 440 +++++++++++++++++++++++++++++++++++
dlls/ddraw/tests/ddraw2.c | 462 +++++++++++++++++++++++++++++++++++++
dlls/ddraw/tests/ddraw4.c | 467 ++++++++++++++++++++++++++++++++++++++
dlls/ddraw/tests/ddraw7.c | 444 ++++++++++++++++++++++++++++++++++++
4 files changed, 1813 insertions(+)
diff --git a/dlls/ddraw/tests/ddraw1.c b/dlls/ddraw/tests/ddraw1.c
index 0e0a198add2..f9c3634c03e 100644
--- a/dlls/ddraw/tests/ddraw1.c
+++ b/dlls/ddraw/tests/ddraw1.c
@@ -14448,6 +14448,445 @@ static void test_texture_wrong_caps(const GUID *device_guid)
DestroyWindow(window);
}
+static void test_filling_convention(void)
+{
+ static const DWORD colour_bottom = 0x00ffff00;
+ static const DWORD colour_clear = 0x000000ff;
+ static const DWORD colour_right = 0x00000000;
+ static const DWORD colour_left = 0x00ff0000;
+ static const DWORD colour_top = 0x0000ff00;
+ IDirect3DExecuteBuffer *execute_buffer;
+ D3DEXECUTEBUFFERDESC exec_desc;
+ IDirectDrawSurface *backbuffer;
+ IDirect3DMaterial *background;
+ IDirect3DViewport *viewport;
+ unsigned int inst_length;
+ IDirect3DDevice *device;
+ DWORD colour, expected;
+ unsigned int i, x, y;
+ IDirectDraw *ddraw;
+ ULONG refcount;
+ HWND window;
+ HRESULT hr;
+ BOOL todo;
+ void *ptr;
+
+ static const unsigned int vp_size = 8;
+ D3DRECT clear_rect = {{0}, {0}, {vp_size}, {vp_size}};
+
+ /* This test data follows the examples in MSDN's
+ * "Rasterization Rules (Direct3D 9)" article. */
+ static const float eps = 1.0f / 512.0f;
+ D3DLVERTEX center_tris[] =
+ {
+ /* left */
+ {{-2.5f / 4.0f}, {-1.5f / 4.0f}, {0.0f}, 0, {colour_left}},
+ {{-2.5f / 4.0f}, { 2.5f / 4.0f}, {0.0f}, 0, {colour_left}},
+ {{-1.5f / 4.0f}, { 0.5f / 4.0f}, {0.0f}, 0, {colour_left}},
+
+ /* top */
+ {{-1.5f / 4.0f}, { 0.5f / 4.0f}, {0.0f}, 0, {colour_top}},
+ {{-2.5f / 4.0f}, { 2.5f / 4.0f}, {0.0f}, 0, {colour_top}},
+ {{-0.5f / 4.0f}, { 2.5f / 4.0f}, {0.0f}, 0, {colour_top}},
+
+ /* right */
+ {{-0.5f / 4.0f}, {-1.5f / 4.0f}, {0.0f}, 0, {colour_right}},
+ {{-1.5f / 4.0f}, { 0.5f / 4.0f}, {0.0f}, 0, {colour_right}},
+ {{-0.5f / 4.0f}, { 2.5f / 4.0f}, {0.0f}, 0, {colour_right}},
+
+ /* bottom */
+ {{-2.5f / 4.0f}, {-1.5f / 4.0f}, {0.0f}, 0, {colour_bottom}},
+ {{-1.5f / 4.0f}, { 0.5f / 4.0f}, {0.0f}, 0, {colour_bottom}},
+ {{-0.5f / 4.0f}, {-1.5f / 4.0f}, {0.0f}, 0, {colour_bottom}},
+ },
+ edge_tris[] =
+ {
+ /* left */
+ {{-2.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_left}},
+ {{-2.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_left}},
+ {{-1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_left}},
+
+ /* top */
+ {{-1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_top}},
+ {{-2.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_top}},
+ {{ 0.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_top}},
+
+ /* right */
+ {{ 0.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_right}},
+ {{-1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_right}},
+ {{ 0.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_right}},
+
+ /* bottom */
+ {{-2.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
+ {{-1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
+ {{ 0.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
+ },
+ nudge_right_tris[] =
+ {
+ /* left */
+ {{eps - 2.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_left}},
+ {{eps - 2.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_left}},
+ {{eps - 1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_left}},
+
+ /* top */
+ {{eps - 1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_top}},
+ {{eps - 2.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_top}},
+ {{eps - 0.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_top}},
+
+ /* right */
+ {{eps - 0.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_right}},
+ {{eps - 1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_right}},
+ {{eps - 0.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_right}},
+
+ /* bottom */
+ {{eps - 2.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
+ {{eps - 1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
+ {{eps - 0.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
+ },
+ nudge_left_tris[] =
+ {
+ {{-eps - 2.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_left}},
+ {{-eps - 2.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_left}},
+ {{-eps - 1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_left}},
+
+ /* top */
+ {{-eps - 1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_top}},
+ {{-eps - 2.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_top}},
+ {{-eps - 0.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_top}},
+
+ /* right */
+ {{-eps - 0.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_right}},
+ {{-eps - 1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_right}},
+ {{-eps - 0.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_right}},
+
+ /* bottom */
+ {{-eps - 2.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
+ {{-eps - 1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
+ {{-eps - 0.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
+ },
+ nudge_top_tris[] =
+ {
+ /* left */
+ {{-2.0f / 4.0f}, {eps - 1.0f / 4.0f}, {0.0f}, 0, {colour_left}},
+ {{-2.0f / 4.0f}, {eps + 3.0f / 4.0f}, {0.0f}, 0, {colour_left}},
+ {{-1.0f / 4.0f}, {eps + 1.0f / 4.0f}, {0.0f}, 0, {colour_left}},
+
+ /* top */
+ {{-1.0f / 4.0f}, {eps + 1.0f / 4.0f}, {0.0f}, 0, {colour_top}},
+ {{-2.0f / 4.0f}, {eps + 3.0f / 4.0f}, {0.0f}, 0, {colour_top}},
+ {{ 0.0f / 4.0f}, {eps + 3.0f / 4.0f}, {0.0f}, 0, {colour_top}},
+
+ /* right */
+ {{ 0.0f / 4.0f}, {eps - 1.0f / 4.0f}, {0.0f}, 0, {colour_right}},
+ {{-1.0f / 4.0f}, {eps + 1.0f / 4.0f}, {0.0f}, 0, {colour_right}},
+ {{ 0.0f / 4.0f}, {eps + 3.0f / 4.0f}, {0.0f}, 0, {colour_right}},
+
+ /* bottom */
+ {{-2.0f / 4.0f}, {eps - 1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
+ {{-1.0f / 4.0f}, {eps + 1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
+ {{ 0.0f / 4.0f}, {eps - 1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
+ },
+ nudge_bottom_tris[] =
+ {
+ /* left */
+ {{-2.0f / 4.0f}, {-eps - 1.0f / 4.0f}, {0.0f}, 0, {colour_left}},
+ {{-2.0f / 4.0f}, {-eps + 3.0f / 4.0f}, {0.0f}, 0, {colour_left}},
+ {{-1.0f / 4.0f}, {-eps + 1.0f / 4.0f}, {0.0f}, 0, {colour_left}},
+
+ /* top */
+ {{-1.0f / 4.0f}, {-eps + 1.0f / 4.0f}, {0.0f}, 0, {colour_top}},
+ {{-2.0f / 4.0f}, {-eps + 3.0f / 4.0f}, {0.0f}, 0, {colour_top}},
+ {{ 0.0f / 4.0f}, {-eps + 3.0f / 4.0f}, {0.0f}, 0, {colour_top}},
+
+ /* right */
+ {{ 0.0f / 4.0f}, {-eps - 1.0f / 4.0f}, {0.0f}, 0, {colour_right}},
+ {{-1.0f / 4.0f}, {-eps + 1.0f / 4.0f}, {0.0f}, 0, {colour_right}},
+ {{ 0.0f / 4.0f}, {-eps + 3.0f / 4.0f}, {0.0f}, 0, {colour_right}},
+
+ /* bottom */
+ {{-2.0f / 4.0f}, {-eps - 1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
+ {{-1.0f / 4.0f}, {-eps + 1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
+ {{ 0.0f / 4.0f}, {-eps - 1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
+ };
+
+ D3DTLVERTEX center_tris_t[] =
+ {
+ /* left */
+ {{1.5f}, {1.5f}, {0.0f}, {1.0f}, {colour_left}},
+ {{2.5f}, {3.5f}, {0.0f}, {1.0f}, {colour_left}},
+ {{1.5f}, {5.5f}, {0.0f}, {1.0f}, {colour_left}},
+
+ /* top */
+ {{1.5f}, {1.5f}, {0.0f}, {1.0f}, {colour_top}},
+ {{3.5f}, {1.5f}, {0.0f}, {1.0f}, {colour_top}},
+ {{2.5f}, {3.5f}, {0.0f}, {1.0f}, {colour_top}},
+
+ /* right */
+ {{3.5f}, {1.5f}, {0.0f}, {1.0f}, {colour_right}},
+ {{3.5f}, {5.5f}, {0.0f}, {1.0f}, {colour_right}},
+ {{2.5f}, {3.5f}, {0.0f}, {1.0f}, {colour_right}},
+
+ /* bottom */
+ {{2.5f}, {3.5f}, {0.0f}, {1.0f}, {colour_bottom}},
+ {{3.5f}, {5.5f}, {0.0f}, {1.0f}, {colour_bottom}},
+ {{1.5f}, {5.5f}, {0.0f}, {1.0f}, {colour_bottom}},
+ },
+ edge_tris_t[] =
+ {
+ /* left */
+ {{2.0f}, {1.0f}, {0.0f}, {1.0f}, {colour_left}},
+ {{3.0f}, {3.0f}, {0.0f}, {1.0f}, {colour_left}},
+ {{2.0f}, {5.0f}, {0.0f}, {1.0f}, {colour_left}},
+
+ /* top */
+ {{2.0f}, {1.0f}, {0.0f}, {1.0f}, {colour_top}},
+ {{4.0f}, {1.0f}, {0.0f}, {1.0f}, {colour_top}},
+ {{3.0f}, {3.0f}, {0.0f}, {1.0f}, {colour_top}},
+
+ /* right */
+ {{4.0f}, {1.0f}, {0.0f}, {1.0f}, {colour_right}},
+ {{4.0f}, {5.0f}, {0.0f}, {1.0f}, {colour_right}},
+ {{3.0f}, {3.0f}, {0.0f}, {1.0f}, {colour_right}},
+
+ /* bottom */
+ {{3.0f}, {3.0f}, {0.0f}, {1.0f}, {colour_bottom}},
+ {{4.0f}, {5.0f}, {0.0f}, {1.0f}, {colour_bottom}},
+ {{2.0f}, {5.0f}, {0.0f}, {1.0f}, {colour_bottom}},
+ };
+
+ const struct
+ {
+ void *geometry;
+ DWORD op;
+ const char *expected[8];
+ }
+ tests[] =
+ {
+ {
+ center_tris,
+ D3DPROCESSVERTICES_TRANSFORM,
+ {
+ " ",
+ " ",
+ " TT ",
+ " LR ",
+ " LR ",
+ " BB ",
+ " ",
+ " "
+ }
+ },
+ {
+ edge_tris,
+ D3DPROCESSVERTICES_TRANSFORM,
+ {
+ " ",
+ " TT ",
+ " LT ",
+ " LR ",
+ " LB ",
+ " ",
+ " ",
+ " "
+ }
+ },
+ {
+ nudge_right_tris,
+ D3DPROCESSVERTICES_TRANSFORM,
+ {
+ " ",
+ " TT ",
+ " TR ",
+ " LR ",
+ " BR ",
+ " ",
+ " ",
+ " "
+ }
+ },
+ {
+ nudge_left_tris,
+ D3DPROCESSVERTICES_TRANSFORM,
+ {
+ " ",
+ " TT ",
+ " LT ",
+ " LR ",
+ " LB ",
+ " ",
+ " ",
+ " "
+ }
+ },
+ {
+ nudge_top_tris,
+ D3DPROCESSVERTICES_TRANSFORM,
+ {
+ " ",
+ " LT ",
+ " LT ",
+ " LB ",
+ " LB ",
+ " ",
+ " ",
+ " "
+ }
+ },
+ {
+ nudge_bottom_tris,
+ D3DPROCESSVERTICES_TRANSFORM,
+ {
+ " ",
+ " ",
+ " LT ",
+ " Lt ",
+ " LB ",
+ " lB ",
+ " ",
+ " "
+ }
+ },
+ {
+ center_tris_t,
+ D3DPROCESSVERTICES_COPY,
+ {
+ " ",
+ " ",
+ " TT ",
+ " LR ",
+ " LR ",
+ " BB ",
+ " ",
+ " "
+ }
+ },
+ {
+ edge_tris_t,
+ D3DPROCESSVERTICES_COPY,
+ {
+ " ",
+ " TT ",
+ " LT ",
+ " LR ",
+ " LB ",
+ " ",
+ " ",
+ " "
+ }
+ },
+ };
+ static WORD indices[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
+
+ window = create_window();
+ ddraw = create_ddraw();
+ ok(!!ddraw, "Failed to create a ddraw object.\n");
+ if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
+ {
+ skip("Failed to create a 3D device.\n");
+ IDirectDraw_Release(ddraw);
+ DestroyWindow(window);
+ return;
+ }
+
+ hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&backbuffer);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+ viewport = create_viewport(device, 0, 0, vp_size, vp_size);
+ background = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
+ viewport_set_background(device, viewport, background);
+
+ memset(&exec_desc, 0, sizeof(exec_desc));
+ exec_desc.dwSize = sizeof(exec_desc);
+ exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
+ exec_desc.dwBufferSize = 1024;
+ exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
+
+ hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
+ ok(hr == D3D_OK, "Failed to create execute buffer, hr %#x.\n", hr);
+
+ for (i = 0; i < ARRAY_SIZE(tests); ++i)
+ {
+ hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+ hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
+ ok(hr == D3D_OK, "Failed to lock execute buffer, hr %#x.\n", hr);
+
+ /* All test geometry has the same vertex count and vertex size. */
+ memcpy(exec_desc.lpData, tests[i].geometry, sizeof(center_tris));
+ ptr = ((BYTE *)exec_desc.lpData) + sizeof(center_tris);
+ emit_set_rs(&ptr, D3DRENDERSTATE_ZENABLE, FALSE);
+ /* Old WARP versions (w8, early win10) apply color keying without textures. */
+ emit_set_rs(&ptr, D3DRENDERSTATE_COLORKEYENABLE, FALSE);
+
+ emit_process_vertices(&ptr, tests[i].op, 0, 12);
+ emit_tri_indices(&ptr, indices, 4);
+ emit_end(&ptr);
+ inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
+ inst_length -= sizeof(center_tris);
+
+ hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
+ ok(hr == D3D_OK, "Failed to lock execute buffer, hr %#x.\n", hr);
+
+ set_execute_data(execute_buffer, 12, sizeof(center_tris), inst_length);
+
+ hr = IDirect3DDevice_BeginScene(device);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirect3DDevice_EndScene(device);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+ for (y = 0; y < 8; y++)
+ {
+ for (x = 0; x < 8; x++)
+ {
+ todo = FALSE;
+ switch (tests[i].expected[y][x])
+ {
+ case 'l': todo = TRUE;
+ case 'L':
+ expected = colour_left;
+ break;
+ case 't': todo = TRUE;
+ case 'T':
+ expected = colour_top;
+ break;
+ case 'r': todo = TRUE;
+ case 'R':
+ expected = colour_right;
+ break;
+ case 'b': todo = TRUE;
+ case 'B':
+ expected = colour_bottom;
+ break;
+ case ' ':
+ expected = colour_clear;
+ break;
+ default:
+ ok(0, "Unexpected entry in expected test char\n");
+ expected = 0xdeadbeef;
+ }
+ colour = get_surface_color(backbuffer, x, y);
+ /* The nudge-to-bottom test fails on cards that give us a bottom-left
+ * filling convention. The cause isn't the bottom part of the filling
+ * convention, but because wined3d will nudge geometry to the left to
+ * keep diagonals (the 'R' in test case 'edge_tris') intact. */
+ todo_wine_if(todo && !compare_color(colour, expected, 1))
+ ok(compare_color(colour, expected, 1), "Got unexpected colour %08x, %ux%u, case %u.\n",
+ colour, x, y, i);
+ }
+ }
+ }
+
+ destroy_viewport(device, viewport);
+ IDirectDrawSurface_Release(backbuffer);
+ IDirect3DDevice_Release(device);
+ refcount = IDirectDraw_Release(ddraw);
+ ok(!refcount, "Device has %u references left.\n", refcount);
+ DestroyWindow(window);
+}
+
START_TEST(ddraw1)
{
DDDEVICEIDENTIFIER identifier;
@@ -14565,4 +15004,5 @@ START_TEST(ddraw1)
test_window_position();
test_get_display_mode();
run_for_each_device_type(test_texture_wrong_caps);
+ test_filling_convention();
}
diff --git a/dlls/ddraw/tests/ddraw2.c b/dlls/ddraw/tests/ddraw2.c
index a1d4dd942fa..7285c1c3a88 100644
--- a/dlls/ddraw/tests/ddraw2.c
+++ b/dlls/ddraw/tests/ddraw2.c
@@ -15380,6 +15380,467 @@ static void test_texture_wrong_caps(const GUID *device_guid)
DestroyWindow(window);
}
+static void test_filling_convention(void)
+{
+ IDirectDrawSurface *rt, *backbuffer, *cur, *ds;
+ static const DWORD colour_bottom = 0x00ffff00;
+ static const DWORD colour_clear = 0x000000ff;
+ static const DWORD colour_right = 0x00000000;
+ static const DWORD colour_left = 0x00ff0000;
+ static const DWORD colour_top = 0x0000ff00;
+ IDirect3DMaterial2 *background;
+ IDirect3DViewport2 *viewport;
+ IDirect3DDevice2 *device;
+ unsigned int i, j, x, y;
+ DWORD colour, expected;
+ IDirectDraw2 *ddraw;
+ DDSURFACEDESC desc;
+ IDirect3D2 *d3d;
+ ULONG refcount;
+ HWND window;
+ HRESULT hr;
+ BOOL todo;
+
+ static const unsigned int vp_size = 8;
+ D3DRECT clear_rect = {{0}, {0}, {vp_size}, {vp_size}};
+
+ /* This test data follows the examples in MSDN's
+ * "Rasterization Rules (Direct3D 9)" article. */
+ static const float eps = 1.0f / 512.0f;
+ D3DLVERTEX center_tris[] =
+ {
+ /* left */
+ {{-2.5f / 4.0f}, {-1.5f / 4.0f}, {0.0f}, 0, {colour_left}},
+ {{-2.5f / 4.0f}, { 2.5f / 4.0f}, {0.0f}, 0, {colour_left}},
+ {{-1.5f / 4.0f}, { 0.5f / 4.0f}, {0.0f}, 0, {colour_left}},
+
+ /* top */
+ {{-1.5f / 4.0f}, { 0.5f / 4.0f}, {0.0f}, 0, {colour_top}},
+ {{-2.5f / 4.0f}, { 2.5f / 4.0f}, {0.0f}, 0, {colour_top}},
+ {{-0.5f / 4.0f}, { 2.5f / 4.0f}, {0.0f}, 0, {colour_top}},
+
+ /* right */
+ {{-0.5f / 4.0f}, {-1.5f / 4.0f}, {0.0f}, 0, {colour_right}},
+ {{-1.5f / 4.0f}, { 0.5f / 4.0f}, {0.0f}, 0, {colour_right}},
+ {{-0.5f / 4.0f}, { 2.5f / 4.0f}, {0.0f}, 0, {colour_right}},
+
+ /* bottom */
+ {{-2.5f / 4.0f}, {-1.5f / 4.0f}, {0.0f}, 0, {colour_bottom}},
+ {{-1.5f / 4.0f}, { 0.5f / 4.0f}, {0.0f}, 0, {colour_bottom}},
+ {{-0.5f / 4.0f}, {-1.5f / 4.0f}, {0.0f}, 0, {colour_bottom}},
+ },
+ edge_tris[] =
+ {
+ /* left */
+ {{-2.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_left}},
+ {{-2.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_left}},
+ {{-1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_left}},
+
+ /* top */
+ {{-1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_top}},
+ {{-2.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_top}},
+ {{ 0.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_top}},
+
+ /* right */
+ {{ 0.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_right}},
+ {{-1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_right}},
+ {{ 0.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_right}},
+
+ /* bottom */
+ {{-2.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
+ {{-1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
+ {{ 0.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
+ },
+ nudge_right_tris[] =
+ {
+ /* left */
+ {{eps - 2.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_left}},
+ {{eps - 2.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_left}},
+ {{eps - 1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_left}},
+
+ /* top */
+ {{eps - 1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_top}},
+ {{eps - 2.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_top}},
+ {{eps - 0.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_top}},
+
+ /* right */
+ {{eps - 0.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_right}},
+ {{eps - 1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_right}},
+ {{eps - 0.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_right}},
+
+ /* bottom */
+ {{eps - 2.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
+ {{eps - 1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
+ {{eps - 0.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
+ },
+ nudge_left_tris[] =
+ {
+ {{-eps - 2.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_left}},
+ {{-eps - 2.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_left}},
+ {{-eps - 1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_left}},
+
+ /* top */
+ {{-eps - 1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_top}},
+ {{-eps - 2.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_top}},
+ {{-eps - 0.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_top}},
+
+ /* right */
+ {{-eps - 0.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_right}},
+ {{-eps - 1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_right}},
+ {{-eps - 0.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_right}},
+
+ /* bottom */
+ {{-eps - 2.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
+ {{-eps - 1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
+ {{-eps - 0.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
+ },
+ nudge_top_tris[] =
+ {
+ /* left */
+ {{-2.0f / 4.0f}, {eps - 1.0f / 4.0f}, {0.0f}, 0, {colour_left}},
+ {{-2.0f / 4.0f}, {eps + 3.0f / 4.0f}, {0.0f}, 0, {colour_left}},
+ {{-1.0f / 4.0f}, {eps + 1.0f / 4.0f}, {0.0f}, 0, {colour_left}},
+
+ /* top */
+ {{-1.0f / 4.0f}, {eps + 1.0f / 4.0f}, {0.0f}, 0, {colour_top}},
+ {{-2.0f / 4.0f}, {eps + 3.0f / 4.0f}, {0.0f}, 0, {colour_top}},
+ {{ 0.0f / 4.0f}, {eps + 3.0f / 4.0f}, {0.0f}, 0, {colour_top}},
+
+ /* right */
+ {{ 0.0f / 4.0f}, {eps - 1.0f / 4.0f}, {0.0f}, 0, {colour_right}},
+ {{-1.0f / 4.0f}, {eps + 1.0f / 4.0f}, {0.0f}, 0, {colour_right}},
+ {{ 0.0f / 4.0f}, {eps + 3.0f / 4.0f}, {0.0f}, 0, {colour_right}},
+
+ /* bottom */
+ {{-2.0f / 4.0f}, {eps - 1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
+ {{-1.0f / 4.0f}, {eps + 1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
+ {{ 0.0f / 4.0f}, {eps - 1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
+ },
+ nudge_bottom_tris[] =
+ {
+ /* left */
+ {{-2.0f / 4.0f}, {-eps - 1.0f / 4.0f}, {0.0f}, 0, {colour_left}},
+ {{-2.0f / 4.0f}, {-eps + 3.0f / 4.0f}, {0.0f}, 0, {colour_left}},
+ {{-1.0f / 4.0f}, {-eps + 1.0f / 4.0f}, {0.0f}, 0, {colour_left}},
+
+ /* top */
+ {{-1.0f / 4.0f}, {-eps + 1.0f / 4.0f}, {0.0f}, 0, {colour_top}},
+ {{-2.0f / 4.0f}, {-eps + 3.0f / 4.0f}, {0.0f}, 0, {colour_top}},
+ {{ 0.0f / 4.0f}, {-eps + 3.0f / 4.0f}, {0.0f}, 0, {colour_top}},
+
+ /* right */
+ {{ 0.0f / 4.0f}, {-eps - 1.0f / 4.0f}, {0.0f}, 0, {colour_right}},
+ {{-1.0f / 4.0f}, {-eps + 1.0f / 4.0f}, {0.0f}, 0, {colour_right}},
+ {{ 0.0f / 4.0f}, {-eps + 3.0f / 4.0f}, {0.0f}, 0, {colour_right}},
+
+ /* bottom */
+ {{-2.0f / 4.0f}, {-eps - 1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
+ {{-1.0f / 4.0f}, {-eps + 1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
+ {{ 0.0f / 4.0f}, {-eps - 1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
+ };
+
+ D3DTLVERTEX center_tris_t[] =
+ {
+ /* left */
+ {{1.5f}, {1.5f}, {0.0f}, {1.0f}, {colour_left}},
+ {{2.5f}, {3.5f}, {0.0f}, {1.0f}, {colour_left}},
+ {{1.5f}, {5.5f}, {0.0f}, {1.0f}, {colour_left}},
+
+ /* top */
+ {{1.5f}, {1.5f}, {0.0f}, {1.0f}, {colour_top}},
+ {{3.5f}, {1.5f}, {0.0f}, {1.0f}, {colour_top}},
+ {{2.5f}, {3.5f}, {0.0f}, {1.0f}, {colour_top}},
+
+ /* right */
+ {{3.5f}, {1.5f}, {0.0f}, {1.0f}, {colour_right}},
+ {{3.5f}, {5.5f}, {0.0f}, {1.0f}, {colour_right}},
+ {{2.5f}, {3.5f}, {0.0f}, {1.0f}, {colour_right}},
+
+ /* bottom */
+ {{2.5f}, {3.5f}, {0.0f}, {1.0f}, {colour_bottom}},
+ {{3.5f}, {5.5f}, {0.0f}, {1.0f}, {colour_bottom}},
+ {{1.5f}, {5.5f}, {0.0f}, {1.0f}, {colour_bottom}},
+ },
+ edge_tris_t[] =
+ {
+ /* left */
+ {{2.0f}, {1.0f}, {0.0f}, {1.0f}, {colour_left}},
+ {{3.0f}, {3.0f}, {0.0f}, {1.0f}, {colour_left}},
+ {{2.0f}, {5.0f}, {0.0f}, {1.0f}, {colour_left}},
+
+ /* top */
+ {{2.0f}, {1.0f}, {0.0f}, {1.0f}, {colour_top}},
+ {{4.0f}, {1.0f}, {0.0f}, {1.0f}, {colour_top}},
+ {{3.0f}, {3.0f}, {0.0f}, {1.0f}, {colour_top}},
+
+ /* right */
+ {{4.0f}, {1.0f}, {0.0f}, {1.0f}, {colour_right}},
+ {{4.0f}, {5.0f}, {0.0f}, {1.0f}, {colour_right}},
+ {{3.0f}, {3.0f}, {0.0f}, {1.0f}, {colour_right}},
+
+ /* bottom */
+ {{3.0f}, {3.0f}, {0.0f}, {1.0f}, {colour_bottom}},
+ {{4.0f}, {5.0f}, {0.0f}, {1.0f}, {colour_bottom}},
+ {{2.0f}, {5.0f}, {0.0f}, {1.0f}, {colour_bottom}},
+ };
+
+ const struct
+ {
+ void *geometry;
+ DWORD fvf;
+ const char *expected[8];
+ }
+ tests[] =
+ {
+ {
+ center_tris,
+ D3DVT_LVERTEX,
+ {
+ " ",
+ " ",
+ " TT ",
+ " LR ",
+ " LR ",
+ " BB ",
+ " ",
+ " "
+ }
+ },
+ {
+ edge_tris,
+ D3DVT_LVERTEX,
+ {
+ " ",
+ " TT ",
+ " LT ",
+ " LR ",
+ " LB ",
+ " ",
+ " ",
+ " "
+ }
+ },
+ {
+ nudge_right_tris,
+ D3DVT_LVERTEX,
+ {
+ " ",
+ " TT ",
+ " TR ",
+ " LR ",
+ " BR ",
+ " ",
+ " ",
+ " "
+ }
+ },
+ {
+ nudge_left_tris,
+ D3DVT_LVERTEX,
+ {
+ " ",
+ " TT ",
+ " LT ",
+ " LR ",
+ " LB ",
+ " ",
+ " ",
+ " "
+ }
+ },
+ {
+ nudge_top_tris,
+ D3DVT_LVERTEX,
+ {
+ " ",
+ " LT ",
+ " LT ",
+ " LB ",
+ " LB ",
+ " ",
+ " ",
+ " "
+ }
+ },
+ {
+ nudge_bottom_tris,
+ D3DVT_LVERTEX,
+ {
+ " ",
+ " ",
+ " LT ",
+ " Lt ",
+ " LB ",
+ " lB ",
+ " ",
+ " "
+ }
+ },
+ {
+ center_tris_t,
+ D3DVT_TLVERTEX,
+ {
+ " ",
+ " ",
+ " TT ",
+ " LR ",
+ " LR ",
+ " BB ",
+ " ",
+ " "
+ }
+ },
+ {
+ edge_tris_t,
+ D3DVT_TLVERTEX,
+ {
+ " ",
+ " TT ",
+ " LT ",
+ " LR ",
+ " LB ",
+ " ",
+ " ",
+ " "
+ }
+ },
+ };
+
+ window = create_window();
+ ddraw = create_ddraw();
+ ok(!!ddraw, "Failed to create a ddraw object.\n");
+ if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
+ {
+ skip("Failed to create a 3D device.\n");
+ IDirectDraw2_Release(ddraw);
+ DestroyWindow(window);
+ return;
+ }
+
+ hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirect3DDevice2_GetRenderTarget(device, &backbuffer);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+
+ viewport = create_viewport(device, 0, 0, vp_size, vp_size);
+ background = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
+ viewport_set_background(device, viewport, background);
+ hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+ memset(&desc, 0, sizeof(desc));
+ desc.dwSize = sizeof(desc);
+ desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
+ desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
+ desc.dwWidth = vp_size;
+ desc.dwHeight = vp_size;
+ desc.ddpfPixelFormat.dwSize = sizeof(desc.ddpfPixelFormat);
+ desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
+ desc.ddpfPixelFormat.dwRGBBitCount = 32;
+ desc.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
+ desc.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
+ desc.ddpfPixelFormat.dwBBitMask = 0x000000ff;
+ hr = IDirectDraw2_CreateSurface(ddraw, &desc, &rt, NULL);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+ /* Nvidia on Windows 10 refuses to set the offscreen RT
+ * if it does not have an attached depth stencil. */
+ ds = get_depth_stencil(device);
+ memset(&desc, 0, sizeof(desc));
+ desc.dwSize = sizeof(desc);
+ desc.ddpfPixelFormat.dwSize = sizeof(desc.ddpfPixelFormat);
+ hr = IDirectDrawSurface_GetPixelFormat(ds, &desc.ddpfPixelFormat);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+ IDirectDrawSurface4_Release(ds);
+
+ desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
+ desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
+ desc.dwWidth = vp_size;
+ desc.dwHeight = vp_size;
+ hr = IDirectDraw2_CreateSurface(ddraw, &desc, &ds, NULL);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirectDrawSurface_AddAttachedSurface(rt, ds);
+ ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
+
+ hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+ for (i = 0; i < ARRAY_SIZE(tests); ++i)
+ {
+ for (j = 0; j < 2; ++j)
+ {
+ cur = j ? rt : backbuffer;
+
+ hr = IDirect3DDevice2_SetRenderTarget(device, cur, 0);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+ hr = IDirect3DDevice2_BeginScene(device);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLELIST,
+ tests[i].fvf, tests[i].geometry, 12, 0);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirect3DDevice2_EndScene(device);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+ for (y = 0; y < 8; y++)
+ {
+ for (x = 0; x < 8; x++)
+ {
+ todo = FALSE;
+ switch (tests[i].expected[y][x])
+ {
+ case 'l': todo = TRUE;
+ case 'L':
+ expected = colour_left;
+ break;
+ case 't': todo = TRUE;
+ case 'T':
+ expected = colour_top;
+ break;
+ case 'r': todo = TRUE;
+ case 'R':
+ expected = colour_right;
+ break;
+ case 'b': todo = TRUE;
+ case 'B':
+ expected = colour_bottom;
+ break;
+ case ' ':
+ expected = colour_clear;
+ break;
+ default:
+ ok(0, "Unexpected entry in expected test char\n");
+ expected = 0xdeadbeef;
+ }
+ colour = get_surface_color(cur, x, y);
+ /* The nudge-to-bottom test fails on cards that give us a bottom-left
+ * filling convention. The cause isn't the bottom part of the filling
+ * convention, but because wined3d will nudge geometry to the left to
+ * keep diagonals (the 'R' in test case 'edge_tris') intact. */
+ todo_wine_if(todo && !compare_color(colour, expected, 1))
+ ok(compare_color(colour, expected, 1), "Got unexpected colour %08x, %ux%u, case %u, j %u.\n",
+ colour, x, y, i, j);
+ }
+ }
+ }
+ }
+
+ destroy_viewport(device, viewport);
+ IDirectDrawSurface_Release(backbuffer);
+ IDirectDrawSurface_Release(rt);
+ IDirectDrawSurface_Release(ds);
+ IDirect3D2_Release(d3d);
+ refcount = IDirect3DDevice2_Release(device);
+ ok(!refcount, "Device has %u references left.\n", refcount);
+ refcount = IDirectDraw2_Release(ddraw);
+ ok(!refcount, "Device has %u references left.\n", refcount);
+ DestroyWindow(window);
+}
+
static void run_for_each_device_type(void (*test_func)(const GUID *))
{
test_func(&IID_IDirect3DHALDevice);
@@ -15509,4 +15970,5 @@ START_TEST(ddraw2)
test_window_position();
test_get_display_mode();
run_for_each_device_type(test_texture_wrong_caps);
+ test_filling_convention();
}
diff --git a/dlls/ddraw/tests/ddraw4.c b/dlls/ddraw/tests/ddraw4.c
index 4f052256882..07afc44e519 100644
--- a/dlls/ddraw/tests/ddraw4.c
+++ b/dlls/ddraw/tests/ddraw4.c
@@ -18431,6 +18431,472 @@ static void test_texture_wrong_caps(const GUID *device_guid)
DestroyWindow(window);
}
+static void test_filling_convention(void)
+{
+ IDirectDrawSurface4 *rt, *backbuffer, *cur, *ds;
+ static const DWORD colour_bottom = 0x00ffff00;
+ static const DWORD colour_clear = 0x000000ff;
+ static const DWORD colour_right = 0x00000000;
+ static const DWORD colour_left = 0x00ff0000;
+ static const DWORD colour_top = 0x0000ff00;
+ IDirect3DViewport3 *viewport;
+ IDirect3DDevice3 *device;
+ unsigned int i, j, x, y;
+ DWORD colour, expected;
+ IDirectDraw4 *ddraw;
+ DDSURFACEDESC2 desc;
+ IDirect3D3 *d3d;
+ ULONG refcount;
+ HWND window;
+ HRESULT hr;
+ BOOL todo;
+
+ static const unsigned int vp_size = 8;
+ D3DRECT clear_rect = {{0}, {0}, {vp_size}, {vp_size}};
+
+ /* This test data follows the examples in MSDN's
+ * "Rasterization Rules (Direct3D 9)" article. */
+ static const float eps = 1.0f / 512.0f;
+ struct
+ {
+ struct vec3 position;
+ DWORD diffuse;
+ }
+ center_tris[] =
+ {
+ /* left */
+ {{-2.5f / 4.0f, -1.5f / 4.0f, 0.0f}, colour_left},
+ {{-2.5f / 4.0f, 2.5f / 4.0f, 0.0f}, colour_left},
+ {{-1.5f / 4.0f, 0.5f / 4.0f, 0.0f}, colour_left},
+
+ /* top */
+ {{-1.5f / 4.0f, 0.5f / 4.0f, 0.0f}, colour_top},
+ {{-2.5f / 4.0f, 2.5f / 4.0f, 0.0f}, colour_top},
+ {{-0.5f / 4.0f, 2.5f / 4.0f, 0.0f}, colour_top},
+
+ /* right */
+ {{-0.5f / 4.0f, -1.5f / 4.0f, 0.0f}, colour_right},
+ {{-1.5f / 4.0f, 0.5f / 4.0f, 0.0f}, colour_right},
+ {{-0.5f / 4.0f, 2.5f / 4.0f, 0.0f}, colour_right},
+
+ /* bottom */
+ {{-2.5f / 4.0f, -1.5f / 4.0f, 0.0f}, colour_bottom},
+ {{-1.5f / 4.0f, 0.5f / 4.0f, 0.0f}, colour_bottom},
+ {{-0.5f / 4.0f, -1.5f / 4.0f, 0.0f}, colour_bottom},
+
+ },
+ edge_tris[] =
+ {
+ /* left */
+ {{-2.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_left},
+ {{-2.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_left},
+ {{-1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_left},
+
+ /* top */
+ {{-1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_top},
+ {{-2.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_top},
+ {{ 0.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_top},
+
+ /* right */
+ {{ 0.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_right},
+ {{-1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_right},
+ {{ 0.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_right},
+
+ /* bottom */
+ {{-2.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_bottom},
+ {{-1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_bottom},
+ {{ 0.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_bottom},
+ },
+ nudge_right_tris[] =
+ {
+ /* left */
+ {{eps - 2.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_left},
+ {{eps - 2.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_left},
+ {{eps - 1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_left},
+
+ /* top */
+ {{eps - 1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_top},
+ {{eps - 2.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_top},
+ {{eps - 0.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_top},
+
+ /* right */
+ {{eps - 0.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_right},
+ {{eps - 1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_right},
+ {{eps - 0.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_right},
+
+ /* bottom */
+ {{eps - 2.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_bottom},
+ {{eps - 1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_bottom},
+ {{eps - 0.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_bottom},
+ },
+ nudge_left_tris[] =
+ {
+ {{-eps - 2.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_left},
+ {{-eps - 2.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_left},
+ {{-eps - 1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_left},
+
+ /* top */
+ {{-eps - 1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_top},
+ {{-eps - 2.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_top},
+ {{-eps - 0.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_top},
+
+ /* right */
+ {{-eps - 0.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_right},
+ {{-eps - 1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_right},
+ {{-eps - 0.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_right},
+
+ /* bottom */
+ {{-eps - 2.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_bottom},
+ {{-eps - 1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_bottom},
+ {{-eps - 0.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_bottom},
+ },
+ nudge_top_tris[] =
+ {
+ /* left */
+ {{-2.0f / 4.0f, eps - 1.0f / 4.0f, 0.0f}, colour_left},
+ {{-2.0f / 4.0f, eps + 3.0f / 4.0f, 0.0f}, colour_left},
+ {{-1.0f / 4.0f, eps + 1.0f / 4.0f, 0.0f}, colour_left},
+
+ /* top */
+ {{-1.0f / 4.0f, eps + 1.0f / 4.0f, 0.0f}, colour_top},
+ {{-2.0f / 4.0f, eps + 3.0f / 4.0f, 0.0f}, colour_top},
+ {{ 0.0f / 4.0f, eps + 3.0f / 4.0f, 0.0f}, colour_top},
+
+ /* right */
+ {{ 0.0f / 4.0f, eps - 1.0f / 4.0f, 0.0f}, colour_right},
+ {{-1.0f / 4.0f, eps + 1.0f / 4.0f, 0.0f}, colour_right},
+ {{ 0.0f / 4.0f, eps + 3.0f / 4.0f, 0.0f}, colour_right},
+
+ /* bottom */
+ {{-2.0f / 4.0f, eps - 1.0f / 4.0f, 0.0f}, colour_bottom},
+ {{-1.0f / 4.0f, eps + 1.0f / 4.0f, 0.0f}, colour_bottom},
+ {{ 0.0f / 4.0f, eps - 1.0f / 4.0f, 0.0f}, colour_bottom},
+ },
+ nudge_bottom_tris[] =
+ {
+ /* left */
+ {{-2.0f / 4.0f, -eps - 1.0f / 4.0f, 0.0f}, colour_left},
+ {{-2.0f / 4.0f, -eps + 3.0f / 4.0f, 0.0f}, colour_left},
+ {{-1.0f / 4.0f, -eps + 1.0f / 4.0f, 0.0f}, colour_left},
+
+ /* top */
+ {{-1.0f / 4.0f, -eps + 1.0f / 4.0f, 0.0f}, colour_top},
+ {{-2.0f / 4.0f, -eps + 3.0f / 4.0f, 0.0f}, colour_top},
+ {{ 0.0f / 4.0f, -eps + 3.0f / 4.0f, 0.0f}, colour_top},
+
+ /* right */
+ {{ 0.0f / 4.0f, -eps - 1.0f / 4.0f, 0.0f}, colour_right},
+ {{-1.0f / 4.0f, -eps + 1.0f / 4.0f, 0.0f}, colour_right},
+ {{ 0.0f / 4.0f, -eps + 3.0f / 4.0f, 0.0f}, colour_right},
+
+ /* bottom */
+ {{-2.0f / 4.0f, -eps - 1.0f / 4.0f, 0.0f}, colour_bottom},
+ {{-1.0f / 4.0f, -eps + 1.0f / 4.0f, 0.0f}, colour_bottom},
+ {{ 0.0f / 4.0f, -eps - 1.0f / 4.0f, 0.0f}, colour_bottom},
+ };
+
+ struct
+ {
+ struct vec4 position;
+ DWORD diffuse;
+ }
+ center_tris_t[] =
+ {
+ /* left */
+ {{ 1.5f, 1.5f, 0.0f, 1.0f}, colour_left},
+ {{ 2.5f, 3.5f, 0.0f, 1.0f}, colour_left},
+ {{ 1.5f, 5.5f, 0.0f, 1.0f}, colour_left},
+
+ /* top */
+ {{ 1.5f, 1.5f, 0.0f, 1.0f}, colour_top},
+ {{ 3.5f, 1.5f, 0.0f, 1.0f}, colour_top},
+ {{ 2.5f, 3.5f, 0.0f, 1.0f}, colour_top},
+
+ /* right */
+ {{ 3.5f, 1.5f, 0.0f, 1.0f}, colour_right},
+ {{ 3.5f, 5.5f, 0.0f, 1.0f}, colour_right},
+ {{ 2.5f, 3.5f, 0.0f, 1.0f}, colour_right},
+
+ /* bottom */
+ {{ 2.5f, 3.5f, 0.0f, 1.0f}, colour_bottom},
+ {{ 3.5f, 5.5f, 0.0f, 1.0f}, colour_bottom},
+ {{ 1.5f, 5.5f, 0.0f, 1.0f}, colour_bottom},
+ },
+ edge_tris_t[] =
+ {
+ /* left */
+ {{ 2.0f, 1.0f, 0.0f, 1.0f}, colour_left},
+ {{ 3.0f, 3.0f, 0.0f, 1.0f}, colour_left},
+ {{ 2.0f, 5.0f, 0.0f, 1.0f}, colour_left},
+
+ /* top */
+ {{ 2.0f, 1.0f, 0.0f, 1.0f}, colour_top},
+ {{ 4.0f, 1.0f, 0.0f, 1.0f}, colour_top},
+ {{ 3.0f, 3.0f, 0.0f, 1.0f}, colour_top},
+
+ /* right */
+ {{ 4.0f, 1.0f, 0.0f, 1.0f}, colour_right},
+ {{ 4.0f, 5.0f, 0.0f, 1.0f}, colour_right},
+ {{ 3.0f, 3.0f, 0.0f, 1.0f}, colour_right},
+
+ /* bottom */
+ {{ 3.0f, 3.0f, 0.0f, 1.0f}, colour_bottom},
+ {{ 4.0f, 5.0f, 0.0f, 1.0f}, colour_bottom},
+ {{ 2.0f, 5.0f, 0.0f, 1.0f}, colour_bottom},
+ };
+
+ const struct
+ {
+ void *geometry;
+ DWORD fvf;
+ const char *expected[8];
+ }
+ tests[] =
+ {
+ {
+ center_tris,
+ D3DFVF_XYZ | D3DFVF_DIFFUSE,
+ {
+ " ",
+ " ",
+ " TT ",
+ " LR ",
+ " LR ",
+ " BB ",
+ " ",
+ " "
+ }
+ },
+ {
+ edge_tris,
+ D3DFVF_XYZ | D3DFVF_DIFFUSE,
+ {
+ " ",
+ " TT ",
+ " LT ",
+ " LR ",
+ " LB ",
+ " ",
+ " ",
+ " "
+ }
+ },
+ {
+ nudge_right_tris,
+ D3DFVF_XYZ | D3DFVF_DIFFUSE,
+ {
+ " ",
+ " TT ",
+ " TR ",
+ " LR ",
+ " BR ",
+ " ",
+ " ",
+ " "
+ }
+ },
+ {
+ nudge_left_tris,
+ D3DFVF_XYZ | D3DFVF_DIFFUSE,
+ {
+ " ",
+ " TT ",
+ " LT ",
+ " LR ",
+ " LB ",
+ " ",
+ " ",
+ " "
+ }
+ },
+ {
+ nudge_top_tris,
+ D3DFVF_XYZ | D3DFVF_DIFFUSE,
+ {
+ " ",
+ " LT ",
+ " LT ",
+ " LB ",
+ " LB ",
+ " ",
+ " ",
+ " "
+ }
+ },
+ {
+ nudge_bottom_tris,
+ D3DFVF_XYZ | D3DFVF_DIFFUSE,
+ {
+ " ",
+ " ",
+ " LT ",
+ " Lt ",
+ " LB ",
+ " lB ",
+ " ",
+ " "
+ }
+ },
+ {
+ center_tris_t,
+ D3DFVF_XYZRHW | D3DFVF_DIFFUSE,
+ {
+ " ",
+ " ",
+ " TT ",
+ " LR ",
+ " LR ",
+ " BB ",
+ " ",
+ " "
+ }
+ },
+ {
+ edge_tris_t,
+ D3DFVF_XYZRHW | D3DFVF_DIFFUSE,
+ {
+ " ",
+ " TT ",
+ " LT ",
+ " LR ",
+ " LB ",
+ " ",
+ " ",
+ " "
+ }
+ },
+ };
+
+ window = create_window();
+ if (!(device = create_device(window, DDSCL_NORMAL)))
+ {
+ skip("Failed to create 3D device.\n");
+ DestroyWindow(window);
+ return;
+ }
+
+ hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirect3DDevice3_GetRenderTarget(device, &backbuffer);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ viewport = create_viewport(device, 0, 0, vp_size, vp_size);
+ hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+ memset(&desc, 0, sizeof(desc));
+ desc.dwSize = sizeof(desc);
+ desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
+ desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
+ desc.dwWidth = vp_size;
+ desc.dwHeight = vp_size;
+ desc.ddpfPixelFormat.dwSize = sizeof(desc.ddpfPixelFormat);
+ desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
+ desc.ddpfPixelFormat.dwRGBBitCount = 32;
+ desc.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
+ desc.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
+ desc.ddpfPixelFormat.dwBBitMask = 0x000000ff;
+ hr = IDirectDraw4_CreateSurface(ddraw, &desc, &rt, NULL);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+ /* Nvidia on Windows 10 refuses to set the offscreen RT
+ * if it does not have an attached depth stencil. */
+ ds = get_depth_stencil(device);
+ memset(&desc, 0, sizeof(desc));
+ desc.dwSize = sizeof(desc);
+ desc.ddpfPixelFormat.dwSize = sizeof(desc.ddpfPixelFormat);
+ hr = IDirectDrawSurface4_GetPixelFormat(ds, &desc.ddpfPixelFormat);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+ IDirectDrawSurface4_Release(ds);
+
+ desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
+ desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
+ desc.dwWidth = vp_size;
+ desc.dwHeight = vp_size;
+ hr = IDirectDraw4_CreateSurface(ddraw, &desc, &ds, NULL);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirectDrawSurface4_AddAttachedSurface(rt, ds);
+ ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
+
+ hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+ for (i = 0; i < ARRAY_SIZE(tests); ++i)
+ {
+ for (j = 0; j < 2; ++j)
+ {
+ cur = j ? rt : backbuffer;
+
+ hr = IDirect3DDevice3_SetRenderTarget(device, cur, 0);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, colour_clear, 0.0f, 0);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+ hr = IDirect3DDevice3_BeginScene(device);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLELIST,
+ tests[i].fvf, tests[i].geometry, 12, 0);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirect3DDevice3_EndScene(device);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+ for (y = 0; y < 8; y++)
+ {
+ for (x = 0; x < 8; x++)
+ {
+ todo = FALSE;
+ switch (tests[i].expected[y][x])
+ {
+ case 'l': todo = TRUE;
+ case 'L':
+ expected = colour_left;
+ break;
+ case 't': todo = TRUE;
+ case 'T':
+ expected = colour_top;
+ break;
+ case 'r': todo = TRUE;
+ case 'R':
+ expected = colour_right;
+ break;
+ case 'b': todo = TRUE;
+ case 'B':
+ expected = colour_bottom;
+ break;
+ case ' ':
+ expected = colour_clear;
+ break;
+ default:
+ ok(0, "Unexpected entry in expected test char\n");
+ expected = 0xdeadbeef;
+ }
+ colour = get_surface_color(cur, x, y);
+ /* The nudge-to-bottom test fails on cards that give us a bottom-left
+ * filling convention. The cause isn't the bottom part of the filling
+ * convention, but because wined3d will nudge geometry to the left to
+ * keep diagonals (the 'R' in test case 'edge_tris') intact. */
+ todo_wine_if(todo && !compare_color(colour, expected, 1))
+ ok(compare_color(colour, expected, 1), "Got unexpected colour %08x, %ux%u, case %u, j %u.\n",
+ colour, x, y, i, j);
+ }
+ }
+ }
+ }
+
+ destroy_viewport(device, viewport);
+ IDirectDrawSurface4_Release(backbuffer);
+ IDirectDrawSurface4_Release(rt);
+ IDirectDrawSurface4_Release(ds);
+ IDirectDraw4_Release(ddraw);
+ IDirect3D3_Release(d3d);
+ refcount = IDirect3DDevice3_Release(device);
+ ok(!refcount, "Device has %u references left.\n", refcount);
+ DestroyWindow(window);
+}
+
START_TEST(ddraw4)
{
DDDEVICEIDENTIFIER identifier;
@@ -18570,4 +19036,5 @@ START_TEST(ddraw4)
test_window_position();
test_get_display_mode();
run_for_each_device_type(test_texture_wrong_caps);
+ test_filling_convention();
}
diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c
index 4402f2d93b5..29fa3434d4b 100644
--- a/dlls/ddraw/tests/ddraw7.c
+++ b/dlls/ddraw/tests/ddraw7.c
@@ -18684,6 +18684,449 @@ static void test_texture_wrong_caps(const GUID *device_guid)
DestroyWindow(window);
}
+static void test_filling_convention(void)
+{
+ static const DWORD colour_bottom = 0x00ffff00;
+ static const DWORD colour_clear = 0x000000ff;
+ static const DWORD colour_right = 0x00000000;
+ static const DWORD colour_left = 0x00ff0000;
+ static const DWORD colour_top = 0x0000ff00;
+ IDirectDrawSurface7 *rt, *backbuffer, *cur;
+ IDirect3DDevice7 *device;
+ unsigned int i, j, x, y;
+ DWORD colour, expected;
+ IDirectDraw7 *ddraw;
+ DDSURFACEDESC2 desc;
+ IDirect3D7 *d3d;
+ ULONG refcount;
+ HWND window;
+ HRESULT hr;
+ BOOL todo;
+
+ static const unsigned int vp_size = 8;
+ D3DVIEWPORT7 vp = { 0, 0, vp_size, vp_size, 0.0, 1.0 };
+
+ /* This test data follows the examples in MSDN's
+ * "Rasterization Rules (Direct3D 9)" article. */
+ static const float eps = 1.0f / 512.0f;
+ struct
+ {
+ struct vec3 position;
+ DWORD diffuse;
+ }
+ center_tris[] =
+ {
+ /* left */
+ {{-2.5f / 4.0f, -1.5f / 4.0f, 0.0f}, colour_left},
+ {{-2.5f / 4.0f, 2.5f / 4.0f, 0.0f}, colour_left},
+ {{-1.5f / 4.0f, 0.5f / 4.0f, 0.0f}, colour_left},
+
+ /* top */
+ {{-1.5f / 4.0f, 0.5f / 4.0f, 0.0f}, colour_top},
+ {{-2.5f / 4.0f, 2.5f / 4.0f, 0.0f}, colour_top},
+ {{-0.5f / 4.0f, 2.5f / 4.0f, 0.0f}, colour_top},
+
+ /* right */
+ {{-0.5f / 4.0f, -1.5f / 4.0f, 0.0f}, colour_right},
+ {{-1.5f / 4.0f, 0.5f / 4.0f, 0.0f}, colour_right},
+ {{-0.5f / 4.0f, 2.5f / 4.0f, 0.0f}, colour_right},
+
+ /* bottom */
+ {{-2.5f / 4.0f, -1.5f / 4.0f, 0.0f}, colour_bottom},
+ {{-1.5f / 4.0f, 0.5f / 4.0f, 0.0f}, colour_bottom},
+ {{-0.5f / 4.0f, -1.5f / 4.0f, 0.0f}, colour_bottom},
+
+ },
+ edge_tris[] =
+ {
+ /* left */
+ {{-2.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_left},
+ {{-2.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_left},
+ {{-1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_left},
+
+ /* top */
+ {{-1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_top},
+ {{-2.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_top},
+ {{ 0.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_top},
+
+ /* right */
+ {{ 0.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_right},
+ {{-1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_right},
+ {{ 0.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_right},
+
+ /* bottom */
+ {{-2.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_bottom},
+ {{-1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_bottom},
+ {{ 0.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_bottom},
+ },
+ nudge_right_tris[] =
+ {
+ /* left */
+ {{eps - 2.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_left},
+ {{eps - 2.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_left},
+ {{eps - 1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_left},
+
+ /* top */
+ {{eps - 1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_top},
+ {{eps - 2.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_top},
+ {{eps - 0.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_top},
+
+ /* right */
+ {{eps - 0.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_right},
+ {{eps - 1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_right},
+ {{eps - 0.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_right},
+
+ /* bottom */
+ {{eps - 2.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_bottom},
+ {{eps - 1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_bottom},
+ {{eps - 0.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_bottom},
+ },
+ nudge_left_tris[] =
+ {
+ {{-eps - 2.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_left},
+ {{-eps - 2.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_left},
+ {{-eps - 1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_left},
+
+ /* top */
+ {{-eps - 1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_top},
+ {{-eps - 2.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_top},
+ {{-eps - 0.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_top},
+
+ /* right */
+ {{-eps - 0.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_right},
+ {{-eps - 1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_right},
+ {{-eps - 0.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_right},
+
+ /* bottom */
+ {{-eps - 2.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_bottom},
+ {{-eps - 1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_bottom},
+ {{-eps - 0.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_bottom},
+ },
+ nudge_top_tris[] =
+ {
+ /* left */
+ {{-2.0f / 4.0f, eps - 1.0f / 4.0f, 0.0f}, colour_left},
+ {{-2.0f / 4.0f, eps + 3.0f / 4.0f, 0.0f}, colour_left},
+ {{-1.0f / 4.0f, eps + 1.0f / 4.0f, 0.0f}, colour_left},
+
+ /* top */
+ {{-1.0f / 4.0f, eps + 1.0f / 4.0f, 0.0f}, colour_top},
+ {{-2.0f / 4.0f, eps + 3.0f / 4.0f, 0.0f}, colour_top},
+ {{ 0.0f / 4.0f, eps + 3.0f / 4.0f, 0.0f}, colour_top},
+
+ /* right */
+ {{ 0.0f / 4.0f, eps - 1.0f / 4.0f, 0.0f}, colour_right},
+ {{-1.0f / 4.0f, eps + 1.0f / 4.0f, 0.0f}, colour_right},
+ {{ 0.0f / 4.0f, eps + 3.0f / 4.0f, 0.0f}, colour_right},
+
+ /* bottom */
+ {{-2.0f / 4.0f, eps - 1.0f / 4.0f, 0.0f}, colour_bottom},
+ {{-1.0f / 4.0f, eps + 1.0f / 4.0f, 0.0f}, colour_bottom},
+ {{ 0.0f / 4.0f, eps - 1.0f / 4.0f, 0.0f}, colour_bottom},
+ },
+ nudge_bottom_tris[] =
+ {
+ /* left */
+ {{-2.0f / 4.0f, -eps - 1.0f / 4.0f, 0.0f}, colour_left},
+ {{-2.0f / 4.0f, -eps + 3.0f / 4.0f, 0.0f}, colour_left},
+ {{-1.0f / 4.0f, -eps + 1.0f / 4.0f, 0.0f}, colour_left},
+
+ /* top */
+ {{-1.0f / 4.0f, -eps + 1.0f / 4.0f, 0.0f}, colour_top},
+ {{-2.0f / 4.0f, -eps + 3.0f / 4.0f, 0.0f}, colour_top},
+ {{ 0.0f / 4.0f, -eps + 3.0f / 4.0f, 0.0f}, colour_top},
+
+ /* right */
+ {{ 0.0f / 4.0f, -eps - 1.0f / 4.0f, 0.0f}, colour_right},
+ {{-1.0f / 4.0f, -eps + 1.0f / 4.0f, 0.0f}, colour_right},
+ {{ 0.0f / 4.0f, -eps + 3.0f / 4.0f, 0.0f}, colour_right},
+
+ /* bottom */
+ {{-2.0f / 4.0f, -eps - 1.0f / 4.0f, 0.0f}, colour_bottom},
+ {{-1.0f / 4.0f, -eps + 1.0f / 4.0f, 0.0f}, colour_bottom},
+ {{ 0.0f / 4.0f, -eps - 1.0f / 4.0f, 0.0f}, colour_bottom},
+ };
+
+ struct
+ {
+ struct vec4 position;
+ DWORD diffuse;
+ }
+ center_tris_t[] =
+ {
+ /* left */
+ {{ 1.5f, 1.5f, 0.0f, 1.0f}, colour_left},
+ {{ 2.5f, 3.5f, 0.0f, 1.0f}, colour_left},
+ {{ 1.5f, 5.5f, 0.0f, 1.0f}, colour_left},
+
+ /* top */
+ {{ 1.5f, 1.5f, 0.0f, 1.0f}, colour_top},
+ {{ 3.5f, 1.5f, 0.0f, 1.0f}, colour_top},
+ {{ 2.5f, 3.5f, 0.0f, 1.0f}, colour_top},
+
+ /* right */
+ {{ 3.5f, 1.5f, 0.0f, 1.0f}, colour_right},
+ {{ 3.5f, 5.5f, 0.0f, 1.0f}, colour_right},
+ {{ 2.5f, 3.5f, 0.0f, 1.0f}, colour_right},
+
+ /* bottom */
+ {{ 2.5f, 3.5f, 0.0f, 1.0f}, colour_bottom},
+ {{ 3.5f, 5.5f, 0.0f, 1.0f}, colour_bottom},
+ {{ 1.5f, 5.5f, 0.0f, 1.0f}, colour_bottom},
+ },
+ edge_tris_t[] =
+ {
+ /* left */
+ {{ 2.0f, 1.0f, 0.0f, 1.0f}, colour_left},
+ {{ 3.0f, 3.0f, 0.0f, 1.0f}, colour_left},
+ {{ 2.0f, 5.0f, 0.0f, 1.0f}, colour_left},
+
+ /* top */
+ {{ 2.0f, 1.0f, 0.0f, 1.0f}, colour_top},
+ {{ 4.0f, 1.0f, 0.0f, 1.0f}, colour_top},
+ {{ 3.0f, 3.0f, 0.0f, 1.0f}, colour_top},
+
+ /* right */
+ {{ 4.0f, 1.0f, 0.0f, 1.0f}, colour_right},
+ {{ 4.0f, 5.0f, 0.0f, 1.0f}, colour_right},
+ {{ 3.0f, 3.0f, 0.0f, 1.0f}, colour_right},
+
+ /* bottom */
+ {{ 3.0f, 3.0f, 0.0f, 1.0f}, colour_bottom},
+ {{ 4.0f, 5.0f, 0.0f, 1.0f}, colour_bottom},
+ {{ 2.0f, 5.0f, 0.0f, 1.0f}, colour_bottom},
+ };
+
+ const struct
+ {
+ void *geometry;
+ DWORD fvf;
+ const char *expected[8];
+ }
+ tests[] =
+ {
+ {
+ center_tris,
+ D3DFVF_XYZ | D3DFVF_DIFFUSE,
+ {
+ " ",
+ " ",
+ " TT ",
+ " LR ",
+ " LR ",
+ " BB ",
+ " ",
+ " "
+ }
+ },
+ {
+ edge_tris,
+ D3DFVF_XYZ | D3DFVF_DIFFUSE,
+ {
+ " ",
+ " TT ",
+ " LT ",
+ " LR ",
+ " LB ",
+ " ",
+ " ",
+ " "
+ }
+ },
+ {
+ nudge_right_tris,
+ D3DFVF_XYZ | D3DFVF_DIFFUSE,
+ {
+ " ",
+ " TT ",
+ " TR ",
+ " LR ",
+ " BR ",
+ " ",
+ " ",
+ " "
+ }
+ },
+ {
+ nudge_left_tris,
+ D3DFVF_XYZ | D3DFVF_DIFFUSE,
+ {
+ " ",
+ " TT ",
+ " LT ",
+ " LR ",
+ " LB ",
+ " ",
+ " ",
+ " "
+ }
+ },
+ {
+ nudge_top_tris,
+ D3DFVF_XYZ | D3DFVF_DIFFUSE,
+ {
+ " ",
+ " LT ",
+ " LT ",
+ " LB ",
+ " LB ",
+ " ",
+ " ",
+ " "
+ }
+ },
+ {
+ nudge_bottom_tris,
+ D3DFVF_XYZ | D3DFVF_DIFFUSE,
+ {
+ " ",
+ " ",
+ " LT ",
+ " Lt ",
+ " LB ",
+ " lB ",
+ " ",
+ " "
+ }
+ },
+ {
+ center_tris_t,
+ D3DFVF_XYZRHW | D3DFVF_DIFFUSE,
+ {
+ " ",
+ " ",
+ " TT ",
+ " LR ",
+ " LR ",
+ " BB ",
+ " ",
+ " "
+ }
+ },
+ {
+ edge_tris_t,
+ D3DFVF_XYZRHW | D3DFVF_DIFFUSE,
+ {
+ " ",
+ " TT ",
+ " LT ",
+ " LR ",
+ " LB ",
+ " ",
+ " ",
+ " "
+ }
+ },
+ };
+
+ window = create_window();
+ if (!(device = create_device(window, DDSCL_NORMAL)))
+ {
+ skip("Failed to create 3D device.\n");
+ DestroyWindow(window);
+ return;
+ }
+
+ hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirect3DDevice7_GetRenderTarget(device, &backbuffer);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+
+ memset(&desc, 0, sizeof(desc));
+ desc.dwSize = sizeof(desc);
+ desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
+ desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
+ desc.dwWidth = vp_size;
+ desc.dwHeight = vp_size;
+ desc.ddpfPixelFormat.dwSize = sizeof(desc.ddpfPixelFormat);
+ desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
+ desc.ddpfPixelFormat.dwRGBBitCount = 32;
+ desc.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
+ desc.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
+ desc.ddpfPixelFormat.dwBBitMask = 0x000000ff;
+ hr = IDirectDraw7_CreateSurface(ddraw, &desc, &rt, NULL);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+ hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+ for (i = 0; i < ARRAY_SIZE(tests); ++i)
+ {
+ for (j = 0; j < 2; ++j)
+ {
+ cur = j ? rt : backbuffer;
+
+ hr = IDirect3DDevice7_SetRenderTarget(device, cur, 0);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, colour_clear, 0.0f, 0);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirect3DDevice7_SetViewport(device, &vp);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+ hr = IDirect3DDevice7_BeginScene(device);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLELIST,
+ tests[i].fvf, tests[i].geometry, 12, 0);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirect3DDevice7_EndScene(device);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+ for (y = 0; y < 8; y++)
+ {
+ for (x = 0; x < 8; x++)
+ {
+ todo = FALSE;
+ switch (tests[i].expected[y][x])
+ {
+ case 'l': todo = TRUE;
+ case 'L':
+ expected = colour_left;
+ break;
+ case 't': todo = TRUE;
+ case 'T':
+ expected = colour_top;
+ break;
+ case 'r': todo = TRUE;
+ case 'R':
+ expected = colour_right;
+ break;
+ case 'b': todo = TRUE;
+ case 'B':
+ expected = colour_bottom;
+ break;
+ case ' ':
+ expected = colour_clear;
+ break;
+ default:
+ ok(0, "Unexpected entry in expected test char\n");
+ expected = 0xdeadbeef;
+ }
+ colour = get_surface_color(cur, x, y);
+ /* The nudge-to-bottom test fails on cards that give us a bottom-left
+ * filling convention. The cause isn't the bottom part of the filling
+ * convention, but because wined3d will nudge geometry to the left to
+ * keep diagonals (the 'R' in test case 'edge_tris') intact. */
+ todo_wine_if(todo && !compare_color(colour, expected, 1))
+ ok(compare_color(colour, expected, 1), "Got unexpected colour %08x, %ux%u, case %u, j %u.\n",
+ colour, x, y, i, j);
+ }
+ }
+ }
+ }
+
+ IDirectDrawSurface7_Release(backbuffer);
+ IDirectDrawSurface7_Release(rt);
+ IDirectDraw7_Release(ddraw);
+ IDirect3D7_Release(d3d);
+ refcount = IDirect3DDevice7_Release(device);
+ ok(!refcount, "Device has %u references left.\n", refcount);
+ DestroyWindow(window);
+}
+
static void run_for_each_device_type(void (*test_func)(const GUID *))
{
test_func(hw_device_guid);
@@ -18861,4 +19304,5 @@ START_TEST(ddraw7)
test_window_position();
test_get_display_mode();
run_for_each_device_type(test_texture_wrong_caps);
+ test_filling_convention();
}
--
2.32.0
3
2