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:
@ -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,
|
||||
|
Reference in New Issue
Block a user