[gegl/abyss] abyss: initial abyss policy in gegl_buffer_iterate



commit 8feace47dbb85ecc51387d8a5bf9e8d84a41ead0
Author: Ville Sokk <ville sokk gmail com>
Date:   Wed Jun 20 21:34:06 2012 +0300

    abyss: initial abyss policy in gegl_buffer_iterate

 gegl/buffer/gegl-buffer-access.c |  410 ++++++++++++++++++++++++++------------
 1 files changed, 282 insertions(+), 128 deletions(-)
---
diff --git a/gegl/buffer/gegl-buffer-access.c b/gegl/buffer/gegl-buffer-access.c
index 3338ccb..6f9ad55 100644
--- a/gegl/buffer/gegl-buffer-access.c
+++ b/gegl/buffer/gegl-buffer-access.c
@@ -331,16 +331,13 @@ gegl_buffer_flush (GeglBuffer *buffer)
                             GEGL_TILE_FLUSH, 0,0,0,NULL);
 }
 
-
-
 static inline void
-gegl_buffer_iterate (GeglBuffer          *buffer,
-                     const GeglRectangle *roi, /* or NULL for extent */
-                     guchar              *buf,
-                     gint                 rowstride,
-                     gboolean             write,
-                     const Babl          *format,
-                     gint                 level)
+gegl_buffer_iterate_write (GeglBuffer          *buffer,
+                           const GeglRectangle *roi, /* or NULL for extent */
+                           guchar              *buf,
+                           gint                 rowstride,
+                           const Babl          *format,
+                           gint                 level)
 {
   gint  tile_width  = buffer->tile_storage->tile_width;
   gint  tile_height = buffer->tile_storage->tile_height;
@@ -388,50 +385,194 @@ gegl_buffer_iterate (GeglBuffer          *buffer,
     buf_stride = rowstride;
 
   if (format == buffer->soft_format)
-    {
       fish = NULL;
-    }
   else
-    {
-      if (write)
-        {
-          fish = babl_fish ((gpointer) format,
-                            (gpointer) buffer->soft_format);
-        }
-      else
-        {
-          fish = babl_fish ((gpointer) buffer->soft_format,
-                            (gpointer) format);
-        }
-    }
+      fish = babl_fish ((gpointer) format,
+                        (gpointer) buffer->soft_format);
 
   while (bufy < height)
     {
       gint tiledy  = buffer_y + bufy;
       gint offsety = gegl_tile_offset (tiledy, tile_height);
-
       gint bufx    = 0;
 
-      if (!(buffer_y + bufy + (tile_height) >= buffer_abyss_y &&
-            buffer_y + bufy < abyss_y_total))
-        { /* entire row of tiles is in abyss */
-          if (!write)
+      while (bufx < width)
+        {
+          gint      tiledx  = buffer_x + bufx;
+          gint      offsetx = gegl_tile_offset (tiledx, tile_width);
+          gint      y       = bufy;
+          gint      lskip, rskip, pixels, row;
+          guchar   *bp, *tile_base, *tp;
+          GeglTile *tile;
+
+          bp = buf + bufy * buf_stride + bufx * bpx_size;
+
+          if (width + offsetx - bufx < tile_width)
+            pixels = (width + offsetx - bufx) - offsetx;
+          else
+            pixels = tile_width - offsetx;
+
+          tile = gegl_tile_source_get_tile ((GeglTileSource *) (buffer),
+                                            gegl_tile_indice (tiledx, tile_width),
+                                            gegl_tile_indice (tiledy, tile_height),
+                                            level);
+
+          lskip = (buffer_abyss_x) - (buffer_x + bufx);
+          /* gap between left side of tile, and abyss */
+          rskip = (buffer_x + bufx + pixels) - abyss_x_total;
+          /* gap between right side of tile, and abyss */
+
+          if (lskip < 0)
+            lskip = 0;
+          if (lskip > pixels)
+            lskip = pixels;
+          if (rskip < 0)
+            rskip = 0;
+          if (rskip > pixels)
+            rskip = pixels;
+
+          if (!tile)
             {
-              gint    row;
-              gint    y  = bufy;
-              guchar *bp = buf + ((bufy) * width) * bpx_size;
+              g_warning ("didn't get tile, trying to continue");
+              bufx += (tile_width - offsetx);
+              continue;
+            }
 
+          gegl_tile_lock (tile);
+
+          tile_base = gegl_tile_get_data (tile);
+          tp        = ((guchar *) tile_base) + (offsety * tile_width + offsetx) * px_size;
+
+          if (fish)
+            {
+              for (row = offsety;
+                   row < tile_height &&
+                     y < height &&
+                     buffer_y + y < abyss_y_total;
+                   row++, y++)
+                {
+
+                  if (buffer_y + y >= buffer_abyss_y &&
+                      buffer_y + y < abyss_y_total)
+                    {
+                      babl_process (fish, bp + lskip * bpx_size, tp + lskip * px_size,
+                                    pixels - lskip - rskip);
+                    }
+
+                  tp += tile_stride;
+                  bp += buf_stride;
+                }
+            }
+          else
+            {
               for (row = offsety;
                    row < tile_height && y < height;
                    row++, y++)
                 {
-                  memset (bp, 0x00, buf_stride);
+
+                  if (buffer_y + y >= buffer_abyss_y &&
+                      buffer_y + y < abyss_y_total)
+                    {
+
+                      memcpy (tp + lskip * px_size, bp + lskip * px_size,
+                              (pixels - lskip - rskip) * px_size);
+                    }
+
+                  tp += tile_stride;
                   bp += buf_stride;
                 }
             }
+
+          gegl_tile_unlock (tile);
+          gegl_tile_unref (tile);
+          bufx += (tile_width - offsetx);
         }
-      else
+      bufy += (tile_height - offsety);
+    }
+}
+
+static inline void
+gegl_buffer_iterate_read (GeglBuffer          *buffer,
+                          const GeglRectangle *roi, /* or NULL for extent */
+                          guchar              *buf,
+                          gint                 rowstride,
+                          const Babl          *format,
+                          gint                 level,
+                          GeglAbyssPolicy      repeat_mode)
+{
+  gint  tile_width  = buffer->tile_storage->tile_width;
+  gint  tile_height = buffer->tile_storage->tile_height;
+  gint  px_size     = babl_format_get_bytes_per_pixel (buffer->soft_format);
+  gint  bpx_size    = babl_format_get_bytes_per_pixel (format);
+  gint  tile_stride = px_size * tile_width;
+  gint  buf_stride;
+  gint  bufy = 0;
+
+  gint  buffer_shift_x = buffer->shift_x;
+  gint  buffer_shift_y = buffer->shift_y;
+
+  gint  width          = buffer->extent.width;
+  gint  height         = buffer->extent.height;
+  gint  buffer_x       = buffer->extent.x + buffer_shift_x;
+  gint  buffer_y       = buffer->extent.y + buffer_shift_y;
+
+  gint  buffer_abyss_x = buffer->abyss.x + buffer_shift_x;
+  gint  buffer_abyss_y = buffer->abyss.y + buffer_shift_y;
+  gint  abyss_x_total  = buffer_abyss_x + buffer->abyss.width;
+  gint  abyss_y_total  = buffer_abyss_y + buffer->abyss.height;
+  gint  factor         = 1<<level;
+  const Babl *fish;
+
+  /* roi specified, override buffers extent */
+  if (roi)
+    {
+      width  = roi->width;
+      height = roi->height;
+      buffer_x = roi->x + buffer_shift_x;
+      buffer_y = roi->y + buffer_shift_y;
+    }
 
+  buffer_abyss_x /= factor;
+  buffer_abyss_y /= factor;
+  abyss_x_total  /= factor;
+  abyss_y_total  /= factor;
+  buffer_x       /= factor;
+  buffer_y       /= factor;
+  width          /= factor;
+  height         /= factor;
+
+  buf_stride = width * bpx_size;
+  if (rowstride != GEGL_AUTO_ROWSTRIDE)
+    buf_stride = rowstride;
+
+  if (format == buffer->soft_format)
+      fish = NULL;
+  else
+      fish = babl_fish ((gpointer) buffer->soft_format,
+                        (gpointer) format);
+
+  while (bufy < height)
+    {
+      gint tiledy  = buffer_y + bufy;
+      gint offsety = gegl_tile_offset (tiledy, tile_height);
+      gint bufx    = 0;
+
+      if (!(buffer_y + bufy + (tile_height) >= buffer_abyss_y &&
+            buffer_y + bufy < abyss_y_total))
+        { /* entire row of tiles is in abyss */
+          gint    row;
+          gint    y  = bufy;
+          guchar *bp = buf + ((bufy) * width) * bpx_size;
+
+          for (row = offsety;
+               row < tile_height && y < height;
+               row++, y++)
+            {
+              memset (bp, 0x00, buf_stride);
+              bp += buf_stride;
+            }
+        }
+      else
         while (bufx < width)
           {
             gint    tiledx  = buffer_x + bufx;
@@ -446,35 +587,32 @@ gegl_buffer_iterate (GeglBuffer          *buffer,
             else
               pixels = tile_width - offsetx;
 
-
             if (!(buffer_x + bufx + tile_width >= buffer_abyss_x &&
                   buffer_x + bufx < abyss_x_total))
               { /* entire tile is in abyss */
-                if (!write)
-                  {
-                    gint row;
-                    gint y = bufy;
+                gint row;
+                gint y = bufy;
 
-                    for (row = offsety;
-                         row < tile_height && y < height;
-                         row++, y++)
-                      {
-                        memset (bp, 0x00, pixels * bpx_size);
-                        bp += buf_stride;
-                      }
+                for (row = offsety;
+                     row < tile_height && y < height;
+                     row++, y++)
+                  {
+                    memset (bp, 0x00, pixels * bpx_size);
+                    bp += buf_stride;
                   }
               }
             else
               {
                 guchar   *tile_base, *tp;
+                gint      row, y, lskip, rskip;
                 GeglTile *tile = gegl_tile_source_get_tile ((GeglTileSource *) (buffer),
-                                                           gegl_tile_indice (tiledx, tile_width),
-                                                           gegl_tile_indice (tiledy, tile_height),
-                                                           level);
+                                                            gegl_tile_indice (tiledx, tile_width),
+                                                            gegl_tile_indice (tiledy, tile_height),
+                                                            level);
 
-                gint lskip = (buffer_abyss_x) - (buffer_x + bufx);
+                lskip = (buffer_abyss_x) - (buffer_x + bufx);
                 /* gap between left side of tile, and abyss */
-                gint rskip = (buffer_x + bufx + pixels) - abyss_x_total;
+                rskip = (buffer_x + bufx + pixels) - abyss_x_total;
                 /* gap between right side of tile, and abyss */
 
                 if (lskip < 0)
@@ -493,97 +631,112 @@ gegl_buffer_iterate (GeglBuffer          *buffer,
                     continue;
                   }
 
-                if (write)
-                  gegl_tile_lock (tile);
-
                 tile_base = gegl_tile_get_data (tile);
                 tp        = ((guchar *) tile_base) + (offsety * tile_width + offsetx) * px_size;
 
-                if (write)
+                y = bufy;
+                for (row = offsety;
+                     row < tile_height && y < height;
+                     row++, y++)
                   {
-                    gint row;
-                    gint y = bufy;
-
-
-                    if (fish)
+                    if (buffer_y + y >= buffer_abyss_y &&
+                        buffer_y + y < abyss_y_total)
                       {
-                        for (row = offsety;
-                             row < tile_height &&
-                             y < height &&
-                             buffer_y + y < abyss_y_total;
-                             row++, y++)
-                          {
-
-                            if (buffer_y + y >= buffer_abyss_y &&
-                                buffer_y + y < abyss_y_total)
-                              {
-                                babl_process (fish, bp + lskip * bpx_size, tp + lskip * px_size,
-                                 pixels - lskip - rskip);
-                              }
-
-                            tp += tile_stride;
-                            bp += buf_stride;
-                          }
+                        if (fish)
+                          babl_process (fish, tp, bp, pixels);
+                        else
+                          memcpy (bp, tp, pixels * px_size);
                       }
                     else
                       {
-                        for (row = offsety;
-                             row < tile_height && y < height;
-                             row++, y++)
-                          {
-
-                            if (buffer_y + y >= buffer_abyss_y &&
-                                buffer_y + y < abyss_y_total)
-                              {
+                        /* entire row in abyss */
 
-                                memcpy (tp + lskip * px_size, bp + lskip * px_size,
-                                      (pixels - lskip - rskip) * px_size);
-                              }
-
-                            tp += tile_stride;
-                            bp += buf_stride;
-                          }
-                      }
-
-                    gegl_tile_unlock (tile);
-                  }
-                else /* read */
-                  {
-                    gint row;
-                    gint y = bufy;
-
-                    for (row = offsety;
-                         row < tile_height && y < height;
-                         row++, y++)
-                      {
-                        if (buffer_y + y >= buffer_abyss_y &&
-                            buffer_y + y < abyss_y_total)
-                          {
-                            if (fish)
-                              babl_process (fish, tp, bp, pixels);
-                            else
-                              memcpy (bp, tp, pixels * px_size);
-                          }
-                        else
+                        if (repeat_mode == GEGL_ABYSS_NONE)
                           {
-                            /* entire row in abyss */
                             memset (bp, 0x00, pixels * bpx_size);
                           }
-
-                          /* left hand zeroing of abyss in tile */
-                        if (lskip)
+                        else if (repeat_mode == GEGL_ABYSS_WHITE ||
+                                 repeat_mode == GEGL_ABYSS_BLACK)
                           {
-                            memset (bp, 0x00, bpx_size * lskip);
+                            gfloat color_a[4] = {0.0, 0.0, 0.0, 1.0};
+                            guchar color[128];
+                            gint   i;
+
+                            if (repeat_mode == GEGL_ABYSS_WHITE)
+                              for (i = 0; i < 3; i++)
+                                color_a[i] = 1.0;
+                            babl_process (babl_fish (babl_format ("RGBA float"), format),
+                                          color_a, color, 1);
+
+                            for (i = 0; i < pixels * bpx_size; i += bpx_size)
+                              memcpy (bp + i, color, bpx_size);
                           }
-
-                        /* right side zeroing of abyss in tile */
-                        if (rskip)
+                        else
                           {
-                            memset (bp + (pixels - rskip) * bpx_size, 0x00, bpx_size * rskip);
+                            gint      i, atiledx, atiledy, aoffsetx, aoffsety;
+                            GeglTile *abysstile;
+                            guchar   *data;
+
+                            if (repeat_mode == GEGL_ABYSS_LOOP)
+                              {
+                                atiledx = buffer_abyss_x + (buffer_x + bufx - buffer_abyss_x) % buffer->abyss.width;
+                                atiledy = buffer_abyss_y + (buffer_y + y - buffer_abyss_y) % buffer->abyss.height;
+                              }
+                            else
+                              {
+                                atiledx = CLAMP (buffer_x + bufx, buffer_abyss_x, abyss_x_total - 1);
+                                atiledy = CLAMP (buffer_y + y, buffer_abyss_y, abyss_y_total - 1);
+                              }
+                            aoffsetx = gegl_tile_offset (atiledx, tile_width);
+                            aoffsety = gegl_tile_offset (atiledy, tile_height);
+                            abysstile = gegl_tile_source_get_tile ((GeglTileSource *) (buffer),
+                                                                   gegl_tile_indice (atiledx, tile_width),
+                                                                   gegl_tile_indice (atiledy, tile_height),
+                                                                   level);
+                            data = gegl_tile_get_data (abysstile) + (aoffsety * tile_width + aoffsetx) * px_size;
+                            if (repeat_mode == GEGL_ABYSS_LOOP)
+                              {
+                                if (fish)
+                                  babl_process (fish, data, bp, pixels);
+                                else
+                                  memcpy (bp, data, pixels * bpx_size);
+                              }
+                            else
+                              {
+                                /* if x was clamped, copy a single pixel repeatedly */
+                                if (atiledx != buffer_x + bufx)
+                                  {
+                                    guchar color[128];
+
+                                    if (fish)
+                                      babl_process (fish, data, color, 1);
+                                    else
+                                      memcpy (color, data, px_size);
+                                    for (i = 0; i < pixels * bpx_size; i += bpx_size)
+                                      memcpy (bp + i, color, bpx_size);
+                                  }
+                                else
+                                  {
+                                    if (fish)
+                                      babl_process (fish, data, bp, pixels);
+                                    else
+                                      memcpy (bp, data, pixels * bpx_size);
+                                  }
+                              }
+                            gegl_tile_unref (abysstile);
                           }
-                        tp += tile_stride;
-                        bp += buf_stride;
                       }
+
+                    /* left hand zeroing of abyss in tile */
+                    if (lskip)
+                      memset (bp, 0x00, bpx_size * lskip);
+
+                    /* right side zeroing of abyss in tile */
+                    if (rskip)
+                      memset (bp + (pixels - rskip) * bpx_size, 0x00, bpx_size * rskip);
+
+                    tp += tile_stride;
+                    bp += buf_stride;
                   }
                 gegl_tile_unref (tile);
               }
@@ -627,7 +780,7 @@ gegl_buffer_set_unlocked_no_notify (GeglBuffer          *buffer,
     }
   else
 #endif
-    gegl_buffer_iterate (buffer, rect, (void *) src, rowstride, TRUE, format, 0);
+    gegl_buffer_iterate_write (buffer, rect, (void *) src, rowstride, format, 0);
 
   if (gegl_buffer_is_shared(buffer))
     {
@@ -997,7 +1150,7 @@ gegl_buffer_get_unlocked (GeglBuffer          *buffer,
 
   if (!rect && scale == 1.0)
     {
-      gegl_buffer_iterate (buffer, NULL, dest_buf, rowstride, FALSE, format, 0);
+      gegl_buffer_iterate_read (buffer, NULL, dest_buf, rowstride, format, 0, repeat_mode);
       return;
     }
 
@@ -1009,7 +1162,7 @@ gegl_buffer_get_unlocked (GeglBuffer          *buffer,
     }
   if (GEGL_FLOAT_EQUAL (scale, 1.0))
     {
-      gegl_buffer_iterate (buffer, rect, dest_buf, rowstride, FALSE, format, 0);
+      gegl_buffer_iterate_read (buffer, rect, dest_buf, rowstride, format, 0, repeat_mode);
       return;
     }
   else
@@ -1049,7 +1202,8 @@ gegl_buffer_get_unlocked (GeglBuffer          *buffer,
       offset_y = rect->y-floor(rect->y/scale) * scale;
 
       sample_buf = g_malloc (buf_width * buf_height * bpp);
-      gegl_buffer_iterate (buffer, &sample_rect, sample_buf, GEGL_AUTO_ROWSTRIDE, FALSE, format, level);
+      gegl_buffer_iterate_read (buffer, &sample_rect, sample_buf, GEGL_AUTO_ROWSTRIDE,
+                                format, level, repeat_mode);
 #if 1
   /* slows testing of rendering code speed too much for now and
    * no time to make a fast implementation



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