From: Brendan McGrath bmcgrath@codeweavers.com
Ensures the Direct 2D lock is held before attempting to access Direct 2D exclusive resources.
This fixes periodic crashes in PowerPoint 365 --- dlls/d2d1/d2d1_private.h | 25 ++++++++++++++++++++++++- dlls/d2d1/device.c | 11 +++++++++++ dlls/d2d1/factory.c | 23 +---------------------- dlls/d2d1/tests/d2d1.c | 5 +++-- 4 files changed, 39 insertions(+), 25 deletions(-)
diff --git a/dlls/d2d1/d2d1_private.h b/dlls/d2d1/d2d1_private.h index 1dd5cdb0a39..36bedf8331c 100644 --- a/dlls/d2d1/d2d1_private.h +++ b/dlls/d2d1/d2d1_private.h @@ -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); diff --git a/dlls/d2d1/device.c b/dlls/d2d1/device.c index e5548878ee9..505bdc8c00e 100644 --- a/dlls/d2d1/device.c +++ b/dlls/d2d1/device.c @@ -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;
diff --git a/dlls/d2d1/factory.c b/dlls/d2d1/factory.c index 3b2b1f5e4ec..d349da376fc 100644 --- a/dlls/d2d1/factory.c +++ b/dlls/d2d1/factory.c @@ -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); diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index 3a8d97162fa..61177aba9de 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -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);