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); NULL, x, y, width, height);
} }
applicator = gimp_applicator_new (NULL, FALSE, FALSE); applicator = gimp_applicator_new (NULL);
if (mask) if (mask)
{ {

View File

@ -150,10 +150,7 @@ gimp_drawable_merge_filter (GimpDrawable *drawable,
if (applicator) if (applicator)
{ {
/* disable the preview crop, this will force-process the /* disable the preview crop */
* cached result from the preview cache into the result
* cache, involving only the layer and affect nodes
*/
gimp_applicator_set_preview (applicator, FALSE, gimp_applicator_set_preview (applicator, FALSE,
GEGL_RECTANGLE (0, 0, 0, 0)); 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); 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_filter_set_applicator (private->fs_filter, private->fs_applicator);
gimp_applicator_set_cache (private->fs_applicator, TRUE);
private->fs_crop_node = private->fs_crop_node =
gegl_node_new_child (node, gegl_node_new_child (node,
"operation", "gegl:crop", "operation", "gegl:crop",

View File

@ -212,10 +212,12 @@ gimp_drawable_filter_new (GimpDrawable *drawable,
gegl_node_add_child (node, operation); 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_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"); filter->has_input = gegl_node_has_pad (filter->operation, "input");
if (filter->has_input) if (filter->has_input)

View File

@ -104,9 +104,7 @@ gimp_applicator_get_property (GObject *object,
} }
GimpApplicator * GimpApplicator *
gimp_applicator_new (GeglNode *parent, gimp_applicator_new (GeglNode *parent)
gboolean use_split_preview,
gboolean use_result_cache)
{ {
GimpApplicator *applicator; GimpApplicator *applicator;
@ -152,30 +150,8 @@ gimp_applicator_new (GeglNode *parent,
applicator->apply_offset_node, applicator->apply_offset_node,
NULL); NULL);
if (use_split_preview) gegl_node_connect_to (applicator->apply_offset_node, "output",
{ applicator->mode_node, "aux");
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");
}
applicator->mask_node = applicator->mask_node =
gegl_node_new_child (applicator->node, gegl_node_new_child (applicator->node,
@ -197,33 +173,28 @@ gimp_applicator_new (GeglNode *parent,
"mask", applicator->affect, "mask", applicator->affect,
NULL); NULL);
applicator->output_convert_format_node = applicator->convert_format_node =
gegl_node_new_child (applicator->node, gegl_node_new_child (applicator->node,
"operation", "gegl:nop", "operation", "gegl:nop",
NULL); NULL);
if (use_result_cache) applicator->cache_node =
{ gegl_node_new_child (applicator->node,
applicator->output_cache_node = "operation", "gegl:nop",
gegl_node_new_child (applicator->node, NULL);
"operation", "gegl:cache",
NULL);
gegl_node_link_many (applicator->input_node, applicator->preview_crop_node =
applicator->affect_node, gegl_node_new_child (applicator->node,
applicator->output_convert_format_node, "operation", "gegl:nop",
applicator->output_cache_node, NULL);
applicator->output_node,
NULL); gegl_node_link_many (applicator->input_node,
} applicator->affect_node,
else applicator->convert_format_node,
{ applicator->cache_node,
gegl_node_link_many (applicator->input_node, applicator->preview_crop_node,
applicator->affect_node, applicator->output_node,
applicator->output_convert_format_node, NULL);
applicator->output_node,
NULL);
}
gegl_node_connect_to (applicator->mode_node, "output", gegl_node_connect_to (applicator->mode_node, "output",
applicator->affect_node, "aux"); applicator->affect_node, "aux");
@ -496,21 +467,55 @@ gimp_applicator_set_output_format (GimpApplicator *applicator,
if (applicator->output_format != format) if (applicator->output_format != format)
{ {
applicator->output_format = format;
if (format) if (format)
{ {
gegl_node_set (applicator->output_convert_format_node, if (! applicator->output_format)
"operation", "gegl:convert-format", {
"format", 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); NULL);
} }
else else
{ {
gegl_node_set (applicator->output_convert_format_node, gegl_node_set (applicator->cache_node,
"operation", "gegl:nop", "operation", "gegl:nop",
NULL); NULL);
} }
applicator->cache_enabled = enable;
} }
} }
@ -518,6 +523,38 @@ gboolean gegl_buffer_list_valid_rectangles (GeglBuffer *buffer,
GeglRectangle **rectangles, GeglRectangle **rectangles,
gint *n_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 void
gimp_applicator_set_preview (GimpApplicator *applicator, gimp_applicator_set_preview (GimpApplicator *applicator,
gboolean enable, gboolean enable,
@ -526,9 +563,6 @@ gimp_applicator_set_preview (GimpApplicator *applicator,
g_return_if_fail (GIMP_IS_APPLICATOR (applicator)); g_return_if_fail (GIMP_IS_APPLICATOR (applicator));
g_return_if_fail (rect != NULL); g_return_if_fail (rect != NULL);
if (! applicator->preview_cache_node)
return;
if (applicator->preview_enabled != enable || if (applicator->preview_enabled != enable ||
applicator->preview_rect.x != rect->x || applicator->preview_rect.x != rect->x ||
applicator->preview_rect.y != rect->y || applicator->preview_rect.y != rect->y ||
@ -562,41 +596,10 @@ gimp_applicator_set_preview (GimpApplicator *applicator,
} }
else if (applicator->preview_enabled) else if (applicator->preview_enabled)
{ {
GeglBuffer *cache;
gegl_node_disconnect (applicator->preview_crop_node, "aux"); gegl_node_disconnect (applicator->preview_crop_node, "aux");
gegl_node_set (applicator->preview_crop_node, gegl_node_set (applicator->preview_crop_node,
"operation", "gegl:nop", "operation", "gegl:nop",
NULL); 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; applicator->preview_enabled = enable;
@ -613,32 +616,3 @@ gimp_applicator_blit (GimpApplicator *applicator,
gegl_node_blit (applicator->dest_node, 1.0, rect, gegl_node_blit (applicator->dest_node, 1.0, rect,
NULL, NULL, 0, GEGL_BLIT_DEFAULT); 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; gint apply_offset_y;
GeglNode *apply_offset_node; GeglNode *apply_offset_node;
gboolean preview_enabled;
GeglRectangle preview_rect;
GeglNode *preview_cache_node;
GeglNode *preview_crop_node;
gdouble opacity; gdouble opacity;
GimpLayerMode paint_mode; GimpLayerMode paint_mode;
GimpLayerColorSpace blend_space; GimpLayerColorSpace blend_space;
@ -64,9 +59,14 @@ struct _GimpApplicator
GeglNode *affect_node; GeglNode *affect_node;
const Babl *output_format; 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; GeglBuffer *src_buffer;
GeglNode *src_node; GeglNode *src_node;
@ -90,9 +90,7 @@ struct _GimpApplicatorClass
GType gimp_applicator_get_type (void) G_GNUC_CONST; GType gimp_applicator_get_type (void) G_GNUC_CONST;
GimpApplicator * gimp_applicator_new (GeglNode *parent, GimpApplicator * gimp_applicator_new (GeglNode *parent);
gboolean use_split_preview,
gboolean use_result_cache);
void gimp_applicator_set_src_buffer (GimpApplicator *applicator, void gimp_applicator_set_src_buffer (GimpApplicator *applicator,
GeglBuffer *dest_buffer); GeglBuffer *dest_buffer);
@ -124,6 +122,12 @@ void gimp_applicator_set_affect (GimpApplicator *applicator
void gimp_applicator_set_output_format (GimpApplicator *applicator, void gimp_applicator_set_output_format (GimpApplicator *applicator,
const Babl *format); 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, void gimp_applicator_set_preview (GimpApplicator *applicator,
gboolean enable, gboolean enable,
const GeglRectangle *rect); const GeglRectangle *rect);
@ -131,9 +135,5 @@ void gimp_applicator_set_preview (GimpApplicator *applicator
void gimp_applicator_blit (GimpApplicator *applicator, void gimp_applicator_blit (GimpApplicator *applicator,
const GeglRectangle *rect); const GeglRectangle *rect);
GeglBuffer * gimp_applicator_get_cache_buffer (GimpApplicator *applicator,
GeglRectangle **rectangles,
gint *n_rectangles);
#endif /* __GIMP_APPLICATOR_H__ */ #endif /* __GIMP_APPLICATOR_H__ */

View File

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