|
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 |
|