gegl r2181 - in trunk: . gegl/buffer



Author: ok
Date: Wed Apr 16 23:05:47 2008
New Revision: 2181
URL: http://svn.gnome.org/viewvc/gegl?rev=2181&view=rev

Log:
* gegl/buffer/gegl-buffer.c: split out bits of functionality to the
two files below:
* gegl/buffer/gegl-buffer-access.c: (pset), (pget),
(gegl_buffer_flush), (gegl_buffer_iterate), (gegl_buffer_set),
(gegl_buffer_get_scaled), (resample_nearest), (box_filter),
(resample_boxfilter_u8), (gegl_buffer_get),
(gegl_buffer_get_abyss), (gegl_buffer_sample),
(gegl_buffer_sample_cleanup):
* gegl/buffer/gegl-buffer-share.c: (gegl_buffer_share),
(gegl_buffer_make_uri), (gegl_buffer_open):
* gegl/buffer/Makefile.am: updated.


Added:
   trunk/gegl/buffer/gegl-buffer-access.c
   trunk/gegl/buffer/gegl-buffer-share.c
Modified:
   trunk/ChangeLog
   trunk/gegl/buffer/Makefile.am
   trunk/gegl/buffer/gegl-buffer.c

Modified: trunk/gegl/buffer/Makefile.am
==============================================================================
--- trunk/gegl/buffer/Makefile.am	(original)
+++ trunk/gegl/buffer/Makefile.am	Wed Apr 16 23:05:47 2008
@@ -1,9 +1,11 @@
 noinst_LTLIBRARIES = libbuffer.la
 
 BUFFER_sources = \
+    gegl-buffer.c		\
+    gegl-buffer-access.c	\
+    gegl-buffer-share.c		\
     gegl-buffer-save.c		\
     gegl-buffer-load.c		\
-    gegl-buffer.c		\
     gegl-cache.c		\
     gegl-sampler.c		\
     gegl-sampler-cubic.c	\

Added: trunk/gegl/buffer/gegl-buffer-access.c
==============================================================================
--- (empty file)
+++ trunk/gegl/buffer/gegl-buffer-access.c	Wed Apr 16 23:05:47 2008
@@ -0,0 +1,1127 @@
+/* This file is part of GEGL.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright 2006,2007 Ãyvind KolÃs <pippin gimp org>
+ */
+
+#include "config.h"
+#include <string.h>
+#include <math.h>
+
+#include <glib-object.h>
+#include <glib/gprintf.h>
+
+#include "gegl-types.h"
+#include "gegl-buffer-types.h"
+#include "gegl-buffer.h"
+#include "gegl-buffer-private.h"
+#include "gegl-tile-storage.h"
+#include "gegl-utils.h"
+#include "gegl-sampler-nearest.h"
+#include "gegl-sampler-linear.h"
+#include "gegl-sampler-cubic.h"
+
+
+
+#ifdef BABL
+#undef BABL
+#endif
+
+#define BABL(o)     ((Babl *) (o))
+
+#ifdef FMTPXS
+#undef FMTPXS
+#endif
+#define FMTPXS(fmt)    (BABL (fmt)->format.bytes_per_pixel)
+
+#if 0
+static inline void
+pset (GeglBuffer *buffer,
+      gint        x,
+      gint        y,
+      const Babl *format,
+      guchar     *buf)
+{
+  gint  tile_width  = buffer->tile_storage->tile_width;
+  gint  tile_height  = buffer->tile_storage->tile_width;
+  gint  px_size     = gegl_buffer_px_size (buffer);
+  gint  bpx_size    = FMTPXS (format);
+  Babl *fish        = NULL;
+
+  gint  abyss_x_total  = buffer->abyss.x + buffer->abyss.width;
+  gint  abyss_y_total  = buffer->abyss.y + buffer->abyss.height;
+  gint  buffer_x       = buffer->extent.x;
+  gint  buffer_y       = buffer->extent.y;
+  gint  buffer_abyss_x = buffer->abyss.x;
+  gint  buffer_abyss_y = buffer->abyss.y;
+
+  if (format != buffer->format)
+    {
+      fish = babl_fish (buffer->format, format);
+    }
+
+  {
+    if (!(buffer_y + y >= buffer_abyss_y &&
+          buffer_y + y < abyss_y_total &&
+          buffer_x + x >= buffer_abyss_x &&
+          buffer_x + x < abyss_x_total))
+      { /* in abyss */
+        return;
+      }
+    else
+      {
+        gint      tiledy = buffer_y + buffer->shift_y + y;
+        gint      tiledx = buffer_x + buffer->shift_x + x;
+
+        GeglTile *tile = gegl_tile_source_get_tile ((GeglTileSource *) (buffer),
+                                                gegl_tile_indice (tiledx, tile_width),
+                                                gegl_tile_indice (tiledy, tile_height),
+                                                0);
+
+        if (tile)
+          {
+            gint    offsetx = gegl_tile_offset (tiledx, tile_width);
+            gint    offsety = gegl_tile_offset (tiledy, tile_height);
+            guchar *tp;
+
+            gegl_tile_lock (tile);
+            tp = gegl_tile_get_data (tile) +
+                 (offsety * tile_width + offsetx) * px_size;
+            if (fish)
+              babl_process (fish, buf, tp, 1);
+            else
+              memcpy (tp, buf, bpx_size);
+
+            gegl_tile_unlock (tile);
+            g_object_unref (tile);
+          }
+      }
+  }
+  return;
+}
+#endif
+
+static inline void
+pset (GeglBuffer *buffer,
+      gint        x,
+      gint        y,
+      const Babl *format,
+      gpointer    data)
+{
+  guchar *buf         = data;
+  gint    tile_width  = buffer->tile_storage->tile_width;
+  gint    tile_height = buffer->tile_storage->tile_height;
+  gint    bpx_size    = FMTPXS (format);
+  Babl   *fish        = NULL;
+
+  gint  buffer_shift_x = buffer->shift_x;
+  gint  buffer_shift_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  px_size        = FMTPXS (buffer->format);
+
+  if (format != buffer->format)
+    {
+      fish = babl_fish ((gpointer) buffer->format,
+                        (gpointer) format);
+    }
+
+  {
+    gint tiledy   = y + buffer_shift_y;
+    gint tiledx   = x + buffer_shift_x;
+
+    if (!(tiledy >= buffer_abyss_y &&
+          tiledy  < abyss_y_total &&
+          tiledx >= buffer_abyss_x &&
+          tiledx  < abyss_x_total))
+      { /* in abyss */
+        return;
+      }
+    else
+      {
+        gint      indice_x = gegl_tile_indice (tiledx, tile_width);
+        gint      indice_y = gegl_tile_indice (tiledy, tile_height);
+        GeglTile *tile     = NULL;
+
+        if (buffer->hot_tile &&
+            buffer->hot_tile->storage_x == indice_x &&
+            buffer->hot_tile->storage_y == indice_y)
+          {
+            tile = buffer->hot_tile;
+          }
+        else
+          {
+            if (buffer->hot_tile)
+              {
+                g_object_unref (buffer->hot_tile);
+                buffer->hot_tile = NULL;
+              }
+            tile = gegl_tile_source_get_tile ((GeglTileSource *) (buffer),
+                                             indice_x, indice_y,
+                                             0);
+          }
+
+        if (tile)
+          {
+            gint    offsetx = gegl_tile_offset (tiledx, tile_width);
+            gint    offsety = gegl_tile_offset (tiledy, tile_height);
+            guchar *tp;
+
+            gegl_tile_lock (tile);
+
+            tp = gegl_tile_get_data (tile) +
+                 (offsety * tile_width + offsetx) * px_size;
+            if (fish)
+              babl_process (fish, buf, tp, 1);
+            else
+              memcpy (tp, buf, bpx_size);
+
+            gegl_tile_unlock (tile);
+            buffer->hot_tile = tile;
+          }
+      }
+  }
+}
+
+static inline void
+pget (GeglBuffer *buffer,
+      gint        x,
+      gint        y,
+      const Babl *format,
+      gpointer    data)
+{
+  guchar *buf         = data;
+  gint    tile_width  = buffer->tile_storage->tile_width;
+  gint    tile_height = buffer->tile_storage->tile_height;
+  gint    bpx_size    = FMTPXS (format);
+  Babl   *fish        = NULL;
+
+  gint  buffer_shift_x = buffer->shift_x;
+  gint  buffer_shift_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  px_size        = FMTPXS (buffer->format);
+
+  if (format != buffer->format)
+    {
+      fish = babl_fish ((gpointer) buffer->format,
+                        (gpointer) format);
+    }
+
+  {
+    gint tiledy = y + buffer_shift_y;
+    gint tiledx = x + buffer_shift_x;
+
+    if (!(tiledy >= buffer_abyss_y &&
+          tiledy <  abyss_y_total  &&
+          tiledx >= buffer_abyss_x &&
+          tiledx <  abyss_x_total))
+      { /* in abyss */
+        memset (buf, 0x00, bpx_size);
+        return;
+      }
+    else
+      {
+        gint      indice_x = gegl_tile_indice (tiledx, tile_width);
+        gint      indice_y = gegl_tile_indice (tiledy, tile_height);
+        GeglTile *tile     = NULL;
+
+        if (buffer->hot_tile &&
+            buffer->hot_tile->storage_x == indice_x &&
+            buffer->hot_tile->storage_y == indice_y)
+          {
+            tile = buffer->hot_tile;
+          }
+        else
+          {
+            if (buffer->hot_tile)
+              {
+                g_object_unref (buffer->hot_tile);
+                buffer->hot_tile = NULL;
+              }
+            tile = gegl_tile_source_get_tile ((GeglTileSource *) (buffer),
+                                           indice_x, indice_y,
+                                           0);
+          }
+
+        if (tile)
+          {
+            gint    offsetx = gegl_tile_offset (tiledx, tile_width);
+            gint    offsety = gegl_tile_offset (tiledy, tile_height);
+            guchar *tp      = gegl_tile_get_data (tile) +
+                              (offsety * tile_width + offsetx) * px_size;
+            if (fish)
+              babl_process (fish, tp, buf, 1);
+            else
+              memcpy (buf, tp, px_size);
+
+            /*g_object_unref (tile);*/
+            buffer->hot_tile = tile;
+          }
+      }
+  }
+}
+
+/* flush any unwritten data (flushes the hot-cache of a single
+ * tile used by gegl_buffer_set for 1x1 pixel sized rectangles
+ */
+void
+gegl_buffer_flush (GeglBuffer *buffer)
+{
+  g_return_if_fail (GEGL_IS_BUFFER (buffer));
+
+  if (buffer->hot_tile)
+    {
+      g_object_unref (buffer->hot_tile);
+      buffer->hot_tile = NULL;
+    }
+}
+
+
+static void inline
+gegl_buffer_iterate (GeglBuffer *buffer,
+                     guchar     *buf,
+                     gint        rowstride,
+                     gboolean    write,
+                     const Babl *format,
+                     gint        level)
+{
+  gint  width       = buffer->extent.width;
+  gint  height      = buffer->extent.height;
+  gint  tile_width  = buffer->tile_storage->tile_width;
+  gint  tile_height = buffer->tile_storage->tile_height;
+  gint  px_size     = FMTPXS (buffer->format);
+  gint  bpx_size    = FMTPXS (format);
+  gint  tile_stride = px_size * tile_width;
+  gint  buf_stride;
+  gint  bufy = 0;
+  Babl *fish;
+
+  gint  buffer_shift_x = buffer->shift_x;
+  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  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  i;
+  gint  factor = 1;
+
+  for (i = 0; i < level; i++)
+    {
+      factor *= 2;
+    }
+
+  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->format)
+    {
+      fish = NULL;
+    }
+  else
+    {
+      if (write)
+        {
+          fish = babl_fish ((gpointer) format,
+                            (gpointer) buffer->format);
+        }
+      else
+        {
+          fish = babl_fish ((gpointer) buffer->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 */
+          if (!write)
+            {
+              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;
+            gint    offsetx = gegl_tile_offset (tiledx, tile_width);
+            gint    pixels;
+            guchar *bp;
+
+            bp = buf + bufy * buf_stride + bufx * bpx_size;
+
+            if (width + offsetx - bufx < tile_width)
+              pixels = (width + offsetx - bufx) - offsetx;
+            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;
+
+                    for (row = offsety;
+                         row < tile_height && y < height;
+                         row++, y++)
+                      {
+                        memset (bp, 0x00, pixels * bpx_size);
+                        bp += buf_stride;
+                      }
+                  }
+              }
+            else
+              {
+                guchar   *tile_base, *tp;
+                GeglTile *tile = gegl_tile_source_get_tile ((GeglTileSource *) (buffer),
+                                                           gegl_tile_indice (tiledx, tile_width),
+                                                           gegl_tile_indice (tiledy, tile_height),
+                                                           level);
+
+                gint lskip = (buffer_abyss_x) - (buffer_x + bufx);
+                /* gap between left side of tile, and abyss */
+                gint 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)
+                  {
+                    g_warning ("didn't get tile, trying to continue");
+                    bufx += (tile_width - offsetx);
+                    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)
+                  {
+                    gint row;
+                    gint y = bufy;
+
+
+                    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++)
+                          {
+
+                            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);
+                  }
+                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
+                          {
+                            /* entire row in abyss */
+                            memset (bp, 0x00, pixels * bpx_size);
+                          }
+
+                          /* 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;
+                      }
+                  }
+                g_object_unref (tile);
+              }
+            bufx += (tile_width - offsetx);
+          }
+      bufy += (tile_height - offsety);
+    }
+}
+
+void
+gegl_buffer_set (GeglBuffer          *buffer,
+                 const GeglRectangle *rect,
+                 const Babl          *format,
+                 void                *src,
+                 gint                 rowstride)
+{
+  GeglBuffer *sub_buf;
+
+  g_return_if_fail (GEGL_IS_BUFFER (buffer));
+
+#if ENABLE_MP
+  g_static_rec_mutex_lock (&mutex);
+#endif
+
+  if (format == NULL)
+    format = buffer->format;
+
+  /* FIXME: go through chain of sources up to but not including
+   * tile_storage and disassociated Sampler */
+
+  if (rect && rect->width == 1 && rect->height == 1) /* fast path */
+    {
+      pset (buffer, rect->x, rect->y, format, src);
+    }
+  /* FIXME: if rect->width == TILE_WIDTH and rect->height == TILE_HEIGHT and
+   * aligned with tile grid, do a fast path, also provide helper functions
+   * for getting the upper left coords of tiles.
+   */
+  else if (rect == NULL)
+    {
+      gegl_buffer_iterate (buffer, src, rowstride, TRUE, format, 0);
+    }
+  else
+    {
+      sub_buf = gegl_buffer_create_sub_buffer (buffer, rect);
+      gegl_buffer_iterate (sub_buf, src, rowstride, TRUE, format, 0);
+      g_object_unref (sub_buf);
+    }
+
+#if ENABLE_MP
+  g_static_rec_mutex_unlock (&mutex);
+#endif
+}
+
+/*
+ * buffer: the buffer to get data from
+ * rect:   the (full size rectangle to sample)
+ * dst:    the destination buffer to write to
+ * format: the format to write in
+ * level:  halving levels 0 = 1:1 1=1:2 2=1:4 3=1:8 ..
+ *
+ */
+static void
+gegl_buffer_get_scaled (GeglBuffer          *buffer,
+                        const GeglRectangle *rect,
+                        void                *dst,
+                        gint                 rowstride,
+                        const void          *format,
+                        gint                 level)
+{
+  GeglBuffer *sub_buf = gegl_buffer_create_sub_buffer (buffer, rect);
+  gegl_buffer_iterate (sub_buf, dst, rowstride, FALSE, format, level);
+  g_object_unref (sub_buf);
+}
+
+#if 0
+
+/*
+ *  slow nearest neighbour resampler that seems to be
+ *  completely correct.
+ */
+
+static void
+resample_nearest (void   *dest_buf,
+                  void   *source_buf,
+                  gint    dest_w,
+                  gint    dest_h,
+                  gint    source_w,
+                  gint    source_h,
+                  gdouble offset_x,
+                  gdouble offset_y,
+                  gdouble scale,
+                  gint    bpp,
+                  gint    rowstride)
+{
+  gint x, y;
+
+  if (rowstride == GEGL_AUTO_ROWSTRIDE)
+     rowstride = dest_w * bpp;
+
+  for (y = 0; y < dest_h; y++)
+    {
+      gint    sy;
+      guchar *dst;
+      guchar *src_base;
+
+      sy = (y + offset_y) / scale;
+
+
+      if (sy >= source_h)
+        sy = source_h - 1;
+
+      dst      = ((guchar *) dest_buf) + y * rowstride;
+      src_base = ((guchar *) source_buf) + sy * source_w * bpp;
+
+      for (x = 0; x < dest_w; x++)
+        {
+          gint    sx;
+          guchar *src;
+          sx = (x + offset_x) / scale;
+
+          if (sx >= source_w)
+            sx = source_w - 1;
+          src = src_base + sx * bpp;
+
+          memcpy (dst, src, bpp);
+          dst += bpp;
+        }
+    }
+}
+#endif
+
+/* Optimized|obfuscated version of the nearest neighbour resampler
+ * XXX: seems to contains some very slight inprecision in the rendering.
+ */
+static void
+resample_nearest (void   *dest_buf,
+                  void   *source_buf,
+                  gint    dest_w,
+                  gint    dest_h,
+                  gint    source_w,
+                  gint    source_h,
+                  gdouble offset_x,
+                  gdouble offset_y,
+                  gdouble scale,
+                  gint    bpp,
+                  gint    rowstride)
+{
+  gint x, y;
+  guint xdiff, ydiff, xstart, sy;
+
+  if (rowstride == GEGL_AUTO_ROWSTRIDE)
+     rowstride = dest_w * bpp;
+
+  xdiff = 65536 / scale;
+  ydiff = 65536 / scale;
+  xstart = (offset_x * 65536) / scale;
+  sy = (offset_y * 65536) / scale;
+
+  for (y = 0; y < dest_h; y++)
+    {
+      guchar *dst;
+      guchar *src_base;
+      guint sx;
+      guint px = 0;
+      guchar *src;
+
+      if (sy >= source_h << 16)
+        sy = (source_h - 1) << 16;
+
+      dst      = ((guchar *) dest_buf) + y * rowstride;
+      src_base = ((guchar *) source_buf) + (sy >> 16) * source_w * bpp;
+
+      sx = xstart;
+      src = src_base;
+
+      /* this is the loop that is actually properly optimized,
+       * portions of the setup is done for all the rows outside the y
+       * loop as well */
+      for (x = 0; x < dest_w; x++)
+        {
+          gint diff;
+          gint ssx = sx>>16;
+          if ( (diff = ssx - px) > 0)
+            {
+              if (ssx < source_w)
+                src += diff * bpp;
+              px += diff;
+            }
+          memcpy (dst, src, bpp);
+          dst += bpp;
+          sx += xdiff;
+        }
+      sy += ydiff;
+    }
+}
+
+static inline void
+box_filter (guint          left_weight,
+            guint          center_weight,
+            guint          right_weight,
+            guint          top_weight,
+            guint          middle_weight,
+            guint          bottom_weight,
+            guint          sum,
+            const guchar **src,   /* the 9 surrounding source pixels */
+            guchar        *dest,
+            gint           components)
+{
+  /* NOTE: this box filter presumes pre-multiplied alpha, if there
+   * is alpha.
+   */
+  gint i;
+  for (i = 0; i < components; i++)
+    {
+      dest[i] = ( left_weight   * ((src[0][i] * top_weight) +
+                                   (src[3][i] * middle_weight) +
+                                   (src[6][i] * bottom_weight))
+                + center_weight * ((src[1][i] * top_weight) +
+                                   (src[4][i] * middle_weight) +
+                                   (src[7][i] * bottom_weight))
+                + right_weight  * ((src[2][i] * top_weight) +
+                                   (src[5][i] * middle_weight) +
+                                   (src[8][i] * bottom_weight))) / sum;
+    }
+}
+
+static void
+resample_boxfilter_u8 (void   *dest_buf,
+                       void   *source_buf,
+                       gint    dest_w,
+                       gint    dest_h,
+                       gint    source_w,
+                       gint    source_h,
+                       gdouble offset_x,
+                       gdouble offset_y,
+                       gdouble scale,
+                       gint    components,
+                       gint    rowstride)
+{
+  gint x, y;
+  gint iscale      = scale * 256;
+  gint s_rowstride = source_w * components;
+  gint d_rowstride = dest_w * components;
+
+  gint          footprint_x;
+  gint          footprint_y;
+  guint         foosum;
+
+  guint         left_weight;
+  guint         center_weight;
+  guint         right_weight;
+
+  guint         top_weight;
+  guint         middle_weight;
+  guint         bottom_weight;
+
+  footprint_y = (1.0 / scale) * 256;
+  footprint_x = (1.0 / scale) * 256;
+  foosum = footprint_x * footprint_y;
+
+  if (rowstride != GEGL_AUTO_ROWSTRIDE)
+    d_rowstride = rowstride;
+
+  for (y = 0; y < dest_h; y++)
+    {
+      gint    sy;
+      gint    dy;
+      guchar *dst;
+      const guchar *src_base;
+      gint sx;
+      gint xdelta;
+
+      sy = ((y + offset_y) * 65536) / iscale;
+
+      if (sy >= (source_h - 1) << 8)
+        sy = (source_h - 2) << 8;/* is this the right thing to do? */
+
+      dy = sy & 255;
+
+      dst      = ((guchar *) dest_buf) + y * d_rowstride;
+      src_base = ((guchar *) source_buf) + (sy >> 8) * s_rowstride;
+
+      if (dy > footprint_y / 2)
+        top_weight = 0;
+      else
+        top_weight = footprint_y / 2 - dy;
+
+      if (0xff - dy > footprint_y / 2)
+        bottom_weight = 0;
+      else
+        bottom_weight = footprint_y / 2 - (0xff - dy);
+
+      middle_weight = footprint_y - top_weight - bottom_weight;
+
+      sx = (offset_x *65536) / iscale;
+      xdelta = 65536/iscale;
+
+      /* XXX: needs quite a bit of optimization */
+      for (x = 0; x < dest_w; x++)
+        {
+          gint          dx;
+          const guchar *src[9];
+
+          /*sx = (x << 16) / iscale;*/
+          dx = sx & 255;
+
+          if (dx > footprint_x / 2)
+            left_weight = 0;
+          else
+            left_weight = footprint_x / 2 - dx;
+
+          if (0xff - dx > footprint_x / 2)
+            right_weight = 0;
+          else
+            right_weight = footprint_x / 2 - (0xff - dx);
+
+          center_weight = footprint_x - left_weight - right_weight;
+
+          src[4] = src_base + (sx >> 8) * components;
+          src[1] = src[4] - s_rowstride;
+          src[7] = src[4] + s_rowstride;
+
+          src[2] = src[1] + components;
+          src[5] = src[4] + components;
+          src[8] = src[7] + components;
+
+          src[0] = src[1] - components;
+          src[3] = src[4] - components;
+          src[6] = src[7] - components;
+
+          if ((sx >>8) - 1<0)
+            {
+              src[0]=src[1];
+              src[3]=src[4];
+              src[6]=src[7];
+            }
+          if ((sy >> 8) - 1 < 0)
+            {
+              src[0]=src[3];
+              src[1]=src[4];
+              src[2]=src[5];
+            }
+          if ((sx >>8) + 1 >= source_w)
+            {
+              src[2]=src[1];
+              src[5]=src[4];
+              src[8]=src[7];
+              break;
+            }
+          if ((sy >> 8) + 1 >= source_h)
+            {
+              src[6]=src[3];
+              src[7]=src[4];
+              src[8]=src[5];
+            }
+
+          box_filter (left_weight,
+                      center_weight,
+                      right_weight,
+                      top_weight,
+                      middle_weight,
+                      bottom_weight,
+                      foosum,
+                      src,   /* the 9 surrounding source pixels */
+                      dst,
+                      components);
+
+
+          dst += components;
+          sx += xdelta;
+        }
+    }
+}
+
+void
+gegl_buffer_get (GeglBuffer          *buffer,
+                 gdouble              scale,
+                 const GeglRectangle *rect,
+                 const Babl          *format,
+                 gpointer             dest_buf,
+                 gint                 rowstride)
+{
+  g_return_if_fail (GEGL_IS_BUFFER (buffer));
+#if ENABLE_MP
+  g_static_rec_mutex_lock (&mutex);
+#endif
+
+  if (format == NULL)
+    format = buffer->format;
+
+  if (scale == 1.0 &&
+      rect &&
+      rect->width == 1 &&
+      rect->height == 1)  /* fast path */
+    {
+      pget (buffer, rect->x, rect->y, format, dest_buf);
+#if ENABLE_MP
+      g_static_rec_mutex_unlock (&mutex);
+#endif
+      return;
+    }
+
+  if (!rect && scale == 1.0)
+    {
+      gegl_buffer_iterate (buffer, dest_buf, rowstride, FALSE, format, 0);
+#if ENABLE_MP
+      g_static_rec_mutex_unlock (&mutex);
+#endif
+      return;
+    }
+  if (rect->width == 0 ||
+      rect->height == 0)
+    {
+#if ENABLE_MP
+      g_static_rec_mutex_unlock (&mutex);
+#endif
+      return;
+    }
+  if (GEGL_FLOAT_EQUAL (scale, 1.0))
+    {
+      gegl_buffer_get_scaled (buffer, rect, dest_buf, rowstride, format, 0);
+#if ENABLE_MP
+      g_static_rec_mutex_unlock (&mutex);
+#endif
+      return;
+    }
+  else
+    {
+      gint          level       = 0;
+      gint          buf_width   = rect->width / scale;
+      gint          buf_height  = rect->height / scale;
+      gint          bpp         = BABL (format)->format.bytes_per_pixel;
+      GeglRectangle sample_rect = { floor(rect->x/scale),
+                                    floor(rect->y/scale),
+                                    buf_width,
+                                    buf_height };
+      void         *sample_buf;
+      gint          factor = 1;
+      gdouble       offset_x;
+      gdouble       offset_y;
+
+      while (scale <= 0.5)
+        {
+          scale  *= 2;
+          factor *= 2;
+          level++;
+        }
+
+      buf_width  /= factor;
+      buf_height /= factor;
+
+      /* ensure we always have some data to sample from */
+      sample_rect.width  += factor * 2;
+      sample_rect.height += factor * 2;
+      buf_width          += 2;
+      buf_height         += 2;
+
+
+      offset_x = rect->x-floor(rect->x/scale) * scale;
+      offset_y = rect->y-floor(rect->y/scale) * scale;
+
+
+      sample_buf = g_malloc (buf_width * buf_height * bpp);
+      gegl_buffer_get_scaled (buffer, &sample_rect, sample_buf, GEGL_AUTO_ROWSTRIDE, format, level);
+
+      if (BABL (format)->format.type[0] == (BablType *) babl_type ("u8")
+          && !(level == 0 && scale > 1.99))
+        { /* do box-filter resampling if we're 8bit (which projections are) */
+
+          /* XXX: use box-filter also for > 1.99 when testing and probably
+           * later, there are some bugs when doing so
+           */
+          resample_boxfilter_u8 (dest_buf,
+                                 sample_buf,
+                                 rect->width,
+                                 rect->height,
+                                 buf_width,
+                                 buf_height,
+                                 offset_x,
+                                 offset_y,
+                                 scale,
+                                 bpp,
+                                 rowstride);
+        }
+      else
+        {
+          resample_nearest (dest_buf,
+                            sample_buf,
+                            rect->width,
+                            rect->height,
+                            buf_width,
+                            buf_height,
+                            offset_x,
+                            offset_y,
+                            scale,
+                            bpp,
+                            rowstride);
+        }
+      g_free (sample_buf);
+    }
+#if ENABLE_MP
+  g_static_rec_mutex_unlock (&mutex);
+#endif
+}
+
+const GeglRectangle *
+gegl_buffer_get_abyss (GeglBuffer *buffer)
+{
+  g_return_val_if_fail (GEGL_IS_BUFFER (buffer), NULL);
+
+  return &buffer->abyss;
+}
+
+void
+gegl_buffer_sample (GeglBuffer       *buffer,
+                    gdouble           x,
+                    gdouble           y,
+                    gdouble           scale,
+                    gpointer          dest,
+                    const Babl       *format,
+                    GeglInterpolation interpolation)
+{
+  g_return_if_fail (GEGL_IS_BUFFER (buffer));
+
+/*#define USE_WORKING_SHORTCUT*/
+#ifdef USE_WORKING_SHORTCUT
+  pget (buffer, x, y, format, dest);
+  return;
+#endif
+
+#if ENABLE_MP
+  g_static_rec_mutex_lock (&mutex);
+#endif
+
+  /* look up appropriate sampler,. */
+  if (buffer->sampler == NULL)
+    {
+      /* FIXME: should probably check if the desired form of interpolation
+       * changes from the currently cached sampler.
+       */
+      GType interpolation_type = 0;
+
+      switch (interpolation)
+        {
+          case GEGL_INTERPOLATION_NEAREST:
+            interpolation_type=GEGL_TYPE_SAMPLER_NEAREST;
+            break;
+          case GEGL_INTERPOLATION_LINEAR:
+            interpolation_type=GEGL_TYPE_SAMPLER_LINEAR;
+            break;
+          default:
+            g_warning ("unimplemented interpolation type %i", interpolation);
+        }
+      buffer->sampler = g_object_new (interpolation_type,
+                                           "buffer", buffer,
+                                           "format", format,
+                                           NULL);
+      gegl_sampler_prepare (buffer->sampler);
+    }
+  gegl_sampler_get (buffer->sampler, x, y, dest);
+
+#if ENABLE_MP
+  g_static_rec_mutex_unlock (&mutex);
+#endif
+
+  /* if none found, create a singleton sampler for this buffer,
+   * a function to clean up the samplers set for a buffer should
+   * also be provided */
+
+  /* if (scale < 1.0) do decimation, possibly using pyramid instead */
+
+}
+
+void
+gegl_buffer_sample_cleanup (GeglBuffer *buffer)
+{
+  g_return_if_fail (GEGL_IS_BUFFER (buffer));
+
+  if (buffer->sampler)
+    {
+      g_object_unref (buffer->sampler);
+      buffer->sampler = NULL;
+    }
+}

Added: trunk/gegl/buffer/gegl-buffer-share.c
==============================================================================
--- (empty file)
+++ trunk/gegl/buffer/gegl-buffer-share.c	Wed Apr 16 23:05:47 2008
@@ -0,0 +1,111 @@
+/* This file is part of GEGL.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright 2006,2007 Ãyvind KolÃs <pippin gimp org>
+ */
+
+#include "config.h"
+#include <string.h>
+
+#include <glib-object.h>
+#include <glib/gprintf.h>
+
+#include "gegl-types.h"
+#include "gegl-buffer-types.h"
+#include "gegl-buffer.h"
+#include "gegl-buffer-private.h"
+#include "gegl-id-pool.h"
+
+static GeglIDPool *pool = NULL;
+
+guint
+gegl_buffer_share (GeglBuffer *buffer)
+{
+  guint id;
+  if (!pool)
+    pool = gegl_id_pool_new (16);
+  id = gegl_id_pool_add (pool, buffer);
+  /* FIXME: weak reference to void the handle when the buffer is
+   * finalized
+   */
+  return id;
+}
+
+
+void
+gegl_buffer_make_uri (gchar       *buf_128,
+                      gchar       *host,
+                      gint         port,
+                      gint         process,
+                      gint         handle)
+{
+  gchar *p=buf_128;
+
+  g_sprintf (p, "buffer://%s", host?host:"");
+  p+=strlen (p);
+  if (port)
+    {
+      g_sprintf (p, ":%i", port);
+      p+=strlen (p);
+    }
+  g_sprintf (p, "/");
+  p+=strlen (p);
+  if (process)
+    {
+      g_sprintf (p, "%i", process);
+      p+=strlen (p);
+    }
+  g_sprintf (p, "/");
+  p+=strlen (p);
+  if (handle || 1)
+    {
+      g_sprintf (p, "%i", handle);
+      p+=strlen (p);
+    }
+  else
+    {
+      g_warning ("no handle provided when building uri:\n%s\n", buf_128);
+    }
+}
+
+
+GeglBuffer*
+gegl_buffer_open (const gchar *uri)
+{
+  /* only supports local addresses for now */
+  guint process; /* self */
+  guint handle;
+
+  process = 0;
+  handle = 0;
+
+  if (!pool)
+    pool = gegl_id_pool_new (16);
+
+  if (!g_str_has_prefix (uri, "buffer://"))
+   {
+     g_warning ("'%s' does not start like a valid buffer handle", uri);
+     return NULL;
+   }
+  if (g_str_has_prefix (uri, "buffer:////"))
+   {
+     /* local buffer */
+     handle = atoi (uri + 11);
+     g_print ("got %i, %p\n", handle, gegl_id_pool_lookup (pool, handle));
+     return gegl_buffer_create_sub_buffer (gegl_id_pool_lookup (pool, handle), NULL);
+   }
+  g_warning ("don't know how to handle buffer path: %s", uri);
+  return NULL;
+}

Modified: trunk/gegl/buffer/gegl-buffer.c
==============================================================================
--- trunk/gegl/buffer/gegl-buffer.c	(original)
+++ trunk/gegl/buffer/gegl-buffer.c	Wed Apr 16 23:05:47 2008
@@ -639,1160 +639,6 @@
 }
 
 
-/***************************************************************************/
-
-static const void *int_gegl_buffer_get_format (GeglBuffer *buffer)
-{
-  g_assert (buffer);
-  if (buffer->format != NULL)
-    return buffer->format;
-  return gegl_buffer_backend (buffer)->format;
-}
-
-static void
-gegl_buffer_void (GeglBuffer *buffer)
-{
-  gint width       = buffer->extent.width;
-  gint height      = buffer->extent.height;
-  gint tile_width  = buffer->tile_storage->tile_width;
-  gint tile_height = buffer->tile_storage->tile_height;
-  gint bufy        = 0;
-
-  {
-    gint z;
-    gint factor = 1;
-    for (z = 0; z <= buffer->max_z; z++)
-      {
-        bufy = 0;
-        while (bufy < height)
-          {
-            gint tiledy  = buffer->extent.y + buffer->shift_y + bufy;
-            gint offsety = gegl_tile_offset (tiledy, tile_height);
-            gint bufx    = 0;
-            gint ty = gegl_tile_indice (tiledy / factor, tile_height);
-
-            if (z != 0 ||  /* FIXME: handle z==0 correctly */
-                ty >= buffer->min_y)
-              while (bufx < width)
-                {
-                  gint tiledx  = buffer->extent.x + buffer->shift_x + bufx;
-                  gint offsetx = gegl_tile_offset (tiledx, tile_width);
-
-                  gint tx = gegl_tile_indice (tiledx / factor, tile_width);
-
-                  if (z != 0 ||
-                      tx >= buffer->min_x)
-                  gegl_tile_source_command (GEGL_TILE_SOURCE (buffer),
-                                         GEGL_TILE_VOID, tx, ty, z, NULL);
-
-                  if (z != 0 ||
-                      tx > buffer->max_x)
-                    goto done_with_row;
-
-                  bufx += (tile_width - offsetx) * factor;
-                }
-done_with_row:
-            bufy += (tile_height - offsety) * factor;
-
-                  if (z != 0 ||
-                      ty > buffer->max_y)
-                    break;
-          }
-        factor *= 2;
-      }
-  }
-}
-
-#ifdef BABL
-#undef BABL
-#endif
-
-#define BABL(o)     ((Babl *) (o))
-
-#ifdef FMTPXS
-#undef FMTPXS
-#endif
-#define FMTPXS(fmt)    (BABL (fmt)->format.bytes_per_pixel)
-
-#if 0
-static inline void
-pset (GeglBuffer *buffer,
-      gint        x,
-      gint        y,
-      const Babl *format,
-      guchar     *buf)
-{
-  gint  tile_width  = buffer->tile_storage->tile_width;
-  gint  tile_height  = buffer->tile_storage->tile_width;
-  gint  px_size     = gegl_buffer_px_size (buffer);
-  gint  bpx_size    = FMTPXS (format);
-  Babl *fish        = NULL;
-
-  gint  abyss_x_total  = buffer->abyss.x + buffer->abyss.width;
-  gint  abyss_y_total  = buffer->abyss.y + buffer->abyss.height;
-  gint  buffer_x       = buffer->extent.x;
-  gint  buffer_y       = buffer->extent.y;
-  gint  buffer_abyss_x = buffer->abyss.x;
-  gint  buffer_abyss_y = buffer->abyss.y;
-
-  if (format != buffer->format)
-    {
-      fish = babl_fish (buffer->format, format);
-    }
-
-  {
-    if (!(buffer_y + y >= buffer_abyss_y &&
-          buffer_y + y < abyss_y_total &&
-          buffer_x + x >= buffer_abyss_x &&
-          buffer_x + x < abyss_x_total))
-      { /* in abyss */
-        return;
-      }
-    else
-      {
-        gint      tiledy = buffer_y + buffer->shift_y + y;
-        gint      tiledx = buffer_x + buffer->shift_x + x;
-
-        GeglTile *tile = gegl_tile_source_get_tile ((GeglTileSource *) (buffer),
-                                                gegl_tile_indice (tiledx, tile_width),
-                                                gegl_tile_indice (tiledy, tile_height),
-                                                0);
-
-        if (tile)
-          {
-            gint    offsetx = gegl_tile_offset (tiledx, tile_width);
-            gint    offsety = gegl_tile_offset (tiledy, tile_height);
-            guchar *tp;
-
-            gegl_tile_lock (tile);
-            tp = gegl_tile_get_data (tile) +
-                 (offsety * tile_width + offsetx) * px_size;
-            if (fish)
-              babl_process (fish, buf, tp, 1);
-            else
-              memcpy (tp, buf, bpx_size);
-
-            gegl_tile_unlock (tile);
-            g_object_unref (tile);
-          }
-      }
-  }
-  return;
-}
-#endif
-
-static inline void
-pset (GeglBuffer *buffer,
-      gint        x,
-      gint        y,
-      const Babl *format,
-      gpointer    data)
-{
-  guchar *buf         = data;
-  gint    tile_width  = buffer->tile_storage->tile_width;
-  gint    tile_height = buffer->tile_storage->tile_height;
-  gint    bpx_size    = FMTPXS (format);
-  Babl   *fish        = NULL;
-
-  gint  buffer_shift_x = buffer->shift_x;
-  gint  buffer_shift_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  px_size        = FMTPXS (buffer->format);
-
-  if (format != buffer->format)
-    {
-      fish = babl_fish ((gpointer) buffer->format,
-                        (gpointer) format);
-    }
-
-  {
-    gint tiledy   = y + buffer_shift_y;
-    gint tiledx   = x + buffer_shift_x;
-
-    if (!(tiledy >= buffer_abyss_y &&
-          tiledy  < abyss_y_total &&
-          tiledx >= buffer_abyss_x &&
-          tiledx  < abyss_x_total))
-      { /* in abyss */
-        return;
-      }
-    else
-      {
-        gint      indice_x = gegl_tile_indice (tiledx, tile_width);
-        gint      indice_y = gegl_tile_indice (tiledy, tile_height);
-        GeglTile *tile     = NULL;
-
-        if (buffer->hot_tile &&
-            buffer->hot_tile->storage_x == indice_x &&
-            buffer->hot_tile->storage_y == indice_y)
-          {
-            tile = buffer->hot_tile;
-          }
-        else
-          {
-            if (buffer->hot_tile)
-              {
-                g_object_unref (buffer->hot_tile);
-                buffer->hot_tile = NULL;
-              }
-            tile = gegl_tile_source_get_tile ((GeglTileSource *) (buffer),
-                                             indice_x, indice_y,
-                                             0);
-          }
-
-        if (tile)
-          {
-            gint    offsetx = gegl_tile_offset (tiledx, tile_width);
-            gint    offsety = gegl_tile_offset (tiledy, tile_height);
-            guchar *tp;
-
-            gegl_tile_lock (tile);
-
-            tp = gegl_tile_get_data (tile) +
-                 (offsety * tile_width + offsetx) * px_size;
-            if (fish)
-              babl_process (fish, buf, tp, 1);
-            else
-              memcpy (tp, buf, bpx_size);
-
-            gegl_tile_unlock (tile);
-            buffer->hot_tile = tile;
-          }
-      }
-  }
-}
-
-static inline void
-pget (GeglBuffer *buffer,
-      gint        x,
-      gint        y,
-      const Babl *format,
-      gpointer    data)
-{
-  guchar *buf         = data;
-  gint    tile_width  = buffer->tile_storage->tile_width;
-  gint    tile_height = buffer->tile_storage->tile_height;
-  gint    bpx_size    = FMTPXS (format);
-  Babl   *fish        = NULL;
-
-  gint  buffer_shift_x = buffer->shift_x;
-  gint  buffer_shift_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  px_size        = FMTPXS (buffer->format);
-
-  if (format != buffer->format)
-    {
-      fish = babl_fish ((gpointer) buffer->format,
-                        (gpointer) format);
-    }
-
-  {
-    gint tiledy = y + buffer_shift_y;
-    gint tiledx = x + buffer_shift_x;
-
-    if (!(tiledy >= buffer_abyss_y &&
-          tiledy <  abyss_y_total  &&
-          tiledx >= buffer_abyss_x &&
-          tiledx <  abyss_x_total))
-      { /* in abyss */
-        memset (buf, 0x00, bpx_size);
-        return;
-      }
-    else
-      {
-        gint      indice_x = gegl_tile_indice (tiledx, tile_width);
-        gint      indice_y = gegl_tile_indice (tiledy, tile_height);
-        GeglTile *tile     = NULL;
-
-        if (buffer->hot_tile &&
-            buffer->hot_tile->storage_x == indice_x &&
-            buffer->hot_tile->storage_y == indice_y)
-          {
-            tile = buffer->hot_tile;
-          }
-        else
-          {
-            if (buffer->hot_tile)
-              {
-                g_object_unref (buffer->hot_tile);
-                buffer->hot_tile = NULL;
-              }
-            tile = gegl_tile_source_get_tile ((GeglTileSource *) (buffer),
-                                           indice_x, indice_y,
-                                           0);
-          }
-
-        if (tile)
-          {
-            gint    offsetx = gegl_tile_offset (tiledx, tile_width);
-            gint    offsety = gegl_tile_offset (tiledy, tile_height);
-            guchar *tp      = gegl_tile_get_data (tile) +
-                              (offsety * tile_width + offsetx) * px_size;
-            if (fish)
-              babl_process (fish, tp, buf, 1);
-            else
-              memcpy (buf, tp, px_size);
-
-            /*g_object_unref (tile);*/
-            buffer->hot_tile = tile;
-          }
-      }
-  }
-}
-
-/* flush any unwritten data (flushes the hot-cache of a single
- * tile used by gegl_buffer_set for 1x1 pixel sized rectangles
- */
-void
-gegl_buffer_flush (GeglBuffer *buffer)
-{
-  g_return_if_fail (GEGL_IS_BUFFER (buffer));
-
-  if (buffer->hot_tile)
-    {
-      g_object_unref (buffer->hot_tile);
-      buffer->hot_tile = NULL;
-    }
-}
-
-
-static void inline
-gegl_buffer_iterate (GeglBuffer *buffer,
-                     guchar     *buf,
-                     gint        rowstride,
-                     gboolean    write,
-                     const Babl *format,
-                     gint        level)
-{
-  gint  width       = buffer->extent.width;
-  gint  height      = buffer->extent.height;
-  gint  tile_width  = buffer->tile_storage->tile_width;
-  gint  tile_height = buffer->tile_storage->tile_height;
-  gint  px_size     = FMTPXS (buffer->format);
-  gint  bpx_size    = FMTPXS (format);
-  gint  tile_stride = px_size * tile_width;
-  gint  buf_stride;
-  gint  bufy = 0;
-  Babl *fish;
-
-  gint  buffer_shift_x = buffer->shift_x;
-  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  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  i;
-  gint  factor = 1;
-
-  for (i = 0; i < level; i++)
-    {
-      factor *= 2;
-    }
-
-  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->format)
-    {
-      fish = NULL;
-    }
-  else
-    {
-      if (write)
-        {
-          fish = babl_fish ((gpointer) format,
-                            (gpointer) buffer->format);
-        }
-      else
-        {
-          fish = babl_fish ((gpointer) buffer->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 */
-          if (!write)
-            {
-              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;
-            gint    offsetx = gegl_tile_offset (tiledx, tile_width);
-            gint    pixels;
-            guchar *bp;
-
-            bp = buf + bufy * buf_stride + bufx * bpx_size;
-
-            if (width + offsetx - bufx < tile_width)
-              pixels = (width + offsetx - bufx) - offsetx;
-            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;
-
-                    for (row = offsety;
-                         row < tile_height && y < height;
-                         row++, y++)
-                      {
-                        memset (bp, 0x00, pixels * bpx_size);
-                        bp += buf_stride;
-                      }
-                  }
-              }
-            else
-              {
-                guchar   *tile_base, *tp;
-                GeglTile *tile = gegl_tile_source_get_tile ((GeglTileSource *) (buffer),
-                                                           gegl_tile_indice (tiledx, tile_width),
-                                                           gegl_tile_indice (tiledy, tile_height),
-                                                           level);
-
-                gint lskip = (buffer_abyss_x) - (buffer_x + bufx);
-                /* gap between left side of tile, and abyss */
-                gint 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)
-                  {
-                    g_warning ("didn't get tile, trying to continue");
-                    bufx += (tile_width - offsetx);
-                    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)
-                  {
-                    gint row;
-                    gint y = bufy;
-
-
-                    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++)
-                          {
-
-                            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);
-                  }
-                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
-                          {
-                            /* entire row in abyss */
-                            memset (bp, 0x00, pixels * bpx_size);
-                          }
-
-                          /* 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;
-                      }
-                  }
-                g_object_unref (tile);
-              }
-            bufx += (tile_width - offsetx);
-          }
-      bufy += (tile_height - offsety);
-    }
-}
-
-void
-gegl_buffer_set (GeglBuffer          *buffer,
-                 const GeglRectangle *rect,
-                 const Babl          *format,
-                 void                *src,
-                 gint                 rowstride)
-{
-  GeglBuffer *sub_buf;
-
-  g_return_if_fail (GEGL_IS_BUFFER (buffer));
-
-#if ENABLE_MP
-  g_static_rec_mutex_lock (&mutex);
-#endif
-
-  if (format == NULL)
-    format = buffer->format;
-
-  /* FIXME: go through chain of sources up to but not including
-   * tile_storage and disassociated Sampler */
-
-  if (rect && rect->width == 1 && rect->height == 1) /* fast path */
-    {
-      pset (buffer, rect->x, rect->y, format, src);
-    }
-  /* FIXME: if rect->width == TILE_WIDTH and rect->height == TILE_HEIGHT and
-   * aligned with tile grid, do a fast path, also provide helper functions
-   * for getting the upper left coords of tiles.
-   */
-  else if (rect == NULL)
-    {
-      gegl_buffer_iterate (buffer, src, rowstride, TRUE, format, 0);
-    }
-  else
-    {
-      sub_buf = gegl_buffer_create_sub_buffer (buffer, rect);
-      gegl_buffer_iterate (sub_buf, src, rowstride, TRUE, format, 0);
-      g_object_unref (sub_buf);
-    }
-
-#if ENABLE_MP
-  g_static_rec_mutex_unlock (&mutex);
-#endif
-}
-
-/*
- * buffer: the buffer to get data from
- * rect:   the (full size rectangle to sample)
- * dst:    the destination buffer to write to
- * format: the format to write in
- * level:  halving levels 0 = 1:1 1=1:2 2=1:4 3=1:8 ..
- *
- */
-static void
-gegl_buffer_get_scaled (GeglBuffer          *buffer,
-                        const GeglRectangle *rect,
-                        void                *dst,
-                        gint                 rowstride,
-                        const void          *format,
-                        gint                 level)
-{
-  GeglBuffer *sub_buf = gegl_buffer_create_sub_buffer (buffer, rect);
-  gegl_buffer_iterate (sub_buf, dst, rowstride, FALSE, format, level);
-  g_object_unref (sub_buf);
-}
-
-#if 0
-
-/*
- *  slow nearest neighbour resampler that seems to be
- *  completely correct.
- */
-
-static void
-resample_nearest (void   *dest_buf,
-                  void   *source_buf,
-                  gint    dest_w,
-                  gint    dest_h,
-                  gint    source_w,
-                  gint    source_h,
-                  gdouble offset_x,
-                  gdouble offset_y,
-                  gdouble scale,
-                  gint    bpp,
-                  gint    rowstride)
-{
-  gint x, y;
-
-  if (rowstride == GEGL_AUTO_ROWSTRIDE)
-     rowstride = dest_w * bpp;
-
-  for (y = 0; y < dest_h; y++)
-    {
-      gint    sy;
-      guchar *dst;
-      guchar *src_base;
-
-      sy = (y + offset_y) / scale;
-
-
-      if (sy >= source_h)
-        sy = source_h - 1;
-
-      dst      = ((guchar *) dest_buf) + y * rowstride;
-      src_base = ((guchar *) source_buf) + sy * source_w * bpp;
-
-      for (x = 0; x < dest_w; x++)
-        {
-          gint    sx;
-          guchar *src;
-          sx = (x + offset_x) / scale;
-
-          if (sx >= source_w)
-            sx = source_w - 1;
-          src = src_base + sx * bpp;
-
-          memcpy (dst, src, bpp);
-          dst += bpp;
-        }
-    }
-}
-#endif
-
-/* Optimized|obfuscated version of the nearest neighbour resampler
- * XXX: seems to contains some very slight inprecision in the rendering.
- */
-static void
-resample_nearest (void   *dest_buf,
-                  void   *source_buf,
-                  gint    dest_w,
-                  gint    dest_h,
-                  gint    source_w,
-                  gint    source_h,
-                  gdouble offset_x,
-                  gdouble offset_y,
-                  gdouble scale,
-                  gint    bpp,
-                  gint    rowstride)
-{
-  gint x, y;
-  guint xdiff, ydiff, xstart, sy;
-
-  if (rowstride == GEGL_AUTO_ROWSTRIDE)
-     rowstride = dest_w * bpp;
-
-  xdiff = 65536 / scale;
-  ydiff = 65536 / scale;
-  xstart = (offset_x * 65536) / scale;
-  sy = (offset_y * 65536) / scale;
-
-  for (y = 0; y < dest_h; y++)
-    {
-      guchar *dst;
-      guchar *src_base;
-      guint sx;
-      guint px = 0;
-      guchar *src;
-
-      if (sy >= source_h << 16)
-        sy = (source_h - 1) << 16;
-
-      dst      = ((guchar *) dest_buf) + y * rowstride;
-      src_base = ((guchar *) source_buf) + (sy >> 16) * source_w * bpp;
-
-      sx = xstart;
-      src = src_base;
-
-      /* this is the loop that is actually properly optimized,
-       * portions of the setup is done for all the rows outside the y
-       * loop as well */
-      for (x = 0; x < dest_w; x++)
-        {
-          gint diff;
-          gint ssx = sx>>16;
-          if ( (diff = ssx - px) > 0)
-            {
-              if (ssx < source_w)
-                src += diff * bpp;
-              px += diff;
-            }
-          memcpy (dst, src, bpp);
-          dst += bpp;
-          sx += xdiff;
-        }
-      sy += ydiff;
-    }
-}
-
-static inline void
-box_filter (guint          left_weight,
-            guint          center_weight,
-            guint          right_weight,
-            guint          top_weight,
-            guint          middle_weight,
-            guint          bottom_weight,
-            guint          sum,
-            const guchar **src,   /* the 9 surrounding source pixels */
-            guchar        *dest,
-            gint           components)
-{
-  /* NOTE: this box filter presumes pre-multiplied alpha, if there
-   * is alpha.
-   */
-  gint i;
-  for (i = 0; i < components; i++)
-    {
-      dest[i] = ( left_weight   * ((src[0][i] * top_weight) +
-                                   (src[3][i] * middle_weight) +
-                                   (src[6][i] * bottom_weight))
-                + center_weight * ((src[1][i] * top_weight) +
-                                   (src[4][i] * middle_weight) +
-                                   (src[7][i] * bottom_weight))
-                + right_weight  * ((src[2][i] * top_weight) +
-                                   (src[5][i] * middle_weight) +
-                                   (src[8][i] * bottom_weight))) / sum;
-    }
-}
-
-static void
-resample_boxfilter_u8 (void   *dest_buf,
-                       void   *source_buf,
-                       gint    dest_w,
-                       gint    dest_h,
-                       gint    source_w,
-                       gint    source_h,
-                       gdouble offset_x,
-                       gdouble offset_y,
-                       gdouble scale,
-                       gint    components,
-                       gint    rowstride)
-{
-  gint x, y;
-  gint iscale      = scale * 256;
-  gint s_rowstride = source_w * components;
-  gint d_rowstride = dest_w * components;
-
-  gint          footprint_x;
-  gint          footprint_y;
-  guint         foosum;
-
-  guint         left_weight;
-  guint         center_weight;
-  guint         right_weight;
-
-  guint         top_weight;
-  guint         middle_weight;
-  guint         bottom_weight;
-
-  footprint_y = (1.0 / scale) * 256;
-  footprint_x = (1.0 / scale) * 256;
-  foosum = footprint_x * footprint_y;
-
-  if (rowstride != GEGL_AUTO_ROWSTRIDE)
-    d_rowstride = rowstride;
-
-  for (y = 0; y < dest_h; y++)
-    {
-      gint    sy;
-      gint    dy;
-      guchar *dst;
-      const guchar *src_base;
-      gint sx;
-      gint xdelta;
-
-      sy = ((y + offset_y) * 65536) / iscale;
-
-      if (sy >= (source_h - 1) << 8)
-        sy = (source_h - 2) << 8;/* is this the right thing to do? */
-
-      dy = sy & 255;
-
-      dst      = ((guchar *) dest_buf) + y * d_rowstride;
-      src_base = ((guchar *) source_buf) + (sy >> 8) * s_rowstride;
-
-      if (dy > footprint_y / 2)
-        top_weight = 0;
-      else
-        top_weight = footprint_y / 2 - dy;
-
-      if (0xff - dy > footprint_y / 2)
-        bottom_weight = 0;
-      else
-        bottom_weight = footprint_y / 2 - (0xff - dy);
-
-      middle_weight = footprint_y - top_weight - bottom_weight;
-
-      sx = (offset_x *65536) / iscale;
-      xdelta = 65536/iscale;
-
-      /* XXX: needs quite a bit of optimization */
-      for (x = 0; x < dest_w; x++)
-        {
-          gint          dx;
-          const guchar *src[9];
-
-          /*sx = (x << 16) / iscale;*/
-          dx = sx & 255;
-
-          if (dx > footprint_x / 2)
-            left_weight = 0;
-          else
-            left_weight = footprint_x / 2 - dx;
-
-          if (0xff - dx > footprint_x / 2)
-            right_weight = 0;
-          else
-            right_weight = footprint_x / 2 - (0xff - dx);
-
-          center_weight = footprint_x - left_weight - right_weight;
-
-          src[4] = src_base + (sx >> 8) * components;
-          src[1] = src[4] - s_rowstride;
-          src[7] = src[4] + s_rowstride;
-
-          src[2] = src[1] + components;
-          src[5] = src[4] + components;
-          src[8] = src[7] + components;
-
-          src[0] = src[1] - components;
-          src[3] = src[4] - components;
-          src[6] = src[7] - components;
-
-          if ((sx >>8) - 1<0)
-            {
-              src[0]=src[1];
-              src[3]=src[4];
-              src[6]=src[7];
-            }
-          if ((sy >> 8) - 1 < 0)
-            {
-              src[0]=src[3];
-              src[1]=src[4];
-              src[2]=src[5];
-            }
-          if ((sx >>8) + 1 >= source_w)
-            {
-              src[2]=src[1];
-              src[5]=src[4];
-              src[8]=src[7];
-              break;
-            }
-          if ((sy >> 8) + 1 >= source_h)
-            {
-              src[6]=src[3];
-              src[7]=src[4];
-              src[8]=src[5];
-            }
-
-          box_filter (left_weight,
-                      center_weight,
-                      right_weight,
-                      top_weight,
-                      middle_weight,
-                      bottom_weight,
-                      foosum,
-                      src,   /* the 9 surrounding source pixels */
-                      dst,
-                      components);
-
-
-          dst += components;
-          sx += xdelta;
-        }
-    }
-}
-
-void
-gegl_buffer_get (GeglBuffer          *buffer,
-                 gdouble              scale,
-                 const GeglRectangle *rect,
-                 const Babl          *format,
-                 gpointer             dest_buf,
-                 gint                 rowstride)
-{
-  g_return_if_fail (GEGL_IS_BUFFER (buffer));
-#if ENABLE_MP
-  g_static_rec_mutex_lock (&mutex);
-#endif
-
-  if (format == NULL)
-    format = buffer->format;
-
-  if (scale == 1.0 &&
-      rect &&
-      rect->width == 1 &&
-      rect->height == 1)  /* fast path */
-    {
-      pget (buffer, rect->x, rect->y, format, dest_buf);
-#if ENABLE_MP
-      g_static_rec_mutex_unlock (&mutex);
-#endif
-      return;
-    }
-
-  if (!rect && scale == 1.0)
-    {
-      gegl_buffer_iterate (buffer, dest_buf, rowstride, FALSE, format, 0);
-#if ENABLE_MP
-      g_static_rec_mutex_unlock (&mutex);
-#endif
-      return;
-    }
-  if (rect->width == 0 ||
-      rect->height == 0)
-    {
-#if ENABLE_MP
-      g_static_rec_mutex_unlock (&mutex);
-#endif
-      return;
-    }
-  if (GEGL_FLOAT_EQUAL (scale, 1.0))
-    {
-      gegl_buffer_get_scaled (buffer, rect, dest_buf, rowstride, format, 0);
-#if ENABLE_MP
-      g_static_rec_mutex_unlock (&mutex);
-#endif
-      return;
-    }
-  else
-    {
-      gint          level       = 0;
-      gint          buf_width   = rect->width / scale;
-      gint          buf_height  = rect->height / scale;
-      gint          bpp         = BABL (format)->format.bytes_per_pixel;
-      GeglRectangle sample_rect = { floor(rect->x/scale),
-                                    floor(rect->y/scale),
-                                    buf_width,
-                                    buf_height };
-      void         *sample_buf;
-      gint          factor = 1;
-      gdouble       offset_x;
-      gdouble       offset_y;
-
-      while (scale <= 0.5)
-        {
-          scale  *= 2;
-          factor *= 2;
-          level++;
-        }
-
-      buf_width  /= factor;
-      buf_height /= factor;
-
-      /* ensure we always have some data to sample from */
-      sample_rect.width  += factor * 2;
-      sample_rect.height += factor * 2;
-      buf_width          += 2;
-      buf_height         += 2;
-
-
-      offset_x = rect->x-floor(rect->x/scale) * scale;
-      offset_y = rect->y-floor(rect->y/scale) * scale;
-
-
-      sample_buf = g_malloc (buf_width * buf_height * bpp);
-      gegl_buffer_get_scaled (buffer, &sample_rect, sample_buf, GEGL_AUTO_ROWSTRIDE, format, level);
-
-      if (BABL (format)->format.type[0] == (BablType *) babl_type ("u8")
-          && !(level == 0 && scale > 1.99))
-        { /* do box-filter resampling if we're 8bit (which projections are) */
-
-          /* XXX: use box-filter also for > 1.99 when testing and probably
-           * later, there are some bugs when doing so
-           */
-          resample_boxfilter_u8 (dest_buf,
-                                 sample_buf,
-                                 rect->width,
-                                 rect->height,
-                                 buf_width,
-                                 buf_height,
-                                 offset_x,
-                                 offset_y,
-                                 scale,
-                                 bpp,
-                                 rowstride);
-        }
-      else
-        {
-          resample_nearest (dest_buf,
-                            sample_buf,
-                            rect->width,
-                            rect->height,
-                            buf_width,
-                            buf_height,
-                            offset_x,
-                            offset_y,
-                            scale,
-                            bpp,
-                            rowstride);
-        }
-      g_free (sample_buf);
-    }
-#if ENABLE_MP
-  g_static_rec_mutex_unlock (&mutex);
-#endif
-}
-
-const GeglRectangle *
-gegl_buffer_get_abyss (GeglBuffer *buffer)
-{
-  g_return_val_if_fail (GEGL_IS_BUFFER (buffer), NULL);
-
-  return &buffer->abyss;
-}
-
-void
-gegl_buffer_sample (GeglBuffer       *buffer,
-                    gdouble           x,
-                    gdouble           y,
-                    gdouble           scale,
-                    gpointer          dest,
-                    const Babl       *format,
-                    GeglInterpolation interpolation)
-{
-  g_return_if_fail (GEGL_IS_BUFFER (buffer));
-
-/*#define USE_WORKING_SHORTCUT*/
-#ifdef USE_WORKING_SHORTCUT
-  pget (buffer, x, y, format, dest);
-  return;
-#endif
-
-#if ENABLE_MP
-  g_static_rec_mutex_lock (&mutex);
-#endif
-
-  /* look up appropriate sampler,. */
-  if (buffer->sampler == NULL)
-    {
-      /* FIXME: should probably check if the desired form of interpolation
-       * changes from the currently cached sampler.
-       */
-      GType interpolation_type = 0;
-
-      switch (interpolation)
-        {
-          case GEGL_INTERPOLATION_NEAREST:
-            interpolation_type=GEGL_TYPE_SAMPLER_NEAREST;
-            break;
-          case GEGL_INTERPOLATION_LINEAR:
-            interpolation_type=GEGL_TYPE_SAMPLER_LINEAR;
-            break;
-          default:
-            g_warning ("unimplemented interpolation type %i", interpolation);
-        }
-      buffer->sampler = g_object_new (interpolation_type,
-                                           "buffer", buffer,
-                                           "format", format,
-                                           NULL);
-      gegl_sampler_prepare (buffer->sampler);
-    }
-  gegl_sampler_get (buffer->sampler, x, y, dest);
-
-#if ENABLE_MP
-  g_static_rec_mutex_unlock (&mutex);
-#endif
-
-  /* if none found, create a singleton sampler for this buffer,
-   * a function to clean up the samplers set for a buffer should
-   * also be provided */
-
-  /* if (scale < 1.0) do decimation, possibly using pyramid instead */
-
-}
-
-void
-gegl_buffer_sample_cleanup (GeglBuffer *buffer)
-{
-  g_return_if_fail (GEGL_IS_BUFFER (buffer));
-
-  if (buffer->sampler)
-    {
-      g_object_unref (buffer->sampler);
-      buffer->sampler = NULL;
-    }
-}
 
 const GeglRectangle *
 gegl_buffer_get_extent (GeglBuffer *buffer)
@@ -1927,87 +773,6 @@
  return GEGL_INTERPOLATION_NEAREST;
 }
 
-static GeglIDPool *pool = NULL;
-
-guint
-gegl_buffer_share (GeglBuffer *buffer)
-{
-  guint id;
-  if (!pool)
-    pool = gegl_id_pool_new (16);
-  id = gegl_id_pool_add (pool, buffer);
-  /* FIXME: weak reference to void the handle when the buffer is
-   * finalized
-   */
-  return id;
-}
-
-
-void
-gegl_buffer_make_uri (gchar       *buf_128,
-                      gchar       *host,
-                      gint         port,
-                      gint         process,
-                      gint         handle)
-{
-  gchar *p=buf_128;
-
-  g_sprintf (p, "buffer://%s", host?host:"");
-  p+=strlen (p);
-  if (port)
-    {
-      g_sprintf (p, ":%i", port);
-      p+=strlen (p);
-    }
-  g_sprintf (p, "/");
-  p+=strlen (p);
-  if (process)
-    {
-      g_sprintf (p, "%i", process);
-      p+=strlen (p);
-    }
-  g_sprintf (p, "/");
-  p+=strlen (p);
-  if (handle || 1)
-    {
-      g_sprintf (p, "%i", handle);
-      p+=strlen (p);
-    }
-  else
-    {
-      g_warning ("no handle provided when building uri:\n%s\n", buf_128);
-    }
-}
-
-
-GeglBuffer*
-gegl_buffer_open (const gchar *uri)
-{
-  /* only supports local addresses for now */
-  guint process; /* self */
-  guint handle;
-
-  process = 0;
-  handle = 0;
-
-  if (!pool)
-    pool = gegl_id_pool_new (16);
-
-  if (!g_str_has_prefix (uri, "buffer://"))
-   {
-     g_warning ("'%s' does not start like a valid buffer handle", uri);
-     return NULL;
-   }
-  if (g_str_has_prefix (uri, "buffer:////"))
-   {
-     /* local buffer */
-     handle = atoi (uri + 11);
-     g_print ("got %i, %p\n", handle, gegl_id_pool_lookup (pool, handle));
-     return gegl_buffer_create_sub_buffer (gegl_id_pool_lookup (pool, handle), NULL);
-   }
-  g_warning ("don't know how to handle buffer path: %s", uri);
-  return NULL;
-}
 
 
 
@@ -2061,7 +826,7 @@
 
 
 /* if this function is made to return NULL swapping is disabled */
-const gchar *
+static const gchar *
 gegl_swap_dir (void)
 {
   static gchar *swapdir = "";
@@ -2100,3 +865,67 @@
     }
   return swapdir;
 };
+
+
+static const void *int_gegl_buffer_get_format (GeglBuffer *buffer)
+{
+  g_assert (buffer);
+  if (buffer->format != NULL)
+    return buffer->format;
+  return gegl_buffer_backend (buffer)->format;
+}
+
+
+static void
+gegl_buffer_void (GeglBuffer *buffer)
+{
+  gint width       = buffer->extent.width;
+  gint height      = buffer->extent.height;
+  gint tile_width  = buffer->tile_storage->tile_width;
+  gint tile_height = buffer->tile_storage->tile_height;
+  gint bufy        = 0;
+
+  {
+    gint z;
+    gint factor = 1;
+    for (z = 0; z <= buffer->max_z; z++)
+      {
+        bufy = 0;
+        while (bufy < height)
+          {
+            gint tiledy  = buffer->extent.y + buffer->shift_y + bufy;
+            gint offsety = gegl_tile_offset (tiledy, tile_height);
+            gint bufx    = 0;
+            gint ty = gegl_tile_indice (tiledy / factor, tile_height);
+
+            if (z != 0 ||  /* FIXME: handle z==0 correctly */
+                ty >= buffer->min_y)
+              while (bufx < width)
+                {
+                  gint tiledx  = buffer->extent.x + buffer->shift_x + bufx;
+                  gint offsetx = gegl_tile_offset (tiledx, tile_width);
+
+                  gint tx = gegl_tile_indice (tiledx / factor, tile_width);
+
+                  if (z != 0 ||
+                      tx >= buffer->min_x)
+                  gegl_tile_source_command (GEGL_TILE_SOURCE (buffer),
+                                         GEGL_TILE_VOID, tx, ty, z, NULL);
+
+                  if (z != 0 ||
+                      tx > buffer->max_x)
+                    goto done_with_row;
+
+                  bufx += (tile_width - offsetx) * factor;
+                }
+done_with_row:
+            bufy += (tile_height - offsety) * factor;
+
+                  if (z != 0 ||
+                      ty > buffer->max_y)
+                    break;
+          }
+        factor *= 2;
+      }
+  }
+}



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