DWriteFactory: Make thread-safe

TODO: add comment about shared factory and concurrent accesses
This commit is contained in:
Luca Bacci 2026-03-04 16:23:28 +01:00
parent a13e660512
commit 132b149228
2 changed files with 64 additions and 78 deletions

View file

@ -180,14 +180,15 @@ private:
RefPtr<IWICImagingFactory> WICImagingFactory::mFactoryInstance; RefPtr<IWICImagingFactory> WICImagingFactory::mFactoryInstance;
cairo_atomic_once_t DWriteFactory::mOnceFactories = CAIRO_ATOMIC_ONCE_INIT;
RefPtr<IDWriteFactory> DWriteFactory::mFactoryInstance; RefPtr<IDWriteFactory> DWriteFactory::mFactoryInstance;
RefPtr<IDWriteFactory1> DWriteFactory::mFactoryInstance1; RefPtr<IDWriteFactory1> DWriteFactory::mFactoryInstance1;
RefPtr<IDWriteFactory2> DWriteFactory::mFactoryInstance2; RefPtr<IDWriteFactory2> DWriteFactory::mFactoryInstance2;
RefPtr<IDWriteFactory3> DWriteFactory::mFactoryInstance3; RefPtr<IDWriteFactory3> DWriteFactory::mFactoryInstance3;
RefPtr<IDWriteFactory4> DWriteFactory::mFactoryInstance4; RefPtr<IDWriteFactory4> DWriteFactory::mFactoryInstance4;
RefPtr<IDWriteFactory8> DWriteFactory::mFactoryInstance8; RefPtr<IDWriteFactory8> DWriteFactory::mFactoryInstance8;
cairo_atomic_once_t DWriteFactory::mOnceSystemCollection = CAIRO_ATOMIC_ONCE_INIT;
RefPtr<IDWriteFontCollection> DWriteFactory::mSystemCollection; RefPtr<IDWriteFontCollection> DWriteFactory::mSystemCollection;
RefPtr<IDWriteRenderingParams> DWriteFactory::mDefaultRenderingParams;
RefPtr<ID2D1Factory> D2DFactory::mFactoryInstance; RefPtr<ID2D1Factory> D2DFactory::mFactoryInstance;
@ -196,8 +197,15 @@ _create_rendering_params(IDWriteRenderingParams *params,
const cairo_font_options_t *options, const cairo_font_options_t *options,
cairo_antialias_t antialias) cairo_antialias_t antialias)
{ {
if (!params) RefPtr<IDWriteRenderingParams> default_rendering_params;
params = DWriteFactory::DefaultRenderingParams(); HRESULT hr;
if (!params) {
hr = DWriteFactory::Instance()->CreateRenderingParams(&default_rendering_params);
assert(SUCCEEDED(hr));
params = default_rendering_params.get();
}
FLOAT gamma = params->GetGamma(); FLOAT gamma = params->GetGamma();
FLOAT enhanced_contrast = params->GetEnhancedContrast(); FLOAT enhanced_contrast = params->GetEnhancedContrast();
FLOAT clear_type_level = params->GetClearTypeLevel(); FLOAT clear_type_level = params->GetClearTypeLevel();
@ -242,7 +250,6 @@ _create_rendering_params(IDWriteRenderingParams *params,
if (!modified) if (!modified)
return params; return params;
HRESULT hr;
RefPtr<IDWriteRenderingParams1> params1; RefPtr<IDWriteRenderingParams1> params1;
hr = params->QueryInterface(&params1); hr = params->QueryInterface(&params1);
if (FAILED(hr)) { if (FAILED(hr)) {

View file

@ -39,13 +39,6 @@
#include "dwrite-extra.hpp" #include "dwrite-extra.hpp"
#include "d2d1-extra.hpp" #include "d2d1-extra.hpp"
// DirectWrite is not available on all platforms.
typedef HRESULT (WINAPI*DWriteCreateFactoryFunc)(
DWRITE_FACTORY_TYPE factoryType,
REFIID iid,
IUnknown **factory
);
/* #cairo_scaled_font_t implementation */ /* #cairo_scaled_font_t implementation */
struct _cairo_dwrite_scaled_font { struct _cairo_dwrite_scaled_font {
cairo_scaled_font_t base; cairo_scaled_font_t base;
@ -63,96 +56,56 @@ class DWriteFactory
public: public:
static RefPtr<IDWriteFactory> Instance() static RefPtr<IDWriteFactory> Instance()
{ {
if (!mFactoryInstance) { InitializeFactories();
#ifdef __GNUC__ return mFactoryInstance;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-function-type"
#endif
HMODULE dwrite = _cairo_win32_load_library_from_system32 (L"dwrite.dll");
DWriteCreateFactoryFunc createDWriteFactory = (DWriteCreateFactoryFunc)
GetProcAddress(dwrite, "DWriteCreateFactory");
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
if (createDWriteFactory) {
HRESULT hr = createDWriteFactory(
DWRITE_FACTORY_TYPE_SHARED,
__uuidof(IDWriteFactory),
reinterpret_cast<IUnknown**>(&mFactoryInstance));
assert(SUCCEEDED(hr));
}
}
return mFactoryInstance;
} }
static RefPtr<IDWriteFactory1> Instance1() static RefPtr<IDWriteFactory1> Instance1()
{ {
if (!mFactoryInstance1) { InitializeFactories();
if (Instance()) { return mFactoryInstance1;
Instance()->QueryInterface(&mFactoryInstance1);
}
}
return mFactoryInstance1;
} }
static RefPtr<IDWriteFactory2> Instance2() static RefPtr<IDWriteFactory2> Instance2()
{ {
if (!mFactoryInstance2) { InitializeFactories();
if (Instance()) { return mFactoryInstance2;
Instance()->QueryInterface(&mFactoryInstance2);
}
}
return mFactoryInstance2;
} }
static RefPtr<IDWriteFactory3> Instance3() static RefPtr<IDWriteFactory3> Instance3()
{ {
if (!mFactoryInstance3) { InitializeFactories();
if (Instance()) { return mFactoryInstance3;
Instance()->QueryInterface(&mFactoryInstance3);
}
}
return mFactoryInstance3;
} }
static RefPtr<IDWriteFactory4> Instance4() static RefPtr<IDWriteFactory4> Instance4()
{ {
if (!mFactoryInstance4) { InitializeFactories();
if (Instance()) { return mFactoryInstance4;
Instance()->QueryInterface(&mFactoryInstance4);
}
}
return mFactoryInstance4;
} }
static RefPtr<IDWriteFactory8> Instance8() static RefPtr<IDWriteFactory8> Instance8()
{ {
if (!mFactoryInstance8) { InitializeFactories();
if (Instance()) {
Instance()->QueryInterface(&mFactoryInstance8);
}
}
return mFactoryInstance8; return mFactoryInstance8;
} }
static RefPtr<IDWriteFontCollection> SystemCollection() static RefPtr<IDWriteFontCollection> SystemCollection()
{ {
if (!mSystemCollection) { if (_cairo_atomic_init_once_enter (&mOnceSystemCollection)) {
if (Instance()) { HRESULT hr = Instance()->GetSystemFontCollection(&mSystemCollection);
HRESULT hr = Instance()->GetSystemFontCollection(&mSystemCollection); assert(SUCCEEDED(hr));
assert(SUCCEEDED(hr));
} _cairo_atomic_init_once_leave (&mOnceSystemCollection);
} }
return mSystemCollection; return mSystemCollection;
} }
static RefPtr<IDWriteFontFamily> FindSystemFontFamily(const WCHAR *aFamilyName) static RefPtr<IDWriteFontFamily> FindSystemFontFamily(const WCHAR *aFamilyName)
{ {
UINT32 idx; UINT32 idx;
BOOL found; BOOL found;
if (!SystemCollection()) {
return NULL;
}
SystemCollection()->FindFamilyName(aFamilyName, &idx, &found); SystemCollection()->FindFamilyName(aFamilyName, &idx, &found);
if (!found) { if (!found) {
return NULL; return NULL;
@ -163,25 +116,51 @@ public:
return family; return family;
} }
static RefPtr<IDWriteRenderingParams> DefaultRenderingParams() private:
static void InitializeFactories()
{ {
if (!mDefaultRenderingParams) { if (_cairo_atomic_init_once_enter (&mOnceFactories)) {
if (Instance()) { typedef HRESULT
Instance()->CreateRenderingParams(&mDefaultRenderingParams); (WINAPI *pDWriteCreateFactory_t) (DWRITE_FACTORY_TYPE factoryType,
} REFIID iid,
} IUnknown **factory);
return mDefaultRenderingParams;
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-function-type"
#endif
HMODULE dwrite = _cairo_win32_load_library_from_system32 (L"dwrite.dll");
pDWriteCreateFactory_t pDWriteCreateFactory = (pDWriteCreateFactory_t)
GetProcAddress (dwrite, "DWriteCreateFactory");
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
HRESULT hr = pDWriteCreateFactory (DWRITE_FACTORY_TYPE_SHARED,
__uuidof (IDWriteFactory),
reinterpret_cast<IUnknown**>(&mFactoryInstance));
assert(SUCCEEDED(hr));
mFactoryInstance->QueryInterface(&mFactoryInstance1);
mFactoryInstance->QueryInterface(&mFactoryInstance2);
mFactoryInstance->QueryInterface(&mFactoryInstance3);
mFactoryInstance->QueryInterface(&mFactoryInstance4);
mFactoryInstance->QueryInterface(&mFactoryInstance8);
_cairo_atomic_init_once_leave (&mOnceFactories);
}
} }
private: private:
static cairo_atomic_once_t mOnceFactories;
static RefPtr<IDWriteFactory> mFactoryInstance; static RefPtr<IDWriteFactory> mFactoryInstance;
static RefPtr<IDWriteFactory1> mFactoryInstance1; static RefPtr<IDWriteFactory1> mFactoryInstance1;
static RefPtr<IDWriteFactory2> mFactoryInstance2; static RefPtr<IDWriteFactory2> mFactoryInstance2;
static RefPtr<IDWriteFactory3> mFactoryInstance3; static RefPtr<IDWriteFactory3> mFactoryInstance3;
static RefPtr<IDWriteFactory4> mFactoryInstance4; static RefPtr<IDWriteFactory4> mFactoryInstance4;
static RefPtr<IDWriteFactory8> mFactoryInstance8; static RefPtr<IDWriteFactory8> mFactoryInstance8;
static cairo_atomic_once_t mOnceSystemCollection;
static RefPtr<IDWriteFontCollection> mSystemCollection; static RefPtr<IDWriteFontCollection> mSystemCollection;
static RefPtr<IDWriteRenderingParams> mDefaultRenderingParams;
}; };
class AutoDWriteGlyphRun : public DWRITE_GLYPH_RUN class AutoDWriteGlyphRun : public DWRITE_GLYPH_RUN