gegl r2384 - in trunk: . gegl/buffer gegl/operation



Author: ok
Date: Thu Jun  5 09:55:48 2008
New Revision: 2384
URL: http://svn.gnome.org/viewvc/gegl?rev=2384&view=rev

Log:
* gegl/buffer/gegl-buffer-iterator.[ch]: trimmed down
GeglBufferIterator to a tiny babl powered API.
* gegl/buffer/gegl-buffer-access.c: ported to new API.
* gegl/operation/gegl-operation-point-composer.c: ..
* gegl/operation/gegl-operation-point-filter.c: ..
* gegl/operation/gegl-operation-point-render.c: ..


Modified:
   trunk/ChangeLog
   trunk/gegl/buffer/gegl-buffer-access.c
   trunk/gegl/buffer/gegl-buffer-iterator.c
   trunk/gegl/buffer/gegl-buffer-iterator.h
   trunk/gegl/operation/gegl-operation-point-composer.c
   trunk/gegl/operation/gegl-operation-point-filter.c
   trunk/gegl/operation/gegl-operation-point-render.c

Modified: trunk/gegl/buffer/gegl-buffer-access.c
==============================================================================
--- trunk/gegl/buffer/gegl-buffer-access.c	(original)
+++ trunk/gegl/buffer/gegl-buffer-access.c	Thu Jun  5 09:55:48 2008
@@ -1157,14 +1157,7 @@
                   GeglBuffer          *dst,
                   const GeglRectangle *dst_rect)
 {
-  /* FIXME: make gegl_buffer_copy work with COW shared tiles when possible */
-
-  GeglRectangle src_line;
-  GeglRectangle dst_line;
   Babl         *fish;
-  guchar       *temp;
-  guint         i;
-  gint          pxsize;
 
   g_return_if_fail (GEGL_IS_BUFFER (src));
   g_return_if_fail (GEGL_IS_BUFFER (dst));
@@ -1179,54 +1172,21 @@
       dst_rect = src_rect;
     }
 
-  pxsize = src->tile_storage->px_size;
   fish = babl_fish (src->format, dst->format);
 
-  src_line = *src_rect;
-  src_line.height = 1;
-
-  dst_line = *dst_rect;
-  dst_line.width = src_line.width;
-  dst_line.height = src_line.height;
-
-  if (gegl_buffer_scan_compatible (src, src_rect->x, src_rect->y,
-                                   dst, dst_rect->x, dst_rect->y)) /*  is this check good enough
-                                               *  with the shifts we might
-                                               *  do?
-                                               */
-    {
-      GeglBufferScanIterator read;
-      GeglBufferScanIterator write;
-      gboolean a=FALSE,b=FALSE;
-
-      gegl_buffer_scan_iterator_init (&read,  src, *dst_rect, FALSE);
-      gegl_buffer_scan_iterator_init (&write, dst, *dst_rect, TRUE);
-
-      while (  (a = gegl_buffer_scan_iterator_next (&read)) &&
-               (b = gegl_buffer_scan_iterator_next (&write)))
-        {
-          g_assert (read.length == write.length);
-          babl_process (fish, read.data, write.data, write.length);
-        }
-
-      if (a)
-        while (gegl_buffer_scan_iterator_next (&read));
-      if (b)
-        while (gegl_buffer_scan_iterator_next (&write));
-
-      return;
-    }
-
-  temp = g_malloc (src_line.width * pxsize);
-
-  for (i=0; i<src_rect->height; i++)
     {
-      gegl_buffer_get (src, 1.0, &src_line, dst->format, temp, GEGL_AUTO_ROWSTRIDE);
-      gegl_buffer_set (dst, &dst_line, dst->format, temp, GEGL_AUTO_ROWSTRIDE);
-      src_line.y++;
-      dst_line.y++;
+      GeglRectangle dest_rect_r = *dst_rect;
+      GeglBufferIterator *i;
+      gint read;
+
+      dest_rect_r.width = src_rect->width;
+      dest_rect_r.height = src_rect->height;
+
+      i = gegl_buffer_iterator_new (dst, dest_rect_r, dst->format, GEGL_BUFFER_WRITE);
+      read = gegl_buffer_iterator_add (i, src, *src_rect, src->format, GEGL_BUFFER_READ);
+      while (gegl_buffer_iterator_next (i))
+        babl_process (fish, i->data[read], i->data[0], i->length);
     }
-  g_free (temp);
 }
 
 void

Modified: trunk/gegl/buffer/gegl-buffer-iterator.c
==============================================================================
--- trunk/gegl/buffer/gegl-buffer-iterator.c	(original)
+++ trunk/gegl/buffer/gegl-buffer-iterator.c	Thu Jun  5 09:55:48 2008
@@ -26,68 +26,106 @@
 #include "gegl-types.h"
 #include "gegl-buffer-types.h"
 #include "gegl-buffer-iterator.h"
+#include "gegl-buffer-private.h"
 #include "gegl-tile-storage.h"
-
-gboolean                gegl_buffer_tile_iterator_next (GeglBufferTileIterator *i);
-GeglBufferTileIterator *gegl_buffer_tile_iterator_new  (GeglBuffer             *buffer,
-                                                        GeglRectangle           roi,
-                                                        gboolean                write);
-void                    gegl_buffer_tile_iterator_init (GeglBufferTileIterator *i,
-                                                        GeglBuffer             *buffer,
-                                                        GeglRectangle           roi,
-                                                        gboolean                write);
+#include "gegl-utils.h"
 
 
+typedef struct GeglBufferTileIterator
+{
+  GeglBuffer    *buffer;
+  GeglRectangle  roi;     /* the rectangular region we're iterating over */
+  GeglTile      *tile;    /* current tile */
+  gpointer       data;    /* current tile's data */
+
+  gint           col;     /* the column currently provided for */
+  gint           row;     /* the row currently provided for */
+  gboolean       write;
+  GeglRectangle  subrect;    /* the subrect that intersected roi */
+  gpointer       sub_data;   /* pointer to the subdata as indicated by subrect */
+  gint           rowstride;  /* rowstride for tile, in bytes */
+
+  gint           next_col; /* used internally */
+  gint           next_row; /* used internally */
+} GeglBufferTileIterator;
+
+typedef struct GeglBufferScanIterator {
+  GeglBufferTileIterator tile_iterator; /* must be first member since we do
+                                           casting */
+  gint                   max_size; /* maximum data buffer needed, in bytes */
+  gint                   length;   /* how long the current scan is in pixels */
+  gpointer               data;     /* the current scans data */
+  GeglRectangle          roi;      /* the rectangular subregion of data
+                                    * in the buffer represented by this scan.
+                                    */
+
+  gint                   row;       /* used internally */
+  gint                   next_row;  /* used internally */
+} GeglBufferScanIterator;
 
-#define gegl_buffer_scan_iterator_get_x(i) \
-    ((((GeglBufferTileIterator*)(i))->roi.x) + \
-    (((GeglBufferTileIterator*)(i))->real_col))
-#define gegl_buffer_scan_iterator_get_y(i) \
-    ( (((GeglBufferTileIterator*)(i))->roi.y)+ \
-      (((GeglBufferTileIterator*)(i))->real_row)+ \
-      ((GeglBufferScanIterator*)(i))->real_row)
-
-#define gegl_buffer_scan_iterator_get_rectangle(i,rect_ptr) \
-  do{GeglRectangle *foo = rect_ptr;\
-   if (foo) {\
-   foo->x=gegl_buffer_scan_iterator_get_x(i);\
-   foo->y=gegl_buffer_scan_iterator_get_y(i);\
-   foo->width= ((GeglBufferTileIterator*)i)->subrect.width;\
-   foo->height=((GeglBufferScanIterator*)i)->length/ foo->width;\
-   }}while(0)
-
-void gegl_buffer_tile_iterator_init (GeglBufferTileIterator *i,
-                                     GeglBuffer             *buffer,
-                                     GeglRectangle           roi,
-                                     gboolean                write)
+typedef struct GeglBufferIterators
+{
+  GeglRectangle  roi;                /* current region of interest */
+  gint           length;             /* length of current data in pixels */
+  gpointer       data       [GEGL_BUFFER_MAX_ITERATORS]; 
+
+  gint           iterators;
+  /* the following is private: */
+  gint           iteration_no;
+  GeglRectangle  rect       [GEGL_BUFFER_MAX_ITERATORS];
+  const Babl    *format     [GEGL_BUFFER_MAX_ITERATORS];
+  Babl          *fish       [GEGL_BUFFER_MAX_ITERATORS];
+  Babl          *fish_to    [GEGL_BUFFER_MAX_ITERATORS];
+  GeglBuffer    *buffer     [GEGL_BUFFER_MAX_ITERATORS];
+  guint          flags      [GEGL_BUFFER_MAX_ITERATORS];
+  gpointer       buf        [GEGL_BUFFER_MAX_ITERATORS]; 
+  gboolean       compatible [GEGL_BUFFER_MAX_ITERATORS];
+  GeglBufferScanIterator   i[GEGL_BUFFER_MAX_ITERATORS]; 
+} GeglBufferIterators;
+
+
+static void      gegl_buffer_tile_iterator_init (GeglBufferTileIterator *i,
+                                                 GeglBuffer             *buffer,
+                                                 GeglRectangle           roi,
+                                                 gboolean                write);
+static gboolean  gegl_buffer_tile_iterator_next (GeglBufferTileIterator *i);
+static void      gegl_buffer_scan_iterator_init (GeglBufferScanIterator *i,
+                                                 GeglBuffer             *buffer,
+                                                 GeglRectangle           roi,
+                                                 gboolean                write);
+static gboolean  gegl_buffer_scan_iterator_next (GeglBufferScanIterator *i);
+static gboolean  gegl_buffer_scan_compatible    (GeglBuffer             *input,
+                                                 gint                    x0,
+                                                 gint                    y0,
+                                                 GeglBuffer             *output,
+                                                 gint                    x1,
+                                                 gint                    y1);
+
+
+static void gegl_buffer_tile_iterator_init (GeglBufferTileIterator *i,
+                                            GeglBuffer             *buffer,
+                                            GeglRectangle           roi,
+                                            gboolean                write)
 {
   g_assert (i);
   memset (i, 0, sizeof (GeglBufferTileIterator));
+  if (roi.width == 0 ||
+      roi.height == 0)
+    g_error ("eeek");
   i->buffer = buffer;
   i->roi = roi;
-  i->row    = 0;
-  i->col = 0;
+  i->next_row    = 0;
+  i->next_col = 0;
   i->tile = NULL;
-  i->real_col = 0;
-  i->real_row = 0;
+  i->col = 0;
+  i->row = 0;
   i->write = write;
 }
 
-
-GeglBufferTileIterator *
-gegl_buffer_tile_iterator_new (GeglBuffer    *buffer,
-                               GeglRectangle  roi,
-                               gboolean       write)
-{
-  GeglBufferTileIterator *i = g_malloc (sizeof (GeglBufferTileIterator));
-  gegl_buffer_tile_iterator_init (i, buffer, roi, write);
-  return i; 
-}
-
-void gegl_buffer_scan_iterator_init (GeglBufferScanIterator *i,
-                                     GeglBuffer             *buffer,
-                                     GeglRectangle           roi,
-                                     gboolean                write)
+static void gegl_buffer_scan_iterator_init (GeglBufferScanIterator *i,
+                                            GeglBuffer             *buffer,
+                                            GeglRectangle           roi,
+                                            gboolean                write)
 {
   GeglBufferTileIterator *tile_i = (GeglBufferTileIterator*)i;
   g_assert (i);
@@ -96,21 +134,12 @@
   i->max_size = tile_i->buffer->tile_storage->tile_width *
                 tile_i->buffer->tile_storage->tile_height *
                 tile_i->buffer->format->format.bytes_per_pixel;
-  i->real_row = 0;
+  i->row = 0;
   if (write)
     gegl_buffer_lock (buffer);
 }
 
-GeglBufferScanIterator *gegl_buffer_scan_iterator_new (GeglBuffer             *buffer,
-                                                       GeglRectangle           roi,
-                                                       gboolean                write)
-{
-  GeglBufferScanIterator *i = g_malloc (sizeof (GeglBufferScanIterator));
-  gegl_buffer_scan_iterator_init (i, buffer, roi, write);
-  return i;
-}
-
-gboolean
+static gboolean
 gegl_buffer_scan_iterator_next (GeglBufferScanIterator *i)
 {
   GeglBufferTileIterator *tile_i = (GeglBufferTileIterator*)i;
@@ -119,60 +148,59 @@
     {
       gulp:
       if (!gegl_buffer_tile_iterator_next (tile_i))
-        return FALSE;
+        return FALSE; /* this is where the scan iterator terminates */
+
       i->length = tile_i->subrect.width;
-      i->rowstride = tile_i->subrect.width;
+      i->next_row = 0;
       i->row = 0;
-      i->real_row = 0;
+
+      i->roi.x      = tile_i->roi.x + tile_i->col;
+      i->roi.y      = tile_i->roi.y+ tile_i->row+ i->row;
+      i->roi.width  = tile_i->subrect.width;
+      i->roi.height = tile_i->subrect.height;
     }
   /* we should now have a valid tile */
 
-  if (tile_i->subrect.width == tile_i->buffer->tile_storage->tile_width &&
-      i->row < tile_i->subrect.height)
-    /* the entire contents of the tile can be expressed as one long scan */
-    {
-      gint  px_size = tile_i->buffer->format->format.bytes_per_pixel;
-      guchar *data = tile_i->data;
-      i->length = tile_i->subrect.width * tile_i->subrect.height;
-      i->rowstride = tile_i->subrect.width;
-      i->data = data + px_size * (tile_i->subrect.width * tile_i->subrect.y);
-      i->row = tile_i->subrect.height;
-      i->real_row = 0;
-/*      if (i->rowstride < 0)
-        {
-          return FALSE;
-        }*/
-      gegl_buffer_scan_iterator_get_rectangle (i, &(i->roi));
-      return TRUE;
-    }
-  else if (i->row < tile_i->subrect.height)
-    /* iterate thorugh the scanlines in the subrect */
-    {
-      guchar *data = tile_i->sub_data;
-      i->data = data + i->row * tile_i->rowstride;
-      i->real_row = i->row;
-      i->row ++;
-      return TRUE;
+  if (i->next_row < tile_i->subrect.height)
+    {
+      if (tile_i->subrect.width == tile_i->buffer->tile_storage->tile_width)
+        /* the entire contents of the tile can be expressed as one long scan */
+        {
+          i->length = tile_i->subrect.width * tile_i->subrect.height;
+          i->data = tile_i->sub_data;
+          i->row = 0;
+          i->next_row = tile_i->subrect.height;
+          return TRUE;
+        }
+      else 
+        /* iterate thorugh the scanlines in the subrect */
+        {
+          guchar *data = tile_i->sub_data;
+
+          i->roi.height = 1;
+
+          i->data = data + i->next_row * tile_i->rowstride;
+          i->row = i->next_row;
+          i->next_row ++;
+          return TRUE;
+        }
     }
   else
     { /* we're done with that tile go get another one if possible */
       goto gulp;
     }
 
-  if (tile_i->write)
-    gegl_buffer_unlock (tile_i->buffer);
-
   return FALSE;
 }
 
 
-gboolean gegl_buffer_scan_compatible (GeglBuffer *input,
-                                      gint        x0,
-                                      gint        y0,
-                                      GeglBuffer *output,
-                                      gint        x1,
-                                      gint        y1)
-{
+static gboolean gegl_buffer_scan_compatible (GeglBuffer *input,
+                                             gint        x0,
+                                             gint        y0,
+                                             GeglBuffer *output,
+                                             gint        x1,
+                                             gint        y1)
+{ 
   if (input->tile_storage->tile_width !=
       output->tile_storage->tile_width)
     return FALSE;
@@ -194,7 +222,7 @@
   return TRUE;
 }
 
-gboolean
+static gboolean
 gegl_buffer_tile_iterator_next (GeglBufferTileIterator *i)
 {
   GeglBuffer *buffer = i->buffer;
@@ -204,8 +232,6 @@
   gint  buffer_shift_y = buffer->shift_y;
   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  abyss_x_total  = buffer_abyss_x + buffer->abyss.width;
 
   if (i->roi.width == 0 || i->roi.height == 0)
     return FALSE;
@@ -223,60 +249,25 @@
       i->tile = NULL;
     }
 
-  if (i->col < i->roi.width)
+  if (i->next_col < i->roi.width)
     { /* return tile on this row */
-      gint tiledx = buffer_x + i->col;
-      gint tiledy = buffer_y + i->row;
+      gint tiledx = buffer_x + i->next_col;
+      gint tiledy = buffer_y + i->next_row;
       gint offsetx = gegl_tile_offset (tiledx, tile_width);
       gint offsety = gegl_tile_offset (tiledy, tile_height);
-      gint pixels; 
-
-      if (i->roi.width + offsetx - i->col < tile_width)
-        pixels = (i->roi.width + offsetx - i->col) - offsetx;
-      else
-        pixels = tile_width - offsetx;
 
-     /*if (!(buffer_x + i->col + tile_width >= buffer_abyss_x &&
-                      buffer_x + i->col < abyss_x_total))
-       { 
-          g_warning ("entire tile in abyss?");
-
-          i->col += tile_width - offsetx;
-          goto gulp;
-       }
-     else*/
-       {
+        {
          i->subrect.x = offsetx;
          i->subrect.y = offsety;
-
-         i->subrect.width = 
-           //pixels;
-        (i->roi.width - i->col + tile_width < tile_width) ?
-                             (i->roi.width - i->col + tile_width) - i->subrect.x:
-                             tile_width - i->subrect.x;
-
-
-
-         i->subrect.height = (i->roi.height - i->row + tile_height < tile_height) ?
-                             (i->roi.height - i->row + tile_height) - i->subrect.y:
-                             tile_height - i->subrect.y;
-
-         if(0){
-         gint lskip = (buffer_abyss_x) - (buffer_x + i->col);
-         /* gap between left side of tile, and abyss */
-         gint rskip = (buffer_x + i->col + i->subrect.width) - abyss_x_total;
-         /* gap between right side of tile, and abyss */
-
-           if (lskip < 0)
-              lskip = 0;
-           if (lskip > i->subrect.width)
-              lskip = i->subrect.width;
-           if (rskip < 0)
-              rskip = 0;
-           if (rskip > i->subrect.width)
-              rskip = i->subrect.width;
-           i->subrect.width = i->subrect.width - rskip - lskip;
-         }
+         if (i->roi.width + offsetx - i->next_col < tile_width)
+           i->subrect.width = (i->roi.width + offsetx - i->next_col) - offsetx;
+         else
+           i->subrect.width = tile_width - offsetx;
+
+         if (i->roi.height + offsety - i->next_row < tile_height)
+           i->subrect.height = (i->roi.height + offsety - i->next_row) - offsety;
+         else
+           i->subrect.height = tile_height - offsety;
 
          i->tile = gegl_tile_source_get_tile ((GeglTileSource *) (buffer),
                                                gegl_tile_indice (tiledx, tile_width),
@@ -294,27 +285,28 @@
          i->sub_data = (guchar*)(i->data) + bpp * (i->subrect.y * tile_width + i->subrect.x);
          }
 
-         /* update with new future position (note this means that the
-          * coordinates read from the iterator do not make full sense 
-          * */
-         i->real_col = i->col;
-         i->real_row = i->row;
-         i->col += tile_width - offsetx;
+         i->col = i->next_col;
+         i->row = i->next_row;
+         i->next_col += tile_width - offsetx;
 
          return TRUE;
        }
     }
   else /* move down to next row */
     {
-      gint tiledy = buffer_y + i->row;
-      gint offsety = gegl_tile_offset (tiledy, tile_height);
+      gint tiledy;
+      gint offsety;
 
-      i->real_row = i->row;
-      i->real_col = i->col;
-      i->row += tile_height - offsety;
-      i->col=0;
+      i->row = i->next_row;
+      i->col = i->next_col;
 
-      if (i->row < i->roi.height)
+      tiledy = buffer_y + i->next_row;
+      offsety = gegl_tile_offset (tiledy, tile_height);
+
+      i->next_row += tile_height - offsety;
+      i->next_col=0;
+
+      if (i->next_row < i->roi.height)
         {
           goto gulp; /* return the first tile in the next row */
         }
@@ -323,3 +315,178 @@
     }
   return FALSE;
 }
+
+
+gint
+gegl_buffer_iterator_add (GeglBufferIterator  *iterator,
+                          GeglBuffer          *buffer,
+                          GeglRectangle        roi,
+                          const Babl          *format,
+                          guint                flags)
+{
+  GeglBufferIterators *i = (gpointer)iterator;
+  gint self = 0;
+  if (i->iterators+1 > GEGL_BUFFER_MAX_ITERATORS)
+    {
+      g_error ("too many iterators (%i)", i->iterators+1);
+    }
+
+  if (i->iterators == 0) /* for sanity, we zero at init */
+    {
+      memset (i, 0, sizeof (GeglBufferIterators));
+    }
+
+  self = i->iterators++;
+
+  i->rect[self]=roi;
+  i->buffer[self]=buffer;
+  if (format)
+    i->format[self]=format;
+  else
+    i->format[self]=buffer->format;
+  i->flags[self]=flags;
+
+  if (self==0) /* The first buffer which is always scan aligned */
+    {
+      i->compatible[self]= TRUE;
+      gegl_buffer_scan_iterator_init (&i->i[self], i->buffer[self], i->rect[self], ((i->flags[self] & GEGL_BUFFER_WRITE) != 0) );
+    }
+  else
+    {
+      i->rect[self].width = i->rect[0].width;
+      i->rect[self].height = i->rect[0].height;
+      if (gegl_buffer_scan_compatible (i->buffer[0], i->rect[0].x, i->rect[0].y,
+                                       i->buffer[self], i->rect[self].x, i->rect[self].y))
+        {
+          i->compatible[self] = TRUE;
+          gegl_buffer_scan_iterator_init (&i->i[self], i->buffer[self], i->rect[self], ((i->flags[self] & GEGL_BUFFER_WRITE) != 0));
+        }
+      else
+        {
+          i->buf[self] = gegl_malloc (i->format[self]->format.bytes_per_pixel *
+                                      i->i[0].max_size);
+        }
+    }
+
+  if (i->format[self] != i->buffer[self]->format ||
+      i->compatible[self] == FALSE)
+    {
+      i->buf[self] = gegl_malloc (i->format[self]->format.bytes_per_pixel *
+                                  i->i[0].max_size);
+      if (i->flags[self] & GEGL_BUFFER_READ)
+        i->fish[self] = babl_fish (i->buffer[self]->format, i->format[self]);
+      if (i->flags[self] & GEGL_BUFFER_WRITE)
+        i->fish_to[self] = babl_fish (i->format[self], i->buffer[self]->format);
+     }
+
+  return self;
+}
+
+gboolean gegl_buffer_iterator_next     (GeglBufferIterator *iterator)
+{
+  GeglBufferIterators *i = (gpointer)iterator;
+  gboolean result = FALSE;
+  gint no;
+  /* first we need to finish off any pending write work */
+
+  if (i->buf[0] == (void*)0xdeadbeef)
+    g_error ("%s called on finished buffer iterator", G_STRFUNC);
+  if (i->iteration_no > 0)
+    {
+      for (no=0; no<i->iterators;no++)
+        {
+          if (i->flags[no] & GEGL_BUFFER_WRITE)
+            {
+              if (i->compatible[no])
+                {
+                  if (i->fish_to[no])
+                    babl_process (i->fish_to[no], i->buf[no], i->i[no].data, i->i[no].length);
+                }
+              else
+                {
+                  GeglRectangle rect = i->roi;
+                  rect.x += (i->rect[no].x-i->rect[0].x);
+                  rect.y += (i->rect[no].y-i->rect[0].y);
+                  gegl_buffer_set (i->buffer[no], &rect, i->format[no], i->buf[no], GEGL_AUTO_ROWSTRIDE);
+                }
+            }
+        }
+    }
+
+  g_assert (i->iterators > 0);
+
+  /* then we iterate all */
+  for (no=0; no<i->iterators;no++)
+    {
+      if (i->compatible[no])
+        {
+          gboolean res;
+          res = gegl_buffer_scan_iterator_next (&i->i[no]);
+          if (no == 0)
+            {
+              result = res;
+              i->roi = i->i->roi; /* the "clock" we're operating from is
+                                     the first buffer*/
+              i->length = i->i->length;
+            }
+          else
+            {
+              g_assert (i->length == i->i->length);
+            }
+
+          /* since they were scan compatible this should be true */
+          if (res != result)
+            {
+              g_print ("%i %i %i\n", res, result);
+             } 
+          g_assert (res == result);
+
+          if (i->buf[no]!=NULL)
+            {
+              if (i->flags[no] & GEGL_BUFFER_READ)
+                babl_process (i->fish[no], i->i[no].data, i->buf[no], i->i[no].length);
+              i->data[no]=i->buf[no];
+            }
+          else
+            {
+              i->data[no]=i->i[no].data;
+            }
+        }
+      else
+        {
+          GeglRectangle rect = i->roi;
+          rect.x += (i->rect[no].x-i->rect[0].x);
+          rect.y += (i->rect[no].y-i->rect[0].y);
+          g_assert (i->buf[no]);
+
+          gegl_buffer_get (i->buffer[no], 1.0, &rect, i->format[no], i->buf[no], GEGL_AUTO_ROWSTRIDE);
+          i->data[no]=i->buf[no];
+        }
+    }
+
+  i->iteration_no++;
+
+  if (result == FALSE)
+    {
+      for (no=0; no<i->iterators;no++)
+        {
+          if (i->buf[no])
+            gegl_free (i->buf[no]);
+          i->buf[no]=NULL;
+        }
+      i->buf[0]=(void*)0xdeadbeef;
+      g_free (i);
+    }
+
+  return result;
+}
+
+GeglBufferIterator *gegl_buffer_iterator_new (GeglBuffer          *buffer,
+                                              GeglRectangle        roi, 
+                                              const Babl          *format,
+                                              guint                flags)
+{
+  GeglBufferIterator *i = (gpointer)g_new0 (GeglBufferIterators, 1);
+  gegl_buffer_iterator_add (i, buffer, roi, format, flags);
+  return i;
+}

Modified: trunk/gegl/buffer/gegl-buffer-iterator.h
==============================================================================
--- trunk/gegl/buffer/gegl-buffer-iterator.h	(original)
+++ trunk/gegl/buffer/gegl-buffer-iterator.h	Thu Jun  5 09:55:48 2008
@@ -21,51 +21,77 @@
 #define __GEGL_BUFFER_ITERATOR_H__
 
 #include "gegl-buffer.h"
-#include "gegl-buffer-private.h"
 
-typedef struct GeglBufferTileIterator
+#define GEGL_BUFFER_MAX_ITERATORS 6
+
+#define GEGL_BUFFER_READ      1
+#define GEGL_BUFFER_WRITE     2
+#define GEGL_BUFFER_READWRITE (GEGL_BUFFER_READ|GEGL_BUFFER_WRITE)
+
+typedef struct GeglBufferIterator
 {
-  GeglBuffer    *buffer;
-  GeglTile      *tile;
   GeglRectangle  roi;
-  gint           col;
-  gint           row;
-  gint           real_col;
-  gint           real_row;
-  gboolean       write;
-  GeglRectangle  subrect;
-  gpointer       data;
-  gpointer       sub_data;
-  gint           rowstride;
-} GeglBufferTileIterator;
-
-typedef struct GeglBufferScanIterator {
-  GeglBufferTileIterator tile_iterator;
-  gint                   max_size;  /* in bytes */
-  gint                   rowstride; /* allows computing  */
-  gint                   length;
-  gint                   row;
-  gint                   real_row;
-  gpointer               data;
-  GeglRectangle          roi;
-} GeglBufferScanIterator;
-
-
-GeglBufferScanIterator *gegl_buffer_scan_iterator_new (GeglBuffer    *buffer,
-                                                       GeglRectangle  roi,
-                                                       gboolean       write);
-
-void      gegl_buffer_scan_iterator_init (GeglBufferScanIterator *i,
-                                          GeglBuffer             *buffer,
-                                          GeglRectangle           roi,
-                                          gboolean                write);
-gboolean  gegl_buffer_scan_iterator_next (GeglBufferScanIterator *i);
-gboolean  gegl_buffer_scan_compatible    (GeglBuffer *input,
-                                          gint        x0,
-                                          gint        y0,
-                                          GeglBuffer *output,
-                                          gint        x1,
-                                          gint        y1);
+  gint           length;
+  gpointer       data[GEGL_BUFFER_MAX_ITERATORS];
+} GeglBufferIterator;
+
+
+/**
+ * gegl_buffer_iterator_new:
+ * @buffer: a #GeglBuffer
+ * @roi: the rectangle to iterate over
+ * @format: the format we want to process this buffers data in, pass 0 to use the buffers format.
+ * @flags: whether we need reading or writing to this buffer one of GEGL_BUFFER_READ, GEGL_BUFFER_WRITE and GEGL_BUFFER_READWRITE.
+ *
+ * Create a new buffer iterator, this buffer will be iterated through
+ * in linear chunks, some chunks might be full tiles the coordinates, see
+ * the documentation of gegl_buffer_iterator_next for how to use it and
+ * destroy it.
+ *
+ * Returns: a new buffer iterator that can be used to iterate through the
+ * buffers pixels.
+ */
+GeglBufferIterator * gegl_buffer_iterator_new  (GeglBuffer         *buffer,
+                                                GeglRectangle       roi, 
+                                                const Babl         *format,
+                                                guint               flags);
+
+/**
+ * gegl_buffer_iterator_add:
+ * @iterator: a #GeglBufferIterator
+ * @buffer: a #GeglBuffer
+ * @roi: the rectangle to iterate over
+ * @format: the format we want to process this buffers data in, pass 0 to use the buffers format.
+ * @flags: whether we need reading or writing to this buffer.
+ *
+ * Adds an additional buffer iterator that will be processed in sync with
+ * the original one, if the buffer doesn't align with the other for tile access
+ * the corresponding scans and regions will be serialized automatically using
+ * gegl_buffer_get.
+ *
+ * Returns: an integer handle refering to the indice in the iterator structure
+ * of the added buffer.
+ */
+gint                 gegl_buffer_iterator_add  (GeglBufferIterator *iterator,
+                                                GeglBuffer         *buffer,
+                                                GeglRectangle       roi, 
+                                                const Babl         *format,
+                                                guint               flags);
+
+
+/**
+ * gegl_buffer_iterator_next:
+ * @iterator: a #GeglBufferIterator
+ *
+ * Do an iteration, this causes a new set of iterator->data[] to become
+ * available if there is more data to process. Changed data from a previous
+ * iteration step will also be saved now. When there is no more data to
+ * be processed NULL will be returned (and the iterator handle is no longer
+ * valid).
+ *
+ * Returns: TRUE if there is more work FALSE if iteration is complete.
+ */
+gboolean             gegl_buffer_iterator_next (GeglBufferIterator *iterator);
 
 
 #endif

Modified: trunk/gegl/operation/gegl-operation-point-composer.c
==============================================================================
--- trunk/gegl/operation/gegl-operation-point-composer.c	(original)
+++ trunk/gegl/operation/gegl-operation-point-composer.c	Thu Jun  5 09:55:48 2008
@@ -193,171 +193,33 @@
                                        GeglBuffer          *output,
                                        const GeglRectangle *result)
 {
+  GeglOperationPointComposerClass *point_composer_class = GEGL_OPERATION_POINT_COMPOSER_GET_CLASS (operation);
   const Babl *in_format  = gegl_operation_get_format (operation, "input");
   const Babl *aux_format = gegl_operation_get_format (operation, "aux");
   const Babl *out_format = gegl_operation_get_format (operation, "output");
 
   if ((result->width > 0) && (result->height > 0))
     {
-      gfloat *in_buf = NULL, *out_buf = NULL, *aux_buf = NULL;
+      GeglBufferIterator *i = gegl_buffer_iterator_new (output, *result, out_format, GEGL_BUFFER_WRITE);
+      gint read  = gegl_buffer_iterator_add (i, input,  *result, in_format, GEGL_BUFFER_READ);
 
-      if (gegl_buffer_scan_compatible (input, result->x, result->y,
-                                       output, result->x, result->y))
+      if (aux)
         {
-          gint input_bpp  = in_format->format.bytes_per_pixel;
-          gint output_bpp = output->format->format.bytes_per_pixel;
-          gint aux_bpp    = aux?aux->format->format.bytes_per_pixel:1;
-
-          Babl *infish;
-          Babl *outfish;
-          GeglBufferScanIterator read;
-          GeglBufferScanIterator write;
-          gboolean a = FALSE, b = FALSE;
-
-          gegl_buffer_scan_iterator_init (&read,  input,  *result, FALSE);
-          gegl_buffer_scan_iterator_init (&write, output, *result, TRUE);
-          
-          infish = babl_fish (input->format, in_format);
-          outfish = babl_fish (out_format, output->format);
-
-	 /* FIXME use direct access when possible (avoid conversions and buffers) 
-          */
-           {
-              if (aux)
-                aux_buf = gegl_malloc (aux_bpp * write.max_size);
-
-              if (input->format == in_format &&
-                  output->format == out_format)
-                {
-                  while (  (a = gegl_buffer_scan_iterator_next (&read)) &&
-                           (b = gegl_buffer_scan_iterator_next (&write)))
-                    {
-                   g_assert (read.length == write.length);
-
-                   if (aux) gegl_buffer_get (aux, 1.0, &write.roi, aux_format, aux_buf,
-                                             GEGL_AUTO_ROWSTRIDE);
-
-                   GEGL_OPERATION_POINT_COMPOSER_GET_CLASS (operation)->process (
-                            operation,
-                            read.data,
-                            aux_buf, /* can be NULL */
-                            write.data,
-                            write.length);
-                    }
-                }
-              else if (input->format == in_format &&
-                       output->format != out_format)
-                {
-                  out_buf = gegl_malloc (output_bpp * write.max_size);
-                  while (  (a = gegl_buffer_scan_iterator_next (&read)) &&
-                           (b = gegl_buffer_scan_iterator_next (&write)))
-                    {
-                      g_assert (read.length == write.length);
-
-                      if (aux) gegl_buffer_get (aux, 1.0, &write.roi, aux_format, aux_buf,
-                                                GEGL_AUTO_ROWSTRIDE);
-
-                      GEGL_OPERATION_POINT_COMPOSER_GET_CLASS (operation)->process (
-                            operation,
-                            read.data,
-                            aux_buf, /* can be NULL */
-                            out_buf,
-                            write.length);
-                      babl_process (outfish, out_buf, write.data, write.length);
-                    }
-                  gegl_free (out_buf);
-                }
-              else if (input->format != in_format &&
-                       output->format == out_format)
-                {
-                  in_buf  = gegl_malloc (input_bpp * read.max_size);
-                  while (  (a = gegl_buffer_scan_iterator_next (&read)) &&
-                           (b = gegl_buffer_scan_iterator_next (&write)))
-                    {
-                      g_assert (read.length == write.length);
-                      babl_process (infish, read.data, in_buf, read.length);
-
-                      if (aux) gegl_buffer_get (aux, 1.0, &write.roi, aux_format, aux_buf,
-                                                GEGL_AUTO_ROWSTRIDE);
-
-                      GEGL_OPERATION_POINT_COMPOSER_GET_CLASS (operation)->process (
-                            operation,
-                            in_buf,
-                            aux_buf, /* can be NULL */
-                            write.data,
-                            write.length);
-                    }
-                  gegl_free (in_buf);
-                }
-              else if (input->format != in_format &&
-                       output->format != out_format)
-                {
-                  in_buf  = gegl_malloc (input_bpp * read.max_size);
-                  out_buf = gegl_malloc (output_bpp * write.max_size);
-                  while (  (a = gegl_buffer_scan_iterator_next (&read)) &&
-                           (b = gegl_buffer_scan_iterator_next (&write)))
-                    {
-                      g_assert (read.length == write.length);
-                      babl_process (infish, read.data, in_buf, read.length);
-
-                      if (aux) gegl_buffer_get (aux, 1.0, &write.roi, aux_format, aux_buf,
-                                                GEGL_AUTO_ROWSTRIDE);
-
-                      GEGL_OPERATION_POINT_COMPOSER_GET_CLASS (operation)->process (
-                            operation,
-                            in_buf,
-                            aux_buf, /* can be NULL */
-                            out_buf,
-                            write.length);
-                      babl_process (outfish, out_buf, write.data, write.length);
-                    }
-                  gegl_free (in_buf);
-                  gegl_free (out_buf);
-                }
+          gint foo = gegl_buffer_iterator_add (i, aux,  *result, aux_format, GEGL_BUFFER_READ);
 
+          while (gegl_buffer_iterator_next (i))
+            {
+               point_composer_class->process (operation, i->data[read], i->data[foo], i->data[0], i->length);
             }
-
-          if (aux)
-            gegl_free (aux_buf);
-          return TRUE;
-        }
-
-      in_buf = gegl_malloc (in_format->format.bytes_per_pixel *
-                         output->extent.width * output->extent.height);
-      if (in_format == out_format)
-        {
-          out_buf = in_buf;
         }
       else
         {
-          out_buf = gegl_malloc (out_format->format.bytes_per_pixel *
-                              output->extent.width * output->extent.height);
-        }
-
-      gegl_buffer_get (input, 1.0, result, in_format, in_buf, GEGL_AUTO_ROWSTRIDE);
-
-      if (aux)
-        {
-          aux_buf = gegl_malloc (aux_format->format.bytes_per_pixel *
-                             output->extent.width * output->extent.height);
-          gegl_buffer_get (aux, 1.0, result, aux_format, aux_buf, GEGL_AUTO_ROWSTRIDE);
+          while (gegl_buffer_iterator_next (i))
+            {
+               point_composer_class->process (operation, i->data[read], NULL, i->data[0], i->length);
+            }
         }
-      {
-        GEGL_OPERATION_POINT_COMPOSER_GET_CLASS (operation)->process (
-          operation,
-          in_buf,
-          aux_buf,
-          out_buf,
-          output->extent.width * output->extent.height);
-      }
-
-      gegl_buffer_set (output, NULL, out_format, out_buf, GEGL_AUTO_ROWSTRIDE);
-
-      gegl_free (in_buf);
-      if (in_format != out_format)
-        gegl_free (out_buf);
-      if (aux)
-        gegl_free (aux_buf);
+      return TRUE;
     }
   return TRUE;
 }

Modified: trunk/gegl/operation/gegl-operation-point-filter.c
==============================================================================
--- trunk/gegl/operation/gegl-operation-point-filter.c	(original)
+++ trunk/gegl/operation/gegl-operation-point-filter.c	Thu Jun  5 09:55:48 2008
@@ -75,153 +75,11 @@
 
   if ((result->width > 0) && (result->height > 0))
     {
-      if (gegl_buffer_scan_compatible (input, result->x, result->y,
-                                       output, result->x, result->y))
-        /* We can use the fastest possible path with the least possible
-         * copies using paralell scan iteratator with possibly direct
-         * read write access to buffers.
-         */
-        {
-          gint input_bpp  = in_format->format.bytes_per_pixel;
-          gint output_bpp = output->format->format.bytes_per_pixel;
-          gpointer     *in_buf = NULL;
-          gpointer     *out_buf = NULL;
-          Babl         *infish;
-          Babl         *outfish;
+      GeglBufferIterator *i = gegl_buffer_iterator_new (output, *result, out_format, GEGL_BUFFER_WRITE);
+      gint read  = gegl_buffer_iterator_add (i, input,  *result, in_format, GEGL_BUFFER_READ);
+      while (gegl_buffer_iterator_next (i))
+           point_filter_class->process (operation, i->data[read], i->data[0], i->length, &i->roi);
 
-          GeglBufferScanIterator read;
-          GeglBufferScanIterator write;
-          gegl_buffer_scan_iterator_init (&read,  input,  *result, FALSE);
-          gegl_buffer_scan_iterator_init (&write, output, *result, TRUE);
-
-          g_assert (input->tile_storage->tile_width == output->tile_storage->tile_width);
-
-
-          infish = babl_fish (input->format, in_format);
-          outfish = babl_fish (out_format, output->format);
-         
-          {
-          gboolean a = FALSE, b = FALSE;
-          if (in_format == input->format &&
-              out_format == output->format)
-            {
-              while (  (a = gegl_buffer_scan_iterator_next (&read)) &&
-                       (b = gegl_buffer_scan_iterator_next (&write)))
-                {
-                  g_assert (read.length == write.length);
-                  point_filter_class->process (operation, read.data, write.data, write.length, &write.roi);
-                }
-            }
-          else if (in_format == input->format &&
-                   out_format != output->format)
-            {
-              out_buf = gegl_malloc (output_bpp * write.max_size);
-              while (  (a = gegl_buffer_scan_iterator_next (&read)) &&
-                       (b = gegl_buffer_scan_iterator_next (&write)))
-                {
-                  g_assert (read.length == write.length);
-                  point_filter_class->process (operation, read.data, out_buf, read.length, &write.roi);
-                  babl_process (outfish, out_buf, write.data, write.length);
-                }
-            }
-          else if (in_format != input->format &&
-                   out_format == output->format)
-            {
-              in_buf  = gegl_malloc (input_bpp * read.max_size);
-              while (  (a = gegl_buffer_scan_iterator_next (&read)) &&
-                       (b = gegl_buffer_scan_iterator_next (&write)))
-                {
-                  if (read.length < 0)
-                    continue;
-                  g_assert (read.length == write.length);
-                  babl_process (infish, read.data, in_buf, read.length);
-                  point_filter_class->process (operation, in_buf, write.data, read.length, &write.roi);
-                }
-            }
-          else if (in_format != input->format &&
-                   out_format != output->format)
-            {
-              in_buf  = gegl_malloc (input_bpp * read.max_size);
-              out_buf = gegl_malloc (output_bpp * write.max_size);
-              while (  (a = gegl_buffer_scan_iterator_next (&read)) &&
-                       (b = gegl_buffer_scan_iterator_next (&write)))
-                {
-                  g_assert (read.length == write.length);
-                  babl_process (infish, read.data, in_buf, read.length);
-                  point_filter_class->process (operation, in_buf, out_buf, read.length, &write.roi);
-                  babl_process (outfish, out_buf, write.data, write.length);
-                }
-            }
-
-          if (a)
-            while (gegl_buffer_scan_iterator_next (&read));
-          if (b)
-            while (gegl_buffer_scan_iterator_next (&write));
-          }
-
-          if (in_buf)
-            gegl_free (in_buf);
-          if (out_buf)
-            gegl_free (out_buf);
-        }
-#if 0
-      else
-        /* do the entire buffer */
-        {
-          gfloat *in_buf;
-          gfloat *out_buf;
-          in_buf = gegl_malloc (in_format->format.bytes_per_pixel *
-                             input->extent.width * input->extent.height);
-          out_buf = gegl_malloc (out_format->format.bytes_per_pixel *
-                             output->extent.width * output->extent.height);
-
-          gegl_buffer_get (input, 1.0, result, in_format, in_buf, GEGL_AUTO_ROWSTRIDE);
-
-          GEGL_OPERATION_POINT_FILTER_GET_CLASS (operation)->process (
-            operation,
-            in_buf,
-            out_buf,
-            output->extent.width * output->extent.height);
-
-          gegl_buffer_set (output, result, out_format, out_buf, GEGL_AUTO_ROWSTRIDE);
-          gegl_free (in_buf);
-          gegl_free (out_buf);
-#else
-      else
-        /* do it in vertical chunks of 32 scanlines */
-        {
-          gfloat *in_buf;
-          GeglRectangle roi;
-          gint skip = 32;
-          gfloat *out_buf;
-          in_buf = gegl_malloc (in_format->format.bytes_per_pixel * result->width * skip);
-          out_buf = gegl_malloc (out_format->format.bytes_per_pixel * result->width * skip);
-
-
-          roi = *result;
-          while (roi.y < result->y + result->height && skip >0 )
-            {
-              for (roi.height=skip; (roi.y + skip <= result->y + result->height);
-                   roi.y+=skip)
-                {
-                  gegl_buffer_get (input, 1.0, &roi, in_format, in_buf, GEGL_AUTO_ROWSTRIDE);
-
-                  GEGL_OPERATION_POINT_FILTER_GET_CLASS (operation)->process (
-                    operation,
-                    in_buf,
-                    out_buf,
-                    result->width * skip, &roi);
-
-                  gegl_buffer_set (output, &roi, out_format, out_buf, GEGL_AUTO_ROWSTRIDE);
-                }
-                skip /= 2;
-              }
-
-
-          gegl_free (in_buf);
-          gegl_free (out_buf);
-        }
-#endif
     }
   return TRUE;
 }

Modified: trunk/gegl/operation/gegl-operation-point-render.c
==============================================================================
--- trunk/gegl/operation/gegl-operation-point-render.c	(original)
+++ trunk/gegl/operation/gegl-operation-point-render.c	Thu Jun  5 09:55:48 2008
@@ -94,29 +94,12 @@
 
   if ((result->width > 0) && (result->height > 0))
     {
-      gint output_bpp = output->format->format.bytes_per_pixel;
-      gpointer     *out_buf = NULL;
-      Babl         *outfish;
+      GeglBufferIterator *i = gegl_buffer_iterator_new (output, *result, out_format, GEGL_BUFFER_WRITE);
 
-      GeglBufferScanIterator write;
-      gegl_buffer_scan_iterator_init (&write, output, *result, TRUE);
-
-      outfish = babl_fish (out_format, output->format);
-      
-
-      out_buf = gegl_malloc (output_bpp * write.max_size);
-      while (gegl_buffer_scan_iterator_next (&write))
+      while (gegl_buffer_iterator_next (i))
         {
-          point_render_class->process (operation, out_buf, write.length, &write.roi);
-
-          /* this is the actual write happening directly to the underlying
-           * scan on the tile.
-           */
-          babl_process (outfish, out_buf, write.data, write.length);
+          point_render_class->process (operation, i->data[0], i->length, &i->roi);
         }
-
-      if (out_buf)
-        gegl_free (out_buf);
     }
   return TRUE;
 }



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