mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-06 06:58:00 +02:00
[cairo-xlib] Cache freed GCs
Maintain a cache of freed GCs, one for each used depth.
This commit is contained in:
parent
88c6d25d4e
commit
1d6f7b7a02
4 changed files with 98 additions and 10 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue