Module: wine Branch: master Commit: 72590048b26720b0bc1f2cd3e82578bce885de5c URL: https://gitlab.winehq.org/wine/wine/-/commit/72590048b26720b0bc1f2cd3e82578b...
Author: Brendan McGrath bmcgrath@codeweavers.com Date: Tue Nov 21 16:09:08 2023 +1100
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
---
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);