[gimp/gimp-2-10] app: in GimpProjection, fix reinit. of current row when chunk height changes
- From: Ell <ell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp/gimp-2-10] app: in GimpProjection, fix reinit. of current row when chunk height changes
- Date: Thu, 6 Dec 2018 13:51:28 +0000 (UTC)
commit 61a181933c1b002476d79a23c383b8c02dc2da9d
Author: Ell <ell_se yahoo com>
Date: Thu Dec 6 08:44:23 2018 -0500
app: in GimpProjection, fix reinit. of current row when chunk height changes
In GimpProjection's chunk renderer, when the chunk height changes
in the middle of a row, we need to merge the remainder of the
current render area back into the renderer's update region, and
refetch the remainder of the row as the new render area, so that we
don't miss any unrendered area, or re-render already-rendered area,
due to the change in chunk height. However, we should previously
fail to verify that the fetched area is, in fact, the remainder of
the current row, which could cause us to render the wrong area,
missing parts of the update region.
Fix this, by breaking up some of the chunk-renderer fucntions into
smaller sub-functions, and using those in order to explicitly set
the new render area to the remainder of the current row when the
chunk height changes. This also avoids erroneously merging the
unflushed update region of the projection into the renderer's
update region.
(cherry picked from commit c9c2397b0d384717187870bad95373aff065cf39)
app/core/gimpprojection.c | 132 ++++++++++++++++++++++++++++++----------------
1 file changed, 87 insertions(+), 45 deletions(-)
---
diff --git a/app/core/gimpprojection.c b/app/core/gimpprojection.c
index 58762dcba1..b7b2c26a3d 100644
--- a/app/core/gimpprojection.c
+++ b/app/core/gimpprojection.c
@@ -185,11 +185,16 @@ static void gimp_projection_chunk_render_start (GimpProjection *proj)
static void gimp_projection_chunk_render_stop (GimpProjection *proj);
static gboolean gimp_projection_chunk_render_callback (gpointer data);
static void gimp_projection_chunk_render_init (GimpProjection *proj);
-static void gimp_projection_chunk_render_reinit (GimpProjection *proj,
- gboolean assume_running);
+static void gimp_projection_chunk_render_reinit (GimpProjection *proj);
+static void gimp_projection_chunk_render_merge (GimpProjection *proj);
static gboolean gimp_projection_chunk_render_iteration(GimpProjection *proj,
gboolean chunk);
static gboolean gimp_projection_chunk_render_next_area(GimpProjection *proj);
+static void gimp_projection_chunk_render_set_area (GimpProjection *proj,
+ gint x,
+ gint y,
+ gint w,
+ gint h);
static void gimp_projection_paint_area (GimpProjection *proj,
gboolean now,
gint x,
@@ -605,7 +610,7 @@ gimp_projection_set_priority_rect (GimpProjection *proj,
proj->priv->priority_rect = rect;
if (proj->priv->chunk_render.idle_id)
- gimp_projection_chunk_render_reinit (proj, FALSE);
+ gimp_projection_chunk_render_reinit (proj);
}
}
@@ -898,12 +903,11 @@ gimp_projection_chunk_render_init (GimpProjection *proj)
chunk_render->target_n_pixels = GIMP_PROJECTION_CHUNK_WIDTH *
GIMP_PROJECTION_CHUNK_HEIGHT;
- gimp_projection_chunk_render_reinit (proj, FALSE);
+ gimp_projection_chunk_render_reinit (proj);
}
static void
-gimp_projection_chunk_render_reinit (GimpProjection *proj,
- gboolean assume_running)
+gimp_projection_chunk_render_reinit (GimpProjection *proj)
{
GimpProjectionChunkRender *chunk_render = &proj->priv->chunk_render;
@@ -929,38 +933,9 @@ gimp_projection_chunk_render_reinit (GimpProjection *proj,
* its unrendered area with the update_areas list, and make it start
* work on the next unrendered area in the list.
*/
- if (chunk_render->idle_id || assume_running)
+ if (chunk_render->idle_id)
{
- cairo_rectangle_int_t rect;
- gint work_h = 0;
-
- if (chunk_render->work_x != chunk_render->x)
- {
- work_h = MIN (chunk_render->work_height,
- chunk_render->y + chunk_render->height -
- chunk_render->work_y);
-
- rect.x = chunk_render->work_x;
- rect.y = chunk_render->work_y;
- rect.width = chunk_render->x + chunk_render->width -
- chunk_render->work_x;
- rect.height = work_h;
-
- if (chunk_render->update_region)
- cairo_region_union_rectangle (chunk_render->update_region, &rect);
- else
- chunk_render->update_region = cairo_region_create_rectangle (&rect);
- }
-
- rect.x = chunk_render->x;
- rect.y = chunk_render->work_y + work_h;
- rect.width = chunk_render->width;
- rect.height = chunk_render->y + chunk_render->height - rect.y;
-
- if (chunk_render->update_region)
- cairo_region_union_rectangle (chunk_render->update_region, &rect);
- else
- chunk_render->update_region = cairo_region_create_rectangle (&rect);
+ gimp_projection_chunk_render_merge (proj);
gimp_projection_chunk_render_next_area (proj);
}
@@ -982,6 +957,42 @@ gimp_projection_chunk_render_reinit (GimpProjection *proj,
}
}
+static void
+gimp_projection_chunk_render_merge (GimpProjection *proj)
+{
+ GimpProjectionChunkRender *chunk_render = &proj->priv->chunk_render;
+ cairo_rectangle_int_t rect;
+ gint work_h = 0;
+
+ if (chunk_render->work_x != chunk_render->x)
+ {
+ work_h = MIN (chunk_render->work_height,
+ chunk_render->y + chunk_render->height -
+ chunk_render->work_y);
+
+ rect.x = chunk_render->work_x;
+ rect.y = chunk_render->work_y;
+ rect.width = chunk_render->x + chunk_render->width -
+ chunk_render->work_x;
+ rect.height = work_h;
+
+ if (chunk_render->update_region)
+ cairo_region_union_rectangle (chunk_render->update_region, &rect);
+ else
+ chunk_render->update_region = cairo_region_create_rectangle (&rect);
+ }
+
+ rect.x = chunk_render->x;
+ rect.y = chunk_render->work_y + work_h;
+ rect.width = chunk_render->width;
+ rect.height = chunk_render->y + chunk_render->height - rect.y;
+
+ if (chunk_render->update_region)
+ cairo_region_union_rectangle (chunk_render->update_region, &rect);
+ else
+ chunk_render->update_region = cairo_region_create_rectangle (&rect);
+}
+
/* Unless specified otherwise, projection re-rendering is organised by
* ChunkRender, which amalgamates areas to be re-rendered and breaks
* them into bite-sized chunks which are chewed on in an idle
@@ -1033,11 +1044,21 @@ gimp_projection_chunk_render_iteration (GimpProjection *proj,
if (work_h != chunk_render->work_height)
{
- /* if the chunk height changed in the middle of a row, refetch the
- * current area, so that we're back at the beginning of a row
+ /* if the chunk height changed in the middle of a row, merge the
+ * remaining area back into the update region, and reset the current area
+ * to the remainder of the row, using the new chunk height
*/
if (work_x != chunk_render->x)
- gimp_projection_chunk_render_reinit (proj, TRUE);
+ {
+ gimp_projection_chunk_render_merge (proj);
+
+ gimp_projection_chunk_render_set_area (
+ proj,
+ work_x,
+ work_y,
+ chunk_render->x + chunk_render->width - work_x,
+ work_h);
+ }
chunk_render->work_height = work_h;
}
@@ -1106,11 +1127,34 @@ gimp_projection_chunk_render_next_area (GimpProjection *proj)
cairo_region_destroy (next_region);
- cairo_region_subtract_rectangle (chunk_render->update_region, &rect);
+ gimp_projection_chunk_render_set_area (proj,
+ rect.x, rect.y,
+ rect.width, rect.height);
- if (cairo_region_is_empty (chunk_render->update_region))
+ return TRUE;
+}
+
+static void
+gimp_projection_chunk_render_set_area (GimpProjection *proj,
+ gint x,
+ gint y,
+ gint w,
+ gint h)
+{
+ GimpProjectionChunkRender *chunk_render = &proj->priv->chunk_render;
+ cairo_rectangle_int_t rect;
+
+ rect.x = x;
+ rect.y = y;
+ rect.width = w;
+ rect.height = h;
+
+ if (chunk_render->update_region)
{
- g_clear_pointer (&chunk_render->update_region, cairo_region_destroy);
+ cairo_region_subtract_rectangle (chunk_render->update_region, &rect);
+
+ if (cairo_region_is_empty (chunk_render->update_region))
+ g_clear_pointer (&chunk_render->update_region, cairo_region_destroy);
}
chunk_render->x = rect.x;
@@ -1120,8 +1164,6 @@ gimp_projection_chunk_render_next_area (GimpProjection *proj)
chunk_render->work_x = chunk_render->x;
chunk_render->work_y = chunk_render->y;
-
- return TRUE;
}
static void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]