Commit 50dc4571 authored by Ell's avatar Ell

app: use GimpChunkIterator in gimp_gegl_apply_cached_operation()

In gimp_gegl_apply_cached_operation(), replace the use of
GeglProcessor with GimpChunkIterator, so that we use the same
chunking logic as for rendering projections.  This has the
advantage of better chunk alignment to the tile grid and dynamic
chunk sizing, which improve performance.

Use chunking even when there's no progress indication, since it
generally results in better cache locality.

(cherry picked from commit 4110f7b7)
parent b62e3fd3
......@@ -30,6 +30,7 @@
#include "core/gimp-transform-utils.h"
#include "core/gimp-utils.h"
#include "core/gimpchunkiterator.h"
#include "core/gimpprogress.h"
#include "gimp-gegl-apply-operation.h"
......@@ -77,15 +78,17 @@ gimp_gegl_apply_cached_operation (GeglBuffer *src_buffer,
gint n_valid_rects,
gboolean cancellable)
{
GeglNode *gegl;
GeglNode *effect;
GeglNode *dest_node;
GeglNode *operation_src_node = NULL;
GeglRectangle rect = { 0, };
GeglProcessor *processor = NULL;
gboolean progress_started = FALSE;
gdouble value;
gboolean cancel = FALSE;
GeglNode *gegl;
GeglNode *effect;
GeglNode *dest_node;
GeglNode *operation_src_node = NULL;
GimpChunkIterator *iter;
cairo_region_t *region;
GeglRectangle rect = { 0, };
gboolean progress_started = FALSE;
gboolean cancel = FALSE;
gint all_pixels;
gint done_pixels;
g_return_val_if_fail (src_buffer == NULL || GEGL_IS_BUFFER (src_buffer), FALSE);
g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), FALSE);
......@@ -117,9 +120,9 @@ gimp_gegl_apply_cached_operation (GeglBuffer *src_buffer,
GeglNode *src_node;
/* dup() because reading and writing the same buffer doesn't
* work with area ops when using a processor. See bug #701875.
* work with area ops when working in chunks. See bug #701875.
*/
if (progress && (src_buffer == dest_buffer))
if (src_buffer == dest_buffer)
src_buffer = gegl_buffer_dup (src_buffer);
else
g_object_ref (src_buffer);
......@@ -175,8 +178,6 @@ gimp_gegl_apply_cached_operation (GeglBuffer *src_buffer,
if (progress)
{
processor = gegl_node_new_processor (dest_node, &rect);
if (gimp_progress_is_active (progress))
{
if (undo_desc)
......@@ -197,18 +198,21 @@ gimp_gegl_apply_cached_operation (GeglBuffer *src_buffer,
progress_started = TRUE;
}
}
if (cache)
else
{
cairo_region_t *region;
gint all_pixels;
gint done_pixels = 0;
gint n_rects;
gint i;
cancelable = FALSE;
}
gegl_buffer_freeze_changed (dest_buffer);
region = cairo_region_create_rectangle ((cairo_rectangle_int_t *) &rect);
all_pixels = rect.width * rect.height;
done_pixels = 0;
all_pixels = rect.width * rect.height;
region = cairo_region_create_rectangle ((cairo_rectangle_int_t *) &rect);
if (cache)
{
gint i;
for (i = 0; i < n_valid_rects; i++)
{
......@@ -230,77 +234,48 @@ gimp_gegl_apply_cached_operation (GeglBuffer *src_buffer,
done_pixels += valid_rect.width * valid_rect.height;
if (progress)
gimp_progress_set_value (progress,
(gdouble) done_pixels /
(gdouble) all_pixels);
{
gimp_progress_set_value (progress,
(gdouble) done_pixels /
(gdouble) all_pixels);
}
}
}
n_rects = cairo_region_num_rectangles (region);
iter = gimp_chunk_iterator_new (region);
for (i = 0; ! cancel && (i < n_rects); i++)
{
cairo_rectangle_int_t render_rect;
while (gimp_chunk_iterator_next (iter))
{
GeglRectangle render_rect;
cairo_region_get_rectangle (region, i, &render_rect);
if (cancelable)
{
while (! cancel && g_main_context_pending (NULL))
g_main_context_iteration (NULL, FALSE);
if (progress)
{
gint rect_pixels = render_rect.width * render_rect.height;
#ifdef REUSE_PROCESSOR
gegl_processor_set_rectangle (processor,
(GeglRectangle *) &render_rect);
#else
g_object_unref (processor);
processor = gegl_node_new_processor (dest_node,
(GeglRectangle *) &render_rect);
#endif
while (! cancel && gegl_processor_work (processor, &value))
{
gimp_progress_set_value (progress,
((gdouble) done_pixels +
value * rect_pixels) /
(gdouble) all_pixels);
if (cancellable)
while (! cancel && g_main_context_pending (NULL))
g_main_context_iteration (NULL, FALSE);
}
done_pixels += rect_pixels;
}
else
{
gegl_node_blit (dest_node, 1.0, (GeglRectangle *) &render_rect,
NULL, NULL, 0, GEGL_BLIT_DEFAULT);
}
if (cancel)
break;
}
cairo_region_destroy (region);
}
else
{
if (progress)
while (gimp_chunk_iterator_get_rect (iter, &render_rect))
{
while (! cancel && gegl_processor_work (processor, &value))
{
gimp_progress_set_value (progress, value);
gint rect_pixels = render_rect.width * render_rect.height;
if (cancellable)
while (! cancel && g_main_context_pending (NULL))
g_main_context_iteration (NULL, FALSE);
}
gegl_node_blit (dest_node, 1.0, &render_rect, NULL, NULL, 0,
GEGL_BLIT_DEFAULT);
done_pixels += rect_pixels;
}
else
if (progress)
{
gegl_node_blit (dest_node, 1.0, &rect,
NULL, NULL, 0, GEGL_BLIT_DEFAULT);
gimp_progress_set_value (progress,
(gdouble) done_pixels /
(gdouble) all_pixels);
}
}
if (processor)
g_object_unref (processor);
gegl_buffer_thaw_changed (dest_buffer);
g_object_unref (gegl);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment