Wine-Devel
Threads by month
- ----- 2026 -----
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- 8 participants
- 84547 discussions
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
[PATCH 1/2] ddraw/tests: Port test_filling_convention to ddraw (v2).
by Stefan Dösinger Nov. 15, 2021
by Stefan Dösinger Nov. 15, 2021
Nov. 15, 2021
Signed-off-by: Stefan Dösinger <stefan(a)codeweavers.com>
---
Version 2: Disable culling to make some Win10 versions happy.
---
dlls/ddraw/tests/ddraw1.c | 439 +++++++++++++++++++++++++++++++++++
dlls/ddraw/tests/ddraw2.c | 462 +++++++++++++++++++++++++++++++++++++
dlls/ddraw/tests/ddraw4.c | 467 ++++++++++++++++++++++++++++++++++++++
dlls/ddraw/tests/ddraw7.c | 444 ++++++++++++++++++++++++++++++++++++
4 files changed, 1812 insertions(+)
diff --git a/dlls/ddraw/tests/ddraw1.c b/dlls/ddraw/tests/ddraw1.c
index 0e0a198add2..a9a10a3b8a0 100644
--- a/dlls/ddraw/tests/ddraw1.c
+++ b/dlls/ddraw/tests/ddraw1.c
@@ -14448,6 +14448,444 @@ 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);
+ emit_set_rs(&ptr, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
+
+ 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 +15003,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
3
[PATCH v2 1/2] kernel32/tests: Add SetCurrentConsoleFontEx tests for the current window size
by Hugh McMaster Nov. 15, 2021
by Hugh McMaster Nov. 15, 2021
Nov. 15, 2021
Signed-off-by: Hugh McMaster <hugh.mcmaster(a)outlook.com>
---
Changes in v2:
* Use skip() instead of win_skip() for Unix systems without the test fonts.
dlls/kernel32/tests/console.c | 204 +++++++++++++++++++++++++++++++++-
1 file changed, 202 insertions(+), 2 deletions(-)
diff --git a/dlls/kernel32/tests/console.c b/dlls/kernel32/tests/console.c
index 8b5abfa2da9..355eb296174 100644
--- a/dlls/kernel32/tests/console.c
+++ b/dlls/kernel32/tests/console.c
@@ -3554,10 +3554,18 @@ static void test_GetCurrentConsoleFontEx(HANDLE std_output)
static void test_SetCurrentConsoleFontEx(HANDLE std_output)
{
- CONSOLE_FONT_INFOEX orig_cfix, cfix;
+ CONSOLE_FONT_INFOEX orig_cfix, cfix, tmp;
BOOL ret;
HANDLE pipe1, pipe2;
HANDLE std_input = GetStdHandle(STD_INPUT_HANDLE);
+ unsigned int i, cp, font_family;
+ const WCHAR *fonts[] = { L"Courier New", L"Liberation Mono" };
+ const WCHAR *face_name;
+
+ font_family = TMPF_VECTOR | TMPF_TRUETYPE | FF_MODERN;
+
+ /* Save current console font information */
+ cp = GetConsoleOutputCP();
orig_cfix.cbSize = sizeof(CONSOLE_FONT_INFOEX);
@@ -3651,17 +3659,209 @@ static void test_SetCurrentConsoleFontEx(HANDLE std_output)
ok(!ret, "got %d, expected 0\n", ret);
todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError());
+ /* Try setting console font information for the current window size (maxwindow = FALSE) */
+ SetConsoleOutputCP(CP_UTF8);
+
+ cfix.cbSize = sizeof(cfix);
+ cfix.nFont = 0;
+ cfix.dwFontSize.X = 8;
+ cfix.dwFontSize.Y = 16;
+ cfix.FontFamily = font_family;
+ cfix.FontWeight = FW_NORMAL;
+
+ tmp.cbSize = sizeof(tmp);
+
+ /* Courier New is available in the console by default from Windows 10 build 1607 */
+ for (i = 0; i < ARRAY_SIZE(fonts); i++)
+ {
+ face_name = fonts[i];
+ lstrcpyW(cfix.FaceName, face_name);
+
+ SetCurrentConsoleFontEx(std_output, FALSE, &cfix);
+ GetCurrentConsoleFontEx(std_output, FALSE, &tmp);
+
+ if (!lstrcmpW(tmp.FaceName, face_name)) break;
+ }
+
+ if (i == ARRAY_SIZE(fonts))
+ {
+ SetConsoleOutputCP(cp);
+ skip("%s not available. Skipping SetCurrentConsoleFontEx tests.\n", wine_dbgstr_w(face_name));
+ return;
+ }
+
+ /* Test font size 8x16 */
SetLastError(0xdeadbeef);
ret = SetCurrentConsoleFontEx(std_output, FALSE, &cfix);
todo_wine ok(ret, "got %d, expected non-zero\n", ret);
todo_wine ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError());
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.cbSize = sizeof(tmp);
+ ret = GetCurrentConsoleFontEx(std_output, FALSE, &tmp);
+ ok(ret, "got %d, expected non-zero\n", ret);
+
+ ok(tmp.nFont == cfix.nFont, "got %u, expected %u\n", tmp.nFont, cfix.nFont);
+ todo_wine ok(tmp.dwFontSize.X == cfix.dwFontSize.X, "got %u, expected font width of %u\n",
+ tmp.dwFontSize.X, cfix.dwFontSize.X);
+ todo_wine ok(tmp.dwFontSize.Y == cfix.dwFontSize.Y, "got %u, expected font height of %u\n",
+ tmp.dwFontSize.Y, cfix.dwFontSize.Y);
+ todo_wine ok(tmp.FontFamily == cfix.FontFamily, "got %u, expected %u\n", tmp.FontFamily, cfix.FontFamily);
+ ok(tmp.FontWeight == cfix.FontWeight, "got %u, expected %u\n", tmp.FontWeight, cfix.FontWeight);
+ ok(!lstrcmpW(tmp.FaceName, cfix.FaceName), "got %s, expected %s\n",
+ wine_dbgstr_w(tmp.FaceName), wine_dbgstr_w(cfix.FaceName));
+
+ /* Test font size 10x20 */
+ cfix.dwFontSize.X = 10;
+ cfix.dwFontSize.Y = 20;
SetLastError(0xdeadbeef);
- ret = SetCurrentConsoleFontEx(std_output, TRUE, &cfix);
+ ret = SetCurrentConsoleFontEx(std_output, FALSE, &cfix);
+ todo_wine ok(ret, "got %d, expected non-zero\n", ret);
+ todo_wine ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError());
+
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.cbSize = sizeof(tmp);
+ ret = GetCurrentConsoleFontEx(std_output, FALSE, &tmp);
+ ok(ret, "got %d, expected non-zero\n", ret);
+ ok(tmp.nFont == cfix.nFont, "got %u, expected %u\n", tmp.nFont, cfix.nFont);
+ todo_wine ok(tmp.dwFontSize.X == cfix.dwFontSize.X, "got %u, expected font width of %u\n",
+ tmp.dwFontSize.X, cfix.dwFontSize.X);
+ todo_wine ok(tmp.dwFontSize.Y == cfix.dwFontSize.Y, "got %u, expected font height of %u\n",
+ tmp.dwFontSize.Y, cfix.dwFontSize.Y);
+ todo_wine ok(tmp.FontFamily == cfix.FontFamily, "got %u, expected %u\n", tmp.FontFamily, cfix.FontFamily);
+ ok(tmp.FontWeight == cfix.FontWeight, "got %u, expected %u\n", tmp.FontWeight, cfix.FontWeight);
+ ok(!lstrcmpW(tmp.FaceName, cfix.FaceName), "got %s, expected %s\n",
+ wine_dbgstr_w(tmp.FaceName), wine_dbgstr_w(cfix.FaceName));
+
+ /* Test font size 5x12. We pass in 10x12. */
+ cfix.dwFontSize.Y = 12;
+ SetLastError(0xdeadbeef);
+ ret = SetCurrentConsoleFontEx(std_output, FALSE, &cfix);
+ todo_wine ok(ret, "got %d, expected non-zero\n", ret);
+ todo_wine ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError());
+
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.cbSize = sizeof(tmp);
+ ret = GetCurrentConsoleFontEx(std_output, FALSE, &tmp);
+ ok(ret, "got %d, expected non-zero\n", ret);
+ ok(tmp.nFont == cfix.nFont, "got %u, expected %u\n", tmp.nFont, cfix.nFont);
+ todo_wine ok(tmp.dwFontSize.X == 5, "got %u, expected font width of 5\n", tmp.dwFontSize.X);
+ todo_wine ok(tmp.dwFontSize.Y == 12, "got %u, expected font height of 12\n", tmp.dwFontSize.Y);
+ todo_wine ok(tmp.FontFamily == cfix.FontFamily, "got %u, expected %u\n", tmp.FontFamily, cfix.FontFamily);
+ ok(tmp.FontWeight == cfix.FontWeight, "got %u, expected %u\n", tmp.FontWeight, cfix.FontWeight);
+ ok(!lstrcmpW(tmp.FaceName, cfix.FaceName), "got %s, expected %s\n",
+ wine_dbgstr_w(tmp.FaceName), wine_dbgstr_w(cfix.FaceName));
+
+ /* Test font size 10x20. Font height is 20. All other metrics are zero. */
+ cfix.dwFontSize.X = 0;
+ cfix.dwFontSize.Y = 20;
+ cfix.FontFamily = 0;
+ cfix.FontWeight = 0;
+ SetLastError(0xdeadbeef);
+ ret = SetCurrentConsoleFontEx(std_output, FALSE, &cfix);
+ todo_wine ok(ret, "got %d, expected non-zero\n", ret);
+ todo_wine ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError());
+
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.cbSize = sizeof(tmp);
+ ret = GetCurrentConsoleFontEx(std_output, FALSE, &tmp);
+ ok(ret, "got %d, expected non-zero\n", ret);
+ ok(tmp.nFont == cfix.nFont, "got %u, expected %u\n", tmp.nFont, cfix.nFont);
+ todo_wine ok(tmp.dwFontSize.X == 10, "got %u, expected font width of 10\n", tmp.dwFontSize.X);
+ todo_wine ok(tmp.dwFontSize.Y == 20, "got %u, expected font height of 20\n", tmp.dwFontSize.Y);
+ todo_wine ok(tmp.FontFamily == font_family, "got %u, expected %u\n", tmp.FontFamily, font_family);
+ ok(tmp.FontWeight == FW_NORMAL, "got %u, expected %u\n", tmp.FontWeight, FW_NORMAL);
+ ok(!lstrcmpW(tmp.FaceName, face_name), "got %s, expected %s\n",
+ wine_dbgstr_w(tmp.FaceName), wine_dbgstr_w(face_name));
+
+ /* Test font size 7x14. We pass in 7x0. */
+ cfix = tmp;
+ cfix.dwFontSize.X = 7;
+ cfix.dwFontSize.Y = 0;
+ SetLastError(0xdeadbeef);
+ ret = SetCurrentConsoleFontEx(std_output, FALSE, &cfix);
todo_wine ok(ret, "got %d, expected non-zero\n", ret);
todo_wine ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError());
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.cbSize = sizeof(tmp);
+ ret = GetCurrentConsoleFontEx(std_output, FALSE, &tmp);
+ ok(ret, "got %d, expected non-zero\n", ret);
+ ok(tmp.nFont == cfix.nFont, "got %u, expected %u\n", tmp.nFont, cfix.nFont);
+ todo_wine ok(tmp.dwFontSize.X == 5, "got %u, expected font width of 5\n", tmp.dwFontSize.X);
+ todo_wine ok(tmp.dwFontSize.Y == 12, "got %u, expected font height of 12\n", tmp.dwFontSize.Y);
+ ok(tmp.FontFamily == cfix.FontFamily, "got %u, expected %u\n", tmp.FontFamily, cfix.FontFamily);
+ ok(tmp.FontWeight == cfix.FontWeight, "got %u, expected %u\n", tmp.FontWeight, cfix.FontWeight);
+ ok(!lstrcmpW(tmp.FaceName, cfix.FaceName), "got %s, expected %s\n",
+ wine_dbgstr_w(tmp.FaceName), wine_dbgstr_w(cfix.FaceName));
+
+ /* Test font size with width and height set to 0x0. */
+ cfix.dwFontSize.X = 0;
+ cfix.dwFontSize.Y = 0;
+ SetLastError(0xdeadbeef);
+ ret = SetCurrentConsoleFontEx(std_output, FALSE, &cfix);
+ todo_wine ok(ret, "got %d, expected non-zero\n", ret);
+ todo_wine ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError());
+
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.cbSize = sizeof(tmp);
+ ret = GetCurrentConsoleFontEx(std_output, FALSE, &tmp);
+ ok(ret, "got %d, expected non-zero\n", ret);
+ ok(tmp.nFont == cfix.nFont, "got %u, expected %u\n", tmp.nFont, cfix.nFont);
+ todo_wine ok(tmp.dwFontSize.X == 5, "got %u, expected font width of 5\n", tmp.dwFontSize.X);
+ todo_wine ok(tmp.dwFontSize.Y == 12, "got %u, expected font height of 12\n", tmp.dwFontSize.Y);
+ ok(tmp.FontFamily == cfix.FontFamily, "got %u, expected %u\n", tmp.FontFamily, cfix.FontFamily);
+ ok(tmp.FontWeight == cfix.FontWeight, "got %u, expected %u\n", tmp.FontWeight, cfix.FontWeight);
+ ok(!lstrcmpW(tmp.FaceName, cfix.FaceName), "got %s, expected %s\n",
+ wine_dbgstr_w(tmp.FaceName), wine_dbgstr_w(cfix.FaceName));
+
+ /* Test with invalid font face name */
+ cfix.dwFontSize.X = 8;
+ cfix.dwFontSize.Y = 16;
+ lstrcpyW(cfix.FaceName, L"MissingFont");
+ SetLastError(0xdeadbeef);
+ ret = SetCurrentConsoleFontEx(std_output, FALSE, &cfix);
+ todo_wine ok(ret, "got %d, expected non-zero\n", ret);
+ todo_wine ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError());
+
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.cbSize = sizeof(tmp);
+ ret = GetCurrentConsoleFontEx(std_output, FALSE, &tmp);
+ ok(ret, "got %d, expected non-zero\n", ret);
+ ok(tmp.nFont == cfix.nFont, "got %u, expected %u\n", tmp.nFont, cfix.nFont);
+ todo_wine ok(tmp.dwFontSize.X == cfix.dwFontSize.X, "got %u, expected font width of %u\n",
+ tmp.dwFontSize.X, cfix.dwFontSize.X);
+ todo_wine ok(tmp.dwFontSize.Y == cfix.dwFontSize.Y, "got %u, expected font height of %u\n",
+ tmp.dwFontSize.Y, cfix.dwFontSize.Y);
+ ok(tmp.FontFamily == cfix.FontFamily, "got %u, expected %u\n", tmp.FontFamily, cfix.FontFamily);
+ ok(tmp.FontWeight == cfix.FontWeight, "got %u, expected %u\n", tmp.FontWeight, cfix.FontWeight);
+ ok(!lstrcmpW(tmp.FaceName, face_name), "got %s, expected %s\n",
+ wine_dbgstr_w(tmp.FaceName), wine_dbgstr_w(face_name));
+
+ /* Test with no font face name */
+ cfix.FaceName[0] = 0;
+ SetLastError(0xdeadbeef);
+ ret = SetCurrentConsoleFontEx(std_output, FALSE, &cfix);
+ todo_wine ok(ret, "got %d, expected non-zero\n", ret);
+ todo_wine ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError());
+
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.cbSize = sizeof(tmp);
+ ret = GetCurrentConsoleFontEx(std_output, FALSE, &tmp);
+ ok(ret, "got %d, expected non-zero\n", ret);
+ ok(tmp.nFont == cfix.nFont, "got %u, expected %u\n", tmp.nFont, cfix.nFont);
+ todo_wine ok(tmp.dwFontSize.X == cfix.dwFontSize.X, "got %u, expected font width of %u\n",
+ tmp.dwFontSize.X, cfix.dwFontSize.X);
+ todo_wine ok(tmp.dwFontSize.Y == cfix.dwFontSize.Y, "got %u, expected font height of %u\n",
+ tmp.dwFontSize.Y, cfix.dwFontSize.Y);
+ ok(tmp.FontFamily == cfix.FontFamily, "got %u, expected %u\n", tmp.FontFamily, cfix.FontFamily);
+ ok(tmp.FontWeight == cfix.FontWeight, "got %u, expected %u\n", tmp.FontWeight, cfix.FontWeight);
+ ok(!lstrcmpW(tmp.FaceName, face_name), "got %s, expected %s\n",
+ wine_dbgstr_w(tmp.FaceName), wine_dbgstr_w(face_name));
+
/* Restore original console font parameters */
+ SetConsoleOutputCP(cp);
+
SetLastError(0xdeadbeef);
ret = SetCurrentConsoleFontEx(std_output, FALSE, &orig_cfix);
todo_wine ok(ret, "got %d, expected non-zero\n", ret);
--
2.33.1
1
1
Signed-off-by: Esme Povirk <esme(a)codeweavers.com>
---
Let's Build a Zoo on Steam creates a temporary file
and expects to be able to delete it while playing it.
dlls/mfplat/main.c | 2 +-
dlls/mfplat/tests/mfplat.c | 6 +++++-
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c
index 37a66798b2f..c36a2069bd8 100644
--- a/dlls/mfplat/main.c
+++ b/dlls/mfplat/main.c
@@ -4407,7 +4407,7 @@ HRESULT WINAPI MFCreateFile(MF_FILE_ACCESSMODE accessmode, MF_FILE_OPENMODE open
{
DWORD capabilities = MFBYTESTREAM_IS_SEEKABLE | MFBYTESTREAM_DOES_NOT_USE_NETWORK;
DWORD filecreation_disposition = 0, fileaccessmode = 0, fileattributes = 0;
- DWORD filesharemode = FILE_SHARE_READ;
+ DWORD filesharemode = FILE_SHARE_READ | FILE_SHARE_DELETE;
struct bytestream *object;
FILETIME writetime;
HANDLE file;
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
index 541459c715b..0f928284534 100644
--- a/dlls/mfplat/tests/mfplat.c
+++ b/dlls/mfplat/tests/mfplat.c
@@ -2077,10 +2077,14 @@ static void test_file_stream(void)
hr = MFCreateFile(MF_ACCESSMODE_READ, MF_OPENMODE_FAIL_IF_NOT_EXIST, MF_FILEFLAGS_NONE, pathW, &bytestream);
ok(FAILED(hr), "Unexpected hr %#x.\n", hr);
+ hr = MFCreateFile(MF_ACCESSMODE_READ, MF_OPENMODE_FAIL_IF_NOT_EXIST, MF_FILEFLAGS_NONE, filename, &bytestream);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(DeleteFileW(filename), "failed to delete file\n");
+ IMFByteStream_Release(bytestream);
+
hr = MFShutdown();
ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
- DeleteFileW(filename);
DeleteFileW(newfilename);
}
--
2.25.1
2
1
Nov. 15, 2021
This was changed from a unsigned int to a pointer in
e5d37832ee66d011ba572a9b571e9fb44a7b2b4d and this use was missed,
causing prefix creation hang if the allocated printers array is not
filled with zeros.
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
I'm also not sure to see why this was changed to a pointer, imho it's
a little more ugly than the integer, which would simply have to be
mapped on output for wow64 too and would have required less changes
overall? But maybe there was a specific reason?
dlls/winspool.drv/info.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/winspool.drv/info.c b/dlls/winspool.drv/info.c
index 3424c69d196..ac8f0994a1c 100644
--- a/dlls/winspool.drv/info.c
+++ b/dlls/winspool.drv/info.c
@@ -800,7 +800,7 @@ static BOOL init_unix_printers( void )
if (printer->is_default) default_printer = printer->name;
}
- if (!default_printer && enum_params.num) default_printer = enum_params.printers[0].name;
+ if (!default_printer && num) default_printer = enum_params.printers[0].name;
if (default_printer) SetDefaultPrinterW( default_printer );
if (ppd_dir)
--
2.33.1
3
2
[PATCH 6/6] winecoreaudio: Store the channel count and period_ms directly in the audio client.
by Huw Davies Nov. 15, 2021
by Huw Davies Nov. 15, 2021
Nov. 15, 2021
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/winecoreaudio.drv/mmdevdrv.c | 27 +++++++++++++++------------
1 file changed, 15 insertions(+), 12 deletions(-)
diff --git a/dlls/winecoreaudio.drv/mmdevdrv.c b/dlls/winecoreaudio.drv/mmdevdrv.c
index ebab18df75b..1e37a2a9026 100644
--- a/dlls/winecoreaudio.drv/mmdevdrv.c
+++ b/dlls/winecoreaudio.drv/mmdevdrv.c
@@ -124,6 +124,7 @@ struct ACImpl {
IUnknown *pUnkFTMarshal;
EDataFlow dataflow;
+ UINT32 channel_count, period_ms;
DWORD flags;
HANDLE event;
float *vols;
@@ -1179,7 +1180,7 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
ACImpl *This = impl_from_IAudioClient3(iface);
HRESULT hr;
OSStatus sc;
- int i;
+ UINT32 i;
TRACE("(%p)->(%x, %x, %s, %s, %p, %s)\n", This, mode, flags,
wine_dbgstr_longlong(duration), wine_dbgstr_longlong(period), fmt, debugstr_guid(sessionguid));
@@ -1342,7 +1343,12 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
This->stream->cap_buffer = HeapAlloc(GetProcessHeap(), 0, This->stream->cap_bufsize_frames * This->stream->fmt->nBlockAlign);
}
- This->vols = HeapAlloc(GetProcessHeap(), 0, fmt->nChannels * sizeof(float));
+ This->stream->share = mode;
+ This->flags = flags;
+ This->channel_count = fmt->nChannels;
+ This->period_ms = period / 10000;
+
+ This->vols = HeapAlloc(GetProcessHeap(), 0, This->channel_count * sizeof(float));
if(!This->vols){
CoTaskMemFree(This->stream->fmt);
This->stream->fmt = NULL;
@@ -1351,12 +1357,9 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
return E_OUTOFMEMORY;
}
- for(i = 0; i < fmt->nChannels; ++i)
+ for(i = 0; i < This->channel_count; ++i)
This->vols[i] = 1.f;
- This->stream->share = mode;
- This->flags = flags;
-
hr = get_audio_session(sessionguid, This->parent, fmt->nChannels,
&This->session);
if(FAILED(hr)){
@@ -1906,7 +1909,7 @@ static HRESULT WINAPI AudioClient_Start(IAudioClient3 *iface)
if(This->event && !This->timer)
if(!CreateTimerQueueTimer(&This->timer, g_timer_q, ca_period_cb,
- This, 0, This->stream->period_ms, WT_EXECUTEINTIMERTHREAD)){
+ This, 0, This->period_ms, WT_EXECUTEINTIMERTHREAD)){
This->timer = NULL;
OSSpinLockUnlock(&This->stream->lock);
WARN("Unable to create timer: %u\n", GetLastError());
@@ -3173,7 +3176,7 @@ static HRESULT WINAPI AudioStreamVolume_GetChannelCount(
if(!out)
return E_POINTER;
- *out = This->stream->fmt->nChannels;
+ *out = This->channel_count;
return S_OK;
}
@@ -3189,7 +3192,7 @@ static HRESULT WINAPI AudioStreamVolume_SetChannelVolume(
if(level < 0.f || level > 1.f)
return E_INVALIDARG;
- if(index >= This->stream->fmt->nChannels)
+ if(index >= This->channel_count)
return E_INVALIDARG;
EnterCriticalSection(&g_sessions_lock);
@@ -3214,7 +3217,7 @@ static HRESULT WINAPI AudioStreamVolume_GetChannelVolume(
if(!level)
return E_POINTER;
- if(index >= This->stream->fmt->nChannels)
+ if(index >= This->channel_count)
return E_INVALIDARG;
*level = This->vols[index];
@@ -3234,7 +3237,7 @@ static HRESULT WINAPI AudioStreamVolume_SetAllVolumes(
if(!levels)
return E_POINTER;
- if(count != This->stream->fmt->nChannels)
+ if(count != This->channel_count)
return E_INVALIDARG;
EnterCriticalSection(&g_sessions_lock);
@@ -3260,7 +3263,7 @@ static HRESULT WINAPI AudioStreamVolume_GetAllVolumes(
if(!levels)
return E_POINTER;
- if(count != This->stream->fmt->nChannels)
+ if(count != This->channel_count)
return E_INVALIDARG;
EnterCriticalSection(&g_sessions_lock);
--
2.23.0
1
0
[PATCH 5/6] winecoreaudio: Use the global lock to protect the audio client.
by Huw Davies Nov. 15, 2021
by Huw Davies Nov. 15, 2021
Nov. 15, 2021
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/winecoreaudio.drv/mmdevdrv.c | 115 +++++++++++++++---------------
1 file changed, 59 insertions(+), 56 deletions(-)
diff --git a/dlls/winecoreaudio.drv/mmdevdrv.c b/dlls/winecoreaudio.drv/mmdevdrv.c
index e82962db1ba..ebab18df75b 100644
--- a/dlls/winecoreaudio.drv/mmdevdrv.c
+++ b/dlls/winecoreaudio.drv/mmdevdrv.c
@@ -1234,16 +1234,19 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
}
}
- OSSpinLockLock(&This->stream->lock);
+ EnterCriticalSection(&g_sessions_lock);
if(This->initted){
- OSSpinLockUnlock(&This->stream->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return AUDCLNT_E_ALREADY_INITIALIZED;
}
+ OSSpinLockLock(&This->stream->lock);
+
This->stream->fmt = clone_format(fmt);
if(!This->stream->fmt){
OSSpinLockUnlock(&This->stream->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return E_OUTOFMEMORY;
}
@@ -1259,6 +1262,7 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
CoTaskMemFree(This->stream->fmt);
This->stream->fmt = NULL;
OSSpinLockUnlock(&This->stream->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return hr;
}
@@ -1278,6 +1282,7 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
CoTaskMemFree(This->stream->fmt);
This->stream->fmt = NULL;
OSSpinLockUnlock(&This->stream->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return osstatus_to_hresult(sc);
}
}else{
@@ -1294,6 +1299,7 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
CoTaskMemFree(This->stream->fmt);
This->stream->fmt = NULL;
OSSpinLockUnlock(&This->stream->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return osstatus_to_hresult(sc);
}
}
@@ -1308,6 +1314,7 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
CoTaskMemFree(This->stream->fmt);
This->stream->fmt = NULL;
OSSpinLockUnlock(&This->stream->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return osstatus_to_hresult(sc);
}
@@ -1323,6 +1330,7 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
CoTaskMemFree(This->stream->fmt);
This->stream->fmt = NULL;
OSSpinLockUnlock(&This->stream->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return osstatus_to_hresult(sc);
}
@@ -1339,6 +1347,7 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
CoTaskMemFree(This->stream->fmt);
This->stream->fmt = NULL;
OSSpinLockUnlock(&This->stream->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return E_OUTOFMEMORY;
}
@@ -1348,29 +1357,26 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
This->stream->share = mode;
This->flags = flags;
- EnterCriticalSection(&g_sessions_lock);
-
hr = get_audio_session(sessionguid, This->parent, fmt->nChannels,
&This->session);
if(FAILED(hr)){
- LeaveCriticalSection(&g_sessions_lock);
CoTaskMemFree(This->stream->fmt);
This->stream->fmt = NULL;
HeapFree(GetProcessHeap(), 0, This->vols);
This->vols = NULL;
OSSpinLockUnlock(&This->stream->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return E_INVALIDARG;
}
list_add_tail(&This->session->clients, &This->entry);
- LeaveCriticalSection(&g_sessions_lock);
-
ca_setvol(This, -1);
This->initted = TRUE;
OSSpinLockUnlock(&This->stream->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return S_OK;
}
@@ -1983,41 +1989,35 @@ static HRESULT WINAPI AudioClient_SetEventHandle(IAudioClient3 *iface,
HANDLE event)
{
ACImpl *This = impl_from_IAudioClient3(iface);
+ HRESULT hr = S_OK;
TRACE("(%p)->(%p)\n", This, event);
if(!event)
return E_INVALIDARG;
- OSSpinLockLock(&This->stream->lock);
-
- if(!This->initted){
- OSSpinLockUnlock(&This->stream->lock);
- return AUDCLNT_E_NOT_INITIALIZED;
- }
-
- if(!(This->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK)){
- OSSpinLockUnlock(&This->stream->lock);
- return AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED;
- }
+ EnterCriticalSection(&g_sessions_lock);
- if (This->event){
- OSSpinLockUnlock(&This->stream->lock);
+ if(!This->initted)
+ hr = AUDCLNT_E_NOT_INITIALIZED;
+ else if(!(This->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK))
+ hr = AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED;
+ else if(This->event){
FIXME("called twice\n");
- return HRESULT_FROM_WIN32(ERROR_INVALID_NAME);
- }
-
- This->event = event;
+ hr = HRESULT_FROM_WIN32(ERROR_INVALID_NAME);
+ }else
+ This->event = event;
- OSSpinLockUnlock(&This->stream->lock);
+ LeaveCriticalSection(&g_sessions_lock);
- return S_OK;
+ return hr;
}
static HRESULT WINAPI AudioClient_GetService(IAudioClient3 *iface, REFIID riid,
void **ppv)
{
ACImpl *This = impl_from_IAudioClient3(iface);
+ HRESULT hr;
TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
@@ -2025,24 +2025,24 @@ static HRESULT WINAPI AudioClient_GetService(IAudioClient3 *iface, REFIID riid,
return E_POINTER;
*ppv = NULL;
- OSSpinLockLock(&This->stream->lock);
+ EnterCriticalSection(&g_sessions_lock);
if(!This->initted){
- OSSpinLockUnlock(&This->stream->lock);
- return AUDCLNT_E_NOT_INITIALIZED;
+ hr = AUDCLNT_E_NOT_INITIALIZED;
+ goto end;
}
if(IsEqualIID(riid, &IID_IAudioRenderClient)){
if(This->dataflow != eRender){
- OSSpinLockUnlock(&This->stream->lock);
- return AUDCLNT_E_WRONG_ENDPOINT_TYPE;
+ hr = AUDCLNT_E_WRONG_ENDPOINT_TYPE;
+ goto end;
}
IAudioRenderClient_AddRef(&This->IAudioRenderClient_iface);
*ppv = &This->IAudioRenderClient_iface;
}else if(IsEqualIID(riid, &IID_IAudioCaptureClient)){
if(This->dataflow != eCapture){
- OSSpinLockUnlock(&This->stream->lock);
- return AUDCLNT_E_WRONG_ENDPOINT_TYPE;
+ hr = AUDCLNT_E_WRONG_ENDPOINT_TYPE;
+ goto end;
}
IAudioCaptureClient_AddRef(&This->IAudioCaptureClient_iface);
*ppv = &This->IAudioCaptureClient_iface;
@@ -2056,8 +2056,8 @@ static HRESULT WINAPI AudioClient_GetService(IAudioClient3 *iface, REFIID riid,
if(!This->session_wrapper){
This->session_wrapper = AudioSessionWrapper_Create(This);
if(!This->session_wrapper){
- OSSpinLockUnlock(&This->stream->lock);
- return E_OUTOFMEMORY;
+ hr = E_OUTOFMEMORY;
+ goto end;
}
}else
IAudioSessionControl2_AddRef(&This->session_wrapper->IAudioSessionControl2_iface);
@@ -2067,8 +2067,8 @@ static HRESULT WINAPI AudioClient_GetService(IAudioClient3 *iface, REFIID riid,
if(!This->session_wrapper){
This->session_wrapper = AudioSessionWrapper_Create(This);
if(!This->session_wrapper){
- OSSpinLockUnlock(&This->stream->lock);
- return E_OUTOFMEMORY;
+ hr = E_OUTOFMEMORY;
+ goto end;
}
}else
IChannelAudioVolume_AddRef(&This->session_wrapper->IChannelAudioVolume_iface);
@@ -2078,8 +2078,8 @@ static HRESULT WINAPI AudioClient_GetService(IAudioClient3 *iface, REFIID riid,
if(!This->session_wrapper){
This->session_wrapper = AudioSessionWrapper_Create(This);
if(!This->session_wrapper){
- OSSpinLockUnlock(&This->stream->lock);
- return E_OUTOFMEMORY;
+ hr = E_OUTOFMEMORY;
+ goto end;
}
}else
ISimpleAudioVolume_AddRef(&This->session_wrapper->ISimpleAudioVolume_iface);
@@ -2087,15 +2087,15 @@ static HRESULT WINAPI AudioClient_GetService(IAudioClient3 *iface, REFIID riid,
*ppv = &This->session_wrapper->ISimpleAudioVolume_iface;
}
- if(*ppv){
- OSSpinLockUnlock(&This->stream->lock);
- return S_OK;
+ if(*ppv) hr = S_OK;
+ else{
+ return E_NOINTERFACE;
+ FIXME("stub %s\n", debugstr_guid(riid));
}
- OSSpinLockUnlock(&This->stream->lock);
-
- FIXME("stub %s\n", debugstr_guid(riid));
- return E_NOINTERFACE;
+end:
+ LeaveCriticalSection(&g_sessions_lock);
+ return hr;
}
static HRESULT WINAPI AudioClient_IsOffloadCapable(IAudioClient3 *iface,
@@ -2749,17 +2749,20 @@ static ULONG WINAPI AudioSessionControl_Release(IAudioSessionControl2 *iface)
{
AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
ULONG ref;
+
+ EnterCriticalSection(&g_sessions_lock);
+
ref = InterlockedDecrement(&This->ref);
TRACE("(%p) Refcount now %u\n", This, ref);
if(!ref){
if(This->client){
- OSSpinLockLock(&This->client->stream->lock);
This->client->session_wrapper = NULL;
- OSSpinLockUnlock(&This->client->stream->lock);
AudioClient_Release(&This->client->IAudioClient3_iface);
}
HeapFree(GetProcessHeap(), 0, This);
}
+
+ LeaveCriticalSection(&g_sessions_lock);
return ref;
}
@@ -3189,14 +3192,14 @@ static HRESULT WINAPI AudioStreamVolume_SetChannelVolume(
if(index >= This->stream->fmt->nChannels)
return E_INVALIDARG;
- OSSpinLockLock(&This->stream->lock);
+ EnterCriticalSection(&g_sessions_lock);
This->vols[index] = level;
WARN("CoreAudio doesn't support per-channel volume control\n");
ret = ca_setvol(This, index);
- OSSpinLockUnlock(&This->stream->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return ret;
}
@@ -3223,7 +3226,7 @@ static HRESULT WINAPI AudioStreamVolume_SetAllVolumes(
IAudioStreamVolume *iface, UINT32 count, const float *levels)
{
ACImpl *This = impl_from_IAudioStreamVolume(iface);
- int i;
+ UINT32 i;
HRESULT ret;
TRACE("(%p)->(%d, %p)\n", This, count, levels);
@@ -3234,14 +3237,14 @@ static HRESULT WINAPI AudioStreamVolume_SetAllVolumes(
if(count != This->stream->fmt->nChannels)
return E_INVALIDARG;
- OSSpinLockLock(&This->stream->lock);
+ EnterCriticalSection(&g_sessions_lock);
for(i = 0; i < count; ++i)
This->vols[i] = levels[i];
ret = ca_setvol(This, -1);
- OSSpinLockUnlock(&This->stream->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return ret;
}
@@ -3250,7 +3253,7 @@ static HRESULT WINAPI AudioStreamVolume_GetAllVolumes(
IAudioStreamVolume *iface, UINT32 count, float *levels)
{
ACImpl *This = impl_from_IAudioStreamVolume(iface);
- int i;
+ UINT32 i;
TRACE("(%p)->(%d, %p)\n", This, count, levels);
@@ -3260,12 +3263,12 @@ static HRESULT WINAPI AudioStreamVolume_GetAllVolumes(
if(count != This->stream->fmt->nChannels)
return E_INVALIDARG;
- OSSpinLockLock(&This->stream->lock);
+ EnterCriticalSection(&g_sessions_lock);
for(i = 0; i < count; ++i)
levels[i] = This->vols[i];
- OSSpinLockUnlock(&This->stream->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return S_OK;
}
--
2.23.0
1
0
Nov. 15, 2021
Mainly just for simplicity.
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/winecoreaudio.drv/mmdevdrv.c | 21 ++++++++-------------
1 file changed, 8 insertions(+), 13 deletions(-)
diff --git a/dlls/winecoreaudio.drv/mmdevdrv.c b/dlls/winecoreaudio.drv/mmdevdrv.c
index 11be188d110..e82962db1ba 100644
--- a/dlls/winecoreaudio.drv/mmdevdrv.c
+++ b/dlls/winecoreaudio.drv/mmdevdrv.c
@@ -96,8 +96,6 @@ typedef struct _AudioSession {
float *channel_vols;
BOOL mute;
- CRITICAL_SECTION lock;
-
struct list entry;
} AudioSession;
@@ -827,9 +825,6 @@ static AudioSession *create_session(const GUID *guid, IMMDevice *device,
list_add_head(&g_sessions, &ret->entry);
- InitializeCriticalSection(&ret->lock);
- ret->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": AudioSession.lock");
-
session_init_vols(ret, num_channels);
ret->master_vol = 1.f;
@@ -3056,13 +3051,13 @@ static HRESULT WINAPI SimpleAudioVolume_SetMasterVolume(
if(context)
FIXME("Notifications not supported yet\n");
- EnterCriticalSection(&session->lock);
+ EnterCriticalSection(&g_sessions_lock);
session->master_vol = level;
ret = ca_session_setvol(session, -1);
- LeaveCriticalSection(&session->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return ret;
}
@@ -3094,13 +3089,13 @@ static HRESULT WINAPI SimpleAudioVolume_SetMute(ISimpleAudioVolume *iface,
if(context)
FIXME("Notifications not supported yet\n");
- EnterCriticalSection(&session->lock);
+ EnterCriticalSection(&g_sessions_lock);
session->mute = mute;
ca_session_setvol(session, -1);
- LeaveCriticalSection(&session->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return S_OK;
}
@@ -3356,14 +3351,14 @@ static HRESULT WINAPI ChannelAudioVolume_SetChannelVolume(
if(context)
FIXME("Notifications not supported yet\n");
- EnterCriticalSection(&session->lock);
+ EnterCriticalSection(&g_sessions_lock);
session->channel_vols[index] = level;
WARN("CoreAudio doesn't support per-channel volume control\n");
ret = ca_session_setvol(session, index);
- LeaveCriticalSection(&session->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return ret;
}
@@ -3408,14 +3403,14 @@ static HRESULT WINAPI ChannelAudioVolume_SetAllVolumes(
if(context)
FIXME("Notifications not supported yet\n");
- EnterCriticalSection(&session->lock);
+ EnterCriticalSection(&g_sessions_lock);
for(i = 0; i < count; ++i)
session->channel_vols[i] = levels[i];
ret = ca_session_setvol(session, -1);
- LeaveCriticalSection(&session->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return ret;
}
--
2.23.0
1
0