mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-01-08 18:50:22 +01:00
[cairo] Cache freed gstates.
Reduce the malloc pressure from frequent cairo_save()/cairo_restore() by caching the freed gstates in a list on the context.
This commit is contained in:
parent
c57b1eca18
commit
b2eadb94f8
4 changed files with 35 additions and 57 deletions
|
|
@ -204,47 +204,6 @@ _cairo_gstate_fini (cairo_gstate_t *gstate)
|
|||
gstate->source = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_gstate_destroy (cairo_gstate_t *gstate)
|
||||
{
|
||||
_cairo_gstate_fini (gstate);
|
||||
free (gstate);
|
||||
}
|
||||
|
||||
/**
|
||||
* _cairo_gstate_clone:
|
||||
* @other: a #cairo_gstate_t to be copied, not %NULL.
|
||||
*
|
||||
* Create a new #cairo_gstate_t setting all graphics state parameters
|
||||
* to the same values as contained in @other. gstate->next will be set
|
||||
* to %NULL and may be used by the caller to chain #cairo_gstate_t
|
||||
* objects together.
|
||||
*
|
||||
* Return value: a new #cairo_gstate_t or %NULL if there is insufficient
|
||||
* memory.
|
||||
**/
|
||||
static cairo_status_t
|
||||
_cairo_gstate_clone (cairo_gstate_t *other, cairo_gstate_t **out)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_gstate_t *gstate;
|
||||
|
||||
assert (other != NULL);
|
||||
|
||||
gstate = malloc (sizeof (cairo_gstate_t));
|
||||
if (gstate == NULL)
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
status = _cairo_gstate_init_copy (gstate, other);
|
||||
if (status) {
|
||||
free (gstate);
|
||||
return status;
|
||||
}
|
||||
|
||||
*out = gstate;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* _cairo_gstate_save:
|
||||
* @gstate: input/output gstate pointer
|
||||
|
|
@ -254,14 +213,25 @@ _cairo_gstate_clone (cairo_gstate_t *other, cairo_gstate_t **out)
|
|||
* copy into @gstate. _cairo_gstate_restore() reverses this.
|
||||
**/
|
||||
cairo_status_t
|
||||
_cairo_gstate_save (cairo_gstate_t **gstate)
|
||||
_cairo_gstate_save (cairo_gstate_t **gstate, cairo_gstate_t **freelist)
|
||||
{
|
||||
cairo_gstate_t *top = NULL;
|
||||
cairo_gstate_t *top;
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_gstate_clone (*gstate, &top);
|
||||
if (status)
|
||||
top = *freelist;
|
||||
if (top == NULL) {
|
||||
top = malloc (sizeof (cairo_gstate_t));
|
||||
if (top == NULL)
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
} else
|
||||
*freelist = top->next;
|
||||
|
||||
status = _cairo_gstate_init_copy (top, *gstate);
|
||||
if (status) {
|
||||
top->next = *freelist;
|
||||
*freelist = top;
|
||||
return status;
|
||||
}
|
||||
|
||||
top->next = *gstate;
|
||||
*gstate = top;
|
||||
|
|
@ -276,7 +246,7 @@ _cairo_gstate_save (cairo_gstate_t **gstate)
|
|||
* Reverses the effects of one _cairo_gstate_save() call.
|
||||
**/
|
||||
cairo_status_t
|
||||
_cairo_gstate_restore (cairo_gstate_t **gstate)
|
||||
_cairo_gstate_restore (cairo_gstate_t **gstate, cairo_gstate_t **freelist)
|
||||
{
|
||||
cairo_gstate_t *top;
|
||||
|
||||
|
|
@ -286,7 +256,9 @@ _cairo_gstate_restore (cairo_gstate_t **gstate)
|
|||
|
||||
*gstate = top->next;
|
||||
|
||||
_cairo_gstate_destroy (top);
|
||||
_cairo_gstate_fini (top);
|
||||
top->next = *freelist;
|
||||
*freelist = top;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ struct _cairo {
|
|||
|
||||
cairo_gstate_t *gstate;
|
||||
cairo_gstate_t gstate_tail[1];
|
||||
cairo_gstate_t *gstate_freelist;
|
||||
|
||||
cairo_path_fixed_t path[1];
|
||||
};
|
||||
|
|
|
|||
21
src/cairo.c
21
src/cairo.c
|
|
@ -52,7 +52,8 @@ static const cairo_t _cairo_nil = {
|
|||
{{ /* gstate_tail */
|
||||
0
|
||||
}},
|
||||
{{ /* path */
|
||||
NULL, /* gstate_freelist */
|
||||
{{ /* path */
|
||||
{ 0, 0 }, /* last_move_point */
|
||||
{ 0, 0 }, /* current point */
|
||||
FALSE, /* has_current_point */
|
||||
|
|
@ -205,6 +206,7 @@ cairo_create (cairo_surface_t *target)
|
|||
_cairo_path_fixed_init (cr->path);
|
||||
|
||||
cr->gstate = cr->gstate_tail;
|
||||
cr->gstate_freelist = NULL;
|
||||
status = _cairo_gstate_init (cr->gstate, target);
|
||||
|
||||
if (status)
|
||||
|
|
@ -260,11 +262,16 @@ cairo_destroy (cairo_t *cr)
|
|||
return;
|
||||
|
||||
while (cr->gstate != cr->gstate_tail) {
|
||||
if (_cairo_gstate_restore (&cr->gstate))
|
||||
if (_cairo_gstate_restore (&cr->gstate, &cr->gstate_freelist))
|
||||
break;
|
||||
}
|
||||
|
||||
_cairo_gstate_fini (cr->gstate);
|
||||
while (cr->gstate_freelist != NULL) {
|
||||
cairo_gstate_t *gstate = cr->gstate_freelist;
|
||||
cr->gstate_freelist = gstate->next;
|
||||
free (gstate);
|
||||
}
|
||||
|
||||
_cairo_path_fixed_fini (cr->path);
|
||||
|
||||
|
|
@ -371,10 +378,9 @@ cairo_save (cairo_t *cr)
|
|||
if (cr->status)
|
||||
return;
|
||||
|
||||
status = _cairo_gstate_save (&cr->gstate);
|
||||
if (status) {
|
||||
status = _cairo_gstate_save (&cr->gstate, &cr->gstate_freelist);
|
||||
if (status)
|
||||
_cairo_set_error (cr, status);
|
||||
}
|
||||
}
|
||||
slim_hidden_def(cairo_save);
|
||||
|
||||
|
|
@ -394,10 +400,9 @@ cairo_restore (cairo_t *cr)
|
|||
if (cr->status)
|
||||
return;
|
||||
|
||||
status = _cairo_gstate_restore (&cr->gstate);
|
||||
if (status) {
|
||||
status = _cairo_gstate_restore (&cr->gstate, &cr->gstate_freelist);
|
||||
if (status)
|
||||
_cairo_set_error (cr, status);
|
||||
}
|
||||
}
|
||||
slim_hidden_def(cairo_restore);
|
||||
|
||||
|
|
|
|||
4
src/cairoint.h
Executable file → Normal file
4
src/cairoint.h
Executable file → Normal file
|
|
@ -952,10 +952,10 @@ cairo_private void
|
|||
_cairo_gstate_fini (cairo_gstate_t *gstate);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_save (cairo_gstate_t **gstate);
|
||||
_cairo_gstate_save (cairo_gstate_t **gstate, cairo_gstate_t **freelist);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_restore (cairo_gstate_t **gstate);
|
||||
_cairo_gstate_restore (cairo_gstate_t **gstate, cairo_gstate_t **freelist);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_gstate_is_redirected (cairo_gstate_t *gstate);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue