[gimp] app: in gimp:gradient, improve adaptive supersampling



commit 2cd7938f02a92c63d57c7dc94e9bb93cdea9af05
Author: Ell <ell_se yahoo com>
Date:   Thu Jan 24 04:03:44 2019 -0500

    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
    7f39e412545e2e45fb3386a0941f33de3d1a66ba), is no longer needed.

 app/operations/gimpoperationgradient.c | 95 ++++++++++++++--------------------
 1 file changed, 40 insertions(+), 55 deletions(-)
---
diff --git a/app/operations/gimpoperationgradient.c b/app/operations/gimpoperationgradient.c
index 466de0a3a7..a10900d115 100644
--- a/app/operations/gimpoperationgradient.c
+++ b/app/operations/gimpoperationgradient.c
@@ -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, };
-
-      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 ();
-
-      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);
-
-      if (self->dither)
-        g_rand_free (ppd.dither_rand);
-      g_free (ppd.row_data);
+      PutPixelData ppd;
+
+      ppd.dither_rand = dither_rand;
+
+      while (gegl_buffer_iterator_next (iter))
+        {
+          ppd.data = iter->items[0].data;
+          ppd.roi  = *roi;
+
+          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;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]