app: in GimpApplicator, allow enabling cache/preview after construction; remove preview cache

Remove the use_split_preview and use_result_cache parameters of
gimp_applicator_new(), and allow enabling/disabling the cache
(through gimp_applicator_set_cache()) and the preview crop (through
gimp_applicator_set_preview()) after construction.

Move the preview crop node after the result cache, and remove the
separate preview cache node.  This eliminates an extra cache
buffer, reducing the space consumed by filters, and speeds up split
preview, since the cached result now includes the output
compositing.
This commit is contained in:
Ell 2018-12-29 14:12:51 -05:00
parent 42dd3fd939
commit ab52dc6bca
7 changed files with 115 additions and 140 deletions

View File

@ -104,7 +104,7 @@ gimp_drawable_real_apply_buffer (GimpDrawable *drawable,
NULL, x, y, width, height);
}
applicator = gimp_applicator_new (NULL, FALSE, FALSE);
applicator = gimp_applicator_new (NULL);
if (mask)
{

View File

@ -150,10 +150,7 @@ gimp_drawable_merge_filter (GimpDrawable *drawable,
if (applicator)
{
/* disable the preview crop, this will force-process the
* cached result from the preview cache into the result
* cache, involving only the layer and affect nodes
*/
/* disable the preview crop */
gimp_applicator_set_preview (applicator, FALSE,
GEGL_RECTANGLE (0, 0, 0, 0));

View File

@ -208,10 +208,12 @@ _gimp_drawable_add_floating_sel_filter (GimpDrawable *drawable)
gegl_node_add_child (node, fs_source);
private->fs_applicator = gimp_applicator_new (node, FALSE, TRUE);
private->fs_applicator = gimp_applicator_new (node);
gimp_filter_set_applicator (private->fs_filter, private->fs_applicator);
gimp_applicator_set_cache (private->fs_applicator, TRUE);
private->fs_crop_node =
gegl_node_new_child (node,
"operation", "gegl:crop",

View File

@ -212,10 +212,12 @@ gimp_drawable_filter_new (GimpDrawable *drawable,
gegl_node_add_child (node, operation);
filter->applicator = gimp_applicator_new (node, TRUE, TRUE);
filter->applicator = gimp_applicator_new (node);
gimp_filter_set_applicator (GIMP_FILTER (filter), filter->applicator);
gimp_applicator_set_cache (filter->applicator, TRUE);
filter->has_input = gegl_node_has_pad (filter->operation, "input");
if (filter->has_input)

View File

@ -104,9 +104,7 @@ gimp_applicator_get_property (GObject *object,
}
GimpApplicator *
gimp_applicator_new (GeglNode *parent,
gboolean use_split_preview,
gboolean use_result_cache)
gimp_applicator_new (GeglNode *parent)
{
GimpApplicator *applicator;
@ -152,30 +150,8 @@ gimp_applicator_new (GeglNode *parent,
applicator->apply_offset_node,
NULL);
if (use_split_preview)
{
applicator->preview_cache_node =
gegl_node_new_child (applicator->node,
"operation", "gegl:cache",
NULL);
applicator->preview_crop_node =
gegl_node_new_child (applicator->node,
"operation", "gegl:nop",
NULL);
gegl_node_link_many (applicator->apply_offset_node,
applicator->preview_cache_node,
applicator->preview_crop_node,
NULL);
gegl_node_connect_to (applicator->preview_crop_node, "output",
applicator->mode_node, "aux");
}
else
{
gegl_node_connect_to (applicator->apply_offset_node, "output",
applicator->mode_node, "aux");
}
gegl_node_connect_to (applicator->apply_offset_node, "output",
applicator->mode_node, "aux");
applicator->mask_node =
gegl_node_new_child (applicator->node,
@ -197,33 +173,28 @@ gimp_applicator_new (GeglNode *parent,
"mask", applicator->affect,
NULL);
applicator->output_convert_format_node =
applicator->convert_format_node =
gegl_node_new_child (applicator->node,
"operation", "gegl:nop",
NULL);
if (use_result_cache)
{
applicator->output_cache_node =
gegl_node_new_child (applicator->node,
"operation", "gegl:cache",
NULL);
applicator->cache_node =
gegl_node_new_child (applicator->node,
"operation", "gegl:nop",
NULL);
gegl_node_link_many (applicator->input_node,
applicator->affect_node,
applicator->output_convert_format_node,
applicator->output_cache_node,
applicator->output_node,
NULL);
}
else
{
gegl_node_link_many (applicator->input_node,
applicator->affect_node,
applicator->output_convert_format_node,
applicator->output_node,
NULL);
}
applicator->preview_crop_node =
gegl_node_new_child (applicator->node,
"operation", "gegl:nop",
NULL);
gegl_node_link_many (applicator->input_node,
applicator->affect_node,
applicator->convert_format_node,
applicator->cache_node,
applicator->preview_crop_node,
applicator->output_node,
NULL);
gegl_node_connect_to (applicator->mode_node, "output",
applicator->affect_node, "aux");
@ -496,21 +467,55 @@ gimp_applicator_set_output_format (GimpApplicator *applicator,
if (applicator->output_format != format)
{
applicator->output_format = format;
if (format)
{
gegl_node_set (applicator->output_convert_format_node,
"operation", "gegl:convert-format",
"format", format,
if (! applicator->output_format)
{
gegl_node_set (applicator->convert_format_node,
"operation", "gegl:convert-format",
"format", format,
NULL);
}
else
{
gegl_node_set (applicator->convert_format_node,
"format", format,
NULL);
}
}
else
{
gegl_node_set (applicator->convert_format_node,
"operation", "gegl:nop",
NULL);
}
applicator->output_format = format;
}
}
void
gimp_applicator_set_cache (GimpApplicator *applicator,
gboolean enable)
{
g_return_if_fail (GIMP_IS_APPLICATOR (applicator));
if (applicator->cache_enabled != enable)
{
if (enable)
{
gegl_node_set (applicator->cache_node,
"operation", "gegl:cache",
NULL);
}
else
{
gegl_node_set (applicator->output_convert_format_node,
gegl_node_set (applicator->cache_node,
"operation", "gegl:nop",
NULL);
}
applicator->cache_enabled = enable;
}
}
@ -518,6 +523,38 @@ 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)
{
g_return_val_if_fail (GIMP_IS_APPLICATOR (applicator), NULL);
g_return_val_if_fail (rectangles != NULL, NULL);
g_return_val_if_fail (n_rectangles != NULL, NULL);
if (applicator->cache_enabled)
{
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;
}
void
gimp_applicator_set_preview (GimpApplicator *applicator,
gboolean enable,
@ -526,9 +563,6 @@ gimp_applicator_set_preview (GimpApplicator *applicator,
g_return_if_fail (GIMP_IS_APPLICATOR (applicator));
g_return_if_fail (rect != NULL);
if (! applicator->preview_cache_node)
return;
if (applicator->preview_enabled != enable ||
applicator->preview_rect.x != rect->x ||
applicator->preview_rect.y != rect->y ||
@ -562,41 +596,10 @@ gimp_applicator_set_preview (GimpApplicator *applicator,
}
else if (applicator->preview_enabled)
{
GeglBuffer *cache;
gegl_node_disconnect (applicator->preview_crop_node, "aux");
gegl_node_set (applicator->preview_crop_node,
"operation", "gegl:nop",
NULL);
/* when disabling the preview, preserve the cached result
* by processing it into the output cache, which only
* involves the mode and affect nodes.
*/
gegl_node_get (applicator->preview_cache_node,
"cache", &cache,
NULL);
if (cache)
{
GeglRectangle *rectangles;
gint n_rectangles;
if (gegl_buffer_list_valid_rectangles (cache, &rectangles,
&n_rectangles))
{
gint i;
for (i = 0; i < n_rectangles; i++)
gegl_node_blit (applicator->output_cache_node, 1.0,
&rectangles[i],
NULL, NULL, 0, GEGL_BLIT_DEFAULT);
g_free (rectangles);
}
g_object_unref (cache);
}
}
applicator->preview_enabled = enable;
@ -613,32 +616,3 @@ gimp_applicator_blit (GimpApplicator *applicator,
gegl_node_blit (applicator->dest_node, 1.0, rect,
NULL, NULL, 0, GEGL_BLIT_DEFAULT);
}
GeglBuffer *
gimp_applicator_get_cache_buffer (GimpApplicator *applicator,
GeglRectangle **rectangles,
gint *n_rectangles)
{
g_return_val_if_fail (GIMP_IS_APPLICATOR (applicator), NULL);
g_return_val_if_fail (rectangles != NULL, NULL);
g_return_val_if_fail (n_rectangles != NULL, NULL);
if (applicator->output_cache_node)
{
GeglBuffer *cache;
gegl_node_get (applicator->output_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

@ -48,11 +48,6 @@ struct _GimpApplicator
gint apply_offset_y;
GeglNode *apply_offset_node;
gboolean preview_enabled;
GeglRectangle preview_rect;
GeglNode *preview_cache_node;
GeglNode *preview_crop_node;
gdouble opacity;
GimpLayerMode paint_mode;
GimpLayerColorSpace blend_space;
@ -64,9 +59,14 @@ struct _GimpApplicator
GeglNode *affect_node;
const Babl *output_format;
GeglNode *output_convert_format_node;
GeglNode *convert_format_node;
GeglNode *output_cache_node;
gboolean cache_enabled;
GeglNode *cache_node;
gboolean preview_enabled;
GeglRectangle preview_rect;
GeglNode *preview_crop_node;
GeglBuffer *src_buffer;
GeglNode *src_node;
@ -90,9 +90,7 @@ struct _GimpApplicatorClass
GType gimp_applicator_get_type (void) G_GNUC_CONST;
GimpApplicator * gimp_applicator_new (GeglNode *parent,
gboolean use_split_preview,
gboolean use_result_cache);
GimpApplicator * gimp_applicator_new (GeglNode *parent);
void gimp_applicator_set_src_buffer (GimpApplicator *applicator,
GeglBuffer *dest_buffer);
@ -124,6 +122,12 @@ void gimp_applicator_set_affect (GimpApplicator *applicator
void gimp_applicator_set_output_format (GimpApplicator *applicator,
const Babl *format);
void gimp_applicator_set_cache (GimpApplicator *applicator,
gboolean enable);
GeglBuffer * gimp_applicator_get_cache_buffer (GimpApplicator *applicator,
GeglRectangle **rectangles,
gint *n_rectangles);
void gimp_applicator_set_preview (GimpApplicator *applicator,
gboolean enable,
const GeglRectangle *rect);
@ -131,9 +135,5 @@ void gimp_applicator_set_preview (GimpApplicator *applicator
void gimp_applicator_blit (GimpApplicator *applicator,
const GeglRectangle *rect);
GeglBuffer * gimp_applicator_get_cache_buffer (GimpApplicator *applicator,
GeglRectangle **rectangles,
gint *n_rectangles);
#endif /* __GIMP_APPLICATOR_H__ */

View File

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