D2DFactory: Make thread-safe

This commit is contained in:
Luca Bacci 2026-03-09 12:44:20 +01:00
parent 8a4b99f5a3
commit eede753027
3 changed files with 34 additions and 25 deletions

View file

@ -71,13 +71,6 @@
* Since: 1.18
**/
typedef HRESULT (WINAPI*D2D1CreateFactoryFunc)(
D2D1_FACTORY_TYPE factoryType,
REFIID iid,
CONST D2D1_FACTORY_OPTIONS *pFactoryOptions,
void **factory
);
#define CAIRO_INT_STATUS_SUCCESS (cairo_int_status_t)CAIRO_STATUS_SUCCESS
// Forward declarations
@ -133,31 +126,37 @@ class D2DFactory
public:
static RefPtr<ID2D1Factory> Instance()
{
if (!mFactoryInstance) {
cairo_win32_thread_data_t *thread_data = cairo_win32_thread_data_get ();
if (!thread_data->d2d1_factory) {
typedef HRESULT
(WINAPI *pD2D1CreateFactory_t) (D2D1_FACTORY_TYPE factoryType,
REFIID iid,
CONST D2D1_FACTORY_OPTIONS *pFactoryOptions,
void **factory);
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-function-type"
#endif
/* TODO */
HMODULE d2d1 = _cairo_win32_load_library_from_system32 (L"d2d1.dll");
D2D1CreateFactoryFunc createD2DFactory = (D2D1CreateFactoryFunc)
GetProcAddress(d2d1, "D2D1CreateFactory");
pD2D1CreateFactory_t pD2D1CreateFactory = (pD2D1CreateFactory_t)
GetProcAddress (d2d1, "D2D1CreateFactory");
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
if (createD2DFactory) {
D2D1_FACTORY_OPTIONS options;
options.debugLevel = D2D1_DEBUG_LEVEL_NONE;
createD2DFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED,
__uuidof(ID2D1Factory),
&options,
(void**)&mFactoryInstance);
}
}
return mFactoryInstance;
}
D2D1_FACTORY_OPTIONS options = {
.debugLevel = D2D1_DEBUG_LEVEL_NONE,
};
HRESULT hr = pD2D1CreateFactory (D2D1_FACTORY_TYPE_SINGLE_THREADED,
__uuidof (ID2D1Factory),
&options,
(void**) &thread_data->d2d1_factory);
assert (SUCCEEDED (hr));
}
private:
static RefPtr<ID2D1Factory> mFactoryInstance;
return thread_data->d2d1_factory;
}
};
class WICImagingFactory
@ -190,8 +189,6 @@ RefPtr<IDWriteFactory8> DWriteFactory::mFactoryInstance8;
cairo_atomic_once_t DWriteFactory::mOnceSystemCollection = CAIRO_ATOMIC_ONCE_INIT;
RefPtr<IDWriteFontCollection> DWriteFactory::mSystemCollection;
RefPtr<ID2D1Factory> D2DFactory::mFactoryInstance;
static RefPtr<IDWriteRenderingParams>
_create_rendering_params(IDWriteRenderingParams *params,
const cairo_font_options_t *options,

View file

@ -247,9 +247,17 @@ cairo_win32_async_stdcall_free (stdcall_free_func_t func, void *data);
void
cairo_win32_async_com_release (IUnknown *iface_ptr);
#if CAIRO_HAS_DWRITE_FONT
interface ID2D1Factory;
#endif
typedef struct {
HDC hdc;
#if CAIRO_HAS_DWRITE_FONT
interface ID2D1Factory *d2d1_factory;
#endif
cairo_bool_t added_to_list;
} cairo_win32_thread_data_t;

View file

@ -100,6 +100,10 @@ thread_data_free (cairo_win32_thread_data_t *data)
*/
cairo_win32_async_stdcall_free ((stdcall_free_func_t) DeleteDC, data->hdc);
#if CAIRO_HAS_DWRITE_FONT
cairo_win32_async_com_release ((IUnknown*) data->d2d1_factory);
#endif
#ifdef USE_EXPLICIT_TLS
thread_data_allocation_free (data);
#endif