app: add an optional gegl:cache at the output of GimpApplicator

Add "gboolean use_cache" to gimp_applicator_new(). Don't use a cache
anywhere but in GimpImageMap because it incrementally fills that cache
via the projection update. In gimp_drawable_merge_filter(), get that
cache and pass it to gimp_gegl_apply_cached_operation() which then
avoids doing the work twice for the already cached results. Win!
This commit is contained in:
Michael Natterer 2014-06-18 18:50:53 +02:00
parent 14614cb349
commit db2ea536da
8 changed files with 99 additions and 21 deletions

View File

@ -118,7 +118,8 @@ gimp_drawable_real_apply_buffer (GimpDrawable *drawable,
}
}
applicator = gimp_applicator_new (NULL, gimp_drawable_get_linear (drawable));
applicator = gimp_applicator_new (NULL, gimp_drawable_get_linear (drawable),
FALSE);
if (mask)
{

View File

@ -97,6 +97,9 @@ gimp_drawable_merge_filter (GimpDrawable *drawable,
&rect.width, &rect.height))
{
GimpApplicator *applicator;
GeglBuffer *cache = NULL;
GeglRectangle *rects = NULL;
gint n_rects = 0;
gimp_drawable_push_undo (drawable, undo_desc, NULL,
rect.x, rect.y,
@ -119,13 +122,33 @@ gimp_drawable_merge_filter (GimpDrawable *drawable,
undo->applied_buffer =
gimp_applicator_dup_apply_buffer (applicator, &rect);
}
cache = gimp_applicator_get_cache_buffer (applicator,
&rects, &n_rects);
if (cache)
{
gint i;
for (i = 0; i < n_rects; i++)
g_printerr ("valid: %d %d %d %d\n",
rects[i].x, rects[i].y,
rects[i].width, rects[i].height);
}
}
gimp_gegl_apply_operation (gimp_drawable_get_buffer (drawable),
progress, undo_desc,
gimp_filter_get_node (filter),
gimp_drawable_get_buffer (drawable),
&rect);
gimp_gegl_apply_cached_operation (gimp_drawable_get_buffer (drawable),
progress, undo_desc,
gimp_filter_get_node (filter),
gimp_drawable_get_buffer (drawable),
&rect,
cache, rects, n_rects);
if (cache)
{
g_object_unref (cache);
g_free (rects);
}
gimp_drawable_update (drawable,
rect.x, rect.y,

View File

@ -957,7 +957,7 @@ gimp_drawable_sync_fs_filter (GimpDrawable *drawable,
gegl_node_add_child (node, fs_source);
private->fs_applicator = gimp_applicator_new (node, linear);
private->fs_applicator = gimp_applicator_new (node, linear, FALSE);
private->fs_crop_node =
gegl_node_new_child (node,

View File

@ -614,7 +614,8 @@ gimp_image_merge_layers (GimpImage *image,
applicator =
gimp_applicator_new (NULL,
gimp_drawable_get_linear (GIMP_DRAWABLE (layer)));
gimp_drawable_get_linear (GIMP_DRAWABLE (layer)),
FALSE);
if (gimp_layer_get_mask (layer) &&
gimp_layer_get_apply_mask (layer))

View File

@ -288,7 +288,8 @@ gimp_image_map_apply (GimpImageMap *image_map,
image_map->applicator =
gimp_applicator_new (filter_node,
gimp_drawable_get_linear (image_map->drawable));
gimp_drawable_get_linear (image_map->drawable),
TRUE);
gimp_filter_set_applicator (image_map->filter,
image_map->applicator);

View File

@ -106,7 +106,8 @@ gimp_applicator_get_property (GObject *object,
GimpApplicator *
gimp_applicator_new (GeglNode *parent,
gboolean linear)
gboolean linear,
gboolean use_cache)
{
GimpApplicator *applicator;
@ -148,16 +149,15 @@ gimp_applicator_new (GeglNode *parent,
"operation", "gegl:translate",
NULL);
gegl_node_connect_to (applicator->aux_node, "output",
applicator->apply_offset_node, "input");
applicator->dup_apply_buffer_node =
gegl_node_new_child (applicator->node,
"operation", "gegl:copy-buffer",
NULL);
gegl_node_connect_to (applicator->apply_offset_node, "output",
applicator->dup_apply_buffer_node, "input");
gegl_node_link_many (applicator->aux_node,
applicator->apply_offset_node,
applicator->dup_apply_buffer_node,
NULL);
gegl_node_connect_to (applicator->dup_apply_buffer_node, "output",
applicator->mode_node, "aux");
@ -181,12 +181,29 @@ gimp_applicator_new (GeglNode *parent,
"mask", applicator->affect,
NULL);
gegl_node_connect_to (applicator->input_node, "output",
applicator->affect_node, "input");
if (use_cache)
{
applicator->cache_node =
gegl_node_new_child (applicator->node,
"operation", "gegl:cache",
NULL);
gegl_node_link_many (applicator->input_node,
applicator->affect_node,
applicator->cache_node,
applicator->output_node,
NULL);
}
else
{
gegl_node_link_many (applicator->input_node,
applicator->affect_node,
applicator->output_node,
NULL);
}
gegl_node_connect_to (applicator->mode_node, "output",
applicator->affect_node, "aux");
gegl_node_connect_to (applicator->affect_node, "output",
applicator->output_node, "input");
return applicator;
}
@ -450,3 +467,32 @@ gimp_applicator_dup_apply_buffer (GimpApplicator *applicator,
return buffer;
}
gboolean gegl_buffer_list_valid_rectangles (GeglBuffer *buffer,
GeglRectangle **rectangles,
gint *n_rectangles);
GeglBuffer *
gimp_applicator_get_cache_buffer (GimpApplicator *applicator,
GeglRectangle **rectangles,
gint *n_rectangles)
{
if (applicator->cache_node)
{
GeglBuffer *cache;
gegl_node_get (applicator->cache_node,
"cache", &cache,
NULL);
if (cache)
{
if (gegl_buffer_list_valid_rectangles (cache, rectangles, n_rectangles))
return cache;
g_object_unref (cache);
}
}
return NULL;
}

View File

@ -58,6 +58,8 @@ struct _GimpApplicator
GimpComponentMask affect;
GeglNode *affect_node;
GeglNode *cache_node;
GeglBuffer *src_buffer;
GeglNode *src_node;
@ -81,7 +83,8 @@ struct _GimpApplicatorClass
GType gimp_applicator_get_type (void) G_GNUC_CONST;
GimpApplicator * gimp_applicator_new (GeglNode *parent,
gboolean linear);
gboolean linear,
gboolean use_cache);
void gimp_applicator_set_src_buffer (GimpApplicator *applicator,
GeglBuffer *dest_buffer);
@ -111,6 +114,9 @@ void gimp_applicator_blit (GimpApplicator *applicator,
GeglBuffer * gimp_applicator_dup_apply_buffer (GimpApplicator *applicator,
const GeglRectangle *rect);
GeglBuffer * gimp_applicator_get_cache_buffer (GimpApplicator *applicator,
GeglRectangle **rectangles,
gint *n_rectangles);
#endif /* __GIMP_APPLICATOR_H__ */

View File

@ -429,7 +429,7 @@ gimp_paint_core_start (GimpPaintCore *core,
if (paint_options->use_applicator)
{
core->applicator = gimp_applicator_new (NULL, core->linear_mode);
core->applicator = gimp_applicator_new (NULL, core->linear_mode, FALSE);
if (core->mask_buffer)
{