[cairo-xlib] Cache freed GCs

Maintain a cache of freed GCs, one for each used depth.
This commit is contained in:
Chris Wilson 2007-04-19 13:01:52 +01:00
parent 88c6d25d4e
commit 1d6f7b7a02
4 changed files with 98 additions and 10 deletions

View file

@ -67,11 +67,15 @@ static cairo_xlib_display_t *_cairo_xlib_display_list;
static void
_cairo_xlib_call_close_display_hooks (cairo_xlib_display_t *display)
{
cairo_xlib_hook_t *hooks;
cairo_xlib_screen_info_t *screen;
cairo_xlib_hook_t *hooks;
/* call all registered shutdown routines */
CAIRO_MUTEX_LOCK (display->mutex);
for (screen = display->screens; screen != NULL; screen = screen->next)
_cairo_xlib_screen_info_close_display (screen);
hooks = display->close_display_hooks;
while (hooks != NULL) {
display->close_display_hooks = NULL;

View file

@ -74,6 +74,9 @@ struct _cairo_xlib_screen_info {
cairo_bool_t has_render;
cairo_font_options_t font_options;
GC gc[6];
unsigned int gc_needs_clip_reset;
};
cairo_private cairo_xlib_display_t *
@ -109,6 +112,13 @@ _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 void
_cairo_xlib_screen_info_close_display (cairo_xlib_screen_info_t *info);
cairo_private GC
_cairo_xlib_screen_get_gc (cairo_xlib_screen_info_t *info, int depth);
cairo_private cairo_status_t
_cairo_xlib_screen_put_gc (cairo_xlib_screen_info_t *info, int depth, GC gc, cairo_bool_t reset_clip);
#if CAIRO_HAS_XLIB_XRENDER_SURFACE

View file

@ -254,6 +254,19 @@ _cairo_xlib_screen_info_reference (cairo_xlib_screen_info_t *info)
return info;
}
void
_cairo_xlib_screen_info_close_display (cairo_xlib_screen_info_t *info)
{
int i;
for (i = 0; i < ARRAY_LENGTH (info->gc); i++) {
if (info->gc[i] != NULL) {
XFreeGC (info->display->display, info->gc[i]);
info->gc[i] = NULL;
}
}
}
void
_cairo_xlib_screen_info_destroy (cairo_xlib_screen_info_t *info)
{
@ -277,6 +290,8 @@ _cairo_xlib_screen_info_destroy (cairo_xlib_screen_info_t *info)
assert (list != NULL);
CAIRO_MUTEX_UNLOCK (info->display->mutex);
_cairo_xlib_screen_info_close_display (info);
_cairo_xlib_display_destroy (info->display);
free (info);
@ -323,6 +338,8 @@ _cairo_xlib_screen_info_get (Display *dpy, Screen *screen)
info->screen = screen;
info->has_render = FALSE;
_cairo_font_options_init_default (&info->font_options);
memset (info->gc, 0, sizeof (info->gc));
info->gc_needs_clip_reset = 0;
if (screen) {
int event_base, error_base;
@ -343,3 +360,56 @@ DONE:
return info;
}
static int
depth_to_index (int depth)
{
switch(depth){
case 1: return 0;
case 8: return 1;
case 15: return 2;
case 16: return 3;
case 24: return 4;
case 32: return 5;
}
return 0;
}
GC
_cairo_xlib_screen_get_gc (cairo_xlib_screen_info_t *info, int depth)
{
GC gc;
depth = depth_to_index (depth);
gc = info->gc[depth];
info->gc[depth] = NULL;
if (info->gc_needs_clip_reset & (1 << depth))
XSetClipMask(info->display->display, gc, None);
return gc;
}
cairo_status_t
_cairo_xlib_screen_put_gc (cairo_xlib_screen_info_t *info, int depth, GC gc, cairo_bool_t reset_clip)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
depth = depth_to_index (depth);
if (info->gc[depth] != NULL) {
status = _cairo_xlib_display_queue_work (info->display,
(cairo_xlib_notify_func) XFreeGC,
info->gc[depth],
NULL);
}
info->gc[depth] = gc;
if (reset_clip)
info->gc_needs_clip_reset |= 1 << depth;
else
info->gc_needs_clip_reset &= ~(1 << depth);
return status;
}

View file

@ -309,10 +309,10 @@ _cairo_xlib_surface_finish (void *abstract_surface)
if (surface->gc != NULL) {
cairo_status_t status2;
status2 = _cairo_xlib_display_queue_work (display,
(cairo_xlib_notify_func) XFreeGC,
surface->gc,
NULL);
status2 = _cairo_xlib_screen_put_gc (surface->screen_info,
surface->depth,
surface->gc,
surface->have_clip_rects);
if (status2 == CAIRO_STATUS_SUCCESS)
surface->gc = NULL;
else if (status == CAIRO_STATUS_SUCCESS)
@ -731,11 +731,15 @@ _cairo_xlib_surface_ensure_gc (cairo_xlib_surface_t *surface)
if (surface->gc)
return CAIRO_STATUS_SUCCESS;
gcv.graphics_exposures = False;
surface->gc = XCreateGC (surface->dpy, surface->drawable,
GCGraphicsExposures, &gcv);
if (!surface->gc)
return CAIRO_STATUS_NO_MEMORY;
surface->gc = _cairo_xlib_screen_get_gc (surface->screen_info,
surface->depth);
if (surface->gc == NULL) {
gcv.graphics_exposures = False;
surface->gc = XCreateGC (surface->dpy, surface->drawable,
GCGraphicsExposures, &gcv);
if (!surface->gc)
return CAIRO_STATUS_NO_MEMORY;
}
_cairo_xlib_surface_set_gc_clip_rects (surface);