mirror of https://github.com/GNOME/gimp.git
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.
This commit is contained in:
parent
411ddb7e48
commit
c9c2397b0d
|
@ -186,11 +186,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,
|
||||
|
@ -615,7 +620,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -909,12 +914,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;
|
||||
|
||||
|
@ -940,8 +944,34 @@ 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)
|
||||
{
|
||||
gimp_projection_chunk_render_merge (proj);
|
||||
|
||||
gimp_projection_chunk_render_next_area (proj);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (chunk_render->update_region == NULL)
|
||||
{
|
||||
g_warning ("%s: wanted to start chunk render with no update_region",
|
||||
G_STRFUNC);
|
||||
return;
|
||||
}
|
||||
|
||||
proj->priv->chunk_render.target_n_pixels = GIMP_PROJECTION_CHUNK_WIDTH *
|
||||
GIMP_PROJECTION_CHUNK_HEIGHT;
|
||||
|
||||
gimp_projection_chunk_render_next_area (proj);
|
||||
|
||||
gimp_projection_chunk_render_start (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;
|
||||
|
||||
|
@ -972,25 +1002,6 @@ gimp_projection_chunk_render_reinit (GimpProjection *proj,
|
|||
cairo_region_union_rectangle (chunk_render->update_region, &rect);
|
||||
else
|
||||
chunk_render->update_region = cairo_region_create_rectangle (&rect);
|
||||
|
||||
gimp_projection_chunk_render_next_area (proj);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (chunk_render->update_region == NULL)
|
||||
{
|
||||
g_warning ("%s: wanted to start chunk render with no update_region",
|
||||
G_STRFUNC);
|
||||
return;
|
||||
}
|
||||
|
||||
proj->priv->chunk_render.target_n_pixels = GIMP_PROJECTION_CHUNK_WIDTH *
|
||||
GIMP_PROJECTION_CHUNK_HEIGHT;
|
||||
|
||||
gimp_projection_chunk_render_next_area (proj);
|
||||
|
||||
gimp_projection_chunk_render_start (proj);
|
||||
}
|
||||
}
|
||||
|
||||
/* Unless specified otherwise, projection re-rendering is organised by
|
||||
|
@ -1044,11 +1055,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;
|
||||
}
|
||||
|
@ -1117,10 +1138,33 @@ gimp_projection_chunk_render_next_area (GimpProjection *proj)
|
|||
|
||||
cairo_region_destroy (next_region);
|
||||
|
||||
gimp_projection_chunk_render_set_area (proj,
|
||||
rect.x, rect.y,
|
||||
rect.width, rect.height);
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -1131,8 +1175,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
|
||||
|
|
Loading…
Reference in New Issue