app: in gimp:gradient, improve adaptive supersampling

In gimp:gradient, when using adaptive supersampling, render the
gradient tile-by-tile, using an iterator, instead of row-by-row.
This significantly improves performance, while also avoiding the
assumption that gimp_adaptive_supersample_area() works row-by-row.

Additionally, when not using supersampling, use a single GRand
instance, since the separation to distinct seed and per-tile
instances, which was a threading optimization (commit
7f39e41254), is no longer needed.
This commit is contained in:
Ell 2019-01-24 04:03:44 -05:00
parent 33d5eb2090
commit 2cd7938f02
1 changed files with 37 additions and 52 deletions

View File

@ -80,11 +80,9 @@ typedef struct
typedef struct
{
GeglBuffer *buffer;
gfloat *row_data;
gint roi_x;
gint width;
GRand *dither_rand;
gfloat *data;
GeglRectangle roi;
GRand *dither_rand;
} PutPixelData;
@ -982,8 +980,8 @@ gradient_put_pixel (gint x,
gpointer put_pixel_data)
{
PutPixelData *ppd = put_pixel_data;
const gint index = x - ppd->roi_x;
gfloat *dest = ppd->row_data + 4 * index;
const gint index = (y - ppd->roi.y) * ppd->roi.width + (x - ppd->roi.x);
gfloat *dest = ppd->data + 4 * index;
if (ppd->dither_rand)
{
@ -1011,12 +1009,6 @@ gradient_put_pixel (gint x,
*dest++ = color->b;
*dest++ = color->a;
}
/* Paint whole row if we are on the rightmost pixel */
if (index == (ppd->width - 1))
gegl_buffer_set (ppd->buffer, GEGL_RECTANGLE (ppd->roi_x, y, ppd->width, 1),
0, babl_format ("R'G'B'A float"), ppd->row_data,
GEGL_AUTO_ROWSTRIDE);
}
static gboolean
@ -1035,6 +1027,10 @@ gimp_operation_gradient_process (GeglOperation *operation,
RenderBlendData rbd = { 0, };
GeglBufferIterator *iter;
GeglRectangle *roi;
GRand *dither_rand = NULL;
if (! self->gradient)
return TRUE;
@ -1097,45 +1093,38 @@ gimp_operation_gradient_process (GeglOperation *operation,
/* Render the gradient! */
iter = gegl_buffer_iterator_new (output, result, 0,
babl_format ("R'G'B'A float"),
GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE, 1);
roi = &iter->items[0].roi;
if (self->dither)
dither_rand = g_rand_new ();
if (self->supersample)
{
PutPixelData ppd = { 0, };
PutPixelData ppd;
ppd.buffer = output;
ppd.row_data = g_malloc (sizeof (float) * 4 * result->width);
ppd.roi_x = result->x;
ppd.width = result->width;
if (self->dither)
ppd.dither_rand = g_rand_new ();
ppd.dither_rand = dither_rand;
gimp_adaptive_supersample_area (result->x, result->y,
result->x + result->width - 1,
result->y + result->height - 1,
self->supersample_depth,
self->supersample_threshold,
gradient_render_pixel, &rbd,
gradient_put_pixel, &ppd,
NULL,
NULL);
while (gegl_buffer_iterator_next (iter))
{
ppd.data = iter->items[0].data;
ppd.roi = *roi;
if (self->dither)
g_rand_free (ppd.dither_rand);
g_free (ppd.row_data);
gimp_adaptive_supersample_area (roi->x, roi->y,
roi->x + roi->width - 1,
roi->y + roi->height - 1,
self->supersample_depth,
self->supersample_threshold,
gradient_render_pixel, &rbd,
gradient_put_pixel, &ppd,
NULL,
NULL);
}
}
else
{
GeglBufferIterator *iter;
GeglRectangle *roi;
GRand *seed = NULL;
iter = gegl_buffer_iterator_new (output, result, 0,
babl_format ("R'G'B'A float"),
GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE, 1);
roi = &iter->items[0].roi;
if (self->dither)
seed = g_rand_new ();
while (gegl_buffer_iterator_next (iter))
{
gfloat *dest = iter->items[0].data;
@ -1143,10 +1132,8 @@ gimp_operation_gradient_process (GeglOperation *operation,
gint endy = roi->y + roi->height;
gint x, y;
if (seed)
if (dither_rand)
{
GRand *dither_rand = g_rand_new_with_seed (g_rand_int (seed));
for (y = roi->y; y < endy; y++)
for (x = roi->x; x < endx; x++)
{
@ -1170,8 +1157,6 @@ gimp_operation_gradient_process (GeglOperation *operation,
*dest++ = MAX (b, 0.0);
*dest++ = MAX (a, 0.0);
}
g_rand_free (dither_rand);
}
else
{
@ -1189,11 +1174,11 @@ gimp_operation_gradient_process (GeglOperation *operation,
}
}
}
if (self->dither)
g_rand_free (seed);
}
if (self->dither)
g_rand_free (dither_rand);
g_clear_object (&rbd.dist_sampler);
return TRUE;