Commit 72590048 authored by Brendan McGrath's avatar Brendan McGrath Committed by Alexandre Julliard

d2d1: Acquire lock before attempt to draw to device context.

Ensures the Direct 2D lock is held before attempting to access Direct 2D exclusive resources. This fixes periodic crashes in PowerPoint 365
parent e6954d79
......@@ -171,6 +171,7 @@ struct d2d_device_context
const struct d2d_device_context_ops *ops;
ID2D1Factory *factory;
CRITICAL_SECTION *cs;
struct d2d_device *device;
ID3D11Device1 *d3d_device;
ID3DDeviceContextState *d3d_state;
......@@ -678,7 +679,29 @@ struct d2d_effect_registration
struct d2d_effect_properties properties;
};
struct d2d_factory;
struct d2d_factory
{
ID2D1Factory3 ID2D1Factory3_iface;
ID2D1Multithread ID2D1Multithread_iface;
LONG refcount;
ID3D10Device1 *device;
float dpi_x;
float dpi_y;
struct list effects;
INIT_ONCE init_builtins;
CRITICAL_SECTION cs;
D2D1_FACTORY_TYPE factory_type;
};
static inline struct d2d_factory *unsafe_impl_from_ID2D1Factory(ID2D1Factory *iface)
{
return CONTAINING_RECORD(iface, struct d2d_factory, ID2D1Factory3_iface);
}
void d2d_effects_init_builtins(struct d2d_factory *factory);
struct d2d_effect_registration * d2d_factory_get_registered_effect(ID2D1Factory *factory,
const GUID *effect_id);
......
......@@ -135,6 +135,9 @@ static void d2d_device_context_draw(struct d2d_device_context *render_target, en
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
if (render_target->cs)
EnterCriticalSection(render_target->cs);
ID3D11Device1_GetImmediateContext1(device, &context);
ID3D11DeviceContext1_SwapDeviceContextState(context, render_target->d3d_state, &prev_state);
......@@ -188,6 +191,9 @@ static void d2d_device_context_draw(struct d2d_device_context *render_target, en
ID3D11DeviceContext1_SwapDeviceContextState(context, prev_state, NULL);
ID3D11DeviceContext1_Release(context);
ID3DDeviceContextState_Release(prev_state);
if (render_target->cs)
LeaveCriticalSection(render_target->cs);
}
static void d2d_device_context_set_error(struct d2d_device_context *context, HRESULT code)
......@@ -3196,6 +3202,7 @@ static HRESULT d2d_device_context_init(struct d2d_device_context *render_target,
IDWriteFactory *dwrite_factory;
D3D11_RASTERIZER_DESC rs_desc;
D3D11_BUFFER_DESC buffer_desc;
struct d2d_factory *factory;
unsigned int i;
HRESULT hr;
......@@ -4256,6 +4263,10 @@ static HRESULT d2d_device_context_init(struct d2d_device_context *render_target,
render_target->device = device;
ID2D1Device1_AddRef(&render_target->device->ID2D1Device1_iface);
factory = unsafe_impl_from_ID2D1Factory(render_target->factory);
if (factory->factory_type == D2D1_FACTORY_TYPE_MULTI_THREADED)
render_target->cs = &factory->cs;
render_target->outer_unknown = outer_unknown ? outer_unknown : &render_target->IUnknown_iface;
render_target->ops = ops;
......
......@@ -36,33 +36,11 @@ static void d2d_effect_registration_cleanup(struct d2d_effect_registration *reg)
free(reg);
}
struct d2d_factory
{
ID2D1Factory3 ID2D1Factory3_iface;
ID2D1Multithread ID2D1Multithread_iface;
LONG refcount;
ID3D10Device1 *device;
float dpi_x;
float dpi_y;
struct list effects;
INIT_ONCE init_builtins;
CRITICAL_SECTION cs;
};
static inline struct d2d_factory *impl_from_ID2D1Factory3(ID2D1Factory3 *iface)
{
return CONTAINING_RECORD(iface, struct d2d_factory, ID2D1Factory3_iface);
}
static inline struct d2d_factory *unsafe_impl_from_ID2D1Factory(ID2D1Factory *iface)
{
return CONTAINING_RECORD(iface, struct d2d_factory, ID2D1Factory3_iface);
}
static inline struct d2d_factory *impl_from_ID2D1Multithread(ID2D1Multithread *iface)
{
return CONTAINING_RECORD(iface, struct d2d_factory, ID2D1Multithread_iface);
......@@ -1215,6 +1193,7 @@ static void d2d_factory_init(struct d2d_factory *factory, D2D1_FACTORY_TYPE fact
factory->ID2D1Factory3_iface.lpVtbl = &d2d_factory_vtbl;
factory->ID2D1Multithread_iface.lpVtbl = factory_type == D2D1_FACTORY_TYPE_SINGLE_THREADED ?
&d2d_factory_multithread_noop_vtbl : &d2d_factory_multithread_vtbl;
factory->factory_type = factory_type;
factory->refcount = 1;
d2d_factory_reload_sysmetrics(factory);
list_init(&factory->effects);
......
......@@ -10695,7 +10695,8 @@ static DWORD WINAPI mt_factory_test_thread_func(void *param)
return 0;
}
static DWORD WINAPI mt_factory_test_thread_draw_func(void *param) {
static DWORD WINAPI mt_factory_test_thread_draw_func(void *param)
{
ID2D1RenderTarget *rt = param;
D2D1_COLOR_F color;
HRESULT hr;
......@@ -10777,7 +10778,7 @@ static void test_mt_factory(BOOL d3d11)
thread = CreateThread(NULL, 0, mt_factory_test_thread_draw_func, ctx.rt, 0, NULL);
ok(!!thread, "Failed to create a thread.\n");
ret = WaitForSingleObject(thread, 1000);
todo_wine ok(ret == WAIT_TIMEOUT, "Expected timeout.\n");
ok(ret == WAIT_TIMEOUT, "Expected timeout.\n");
ID2D1Multithread_Leave(multithread);
WaitForSingleObject(thread, INFINITE);
CloseHandle(thread);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment