mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-15 17:18:05 +02:00
D2DFactory: Make thread-safe
This commit is contained in:
parent
61dc0938bf
commit
efd0cad9ae
3 changed files with 44 additions and 25 deletions
|
|
@ -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,41 @@ class D2DFactory
|
|||
public:
|
||||
static RefPtr<ID2D1Factory> Instance()
|
||||
{
|
||||
if (!mFactoryInstance) {
|
||||
/* According to MSDN, using independent, single-threaded D2D1 factories
|
||||
* in each thread is the most scalable solution.
|
||||
*/
|
||||
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 is based on nano-COM (just like DWrite), so there's no need
|
||||
* to ensure an apartment with CoInitializeEx or the implicit MTA.
|
||||
*/
|
||||
D2D1_FACTORY_OPTIONS options { 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
|
||||
|
|
@ -191,8 +194,6 @@ RefPtr<IWICImagingFactory> WICImagingFactory::mFactoryInstance;
|
|||
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,
|
||||
|
|
|
|||
|
|
@ -247,10 +247,18 @@ 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;
|
||||
cairo_bool_t free_hdc;
|
||||
|
||||
#if CAIRO_HAS_DWRITE_FONT
|
||||
interface ID2D1Factory *d2d1_factory;
|
||||
#endif
|
||||
|
||||
cairo_bool_t added_to_list;
|
||||
} cairo_win32_thread_data_t;
|
||||
|
||||
|
|
|
|||
|
|
@ -107,6 +107,16 @@ thread_data_free (cairo_win32_thread_data_t *data)
|
|||
cairo_win32_async_stdcall_free (free_func, data->hdc);
|
||||
}
|
||||
|
||||
#if CAIRO_HAS_DWRITE_FONT
|
||||
/* It's not clear if we can release DWrite objects from DllMain
|
||||
* or in general while holding the loader lock. For one, this
|
||||
* is not allowed for DXGI factories (refer to "DXGI responses
|
||||
* from DLLMain" in MSDN's "DXGI Overview"). Use an asynchronous
|
||||
* release to ensure safety.
|
||||
*/
|
||||
cairo_win32_async_com_release ((IUnknown*) data->d2d1_factory);
|
||||
#endif
|
||||
|
||||
#ifdef USE_EXPLICIT_TLS
|
||||
thread_data_allocation_free (data);
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue