mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-19 14:38:10 +02:00
GDI: Use thread data for font HDC
Use the newly-introduced thread data structure to store the per-thread font HDC. As an added bonus, we can now avoid leaking HDCs on module unlaods.
This commit is contained in:
parent
a9229136ea
commit
1f5230dde0
4 changed files with 44 additions and 18 deletions
|
|
@ -143,19 +143,13 @@ _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font
|
|||
static HDC
|
||||
_get_global_font_dc (void)
|
||||
{
|
||||
static cairo_atomic_once_t once = CAIRO_ATOMIC_ONCE_INIT;
|
||||
static DWORD hdc_tls_index;
|
||||
HDC hdc;
|
||||
cairo_win32_thread_data_t *data = cairo_win32_thread_data_get ();
|
||||
|
||||
if (_cairo_atomic_init_once_enter (&once)) {
|
||||
hdc_tls_index = TlsAlloc ();
|
||||
assert (hdc_tls_index != TLS_OUT_OF_INDEXES);
|
||||
_cairo_atomic_init_once_leave (&once);
|
||||
}
|
||||
if (!data->hdc) {
|
||||
HDC hdc_screen = GetDC (NULL);
|
||||
HDC hdc;
|
||||
|
||||
hdc = TlsGetValue (hdc_tls_index);
|
||||
if (!hdc) {
|
||||
hdc = CreateCompatibleDC (NULL);
|
||||
hdc = CreateCompatibleDC (hdc_screen);
|
||||
if (!hdc) {
|
||||
fprintf (stderr, "%s:%s\n", __FUNCTION__, "CreateCompatibleDC");
|
||||
return NULL;
|
||||
|
|
@ -167,13 +161,19 @@ _get_global_font_dc (void)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (!TlsSetValue (hdc_tls_index, hdc)) {
|
||||
DeleteDC (hdc);
|
||||
return NULL;
|
||||
}
|
||||
data->hdc = hdc;
|
||||
/* From MSDN docs for CreateCompatibleDC:
|
||||
*
|
||||
* If [the reference] hdc is NULL, the thread that calls CreateCompatibleDC
|
||||
* owns the HDC that is created. When this thread is destroyed, the HDC is
|
||||
* no longer valid.
|
||||
*/
|
||||
data->free_hdc = (hdc_screen != NULL);
|
||||
|
||||
ReleaseDC (NULL, hdc_screen);
|
||||
}
|
||||
|
||||
return hdc;
|
||||
return data->hdc;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
|
|
|
|||
|
|
@ -36,14 +36,16 @@
|
|||
#ifndef CAIRO_WIN32_PRIVATE_H
|
||||
#define CAIRO_WIN32_PRIVATE_H
|
||||
|
||||
#include "cairo-win32.h"
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-device-private.h"
|
||||
#include "cairo-surface-clipper-private.h"
|
||||
#include "cairo-surface-private.h"
|
||||
|
||||
#include "cairo-win32.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#define WIN32_FONT_LOGICAL_SCALE 32
|
||||
|
||||
CAIRO_BEGIN_DECLS
|
||||
|
|
@ -236,7 +238,15 @@ cairo_win32_get_system_text_quality (void);
|
|||
HMODULE
|
||||
_cairo_win32_load_library_from_system32 (const wchar_t *name);
|
||||
|
||||
typedef DWORD (__stdcall *stdcall_free_func_t) (void *);
|
||||
|
||||
void
|
||||
cairo_win32_async_stdcall_free (stdcall_free_func_t func, void *data);
|
||||
|
||||
typedef struct {
|
||||
HDC hdc;
|
||||
cairo_bool_t free_hdc;
|
||||
|
||||
cairo_bool_t added_to_list;
|
||||
} cairo_win32_thread_data_t;
|
||||
|
||||
|
|
|
|||
|
|
@ -109,6 +109,12 @@ _cairo_win32_load_library_from_system32 (const wchar_t *name)
|
|||
return module_handle;
|
||||
}
|
||||
|
||||
void
|
||||
cairo_win32_async_stdcall_free (stdcall_free_func_t func, void *data)
|
||||
{
|
||||
QueueUserWorkItem (func, data, WT_EXECUTEDEFAULT);
|
||||
}
|
||||
|
||||
static void
|
||||
cairo_win32_initialize (void)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -97,6 +97,16 @@ thread_data_free (cairo_win32_thread_data_t *data)
|
|||
{
|
||||
/* Loader-lock-safe */
|
||||
|
||||
if (data->free_hdc) {
|
||||
/* Delete the HDC explicitly only if it was created via a non-NULL
|
||||
* reference HDC. Otherwise the system deletes it automatically on
|
||||
* thread-exit and our asynchronous delete would be racy. For more
|
||||
* informations, refer to the MSDN docs for CreateCompatibleDC.
|
||||
*/
|
||||
void *free_func = DeleteDC;
|
||||
cairo_win32_async_stdcall_free (free_func, data->hdc);
|
||||
}
|
||||
|
||||
#ifdef USE_EXPLICIT_TLS
|
||||
thread_data_allocation_free (data);
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue