[gimp] Bug 790810 - Nested layer groups lead to a deadlock with multithreading
- From: N/A <ell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] Bug 790810 - Nested layer groups lead to a deadlock with multithreading
- Date: Mon, 26 Mar 2018 23:05:36 +0000 (UTC)
commit caa3a98f04334152dbc378bb85bea3bab021c69f
Author: Ell <ell_se yahoo com>
Date: Mon Mar 26 18:51:24 2018 -0400
Bug 790810 - Nested layer groups lead to a deadlock with multithreading
In gimp_operation_buffer_source_validate_process(), align the ROI
to the tile grid *before* intersecting it with the validate-
handler's dirty region. This is necessary since, even though
subsequent operations will only read data within the ROI, the
entire tiles containing the ROI will be fetched, resulting in an
area potentially greater than the ROI. We need to validate this
area in advance, or else it will be validated as part of the
subsequent operations, which can lead into the same deadlock we're
trying to prevent.
app/operations/gimpoperationbuffersourcevalidate.c | 122 +++++++++-----------
1 files changed, 53 insertions(+), 69 deletions(-)
---
diff --git a/app/operations/gimpoperationbuffersourcevalidate.c
b/app/operations/gimpoperationbuffersourcevalidate.c
index 9f898f4..aae7892 100644
--- a/app/operations/gimpoperationbuffersourcevalidate.c
+++ b/app/operations/gimpoperationbuffersourcevalidate.c
@@ -64,10 +64,6 @@ static void gimp_operation_buffer_source_validate_buffer_changed (Ge
const GeglRectangle
*rect,
gpointer
data);
-static void gimp_operation_buffer_source_validate_buffer_validate
(GimpOperationBufferSourceValidate *buffer_source_validate,
- const cairo_rectangle_int_t
*rect,
- gint
level);
-
G_DEFINE_TYPE (GimpOperationBufferSourceValidate, gimp_operation_buffer_source_validate,
GEGL_TYPE_OPERATION_SOURCE)
@@ -255,43 +251,74 @@ gimp_operation_buffer_source_validate_process (GeglOperation *operation,
*/
if (n_threads > 1)
{
+ gint shift_x;
+ gint shift_y;
+ gint tile_width;
+ gint tile_height;
cairo_rectangle_int_t rect;
cairo_region_overlap_t overlap;
- rect.x = result->x;
- rect.y = result->y;
- rect.width = result->width;
- rect.height = result->height;
+ g_object_get (buffer_source_validate->buffer,
+ "shift-x", &shift_x,
+ "shift-y", &shift_y,
+ "tile-width", &tile_width,
+ "tile-height", &tile_height,
+ NULL);
+
+ /* align the rectangle to the tile grid */
+ rect.x = (gint) floor ((gdouble) (result->x + shift_x) / tile_width) *
tile_width;
+ rect.y = (gint) floor ((gdouble) (result->y + shift_y) / tile_height) *
tile_height;
+ rect.width = (gint) ceil ((gdouble) (result->x + result->width + shift_x) / tile_width) *
tile_width - rect.x;
+ rect.height = (gint) ceil ((gdouble) (result->y + result->height + shift_y) / tile_height) *
tile_height - rect.y;
+ /* check if the rectangle interescts with the dirty region */
overlap = cairo_region_contains_rectangle (validate_handler->dirty_region,
&rect);
- if (overlap == CAIRO_REGION_OVERLAP_IN)
- {
- gimp_operation_buffer_source_validate_buffer_validate (
- buffer_source_validate, &rect, level);
- }
- else if (overlap == CAIRO_REGION_OVERLAP_PART)
+ if (overlap != CAIRO_REGION_OVERLAP_OUT)
{
- cairo_region_t *region;
- gint n_rectangles;
- gint i;
+ GeglBufferIterator *iter;
- region = cairo_region_copy (validate_handler->dirty_region);
+ /* if the rectangle is not entirely within the dirty
+ * region ...
+ */
+ if (overlap == CAIRO_REGION_OVERLAP_PART)
+ {
+ cairo_region_t *region;
- cairo_region_intersect_rectangle (region, &rect);
+ /* ... intersect it with region and use the result's
+ * bounds
+ */
+ region = cairo_region_copy (validate_handler->dirty_region);
- n_rectangles = cairo_region_num_rectangles (region);
+ cairo_region_intersect_rectangle (region, &rect);
+ cairo_region_get_extents (region, &rect);
- for (i = 0; i < n_rectangles; i++)
- {
- cairo_region_get_rectangle (region, i, &rect);
+ cairo_region_destroy (region);
- gimp_operation_buffer_source_validate_buffer_validate (
- buffer_source_validate, &rect, level);
+ /* realign the rectangle to the tile grid */
+ rect.x = (gint) floor ((gdouble) (result->x + shift_x) /
tile_width) * tile_width;
+ rect.y = (gint) floor ((gdouble) (result->y + shift_y) /
tile_height) * tile_height;
+ rect.width = (gint) ceil ((gdouble) (result->x + result->width + shift_x) /
tile_width) * tile_width - rect.x;
+ rect.height = (gint) ceil ((gdouble) (result->y + result->height + shift_y) /
tile_height) * tile_height - rect.y;
}
- cairo_region_destroy (region);
+ rect.x -= shift_x;
+ rect.y -= shift_y;
+
+ /* iterate over the rectangle -- this implicitly causes
+ * validation
+ */
+ iter = gegl_buffer_iterator_new (buffer,
+ GEGL_RECTANGLE (rect.x,
+ rect.y,
+ rect.width,
+ rect.height),
+ level, NULL,
+ GEGL_BUFFER_READ,
+ GEGL_ABYSS_NONE);
+
+ while (gegl_buffer_iterator_next (iter));
}
}
}
@@ -314,46 +341,3 @@ gimp_operation_buffer_source_validate_buffer_changed (GeglBuffer *buffe
gegl_operation_invalidate (GEGL_OPERATION (buffer_source_validate),
rect, FALSE);
}
-
-static void
-gimp_operation_buffer_source_validate_buffer_validate (GimpOperationBufferSourceValidate
*buffer_source_validate,
- const cairo_rectangle_int_t *rect,
- gint level)
-{
- gint shift_x;
- gint shift_y;
- gint tile_width;
- gint tile_height;
- GeglRectangle roi;
- GeglBufferIterator *iter;
-
- g_object_get (buffer_source_validate->buffer,
- "shift-x", &shift_x,
- "shift-y", &shift_y,
- "tile-width", &tile_width,
- "tile-height", &tile_height,
- NULL);
-
- /* align rectangle to tile grid */
-
- roi.x = (gint) floor ((gdouble) (rect->x + shift_x) / tile_width) * tile_width;
- roi.y = (gint) floor ((gdouble) (rect->y + shift_y) / tile_height) * tile_height;
- roi.width = (gint) ceil ((gdouble) (rect->x + rect->width + shift_x) / tile_width) * tile_width -
roi.x;
- roi.height = (gint) ceil ((gdouble) (rect->y + rect->height + shift_y) / tile_height) * tile_height -
roi.y;
-
- roi.x -= shift_x;
- roi.y -= shift_y;
-
- /* intersect rectangle with abyss */
-
- gegl_rectangle_intersect (&roi, &roi,
- gegl_buffer_get_abyss (buffer_source_validate->buffer));
-
- /* iterate over rectangle -- this implicitly causes validation */
-
- iter = gegl_buffer_iterator_new (buffer_source_validate->buffer,
- &roi, level, NULL,
- GEGL_BUFFER_READ, GEGL_ABYSS_NONE);
-
- while (gegl_buffer_iterator_next (iter));
-}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]