Blame gegl/buffer/gegl-buffer-iterator.c

Packit bc1512
/* This file is part of GEGL.
Packit bc1512
 *
Packit bc1512
 * This library is free software; you can redistribute it and/or
Packit bc1512
 * modify it under the terms of the GNU Lesser General Public
Packit bc1512
 * License as published by the Free Software Foundation; either
Packit bc1512
 * version 3 of the License, or (at your option) any later version.
Packit bc1512
 *
Packit bc1512
 * This library is distributed in the hope that it will be useful,
Packit bc1512
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit bc1512
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit bc1512
 * Lesser General Public License for more details.
Packit bc1512
 *
Packit bc1512
 * You should have received a copy of the GNU Lesser General Public
Packit bc1512
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
Packit bc1512
 *
Packit bc1512
 * Copyright 2008 Øyvind Kolås <pippin@gimp.org>
Packit bc1512
 */
Packit bc1512
Packit bc1512
#include "config.h"
Packit bc1512
#include <stdlib.h>
Packit bc1512
#include <string.h>
Packit bc1512
#include <math.h>
Packit bc1512
Packit bc1512
#include <glib-object.h>
Packit bc1512
#include <glib/gprintf.h>
Packit bc1512
Packit bc1512
#include "gegl.h"
Packit bc1512
#include "gegl-types-internal.h"
Packit bc1512
#include "gegl-buffer-types.h"
Packit bc1512
#include "gegl-buffer-iterator.h"
Packit bc1512
#include "gegl-buffer-private.h"
Packit bc1512
#include "gegl-tile-storage.h"
Packit bc1512
#include "gegl-utils.h"
Packit bc1512
Packit bc1512
#include "gegl-buffer-cl-cache.h"
Packit bc1512
Packit bc1512
typedef struct GeglBufferTileIterator
Packit bc1512
{
Packit bc1512
  GeglBuffer    *buffer;
Packit bc1512
  GeglRectangle  roi;     /* the rectangular region we're iterating over */
Packit bc1512
  GeglTile      *tile;    /* current tile */
Packit bc1512
  gpointer       data;    /* current tile's data */
Packit bc1512
Packit bc1512
  gint           col;     /* the column currently provided for */
Packit bc1512
  gint           row;     /* the row currently provided for */
Packit bc1512
  gboolean       write;
Packit bc1512
  GeglRectangle  subrect;    /* the subrect that intersected roi */
Packit bc1512
  gpointer       sub_data;   /* pointer to the subdata as indicated by subrect */
Packit bc1512
  gint           rowstride;  /* rowstride for tile, in bytes */
Packit bc1512
Packit bc1512
  gint           next_col; /* used internally */
Packit bc1512
  gint           next_row; /* used internally */
Packit bc1512
  gint           max_size; /* maximum data buffer needed, in bytes */
Packit bc1512
  GeglRectangle  roi2;     /* the rectangular subregion of data
Packit bc1512
                            * in the buffer represented by this scan.
Packit bc1512
                            */
Packit bc1512
  gboolean       same_format;
Packit bc1512
  gint           level;
Packit bc1512
} GeglBufferTileIterator;
Packit bc1512
Packit bc1512
#define GEGL_BUFFER_SCAN_COMPATIBLE   128   /* should be integrated into enum */
Packit bc1512
#define GEGL_BUFFER_FORMAT_COMPATIBLE 256   /* should be integrated into enum */
Packit bc1512
Packit bc1512
#define DEBUG_DIRECT 0
Packit bc1512
Packit bc1512
typedef struct GeglBufferIterators
Packit bc1512
{
Packit bc1512
  /* current region of interest */
Packit bc1512
  gint          length;             /* length of current data in pixels */
Packit bc1512
  gpointer      data[GEGL_BUFFER_MAX_ITERATORS];
Packit bc1512
  GeglRectangle roi[GEGL_BUFFER_MAX_ITERATORS]; /* roi of the current data */
Packit bc1512
Packit bc1512
  /* the following is private: */
Packit bc1512
  gint           iterators;
Packit bc1512
  gint           iteration_no;
Packit bc1512
  gboolean       is_finished;
Packit bc1512
  GeglRectangle  rect       [GEGL_BUFFER_MAX_ITERATORS]; /* the region we iterate on. They can be different from
Packit bc1512
                                                            each other, but width and height are the same */
Packit bc1512
  const Babl    *format     [GEGL_BUFFER_MAX_ITERATORS]; /* The format required for the data */
Packit bc1512
  GeglBuffer    *buffer     [GEGL_BUFFER_MAX_ITERATORS]; /* currently a subbuffer of the original, need to go away */
Packit bc1512
  guint          flags      [GEGL_BUFFER_MAX_ITERATORS];
Packit bc1512
  gpointer       buf        [GEGL_BUFFER_MAX_ITERATORS]; /* no idea */
Packit bc1512
  GeglBufferTileIterator   i[GEGL_BUFFER_MAX_ITERATORS];
Packit bc1512
} GeglBufferIterators;
Packit bc1512
Packit bc1512
Packit bc1512
static void      gegl_buffer_tile_iterator_init (GeglBufferTileIterator *i,
Packit bc1512
                                                 GeglBuffer             *buffer,
Packit bc1512
                                                 GeglRectangle           roi,
Packit bc1512
                                                 gboolean                write,
Packit bc1512
                                                 const Babl             *format,
Packit bc1512
                                                 gint                    level);
Packit bc1512
static gboolean  gegl_buffer_tile_iterator_next (GeglBufferTileIterator *i);
Packit bc1512
Packit bc1512
/*
Packit bc1512
 *  check whether iterations on two buffers starting from the given coordinates with
Packit bc1512
 *  the same width and height would be able to run parallell.
Packit bc1512
 */
Packit bc1512
static gboolean gegl_buffer_scan_compatible (GeglBuffer *bufferA,
Packit bc1512
                                             gint        xA,
Packit bc1512
                                             gint        yA,
Packit bc1512
                                             GeglBuffer *bufferB,
Packit bc1512
                                             gint        xB,
Packit bc1512
                                             gint        yB)
Packit bc1512
{
Packit bc1512
  if (bufferA->tile_storage->tile_width !=
Packit bc1512
      bufferB->tile_storage->tile_width)
Packit bc1512
    return FALSE;
Packit bc1512
  if (bufferA->tile_storage->tile_height !=
Packit bc1512
      bufferB->tile_storage->tile_height)
Packit bc1512
    return FALSE;
Packit bc1512
  if ( (abs((bufferA->shift_x+xA) - (bufferB->shift_x+xB))
Packit bc1512
        % bufferA->tile_storage->tile_width) != 0)
Packit bc1512
    return FALSE;
Packit bc1512
  if ( (abs((bufferA->shift_y+yA) - (bufferB->shift_y+yB))
Packit bc1512
        % bufferA->tile_storage->tile_height) != 0)
Packit bc1512
    return FALSE;
Packit bc1512
  return TRUE;
Packit bc1512
}
Packit bc1512
Packit bc1512
static void gegl_buffer_tile_iterator_init (GeglBufferTileIterator *i,
Packit bc1512
                                            GeglBuffer             *buffer,
Packit bc1512
                                            GeglRectangle           roi,
Packit bc1512
                                            gboolean                write,
Packit bc1512
                                            const Babl             *format,
Packit bc1512
                                            gint                    level)
Packit bc1512
{
Packit bc1512
  g_assert (i);
Packit bc1512
  memset (i, 0, sizeof (GeglBufferTileIterator));
Packit bc1512
Packit bc1512
  i->buffer = buffer;
Packit bc1512
  i->roi = roi;
Packit bc1512
  i->level = level;
Packit bc1512
  i->next_row    = 0;
Packit bc1512
  i->next_col = 0;
Packit bc1512
  i->tile = NULL;
Packit bc1512
  i->col = 0;
Packit bc1512
  i->row = 0;
Packit bc1512
  i->write = write;
Packit bc1512
  
Packit bc1512
  i->max_size = i->buffer->tile_storage->tile_width *
Packit bc1512
                i->buffer->tile_storage->tile_height;
Packit bc1512
Packit bc1512
  i->same_format = format == buffer->format;
Packit bc1512
Packit bc1512
  /* return at the end,. we still want things initialized a bit .. */
Packit bc1512
  g_return_if_fail (roi.width != 0 && roi.height != 0);
Packit bc1512
}
Packit bc1512
Packit bc1512
static gboolean
Packit bc1512
gegl_buffer_tile_iterator_next (GeglBufferTileIterator *i)
Packit bc1512
{
Packit bc1512
  GeglBuffer *buffer   = i->buffer;
Packit bc1512
  gint  tile_width     = buffer->tile_storage->tile_width;
Packit bc1512
  gint  tile_height    = buffer->tile_storage->tile_height;
Packit bc1512
  gint  buffer_shift_x = buffer->shift_x;
Packit bc1512
  gint  buffer_shift_y = buffer->shift_y;
Packit bc1512
  gint  buffer_x       = i->roi.x + buffer_shift_x;
Packit bc1512
  gint  buffer_y       = i->roi.y + buffer_shift_y;
Packit bc1512
Packit bc1512
  if (i->roi.width == 0 || i->roi.height == 0)
Packit bc1512
    return FALSE;
Packit bc1512
Packit bc1512
gulp:
Packit bc1512
Packit bc1512
  /* unref previously held tile */
Packit bc1512
  if (i->tile)
Packit bc1512
    {
Packit bc1512
      if (i->write && i->subrect.width == tile_width && i->same_format)
Packit bc1512
        {
Packit bc1512
          gegl_tile_unlock (i->tile);
Packit bc1512
        }
Packit bc1512
      gegl_tile_unref (i->tile);
Packit bc1512
      i->tile = NULL;
Packit bc1512
    }
Packit bc1512
Packit bc1512
  if (i->next_col < i->roi.width)
Packit bc1512
    { /* return tile on this row */
Packit bc1512
      gint tiledx = buffer_x + i->next_col;
Packit bc1512
      gint tiledy = buffer_y + i->next_row;
Packit bc1512
      gint offsetx = gegl_tile_offset (tiledx, tile_width);
Packit bc1512
      gint offsety = gegl_tile_offset (tiledy, tile_height);
Packit bc1512
Packit bc1512
        {
Packit bc1512
         i->subrect.x = offsetx;
Packit bc1512
         i->subrect.y = offsety;
Packit bc1512
         if (i->roi.width + offsetx - i->next_col < tile_width)
Packit bc1512
           i->subrect.width = (i->roi.width + offsetx - i->next_col) - offsetx;
Packit bc1512
         else
Packit bc1512
           i->subrect.width = tile_width - offsetx;
Packit bc1512
Packit bc1512
         if (i->roi.height + offsety - i->next_row < tile_height)
Packit bc1512
           i->subrect.height = (i->roi.height + offsety - i->next_row) - offsety;
Packit bc1512
         else
Packit bc1512
           i->subrect.height = tile_height - offsety;
Packit bc1512
Packit bc1512
         i->tile = gegl_tile_source_get_tile ((GeglTileSource *) (buffer),
Packit bc1512
                                        gegl_tile_indice (tiledx, tile_width),
Packit bc1512
                                        gegl_tile_indice (tiledy, tile_height),
Packit bc1512
                                        0);
Packit bc1512
         if (i->write && i->subrect.width == tile_width && i->same_format)
Packit bc1512
           {
Packit bc1512
             gegl_tile_lock (i->tile);
Packit bc1512
           }
Packit bc1512
         i->data = gegl_tile_get_data (i->tile);
Packit bc1512
Packit bc1512
         {
Packit bc1512
         gint bpp = babl_format_get_bytes_per_pixel (i->buffer->soft_format);
Packit bc1512
         i->rowstride = bpp * tile_width;
Packit bc1512
         i->sub_data = (guchar*)(i->data) + bpp * 
Packit bc1512
                        (i->subrect.y * tile_width + i->subrect.x);
Packit bc1512
         }
Packit bc1512
Packit bc1512
         i->col = i->next_col;
Packit bc1512
         i->row = i->next_row;
Packit bc1512
         i->next_col += tile_width - offsetx;
Packit bc1512
Packit bc1512
Packit bc1512
         i->roi2.x      = i->roi.x + i->col;
Packit bc1512
         i->roi2.y      = i->roi.y + i->row;
Packit bc1512
         i->roi2.width  = i->subrect.width;
Packit bc1512
         i->roi2.height = i->subrect.height;
Packit bc1512
Packit bc1512
         return TRUE;
Packit bc1512
       }
Packit bc1512
    }
Packit bc1512
  else /* move down to next row */
Packit bc1512
    {
Packit bc1512
      gint tiledy;
Packit bc1512
      gint offsety;
Packit bc1512
Packit bc1512
      i->row = i->next_row;
Packit bc1512
      i->col = i->next_col;
Packit bc1512
Packit bc1512
      tiledy = buffer_y + i->next_row;
Packit bc1512
      offsety = gegl_tile_offset (tiledy, tile_height);
Packit bc1512
Packit bc1512
      i->next_row += tile_height - offsety;
Packit bc1512
      i->next_col=0;
Packit bc1512
Packit bc1512
      if (i->next_row < i->roi.height)
Packit bc1512
        {
Packit bc1512
          goto gulp; /* return the first tile in the next row */
Packit bc1512
        }
Packit bc1512
      return FALSE;
Packit bc1512
    }
Packit bc1512
  return FALSE;
Packit bc1512
}
Packit bc1512
Packit bc1512
#if DEBUG_DIRECT
Packit bc1512
static glong direct_read = 0;
Packit bc1512
static glong direct_write = 0;
Packit bc1512
static glong in_direct_read = 0;
Packit bc1512
static glong in_direct_write = 0;
Packit bc1512
#endif
Packit bc1512
Packit bc1512
Packit bc1512
gint
Packit bc1512
gegl_buffer_iterator_add (GeglBufferIterator  *iterator,
Packit bc1512
                          GeglBuffer          *buffer,
Packit bc1512
                          const GeglRectangle *roi,
Packit bc1512
                          gint                 level,
Packit bc1512
                          const Babl          *format,
Packit bc1512
                          guint                flags,
Packit bc1512
                          GeglAbyssPolicy      abyss_policy)
Packit bc1512
{
Packit bc1512
  GeglBufferIterators *i = (gpointer)iterator;
Packit bc1512
  gint self = 0;
Packit bc1512
  if (i->iterators+1 > GEGL_BUFFER_MAX_ITERATORS)
Packit bc1512
    {
Packit bc1512
      g_error ("too many iterators (%i)", i->iterators+1);
Packit bc1512
    }
Packit bc1512
Packit bc1512
  if (i->iterators == 0) /* for sanity, we zero at init */
Packit bc1512
    {
Packit bc1512
      memset (i, 0, sizeof (GeglBufferIterators));
Packit bc1512
    }
Packit bc1512
Packit bc1512
  /* XXX: should assert that the passed in level matches
Packit bc1512
   * the level of the base iterator.
Packit bc1512
   */
Packit bc1512
Packit bc1512
  self = i->iterators++;
Packit bc1512
Packit bc1512
  if (!roi)
Packit bc1512
    roi = self==0?&(buffer->extent):&(i->rect[0]);
Packit bc1512
  i->rect[self]=*roi;
Packit bc1512
Packit bc1512
  i->buffer[self]= g_object_ref (buffer);
Packit bc1512
Packit bc1512
  if (format)
Packit bc1512
    i->format[self]=format;
Packit bc1512
  else
Packit bc1512
    i->format[self]=buffer->soft_format;
Packit bc1512
  i->flags[self]=flags;
Packit bc1512
Packit bc1512
  if (self==0) /* The first buffer which is always scan aligned */
Packit bc1512
    {
Packit bc1512
      i->flags[self] |= GEGL_BUFFER_SCAN_COMPATIBLE;
Packit bc1512
      gegl_buffer_tile_iterator_init (&i->i[self], i->buffer[self], i->rect[self], ((i->flags[self] & GEGL_BUFFER_WRITE) != 0), i->format[self], iterator->level);
Packit bc1512
    }
Packit bc1512
  else
Packit bc1512
    {
Packit bc1512
      /* we make all subsequently added iterators share the width and height of the first one */
Packit bc1512
      i->rect[self].width = i->rect[0].width;
Packit bc1512
      i->rect[self].height = i->rect[0].height;
Packit bc1512
Packit bc1512
      if (gegl_buffer_scan_compatible (i->buffer[0], i->rect[0].x, i->rect[0].y,
Packit bc1512
                                       i->buffer[self], i->rect[self].x, i->rect[self].y))
Packit bc1512
        {
Packit bc1512
          i->flags[self] |= GEGL_BUFFER_SCAN_COMPATIBLE;
Packit bc1512
          gegl_buffer_tile_iterator_init (&i->i[self], i->buffer[self], i->rect[self], ((i->flags[self] & GEGL_BUFFER_WRITE) != 0), i->format[self], iterator->level);
Packit bc1512
        }
Packit bc1512
    }
Packit bc1512
Packit bc1512
  i->buf[self] = NULL;
Packit bc1512
Packit bc1512
  if (i->format[self] == i->buffer[self]->soft_format)
Packit bc1512
    {
Packit bc1512
      i->flags[self] |= GEGL_BUFFER_FORMAT_COMPATIBLE;
Packit bc1512
    }
Packit bc1512
  return self;
Packit bc1512
}
Packit bc1512
Packit bc1512
/* FIXME: we are currently leaking this buf pool, it should be
Packit bc1512
 * freed when gegl is uninitialized
Packit bc1512
 */
Packit bc1512
Packit bc1512
typedef struct BufInfo {
Packit bc1512
  gint     size;
Packit bc1512
  gint     used;  /* if this buffer is currently allocated */
Packit bc1512
  gpointer buf;
Packit bc1512
} BufInfo;
Packit bc1512
Packit bc1512
static GArray *buf_pool = NULL;
Packit bc1512
Packit bc1512
static GStaticMutex pool_mutex = G_STATIC_MUTEX_INIT;
Packit bc1512
Packit bc1512
static gpointer iterator_buf_pool_get (gint size)
Packit bc1512
{
Packit bc1512
  gint i;
Packit bc1512
  g_static_mutex_lock (&pool_mutex);
Packit bc1512
Packit bc1512
  if (G_UNLIKELY (!buf_pool))
Packit bc1512
    {
Packit bc1512
      buf_pool = g_array_new (TRUE, TRUE, sizeof (BufInfo));
Packit bc1512
    }
Packit bc1512
  for (i=0; i<buf_pool->len; i++)
Packit bc1512
    {
Packit bc1512
      BufInfo *info = &g_array_index (buf_pool, BufInfo, i);
Packit bc1512
      if (info->size >= size && info->used == 0)
Packit bc1512
        {
Packit bc1512
          info->used ++;
Packit bc1512
          g_static_mutex_unlock (&pool_mutex);
Packit bc1512
          return info->buf;
Packit bc1512
        }
Packit bc1512
    }
Packit bc1512
  {
Packit bc1512
    BufInfo info = {0, 1, NULL};
Packit bc1512
    info.size = size;
Packit bc1512
    info.buf = gegl_malloc (size);
Packit bc1512
    g_array_append_val (buf_pool, info);
Packit bc1512
    g_static_mutex_unlock (&pool_mutex);
Packit bc1512
    return info.buf;
Packit bc1512
  }
Packit bc1512
}
Packit bc1512
Packit bc1512
static void iterator_buf_pool_release (gpointer buf)
Packit bc1512
{
Packit bc1512
  gint i;
Packit bc1512
  g_static_mutex_lock (&pool_mutex);
Packit bc1512
  for (i=0; i<buf_pool->len; i++)
Packit bc1512
    {
Packit bc1512
      BufInfo *info = &g_array_index (buf_pool, BufInfo, i);
Packit bc1512
      if (info->buf == buf)
Packit bc1512
        {
Packit bc1512
          info->used --;
Packit bc1512
          g_static_mutex_unlock (&pool_mutex);
Packit bc1512
          return;
Packit bc1512
        }
Packit bc1512
    }
Packit bc1512
  g_assert (0);
Packit bc1512
  g_static_mutex_unlock (&pool_mutex);
Packit bc1512
}
Packit bc1512
Packit bc1512
static void ensure_buf (GeglBufferIterators *i, gint no)
Packit bc1512
{
Packit bc1512
  if (i->buf[no]==NULL)
Packit bc1512
    i->buf[no] = iterator_buf_pool_get (babl_format_get_bytes_per_pixel (i->format[no]) *
Packit bc1512
                                        i->i[0].max_size);
Packit bc1512
}
Packit bc1512
Packit bc1512
void
Packit bc1512
gegl_buffer_iterator_stop (GeglBufferIterator *iterator)
Packit bc1512
{
Packit bc1512
  GeglBufferIterators *i = (gpointer)iterator;
Packit bc1512
  gint no;
Packit bc1512
  for (no=0; no<i->iterators;no++)
Packit bc1512
    {
Packit bc1512
      gint j;
Packit bc1512
      gboolean found = FALSE;
Packit bc1512
      for (j=0; j
Packit bc1512
        if (i->buffer[no]==i->buffer[j])
Packit bc1512
          {
Packit bc1512
            found = TRUE;
Packit bc1512
            break;
Packit bc1512
          }
Packit bc1512
      if (!found)
Packit bc1512
        gegl_buffer_unlock (i->buffer[no]);
Packit bc1512
    }
Packit bc1512
Packit bc1512
  for (no=0; no<i->iterators; no++)
Packit bc1512
    {
Packit bc1512
      if (i->buf[no])
Packit bc1512
        iterator_buf_pool_release (i->buf[no]);
Packit bc1512
      i->buf[no]=NULL;
Packit bc1512
      g_object_unref (i->buffer[no]);
Packit bc1512
    }
Packit bc1512
#if DEBUG_DIRECT
Packit bc1512
  g_print ("%f %f\n", (100.0*direct_read/(in_direct_read+direct_read)),
Packit bc1512
                           100.0*direct_write/(in_direct_write+direct_write));
Packit bc1512
#endif
Packit bc1512
  i->is_finished = TRUE;
Packit bc1512
  g_slice_free (GeglBufferIterators, i);
Packit bc1512
}
Packit bc1512
Packit bc1512
gboolean
Packit bc1512
gegl_buffer_iterator_next (GeglBufferIterator *iterator)
Packit bc1512
{
Packit bc1512
  GeglBufferIterators *i = (gpointer)iterator;
Packit bc1512
  gboolean result = FALSE;
Packit bc1512
  gint no;
Packit bc1512
Packit bc1512
  if (i->is_finished)
Packit bc1512
    g_error ("%s called on finished buffer iterator", G_STRFUNC);
Packit bc1512
  if (i->iteration_no == 0)
Packit bc1512
    {
Packit bc1512
      for (no=0; no<i->iterators;no++)
Packit bc1512
        {
Packit bc1512
          gint j;
Packit bc1512
          gboolean found = FALSE;
Packit bc1512
          for (j=0; j
Packit bc1512
            if (i->buffer[no]==i->buffer[j])
Packit bc1512
              {
Packit bc1512
                found = TRUE;
Packit bc1512
                break;
Packit bc1512
              }
Packit bc1512
          if (!found)
Packit bc1512
            gegl_buffer_lock (i->buffer[no]);
Packit bc1512
Packit bc1512
          if (gegl_cl_is_accelerated ())
Packit bc1512
            gegl_buffer_cl_cache_flush (i->buffer[no], &i->rect[no]);
Packit bc1512
        }
Packit bc1512
    }
Packit bc1512
  else
Packit bc1512
    {
Packit bc1512
      /* complete pending write work */
Packit bc1512
      for (no=0; no<i->iterators;no++)
Packit bc1512
        {
Packit bc1512
          if (i->flags[no] & GEGL_BUFFER_WRITE)
Packit bc1512
            {
Packit bc1512
Packit bc1512
              if (i->flags[no] & GEGL_BUFFER_SCAN_COMPATIBLE &&
Packit bc1512
                  i->flags[no] & GEGL_BUFFER_FORMAT_COMPATIBLE &&
Packit bc1512
                  i->roi[no].width == i->i[no].buffer->tile_storage->tile_width && (i->flags[no] & GEGL_BUFFER_FORMAT_COMPATIBLE))
Packit bc1512
                { /* direct access, don't need to do anything */
Packit bc1512
#if DEBUG_DIRECT
Packit bc1512
                   direct_write += i->roi[no].width * i->roi[no].height;
Packit bc1512
#endif
Packit bc1512
                }
Packit bc1512
              else
Packit bc1512
                {
Packit bc1512
#if DEBUG_DIRECT
Packit bc1512
                  in_direct_write += i->roi[no].width * i->roi[no].height;
Packit bc1512
#endif
Packit bc1512
Packit bc1512
                  ensure_buf (i, no);
Packit bc1512
Packit bc1512
  /* XXX: should perhaps use _set_unlocked, and keep the lock in the
Packit bc1512
   * iterator.
Packit bc1512
   */
Packit bc1512
                  gegl_buffer_set (i->buffer[no], &(i->roi[no]), 0, i->format[no], i->buf[no], GEGL_AUTO_ROWSTRIDE); /* XXX: use correct level */
Packit bc1512
                }
Packit bc1512
            }
Packit bc1512
        }
Packit bc1512
    }
Packit bc1512
Packit bc1512
  g_assert (i->iterators > 0);
Packit bc1512
Packit bc1512
  /* then we iterate all */
Packit bc1512
  for (no=0; no<i->iterators;no++)
Packit bc1512
    {
Packit bc1512
      if (i->flags[no] & GEGL_BUFFER_SCAN_COMPATIBLE)
Packit bc1512
        {
Packit bc1512
          gboolean res;
Packit bc1512
          res = gegl_buffer_tile_iterator_next (&i->i[no]);
Packit bc1512
          if (no == 0)
Packit bc1512
            {
Packit bc1512
              result = res;
Packit bc1512
            }
Packit bc1512
          i->roi[no] = i->i[no].roi2;
Packit bc1512
Packit bc1512
          /* since they were scan compatible this should be true */
Packit bc1512
          if (res != result)
Packit bc1512
            {
Packit bc1512
              g_print ("%i==%i != 0==%i\n", no, res, result);
Packit bc1512
            }
Packit bc1512
          g_assert (res == result);
Packit bc1512
Packit bc1512
          if ((i->flags[no] & GEGL_BUFFER_FORMAT_COMPATIBLE) &&
Packit bc1512
              i->roi[no].width == i->i[no].buffer->tile_storage->tile_width
Packit bc1512
           )
Packit bc1512
            {
Packit bc1512
              /* direct access */
Packit bc1512
              i->data[no]=i->i[no].sub_data;
Packit bc1512
#if DEBUG_DIRECT
Packit bc1512
              direct_read += i->roi[no].width * i->roi[no].height;
Packit bc1512
#endif
Packit bc1512
            }
Packit bc1512
          else
Packit bc1512
            {
Packit bc1512
              ensure_buf (i, no);
Packit bc1512
Packit bc1512
              if (i->flags[no] & GEGL_BUFFER_READ)
Packit bc1512
                {
Packit bc1512
                  gegl_buffer_get_unlocked (i->buffer[no], 1.0, &(i->roi[no]), i->format[no], i->buf[no], GEGL_AUTO_ROWSTRIDE);
Packit bc1512
                }
Packit bc1512
Packit bc1512
              i->data[no]=i->buf[no];
Packit bc1512
#if DEBUG_DIRECT
Packit bc1512
              in_direct_read += i->roi[no].width * i->roi[no].height;
Packit bc1512
#endif
Packit bc1512
            }
Packit bc1512
        }
Packit bc1512
      else
Packit bc1512
        {
Packit bc1512
          /* we copy the roi from iterator 0  */
Packit bc1512
          i->roi[no] = i->roi[0];
Packit bc1512
          i->roi[no].x += (i->rect[no].x-i->rect[0].x);
Packit bc1512
          i->roi[no].y += (i->rect[no].y-i->rect[0].y);
Packit bc1512
Packit bc1512
          ensure_buf (i, no);
Packit bc1512
Packit bc1512
          if (i->flags[no] & GEGL_BUFFER_READ)
Packit bc1512
            {
Packit bc1512
              gegl_buffer_get_unlocked (i->buffer[no], 1.0, &(i->roi[no]), i->format[no], i->buf[no], GEGL_AUTO_ROWSTRIDE);
Packit bc1512
            }
Packit bc1512
          i->data[no]=i->buf[no];
Packit bc1512
Packit bc1512
#if DEBUG_DIRECT
Packit bc1512
          in_direct_read += i->roi[no].width * i->roi[no].height;
Packit bc1512
#endif
Packit bc1512
        }
Packit bc1512
      i->length = i->roi[no].width * i->roi[no].height;
Packit bc1512
    }
Packit bc1512
Packit bc1512
  i->iteration_no++;
Packit bc1512
Packit bc1512
  if (result == FALSE)
Packit bc1512
    gegl_buffer_iterator_stop (iterator);
Packit bc1512
Packit bc1512
  return result;
Packit bc1512
}
Packit bc1512
Packit bc1512
GeglBufferIterator *
Packit bc1512
gegl_buffer_iterator_new (GeglBuffer          *buffer,
Packit bc1512
                          const GeglRectangle *roi,
Packit bc1512
                          gint                 level,
Packit bc1512
                          const Babl          *format,
Packit bc1512
                          guint                flags,
Packit bc1512
                          GeglAbyssPolicy      abyss_policy)
Packit bc1512
{
Packit bc1512
  GeglBufferIterator *i = (gpointer)g_slice_new0 (GeglBufferIterators);
Packit bc1512
  /* Because the iterator is nulled above, we can forgo explicitly setting
Packit bc1512
   * i->is_finished to FALSE. */
Packit bc1512
  i->level = level;
Packit bc1512
  gegl_buffer_iterator_add (i, buffer, roi, level, format, flags, abyss_policy);
Packit bc1512
  return i;
Packit bc1512
}
Packit bc1512