app: render layer-group preview in chunks

In gimp_drawable_get_sub_preview_async(), when the drawable buffer
has a validate handler (i.e., when it's a group layer), use a chunk
iterator to validate the buffer in chunks, where each chunk is
validated in a separate invocation of the async function.  This
prevents validation from blocking the main thread for too long when
the buffer is not already fully validated.

(cherry picked from commit 64bf77aed8)
This commit is contained in:
Ell
2020-03-14 16:02:14 +02:00
parent cd4c81133a
commit fbaf3c4290

View File

@ -39,6 +39,7 @@
#include "gimp-utils.h"
#include "gimpasync.h"
#include "gimpchannel.h"
#include "gimpchunkiterator.h"
#include "gimpimage.h"
#include "gimpimage-color-profile.h"
#include "gimpdrawable-preview.h"
@ -51,10 +52,12 @@
typedef struct
{
const Babl *format;
GeglBuffer *buffer;
GeglRectangle rect;
gdouble scale;
const Babl *format;
GeglBuffer *buffer;
GeglRectangle rect;
gdouble scale;
GimpChunkIterator *iter;
} SubPreviewData;
@ -84,6 +87,8 @@ sub_preview_data_new (const Babl *format,
data->rect = *rect;
data->scale = scale;
data->iter = NULL;
return data;
}
@ -92,6 +97,9 @@ sub_preview_data_free (SubPreviewData *data)
{
g_object_unref (data->buffer);
if (data->iter)
gimp_chunk_iterator_stop (data->iter, TRUE);
g_slice_free (SubPreviewData, data);
}
@ -340,18 +348,44 @@ gimp_drawable_get_sub_preview_async_func (GimpAsync *async,
if (validate)
{
GeglRectangle rect;
if (! data->iter)
{
cairo_region_t *region;
cairo_rectangle_int_t rect;
rect.x = floor (data->rect.x / data->scale);
rect.y = floor (data->rect.y / data->scale);
rect.width = ceil ((data->rect.x + data->rect.width) / data->scale) -
rect.x;
rect.height = ceil ((data->rect.x + data->rect.height) / data->scale) -
rect.y;
rect.x = floor (data->rect.x / data->scale);
rect.y = floor (data->rect.y / data->scale);
rect.width = ceil ((data->rect.x + data->rect.width) /
data->scale) - rect.x;
rect.height = ceil ((data->rect.x + data->rect.height) /
data->scale) - rect.y;
gimp_tile_handler_validate_validate (validate,
data->buffer, &rect,
TRUE, TRUE);
region = cairo_region_copy (validate->dirty_region);
cairo_region_intersect_rectangle (region, &rect);
data->iter = gimp_chunk_iterator_new (region);
}
if (gimp_chunk_iterator_next (data->iter))
{
GeglRectangle rect;
gimp_tile_handler_validate_begin_validate (validate);
while (gimp_chunk_iterator_get_rect (data->iter, &rect))
{
gimp_tile_handler_validate_validate (validate,
data->buffer, &rect,
FALSE, FALSE);
}
gimp_tile_handler_validate_end_validate (validate);
return;
}
data->iter = NULL;
}
gegl_buffer_get (data->buffer, &data->rect, data->scale,