mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-04 21:08:10 +02:00
[cairo-xlib] Split per-display attributes from per-screen.
Previously, we stored the per-display attributes inside a special screen=NULL _cairo_xlib_screen_info_t. Now we keep track of known X displays and store the screen information beneath the display structure alongside the per-display hooks.
This commit is contained in:
parent
9919f1ed9c
commit
dd8681b76b
8 changed files with 359 additions and 267 deletions
|
|
@ -47,8 +47,12 @@ endif
|
|||
|
||||
if CAIRO_HAS_XLIB_SURFACE
|
||||
libcairo_xlib_headers = cairo-xlib.h cairo-xlib-xrender.h
|
||||
libcairo_xlib_sources = cairo-xlib-surface.c cairo-xlib-surface-private.h \
|
||||
cairo-xlib-screen.c cairo-xlib-private.h
|
||||
libcairo_xlib_sources = cairo-xlib-surface.c \
|
||||
cairo-xlib-surface-private.h \
|
||||
cairo-xlib-display.c \
|
||||
cairo-xlib-screen.c \
|
||||
cairo-xlib-private.h \
|
||||
cairo-xlib-test.h
|
||||
backend_pkgconfigs += cairo-xlib.pc
|
||||
endif
|
||||
|
||||
|
|
|
|||
|
|
@ -59,10 +59,6 @@
|
|||
void
|
||||
cairo_debug_reset_static_data (void)
|
||||
{
|
||||
#if CAIRO_HAS_XLIB_SURFACE
|
||||
_cairo_xlib_screen_reset_static_data ();
|
||||
#endif
|
||||
|
||||
_cairo_font_reset_static_data ();
|
||||
|
||||
#if CAIRO_HAS_FT_FONT
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ CAIRO_MUTEX_DECLARE (_cairo_ft_unscaled_font_map_mutex);
|
|||
#endif
|
||||
|
||||
#if CAIRO_HAS_XLIB_SURFACE
|
||||
CAIRO_MUTEX_DECLARE (_cairo_xlib_screen_mutex);
|
||||
CAIRO_MUTEX_DECLARE (_cairo_xlib_display_mutex);
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
|||
258
src/cairo-xlib-display.c
Normal file
258
src/cairo-xlib-display.c
Normal file
|
|
@ -0,0 +1,258 @@
|
|||
/* Cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2007 Chris Wilson
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
* License version 2.1 as published by the Free Software Foundation
|
||||
* (the "LGPL") or, at your option, under the terms of the Mozilla
|
||||
* Public License Version 1.1 (the "MPL"). If you do not alter this
|
||||
* notice, a recipient may use your version of this file under either
|
||||
* the MPL or the LGPL.
|
||||
*
|
||||
* You should have received a copy of the LGPL along with this library
|
||||
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
|
||||
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
|
||||
* the specific language governing rights and limitations.
|
||||
*
|
||||
* The Original Code is the cairo graphics library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Chris Wilson.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-xlib-private.h"
|
||||
|
||||
#include <fontconfig/fontconfig.h>
|
||||
|
||||
#include <X11/Xlibint.h> /* For XESetCloseDisplay */
|
||||
#include <X11/extensions/Xrender.h>
|
||||
|
||||
|
||||
static cairo_xlib_display_t *_cairo_xlib_display_list = NULL;
|
||||
|
||||
static void
|
||||
_cairo_xlib_call_close_display_hooks (cairo_xlib_display_t *display)
|
||||
{
|
||||
cairo_xlib_hook_t *hooks;
|
||||
|
||||
/* call all registered shutdown routines */
|
||||
CAIRO_MUTEX_LOCK (display->mutex);
|
||||
hooks = display->close_display_hooks;
|
||||
while (hooks != NULL) {
|
||||
display->close_display_hooks = NULL;
|
||||
CAIRO_MUTEX_UNLOCK (display->mutex);
|
||||
|
||||
do {
|
||||
cairo_xlib_hook_t *hook = hooks;
|
||||
hooks = hook->next;
|
||||
|
||||
hook->func (display->display, hook->data);
|
||||
|
||||
free (hook);
|
||||
} while (hooks != NULL);
|
||||
|
||||
CAIRO_MUTEX_LOCK (display->mutex);
|
||||
hooks = display->close_display_hooks;
|
||||
}
|
||||
display->closed = TRUE;
|
||||
CAIRO_MUTEX_UNLOCK (display->mutex);
|
||||
}
|
||||
|
||||
cairo_xlib_display_t *
|
||||
_cairo_xlib_display_reference (cairo_xlib_display_t *display)
|
||||
{
|
||||
if (display == NULL)
|
||||
return NULL;
|
||||
|
||||
/* use our mutex until we get a real atomic inc */
|
||||
CAIRO_MUTEX_LOCK (display->mutex);
|
||||
|
||||
assert (display->ref_count > 0);
|
||||
display->ref_count++;
|
||||
|
||||
CAIRO_MUTEX_UNLOCK (display->mutex);
|
||||
|
||||
return display;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_xlib_display_destroy (cairo_xlib_display_t *display)
|
||||
{
|
||||
if (display == NULL)
|
||||
return;
|
||||
|
||||
CAIRO_MUTEX_LOCK (display->mutex);
|
||||
assert (display->ref_count > 0);
|
||||
if (--display->ref_count == 0) {
|
||||
CAIRO_MUTEX_UNLOCK (display->mutex);
|
||||
|
||||
free (display);
|
||||
} else
|
||||
CAIRO_MUTEX_UNLOCK (display->mutex);
|
||||
}
|
||||
|
||||
static int
|
||||
_cairo_xlib_close_display (Display *dpy, XExtCodes *codes)
|
||||
{
|
||||
cairo_xlib_display_t *display, **prev, *next;
|
||||
|
||||
/*
|
||||
* Unhook from the global list
|
||||
*/
|
||||
CAIRO_MUTEX_LOCK (_cairo_xlib_display_mutex);
|
||||
prev = &_cairo_xlib_display_list;
|
||||
for (display = _cairo_xlib_display_list; display; display = next) {
|
||||
next = display->next;
|
||||
if (display->display == dpy) {
|
||||
/* drop the list mutex whilst triggering the hooks */
|
||||
CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex);
|
||||
|
||||
_cairo_xlib_call_close_display_hooks (display);
|
||||
_cairo_xlib_display_destroy (display);
|
||||
|
||||
CAIRO_MUTEX_LOCK (_cairo_xlib_display_mutex);
|
||||
*prev = next;
|
||||
break;
|
||||
} else
|
||||
prev = &display->next;
|
||||
}
|
||||
CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex);
|
||||
|
||||
/* Return value in accordance with requirements of
|
||||
* XESetCloseDisplay */
|
||||
return 0;
|
||||
}
|
||||
|
||||
cairo_xlib_display_t *
|
||||
_cairo_xlib_display_get (Display *dpy)
|
||||
{
|
||||
cairo_xlib_display_t *display;
|
||||
cairo_xlib_display_t **prev;
|
||||
XExtCodes *codes;
|
||||
|
||||
/* There is an apparent deadlock between this mutex and the
|
||||
* mutex for the display, but it's actually safe. For the
|
||||
* app to call XCloseDisplay() while any other thread is
|
||||
* inside this function would be an error in the logic
|
||||
* app, and the CloseDisplay hook is the only other place we
|
||||
* acquire this mutex.
|
||||
*/
|
||||
CAIRO_MUTEX_LOCK (_cairo_xlib_display_mutex);
|
||||
|
||||
for (prev = &_cairo_xlib_display_list; (display = *prev); prev = &(*prev)->next)
|
||||
{
|
||||
if (display->display == dpy) {
|
||||
/*
|
||||
* MRU the list
|
||||
*/
|
||||
if (prev != &_cairo_xlib_display_list) {
|
||||
*prev = display->next;
|
||||
display->next = _cairo_xlib_display_list;
|
||||
_cairo_xlib_display_list = display;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (display != NULL) {
|
||||
display = _cairo_xlib_display_reference (display);
|
||||
goto UNLOCK;
|
||||
}
|
||||
|
||||
display = malloc (sizeof (cairo_xlib_display_t));
|
||||
if (display == NULL)
|
||||
goto UNLOCK;
|
||||
|
||||
codes = XAddExtension (dpy);
|
||||
if (codes == NULL) {
|
||||
free (display);
|
||||
display = NULL;
|
||||
goto UNLOCK;
|
||||
}
|
||||
|
||||
XESetCloseDisplay (dpy, codes->extension, _cairo_xlib_close_display);
|
||||
|
||||
display->ref_count = 2; /* add one for the CloseDisplay */
|
||||
CAIRO_MUTEX_INIT (display->mutex);
|
||||
display->display = dpy;
|
||||
display->screens = NULL;
|
||||
display->close_display_hooks = NULL;
|
||||
display->closed = FALSE;
|
||||
|
||||
display->next = _cairo_xlib_display_list;
|
||||
_cairo_xlib_display_list = display;
|
||||
|
||||
UNLOCK:
|
||||
CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex);
|
||||
return display;
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
_cairo_xlib_add_close_display_hook (Display *dpy, void (*func) (Display *, void *), void *data, const void *key)
|
||||
{
|
||||
cairo_xlib_display_t *display;
|
||||
cairo_xlib_hook_t *hook;
|
||||
cairo_bool_t ret = FALSE;
|
||||
|
||||
display = _cairo_xlib_display_get (dpy);
|
||||
if (display == NULL)
|
||||
return FALSE;
|
||||
|
||||
hook = malloc (sizeof (cairo_xlib_hook_t));
|
||||
if (hook != NULL) {
|
||||
hook->func = func;
|
||||
hook->data = data;
|
||||
hook->key = key;
|
||||
|
||||
CAIRO_MUTEX_LOCK (display->mutex);
|
||||
if (display->closed == FALSE) {
|
||||
hook->next = display->close_display_hooks;
|
||||
display->close_display_hooks = hook;
|
||||
ret = TRUE;
|
||||
}
|
||||
CAIRO_MUTEX_UNLOCK (display->mutex);
|
||||
}
|
||||
|
||||
_cairo_xlib_display_destroy (display);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_xlib_remove_close_display_hooks (Display *dpy, const void *key)
|
||||
{
|
||||
cairo_xlib_display_t *display;
|
||||
cairo_xlib_hook_t *hook, *next, **prev;
|
||||
|
||||
display = _cairo_xlib_display_get (dpy);
|
||||
if (display == NULL)
|
||||
return;
|
||||
|
||||
CAIRO_MUTEX_LOCK (display->mutex);
|
||||
prev = &display->close_display_hooks;
|
||||
for (hook = display->close_display_hooks; hook != NULL; hook = next) {
|
||||
next = hook->next;
|
||||
if (hook->key == key) {
|
||||
*prev = hook->next;
|
||||
free (hook);
|
||||
} else
|
||||
prev = &hook->next;
|
||||
}
|
||||
*prev = NULL;
|
||||
CAIRO_MUTEX_UNLOCK (display->mutex);
|
||||
|
||||
_cairo_xlib_display_destroy (display);
|
||||
}
|
||||
|
|
@ -36,28 +36,53 @@
|
|||
#include "cairoint.h"
|
||||
#include "cairo-xlib.h"
|
||||
|
||||
typedef struct _cairo_xlib_display cairo_xlib_display_t;
|
||||
typedef struct _cairo_xlib_hook cairo_xlib_hook_t;
|
||||
|
||||
struct _cairo_xlib_hook {
|
||||
cairo_xlib_hook_t *next;
|
||||
void (*func) (Display *display, void *data);
|
||||
void *data;
|
||||
void *key;
|
||||
const void *key;
|
||||
};
|
||||
|
||||
struct _cairo_xlib_display {
|
||||
cairo_xlib_display_t *next;
|
||||
unsigned int ref_count;
|
||||
cairo_mutex_t mutex;
|
||||
|
||||
Display *display;
|
||||
cairo_xlib_screen_info_t *screens;
|
||||
|
||||
cairo_xlib_hook_t *close_display_hooks;
|
||||
unsigned int closed :1;
|
||||
};
|
||||
|
||||
struct _cairo_xlib_screen_info {
|
||||
cairo_xlib_screen_info_t *next;
|
||||
unsigned int ref_count;
|
||||
|
||||
Display *display;
|
||||
cairo_xlib_display_t *display;
|
||||
Screen *screen;
|
||||
cairo_bool_t has_render;
|
||||
|
||||
cairo_font_options_t font_options;
|
||||
|
||||
cairo_xlib_hook_t *close_display_hooks;
|
||||
};
|
||||
|
||||
cairo_private cairo_xlib_display_t *
|
||||
_cairo_xlib_display_get (Display *display);
|
||||
|
||||
cairo_private cairo_xlib_display_t *
|
||||
_cairo_xlib_display_reference (cairo_xlib_display_t *info);
|
||||
cairo_private void
|
||||
_cairo_xlib_display_destroy (cairo_xlib_display_t *info);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_xlib_add_close_display_hook (Display *display, void (*func) (Display *, void *), void *data, const void *key);
|
||||
cairo_private void
|
||||
_cairo_xlib_remove_close_display_hooks (Display *display, const void *key);
|
||||
|
||||
|
||||
cairo_private cairo_xlib_screen_info_t *
|
||||
_cairo_xlib_screen_info_get (Display *display, Screen *screen);
|
||||
|
||||
|
|
@ -66,10 +91,6 @@ _cairo_xlib_screen_info_reference (cairo_xlib_screen_info_t *info);
|
|||
cairo_private void
|
||||
_cairo_xlib_screen_info_destroy (cairo_xlib_screen_info_t *info);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_xlib_add_close_display_hook (Display *display, void (*func) (Display *, void *), void *data, void *key);
|
||||
cairo_private void
|
||||
_cairo_xlib_remove_close_display_hook (Display *display, void *key);
|
||||
|
||||
#if CAIRO_HAS_XLIB_XRENDER_SURFACE
|
||||
|
||||
|
|
|
|||
|
|
@ -58,7 +58,6 @@
|
|||
|
||||
#include <fontconfig/fontconfig.h>
|
||||
|
||||
#include <X11/Xlibint.h> /* For XESetCloseDisplay */
|
||||
#include <X11/extensions/Xrender.h>
|
||||
|
||||
static int
|
||||
|
|
@ -133,7 +132,7 @@ get_integer_default (Display *dpy,
|
|||
#endif
|
||||
|
||||
static void
|
||||
_cairo_xlib_init_screen_font_options (cairo_xlib_screen_info_t *info)
|
||||
_cairo_xlib_init_screen_font_options (Display *dpy, cairo_xlib_screen_info_t *info)
|
||||
{
|
||||
cairo_bool_t xft_hinting;
|
||||
cairo_bool_t xft_antialias;
|
||||
|
|
@ -143,23 +142,23 @@ _cairo_xlib_init_screen_font_options (cairo_xlib_screen_info_t *info)
|
|||
cairo_subpixel_order_t subpixel_order;
|
||||
cairo_hint_style_t hint_style;
|
||||
|
||||
if (!get_boolean_default (info->display, "antialias", &xft_antialias))
|
||||
if (!get_boolean_default (dpy, "antialias", &xft_antialias))
|
||||
xft_antialias = TRUE;
|
||||
|
||||
if (!get_boolean_default (info->display, "hinting", &xft_hinting))
|
||||
if (!get_boolean_default (dpy, "hinting", &xft_hinting))
|
||||
xft_hinting = TRUE;
|
||||
|
||||
if (!get_integer_default (info->display, "hintstyle", &xft_hintstyle))
|
||||
if (!get_integer_default (dpy, "hintstyle", &xft_hintstyle))
|
||||
xft_hintstyle = FC_HINT_FULL;
|
||||
|
||||
if (!get_integer_default (info->display, "rgba", &xft_rgba))
|
||||
if (!get_integer_default (dpy, "rgba", &xft_rgba))
|
||||
{
|
||||
xft_rgba = FC_RGBA_UNKNOWN;
|
||||
|
||||
#if RENDER_MAJOR > 0 || RENDER_MINOR >= 6
|
||||
if (info->has_render)
|
||||
{
|
||||
int render_order = XRenderQuerySubpixelOrder (info->display,
|
||||
int render_order = XRenderQuerySubpixelOrder (dpy,
|
||||
XScreenNumberOfScreen (info->screen));
|
||||
|
||||
switch (render_order)
|
||||
|
|
@ -243,37 +242,6 @@ _cairo_xlib_init_screen_font_options (cairo_xlib_screen_info_t *info)
|
|||
cairo_font_options_set_hint_metrics (&info->font_options, CAIRO_HINT_METRICS_ON);
|
||||
}
|
||||
|
||||
static cairo_xlib_screen_info_t *_cairo_xlib_screen_list = NULL;
|
||||
|
||||
/* NOTE: This function must be called with _cairo_xlib_screen_mutex held. */
|
||||
static void
|
||||
_cairo_xlib_call_close_display_hooks (cairo_xlib_screen_info_t *info)
|
||||
{
|
||||
/* call all registered shutdown routines */
|
||||
while (info->close_display_hooks != NULL) {
|
||||
cairo_xlib_hook_t *hooks = info->close_display_hooks;
|
||||
info->close_display_hooks = NULL;
|
||||
|
||||
/* drop the list mutex whilst calling the hooks */
|
||||
CAIRO_MUTEX_UNLOCK (_cairo_xlib_screen_mutex);
|
||||
do {
|
||||
cairo_xlib_hook_t *hook = hooks;
|
||||
hooks = hook->next;
|
||||
|
||||
hook->func (info->display, hook->data);
|
||||
|
||||
free (hook);
|
||||
} while (hooks != NULL);
|
||||
CAIRO_MUTEX_LOCK (_cairo_xlib_screen_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_xlib_screen_info_reference_lock_held (cairo_xlib_screen_info_t *info)
|
||||
{
|
||||
assert (info->ref_count > 0);
|
||||
info->ref_count++;
|
||||
}
|
||||
|
||||
cairo_xlib_screen_info_t *
|
||||
_cairo_xlib_screen_info_reference (cairo_xlib_screen_info_t *info)
|
||||
|
|
@ -281,247 +249,98 @@ _cairo_xlib_screen_info_reference (cairo_xlib_screen_info_t *info)
|
|||
if (info == NULL)
|
||||
return NULL;
|
||||
|
||||
/* use our global mutex until we get a real atomic inc */
|
||||
CAIRO_MUTEX_LOCK (_cairo_xlib_screen_mutex);
|
||||
|
||||
_cairo_xlib_screen_info_reference_lock_held (info);
|
||||
|
||||
CAIRO_MUTEX_UNLOCK (_cairo_xlib_screen_mutex);
|
||||
assert (info->ref_count > 0);
|
||||
info->ref_count++;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_xlib_screen_info_destroy_lock_held (cairo_xlib_screen_info_t *info)
|
||||
{
|
||||
assert (info->ref_count > 0);
|
||||
if (--info->ref_count)
|
||||
return;
|
||||
|
||||
_cairo_xlib_call_close_display_hooks (info);
|
||||
free (info);
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_xlib_screen_info_destroy (cairo_xlib_screen_info_t *info)
|
||||
{
|
||||
cairo_xlib_screen_info_t **prev;
|
||||
cairo_xlib_screen_info_t *list;
|
||||
|
||||
if (info == NULL)
|
||||
return;
|
||||
|
||||
CAIRO_MUTEX_LOCK (_cairo_xlib_screen_mutex);
|
||||
assert (info->ref_count > 0);
|
||||
if (--info->ref_count)
|
||||
return;
|
||||
|
||||
_cairo_xlib_screen_info_destroy_lock_held (info);
|
||||
|
||||
CAIRO_MUTEX_UNLOCK (_cairo_xlib_screen_mutex);
|
||||
}
|
||||
|
||||
static int
|
||||
_cairo_xlib_close_display (Display *dpy, XExtCodes *codes)
|
||||
{
|
||||
cairo_xlib_screen_info_t *info, **prev, *next;
|
||||
|
||||
/*
|
||||
* Unhook from the global list
|
||||
*/
|
||||
CAIRO_MUTEX_LOCK (_cairo_xlib_screen_mutex);
|
||||
|
||||
prev = &_cairo_xlib_screen_list;
|
||||
for (info = _cairo_xlib_screen_list; info; info = next) {
|
||||
next = info->next;
|
||||
if (info->display == dpy) {
|
||||
/* trigger the hooks explicitly as we know the display is closing */
|
||||
_cairo_xlib_call_close_display_hooks (info);
|
||||
_cairo_xlib_screen_info_destroy_lock_held (info);
|
||||
*prev = next;
|
||||
} else {
|
||||
prev = &info->next;
|
||||
CAIRO_MUTEX_LOCK (info->display->mutex);
|
||||
for (prev = &info->display->screens; (list = *prev); prev = &list->next) {
|
||||
if (list == info) {
|
||||
*prev = info->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*prev = NULL;
|
||||
CAIRO_MUTEX_UNLOCK (_cairo_xlib_screen_mutex);
|
||||
assert (list != NULL);
|
||||
CAIRO_MUTEX_UNLOCK (info->display->mutex);
|
||||
|
||||
/* Return value in accordance with requirements of
|
||||
* XESetCloseDisplay */
|
||||
return 0;
|
||||
_cairo_xlib_display_destroy (info->display);
|
||||
|
||||
free (info);
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_xlib_screen_info_reset (void)
|
||||
{
|
||||
/*
|
||||
* Delete everything in the list.
|
||||
*/
|
||||
CAIRO_MUTEX_LOCK (_cairo_xlib_screen_mutex);
|
||||
|
||||
while (_cairo_xlib_screen_list != NULL) {
|
||||
cairo_xlib_screen_info_t *info = _cairo_xlib_screen_list;
|
||||
_cairo_xlib_screen_list = info->next;
|
||||
_cairo_xlib_screen_info_destroy_lock_held (info);
|
||||
}
|
||||
|
||||
CAIRO_MUTEX_UNLOCK (_cairo_xlib_screen_mutex);
|
||||
|
||||
}
|
||||
|
||||
static cairo_xlib_screen_info_t *
|
||||
_cairo_xlib_screen_info_get_lock_held (Display *dpy, Screen *screen)
|
||||
{
|
||||
cairo_xlib_screen_info_t *info;
|
||||
cairo_xlib_screen_info_t **prev;
|
||||
int event_base, error_base;
|
||||
XExtCodes *codes;
|
||||
cairo_bool_t seen_display = FALSE;
|
||||
|
||||
for (prev = &_cairo_xlib_screen_list; (info = *prev); prev = &(*prev)->next)
|
||||
{
|
||||
if (info->display == dpy) {
|
||||
seen_display = TRUE;
|
||||
if (info->screen == screen) {
|
||||
/*
|
||||
* MRU the list
|
||||
*/
|
||||
if (prev != &_cairo_xlib_screen_list) {
|
||||
*prev = info->next;
|
||||
info->next = _cairo_xlib_screen_list;
|
||||
_cairo_xlib_screen_list = info;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (info)
|
||||
return info;
|
||||
|
||||
info = malloc (sizeof (cairo_xlib_screen_info_t));
|
||||
if (!info)
|
||||
return NULL;
|
||||
|
||||
if (!seen_display) {
|
||||
codes = XAddExtension (dpy);
|
||||
if (!codes) {
|
||||
free (info);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
XESetCloseDisplay (dpy, codes->extension, _cairo_xlib_close_display);
|
||||
}
|
||||
|
||||
info->ref_count = 1;
|
||||
info->display = dpy;
|
||||
info->screen = screen;
|
||||
info->close_display_hooks = NULL;
|
||||
info->has_render = FALSE;
|
||||
_cairo_font_options_init_default (&info->font_options);
|
||||
|
||||
if (screen) {
|
||||
info->has_render = (XRenderQueryExtension (dpy, &event_base, &error_base) &&
|
||||
(XRenderFindVisualFormat (dpy, DefaultVisual (dpy, DefaultScreen (dpy))) != 0));
|
||||
_cairo_xlib_init_screen_font_options (info);
|
||||
}
|
||||
|
||||
info->next = _cairo_xlib_screen_list;
|
||||
_cairo_xlib_screen_list = info;
|
||||
|
||||
return info;
|
||||
}
|
||||
cairo_xlib_screen_info_t *
|
||||
_cairo_xlib_screen_info_get (Display *dpy, Screen *screen)
|
||||
{
|
||||
cairo_xlib_screen_info_t *info;
|
||||
cairo_xlib_display_t *display;
|
||||
cairo_xlib_screen_info_t *info = NULL, **prev;
|
||||
|
||||
/* There is an apparent deadlock between this mutex and the
|
||||
* mutex for the display, but it's actually safe. For the
|
||||
* app to call XCloseDisplay() while any other thread is
|
||||
* inside this function would be an error in the logic
|
||||
* app, and the CloseDisplay hook is the only other place we
|
||||
* acquire this mutex.
|
||||
*/
|
||||
CAIRO_MUTEX_LOCK (_cairo_xlib_screen_mutex);
|
||||
display = _cairo_xlib_display_get (dpy);
|
||||
if (display == NULL)
|
||||
return NULL;
|
||||
|
||||
info = _cairo_xlib_screen_info_get_lock_held (dpy, screen);
|
||||
if (info != NULL)
|
||||
_cairo_xlib_screen_info_reference_lock_held (info);
|
||||
CAIRO_MUTEX_LOCK (display->mutex);
|
||||
if (display->closed) {
|
||||
CAIRO_MUTEX_UNLOCK (display->mutex);
|
||||
goto DONE;
|
||||
}
|
||||
|
||||
CAIRO_MUTEX_UNLOCK (_cairo_xlib_screen_mutex);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
_cairo_xlib_add_close_display_hook (Display *dpy, void (*func) (Display *, void *), void *data, void *key)
|
||||
{
|
||||
cairo_xlib_screen_info_t *info;
|
||||
cairo_xlib_hook_t *hook;
|
||||
cairo_xlib_hook_t **prev;
|
||||
cairo_bool_t success = FALSE;
|
||||
|
||||
CAIRO_MUTEX_LOCK (_cairo_xlib_screen_mutex);
|
||||
|
||||
info = _cairo_xlib_screen_info_get_lock_held (dpy, NULL);
|
||||
if (!info)
|
||||
goto unlock;
|
||||
|
||||
for (prev = &info->close_display_hooks; (hook = *prev); prev = &hook->next)
|
||||
{
|
||||
if (hook->key == key) {
|
||||
for (prev = &display->screens; (info = *prev); prev = &(*prev)->next) {
|
||||
if (info->screen == screen) {
|
||||
/*
|
||||
* MRU the list
|
||||
*/
|
||||
if (prev != &info->close_display_hooks) {
|
||||
*prev = hook->next;
|
||||
hook->next = info->close_display_hooks;
|
||||
info->close_display_hooks = hook;
|
||||
if (prev != &display->screens) {
|
||||
*prev = info->next;
|
||||
info->next = display->screens;
|
||||
display->screens = info;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
CAIRO_MUTEX_UNLOCK (display->mutex);
|
||||
|
||||
if (!hook) {
|
||||
hook = malloc (sizeof (cairo_xlib_hook_t));
|
||||
if (!hook)
|
||||
goto unlock;
|
||||
hook->func = func;
|
||||
hook->data = data;
|
||||
hook->key = key;
|
||||
hook->next = info->close_display_hooks;
|
||||
info->close_display_hooks = hook;
|
||||
}
|
||||
if (info != NULL) {
|
||||
info = _cairo_xlib_screen_info_reference (info);
|
||||
} else {
|
||||
info = malloc (sizeof (cairo_xlib_screen_info_t));
|
||||
if (info != NULL) {
|
||||
info->ref_count = 1;
|
||||
info->display = _cairo_xlib_display_reference (display);
|
||||
info->screen = screen;
|
||||
info->has_render = FALSE;
|
||||
_cairo_font_options_init_default (&info->font_options);
|
||||
|
||||
success = TRUE;
|
||||
unlock:
|
||||
CAIRO_MUTEX_UNLOCK (_cairo_xlib_screen_mutex);
|
||||
return success;
|
||||
}
|
||||
if (screen) {
|
||||
int event_base, error_base;
|
||||
info->has_render = (XRenderQueryExtension (dpy, &event_base, &error_base) &&
|
||||
(XRenderFindVisualFormat (dpy, DefaultVisual (dpy, DefaultScreen (dpy))) != 0));
|
||||
_cairo_xlib_init_screen_font_options (dpy, info);
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_xlib_remove_close_display_hook (Display *dpy, void *key)
|
||||
{
|
||||
cairo_xlib_screen_info_t *info;
|
||||
cairo_xlib_hook_t *hook;
|
||||
cairo_xlib_hook_t **prev;
|
||||
|
||||
CAIRO_MUTEX_LOCK (_cairo_xlib_screen_mutex);
|
||||
|
||||
info = _cairo_xlib_screen_info_get_lock_held (dpy, NULL);
|
||||
if (!info)
|
||||
goto unlock;
|
||||
|
||||
for (prev = &info->close_display_hooks; (hook = *prev); prev = &hook->next)
|
||||
{
|
||||
if (hook->key == key) {
|
||||
*prev = hook->next;
|
||||
free (hook);
|
||||
break;
|
||||
CAIRO_MUTEX_LOCK (display->mutex);
|
||||
info->next = display->screens;
|
||||
display->screens = info;
|
||||
CAIRO_MUTEX_UNLOCK (display->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
unlock:
|
||||
CAIRO_MUTEX_UNLOCK (_cairo_xlib_screen_mutex);
|
||||
}
|
||||
DONE:
|
||||
_cairo_xlib_display_destroy (display);
|
||||
|
||||
void
|
||||
_cairo_xlib_screen_reset_static_data (void)
|
||||
{
|
||||
_cairo_xlib_screen_info_reset ();
|
||||
return info;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2319,7 +2319,7 @@ _cairo_xlib_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font)
|
|||
cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private;
|
||||
|
||||
if (font_private) {
|
||||
_cairo_xlib_remove_close_display_hook (font_private->dpy, scaled_font);
|
||||
_cairo_xlib_remove_close_display_hooks (font_private->dpy, scaled_font);
|
||||
XRenderFreeGlyphSet (font_private->dpy, font_private->glyphset);
|
||||
free (font_private);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -512,12 +512,6 @@ _cairo_font_reset_static_data (void);
|
|||
cairo_private void
|
||||
_cairo_ft_font_reset_static_data (void);
|
||||
|
||||
cairo_private void
|
||||
_cairo_xlib_surface_reset_static_data (void);
|
||||
|
||||
cairo_private void
|
||||
_cairo_xlib_screen_reset_static_data (void);
|
||||
|
||||
/* the font backend interface */
|
||||
|
||||
struct _cairo_unscaled_font_backend {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue