diff --git a/gegl/buffer/gegl-buffer-iterator.c b/gegl/buffer/gegl-buffer-iterator.c
index eb7e7a1b..dacbe7ac 100644
--- a/gegl/buffer/gegl-buffer-iterator.c
+++ b/gegl/buffer/gegl-buffer-iterator.c
@@ -18,12 +18,12 @@
  */
 
 #include "config.h"
+
 #include <stdlib.h>
 #include <string.h>
 #include <math.h>
 
 #include <glib-object.h>
-#include <glib/gprintf.h>
 
 #include "gegl.h"
 #include "gegl-types-internal.h"
@@ -56,6 +56,7 @@ typedef enum {
 typedef struct _SubIterState {
   GeglRectangle        full_rect; /* The entire area we are iterating over */
   GeglBuffer          *buffer;
+  GeglNode            *node;
   GeglAccessMode       access_mode;
   GeglAbyssPolicy      abyss_policy;
   const Babl          *format;
@@ -144,6 +145,7 @@ gegl_buffer_iterator_add (GeglBufferIterator  *iter,
   if (priv->state != GeglIteratorState_Invalid)
     {
       sub->buffer       = buf;
+      sub->node         = NULL;
       sub->full_rect    = *roi;
 
       sub->access_mode  = access_mode;
@@ -165,6 +167,53 @@ gegl_buffer_iterator_add (GeglBufferIterator  *iter,
   return index;
 }
 
+int
+gegl_buffer_iterator_add_node (GeglBufferIterator  *iter,
+                               GeglNode            *node,
+                               const GeglRectangle *roi,
+                               gint                 level,
+                               const Babl          *format,
+                               GeglAbyssPolicy      abyss_policy)
+{
+  GeglBufferIteratorPriv *priv = iter->priv;
+  int                     index;
+  SubIterState           *sub;
+
+  g_return_val_if_fail (priv->num_buffers < GEGL_BUFFER_MAX_ITERATORS, 0);
+  g_return_val_if_fail (roi != NULL, 0);
+  g_return_val_if_fail (format != NULL, 0);
+
+  index = priv->num_buffers++;
+  sub = &priv->sub_iter[index];
+
+  if (index == 0 && (roi->width <= 0 || roi->height <= 0))
+    priv->state = GeglIteratorState_Invalid;
+
+  if (priv->state != GeglIteratorState_Invalid)
+    {
+      sub->buffer       = NULL;
+      sub->node         = node;
+      sub->full_rect    = *roi;
+
+      sub->access_mode  = GEGL_ACCESS_READ;
+      sub->abyss_policy = abyss_policy;
+      sub->current_tile = NULL;
+      sub->real_data    = NULL;
+      sub->linear_tile  = NULL;
+      sub->format       = format;
+      sub->format_bpp   = babl_format_get_bytes_per_pixel (format);
+      sub->level        = level;
+
+      if (index > 0)
+        {
+          priv->sub_iter[index].full_rect.width  = priv->sub_iter[0].full_rect.width;
+          priv->sub_iter[index].full_rect.height = priv->sub_iter[0].full_rect.height;
+        }
+    }
+
+  return index;
+}
+
 static void
 release_tile (GeglBufferIterator *iter,
               int index)
@@ -240,7 +289,8 @@ retile_subs (GeglBufferIterator *iter,
   real_roi.height = priv->origin_tile.height;
 
   /* Trim tile down to the iteration roi */
-  gegl_rectangle_intersect (&iter->roi[0], &real_roi, &priv->sub_iter[0].full_rect);
+  gegl_rectangle_intersect (&iter->roi[0], &real_roi,
+                            &priv->sub_iter[0].full_rect);
   priv->sub_iter[0].real_roi = iter->roi[0];
 
   for (index = 1; index < priv->num_buffers; index++)
@@ -347,22 +397,33 @@ get_tile (GeglBufferIterator *iter,
 static inline double
 level_to_scale (int level)
 {
-  return level?1.0/(1<<level):1.0;
+  return level ? 1.0 / (1 << level) : 1.0;
 }
 
 static void
 get_indirect (GeglBufferIterator *iter,
-              int        index)
+              gint                index)
 {
   GeglBufferIteratorPriv *priv = iter->priv;
   SubIterState           *sub  = &priv->sub_iter[index];
 
-  sub->real_data = gegl_malloc (sub->format_bpp * sub->real_roi.width * sub->real_roi.height);
+  sub->real_data = gegl_malloc (sub->format_bpp * sub->real_roi.width *
+                                sub->real_roi.height);
 
   if (sub->access_mode & GEGL_ACCESS_READ)
     {
-      gegl_buffer_get_unlocked (sub->buffer, level_to_scale (sub->level), &sub->real_roi, sub->format, sub->real_data,
-                                GEGL_AUTO_ROWSTRIDE, sub->abyss_policy);
+      if (sub->buffer)
+        {
+          gegl_buffer_get_unlocked (sub->buffer, level_to_scale (sub->level),
+                                    &sub->real_roi, sub->format, sub->real_data,
+                                    GEGL_AUTO_ROWSTRIDE, sub->abyss_policy);
+        }
+      else
+        {
+          gegl_node_blit (sub->node, level_to_scale (sub->level),
+                          &sub->real_roi, sub->format, sub->real_data,
+                          GEGL_AUTO_ROWSTRIDE, 0);
+        }
     }
 
   sub->row_stride = sub->real_roi.width * sub->format_bpp;
@@ -377,12 +438,13 @@ needs_indirect_read (GeglBufferIterator *iter,
 {
   GeglBufferIteratorPriv *priv = iter->priv;
   SubIterState           *sub  = &priv->sub_iter[index];
-  
+
   if (sub->access_mode & GEGL_ITERATOR_INCOMPATIBLE)
     return TRUE;
 
   /* Needs abyss generation */
-  if (!gegl_rectangle_contains (&sub->buffer->abyss, &iter->roi[index]))
+  if (sub->buffer &&
+      ! gegl_rectangle_contains (&sub->buffer->abyss, &iter->roi[index]))
     return TRUE;
 
   return FALSE;
@@ -398,8 +460,9 @@ needs_rows (GeglBufferIterator *iter,
   if (sub->current_tile_mode == GeglIteratorTileMode_GetBuffer)
    return FALSE;
 
-  if (iter->roi[index].width  != sub->buffer->tile_width ||
-      iter->roi[index].height != sub->buffer->tile_height)
+  if (sub->buffer &&
+      (iter->roi[index].width  != sub->buffer->tile_width ||
+       iter->roi[index].height != sub->buffer->tile_height))
     return TRUE;
 
   return FALSE;
@@ -409,58 +472,75 @@ needs_rows (GeglBufferIterator *iter,
 static void
 prepare_iteration (GeglBufferIterator *iter)
 {
-  int index;
   GeglBufferIteratorPriv *priv = iter->priv;
-  gint origin_offset_x;
-  gint origin_offset_y;
+  gint origin_offset_x = 0;
+  gint origin_offset_y = 0;
+  gint index;
 
   /* Set up the origin tile */
   /* FIXME: Pick the most compatable buffer, not just the first */
-  {
-    GeglBuffer *buf = priv->sub_iter[0].buffer;
+  if (priv->sub_iter[0].buffer)
+    {
+      GeglBuffer *buf = priv->sub_iter[0].buffer;
 
-    priv->origin_tile.x      = buf->shift_x;
-    priv->origin_tile.y      = buf->shift_y;
-    priv->origin_tile.width  = buf->tile_width;
-    priv->origin_tile.height = buf->tile_height;
+      priv->origin_tile.x      = buf->shift_x;
+      priv->origin_tile.y      = buf->shift_y;
+      priv->origin_tile.width  = buf->tile_width;
+      priv->origin_tile.height = buf->tile_height;
 
-    origin_offset_x = buf->shift_x + priv->sub_iter[0].full_rect.x;
-    origin_offset_y = buf->shift_y + priv->sub_iter[0].full_rect.y;
-  }
+      origin_offset_x = buf->shift_x + priv->sub_iter[0].full_rect.x;
+      origin_offset_y = buf->shift_y + priv->sub_iter[0].full_rect.y;
+    }
 
   for (index = 0; index < priv->num_buffers; index++)
     {
       SubIterState *sub = &priv->sub_iter[index];
       GeglBuffer *buf   = sub->buffer;
 
-      gint current_offset_x = buf->shift_x + priv->sub_iter[index].full_rect.x;
-      gint current_offset_y = buf->shift_y + priv->sub_iter[index].full_rect.y;
-
-      /* Format converison needed */
-      if (gegl_buffer_get_format (sub->buffer) != sub->format)
-        sub->access_mode |= GEGL_ITERATOR_INCOMPATIBLE;
-      /* Incompatiable tiles */
-      else if ((priv->origin_tile.width  != buf->tile_width) ||
-               (priv->origin_tile.height != buf->tile_height) ||
-               (abs(origin_offset_x - current_offset_x) % priv->origin_tile.width != 0) ||
-               (abs(origin_offset_y - current_offset_y) % priv->origin_tile.height != 0))
+      gint current_offset_x = priv->sub_iter[index].full_rect.x;
+      gint current_offset_y = priv->sub_iter[index].full_rect.y;
+
+      if (buf)
         {
-          /* Check if the buffer is a linear buffer */
-          if ((buf->extent.x      == -buf->shift_x) &&
-              (buf->extent.y      == -buf->shift_y) &&
-              (buf->extent.width  == buf->tile_width) &&
-              (buf->extent.height == buf->tile_height))
-            {
-              sub->linear_tile = gegl_buffer_get_tile (sub->buffer, 0, 0, 0);
+          current_offset_x += buf->shift_x;
+          current_offset_y += buf->shift_y;
+        }
 
-              if (sub->access_mode & GEGL_ACCESS_WRITE)
-                gegl_tile_lock (sub->linear_tile);
+      if (buf)
+        {
+          /* Format converison needed */
+          if (gegl_buffer_get_format (buf) != sub->format)
+            {
+              sub->access_mode |= GEGL_ITERATOR_INCOMPATIBLE;
+            }
+          /* Incompatiable tiles */
+          else if ((priv->origin_tile.width  != buf->tile_width) ||
+                   (priv->origin_tile.height != buf->tile_height) ||
+                   (abs (origin_offset_x - current_offset_x) % priv->origin_tile.width != 0) ||
+                   (abs (origin_offset_y - current_offset_y) % priv->origin_tile.height != 0))
+            {
+              /* Check if the buffer is a linear buffer */
+              if ((buf->extent.x      == -buf->shift_x) &&
+                  (buf->extent.y      == -buf->shift_y) &&
+                  (buf->extent.width  == buf->tile_width) &&
+                  (buf->extent.height == buf->tile_height))
+                {
+                  sub->linear_tile = gegl_buffer_get_tile (buf, 0, 0, 0);
+
+                  if (sub->access_mode & GEGL_ACCESS_WRITE)
+                    gegl_tile_lock (sub->linear_tile);
+                }
+              else
+                sub->access_mode |= GEGL_ITERATOR_INCOMPATIBLE;
             }
-          else
-            sub->access_mode |= GEGL_ITERATOR_INCOMPATIBLE;
+        }
+      else
+        {
+          sub->access_mode |= GEGL_ITERATOR_INCOMPATIBLE;
         }
 
-      gegl_buffer_lock (sub->buffer);
+      if (buf)
+        gegl_buffer_lock (buf);
     }
 }
 
@@ -510,8 +590,8 @@ load_rects (GeglBufferIterator *iter)
 void
 gegl_buffer_iterator_stop (GeglBufferIterator *iter)
 {
-  int index;
   GeglBufferIteratorPriv *priv = iter->priv;
+  gint index;
 
   if (priv->state != GeglIteratorState_Invalid)
     {
@@ -531,7 +611,8 @@ gegl_buffer_iterator_stop (GeglBufferIterator *iter)
               gegl_tile_unref (sub->linear_tile);
             }
 
-          gegl_buffer_unlock (sub->buffer);
+          if (sub->buffer)
+            gegl_buffer_unlock (sub->buffer);
 
           if (sub->access_mode & GEGL_ACCESS_WRITE)
             gegl_buffer_emit_changed_signal (sub->buffer, &sub->full_rect);
@@ -542,7 +623,8 @@ gegl_buffer_iterator_stop (GeglBufferIterator *iter)
   g_slice_free (GeglBufferIterator, iter);
 }
 
-static void linear_shortcut (GeglBufferIterator *iter)
+static void
+linear_shortcut (GeglBufferIterator *iter)
 {
   GeglBufferIteratorPriv *priv = iter->priv;
   SubIterState *sub0 = &priv->sub_iter[0];
@@ -558,30 +640,38 @@ static void linear_shortcut (GeglBufferIterator *iter)
     iter->length = iter->roi[0].width * iter->roi[0].height;
 
     if (priv->sub_iter[0].buffer == sub->buffer && index != 0)
-    {
-      if (sub->format == priv->sub_iter[0].format)
-        re_use_first[index] = 1;
-    }
+      {
+        if (sub->format == priv->sub_iter[0].format)
+          re_use_first[index] = 1;
+      }
 
     if (!re_use_first[index])
-    {
-      gegl_buffer_lock (sub->buffer);
-      if (index == 0)
-        get_tile (iter, index);
-      else
       {
-        if (sub->buffer->tile_width == sub->buffer->extent.width 
-            && sub->buffer->tile_height == sub->buffer->extent.height
-            && sub->buffer->extent.x == iter->roi[index].x
-            && sub->buffer->extent.y == iter->roi[index].y)
-        {
-          get_tile (iter, index);
-        }
+        if (sub->buffer)
+          gegl_buffer_lock (sub->buffer);
+
+        if (sub->buffer && index == 0)
+          {
+            get_tile (iter, index);
+          }
         else
-          get_indirect (iter, index);
+          {
+            if (sub->buffer &&
+                sub->buffer->tile_width == sub->buffer->extent.width &&
+                sub->buffer->tile_height == sub->buffer->extent.height &&
+                sub->buffer->extent.x == iter->roi[index].x &&
+                sub->buffer->extent.y == iter->roi[index].y)
+              {
+                get_tile (iter, index);
+              }
+            else
+              {
+                get_indirect (iter, index);
+              }
+          }
       }
-    }
   }
+
   for (index = 1; index < priv->num_buffers; index++)
   {
     if (re_use_first[index])
@@ -601,11 +691,12 @@ gegl_buffer_iterator_next (GeglBufferIterator *iter)
 
   if (priv->state == GeglIteratorState_Start)
     {
-      int index;
       GeglBuffer *primary = priv->sub_iter[0].buffer;
-      if (primary->tile_width == primary->extent.width 
-          && primary->tile_height == primary->extent.height 
-          && priv->sub_iter[0].full_rect.width == primary->tile_width 
+      gint index;
+
+      if (primary->tile_width == primary->extent.width
+          && primary->tile_height == primary->extent.height
+          && priv->sub_iter[0].full_rect.width == primary->tile_width
           && priv->sub_iter[0].full_rect.height == primary->tile_height
           && priv->sub_iter[0].full_rect.x == primary->extent.x
           && priv->sub_iter[0].full_rect.y == primary->extent.y
@@ -618,7 +709,9 @@ gegl_buffer_iterator_next (GeglBufferIterator *iter)
           for (index = 0; index < priv->num_buffers; index++)
             {
               SubIterState *sub = &priv->sub_iter[index];
-              gegl_buffer_cl_cache_flush (sub->buffer, &sub->full_rect);
+
+              if (sub->buffer)
+                gegl_buffer_cl_cache_flush (sub->buffer, &sub->full_rect);
             }
         linear_shortcut (iter);
         return TRUE;
@@ -630,7 +723,9 @@ gegl_buffer_iterator_next (GeglBufferIterator *iter)
         for (index = 0; index < priv->num_buffers; index++)
           {
             SubIterState *sub = &priv->sub_iter[index];
-            gegl_buffer_cl_cache_flush (sub->buffer, &sub->full_rect);
+
+            if (sub->buffer)
+              gegl_buffer_cl_cache_flush (sub->buffer, &sub->full_rect);
           }
 
       initialize_rects (iter);
diff --git a/gegl/buffer/gegl-buffer-iterator.h b/gegl/buffer/gegl-buffer-iterator.h
index 2ab1764c..82afe578 100644
--- a/gegl/buffer/gegl-buffer-iterator.h
+++ b/gegl/buffer/gegl-buffer-iterator.h
@@ -108,6 +108,13 @@ gint                 gegl_buffer_iterator_add  (GeglBufferIterator  *iterator,
                                                 GeglAccessMode       access_mode,
                                                 GeglAbyssPolicy      abyss_policy);
 
+gint             gegl_buffer_iterator_add_node (GeglBufferIterator  *iterator,
+                                                GeglNode            *buffer,
+                                                const GeglRectangle *roi,
+                                                gint                 level,
+                                                const Babl          *format,
+                                                GeglAbyssPolicy      abyss_policy);
+
 /**
  * gegl_buffer_iterator_stop: (skip)
  * @iterator: a GeglBufferIterator
