gegl r2289 - in trunk: . gegl/buffer gegl/operation
- From: ok svn gnome org
- To: svn-commits-list gnome org
- Subject: gegl r2289 - in trunk: . gegl/buffer gegl/operation
- Date: Fri, 16 May 2008 18:01:36 +0100 (BST)
Author: ok
Date: Fri May 16 17:01:36 2008
New Revision: 2289
URL: http://svn.gnome.org/viewvc/gegl?rev=2289&view=rev
Log:
* gegl/buffer/gegl-buffer-access.c: added gegl_buffer_scan_iterator.
* gegl/buffer/gegl-buffer-private.h: added iterator data structures
for tiles as well as scanlines.
* gegl/buffer/gegl-tile.c: use gegl_malloc for allocating aligned
tile memory.
* gegl/operation/gegl-operation-point-filter.c: make use of scan
iteration when possible between formats.
Modified:
trunk/ChangeLog
trunk/gegl/buffer/gegl-buffer-access.c
trunk/gegl/buffer/gegl-buffer-private.h
trunk/gegl/buffer/gegl-tile.c
trunk/gegl/operation/gegl-operation-point-filter.c
Modified: trunk/gegl/buffer/gegl-buffer-access.c
==============================================================================
--- trunk/gegl/buffer/gegl-buffer-access.c (original)
+++ trunk/gegl/buffer/gegl-buffer-access.c Fri May 16 17:01:36 2008
@@ -41,6 +41,226 @@
#endif
+
+void gegl_buffer_tile_iterator_init (GeglBufferTileIterator *i,
+ GeglBuffer *buffer,
+ GeglRectangle roi,
+ gboolean write)
+{
+ g_assert (i);
+ memset (i, 0, sizeof (GeglBufferTileIterator));
+ i->buffer = buffer;
+ i->roi = roi;
+ i->row = 0;
+ i->col = 0;
+ i->tile = NULL;
+ i->write = write;
+}
+
+
+GeglBufferTileIterator *
+gegl_buffer_tile_iterator_new (GeglBuffer *buffer,
+ GeglRectangle roi,
+ gboolean write)
+{
+ GeglBufferTileIterator *i = g_malloc (sizeof (GeglBufferTileIterator));
+ gegl_buffer_tile_iterator_init (i, buffer, roi, write);
+ return i;
+}
+
+void gegl_buffer_scan_iterator_init (GeglBufferScanIterator *i,
+ GeglBuffer *buffer,
+ GeglRectangle roi,
+ gboolean write)
+{
+ GeglBufferTileIterator *tile_i = (GeglBufferTileIterator*)i;
+ g_assert (i);
+ memset (i, 0, sizeof (GeglBufferScanIterator));
+ gegl_buffer_tile_iterator_init (tile_i, buffer, roi, write);
+ i->max_size = tile_i->buffer->tile_storage->tile_width *
+ tile_i->buffer->tile_storage->tile_height *
+ tile_i->buffer->format->format.bytes_per_pixel;
+}
+
+GeglBufferScanIterator *gegl_buffer_scan_iterator_new (GeglBuffer *buffer,
+ GeglRectangle roi,
+ gboolean write)
+{
+ GeglBufferScanIterator *i = g_malloc (sizeof (GeglBufferScanIterator));
+ gegl_buffer_scan_iterator_init (i, buffer, roi, write);
+ return i;
+}
+
+gboolean
+gegl_buffer_scan_iterator_next (GeglBufferScanIterator *i)
+{
+ GeglBufferTileIterator *tile_i = (GeglBufferTileIterator*)i;
+
+ if (tile_i->tile==NULL)
+ {
+ gulp:
+ if (!gegl_buffer_tile_iterator_next (tile_i))
+ return FALSE;
+ i->width = tile_i->subrect.width;
+ i->row = 0;
+ }
+ /* we should now have a valid tile */
+
+ if (tile_i->subrect.width == tile_i->buffer->tile_storage->tile_width &&
+ i->row < tile_i->subrect.height)
+ /* the entire contents of the tile can be expressed as one long scan */
+ {
+ gint px_size = tile_i->buffer->format->format.bytes_per_pixel;
+ guchar *data = tile_i->data;
+ i->width = tile_i->subrect.width * tile_i->subrect.height;
+ i->data = data + px_size * (tile_i->subrect.width * tile_i->subrect.y);
+ i->row = tile_i->subrect.height;
+ return TRUE;
+ }
+ else if (i->row < tile_i->subrect.height)
+ /* iterate thorugh the scanlines in the subrect */
+ {
+ guchar *data = tile_i->sub_data;
+ i->data = data + i->row * tile_i->rowstride;
+ i->row ++;
+ return TRUE;
+ }
+ else
+ { /* we're done with that tile go get another one if possible */
+ goto gulp;
+ }
+
+ return FALSE;
+}
+
+
+gboolean gegl_buffer_scan_compatible (GeglBuffer *input,
+ GeglBuffer *output)
+{
+ if (input->tile_storage->tile_width !=
+ output->tile_storage->tile_width)
+ return FALSE;
+ if (input->tile_storage->tile_height !=
+ output->tile_storage->tile_height)
+ return FALSE;
+ if (input->shift_x !=
+ output->shift_x)
+ return FALSE;
+ if (input->shift_y !=
+ output->shift_y)
+ return FALSE;
+ return TRUE;
+}
+
+gboolean
+gegl_buffer_tile_iterator_next (GeglBufferTileIterator *i)
+{
+ GeglBuffer *buffer = i->buffer;
+ gint tile_width = buffer->tile_storage->tile_width;
+ gint tile_height = buffer->tile_storage->tile_height;
+ 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 abyss_x_total = buffer_abyss_x + buffer->abyss.width;
+
+ if (i->roi.width == 0 || i->roi.height == 0)
+ return FALSE;
+
+gulp:
+
+ /* unref previous held tile */
+ if (i->tile)
+ {
+ if (i->write)
+ {
+ gegl_tile_unlock (i->tile);
+ }
+ g_object_unref (i->tile);
+ i->tile = NULL;
+ }
+
+ if (i->col < i->roi.width)
+ { /* return tile on this row */
+ gint tiledx = buffer_x + i->col;
+ gint tiledy = buffer_y + i->row;
+ gint offsetx = gegl_tile_offset (tiledx, tile_width);
+ gint offsety = gegl_tile_offset (tiledy, tile_height);
+ gint pixels;
+
+ if (i->roi.width + offsetx - i->col < tile_width)
+ pixels = (i->roi.width + offsetx - i->col) - offsetx;
+ else
+ pixels = tile_width - offsetx;
+
+ if (!(buffer_x + i->col + tile_width >= buffer_abyss_x &&
+ buffer_x + i->col < abyss_x_total))
+ {
+ g_warning ("entire tile in abyss?");
+
+ i->col += tile_width - offsetx;
+ }
+ else
+ {
+ /* gap between left side of tile, and abyss */
+ i->subrect.x = offsetx;
+ i->subrect.y = offsety;
+ /* gap between right side of tile, and abyss */
+
+
+ i->subrect.width = (i->roi.width - i->col < tile_width) ?
+ (i->roi.width - i->col) - i->subrect.x:
+ tile_width - i->subrect.x;
+
+ i->subrect.height = (i->roi.height - i->row < tile_height) ?
+ (i->roi.height - i->row) - i->subrect.y:
+ tile_height - i->subrect.y;
+
+ i->tile = gegl_tile_source_get_tile ((GeglTileSource *) (buffer),
+ gegl_tile_indice (tiledx, tile_width),
+ gegl_tile_indice (tiledy, tile_height),
+ 0);
+ if (i->write)
+ {
+ gegl_tile_lock (i->tile);
+ }
+ i->data = gegl_tile_get_data (i->tile);
+
+ {
+ gint bpp = i->buffer->format->format.bytes_per_pixel;
+ i->rowstride = bpp * tile_width;
+ i->sub_data = (guchar*)(i->data) + bpp * (i->subrect.y * tile_width + i->subrect.x);
+ }
+
+ /* update with new future position (note this means that the
+ * coordinates read from the iterator do not make full sense
+ * */
+ i->col += tile_width - offsetx;
+
+ return TRUE;
+ }
+ }
+ else /* move down to next row */
+ {
+ gint tiledy = buffer_y + i->row;
+ gint offsety = gegl_tile_offset (tiledy, tile_height);
+
+ i->row += tile_height - offsety;
+ i->col=0;
+
+ if (i->row < i->roi.height)
+ {
+ goto gulp; /* return the first tile in the next row */
+ }
+
+ return FALSE;
+ }
+ return FALSE;
+}
+
+
+
#ifdef BABL
#undef BABL
#endif
@@ -310,6 +530,7 @@
}
+
static void inline
gegl_buffer_iterate (GeglBuffer *buffer,
guchar *buf,
@@ -579,14 +800,7 @@
#if ENABLE_MP
g_static_rec_mutex_lock (&mutex);
#endif
- if (gegl_buffer_is_shared(buffer))
- {
- while (gegl_buffer_try_lock (buffer)==FALSE)
- {
- g_print ("failed to aquire lock sleeping 100ms");
- g_usleep (100000);
- }
- }
+ gegl_buffer_lock (buffer);
if (format == NULL)
format = buffer->format;
@@ -613,8 +827,8 @@
if (gegl_buffer_is_shared(buffer))
{
gegl_buffer_flush (buffer);
- gegl_buffer_unlock (buffer);
}
+ gegl_buffer_unlock (buffer); /* XXX: should this happen before flush? */
#if ENABLE_MP
g_static_rec_mutex_unlock (&mutex);
#endif
@@ -1250,4 +1464,3 @@
new, gegl_buffer_get_extent (buffer));
return new;
}
-
Modified: trunk/gegl/buffer/gegl-buffer-private.h
==============================================================================
--- trunk/gegl/buffer/gegl-buffer-private.h (original)
+++ trunk/gegl/buffer/gegl-buffer-private.h Fri May 16 17:01:36 2008
@@ -96,7 +96,51 @@
gboolean gegl_buffer_is_shared (GeglBuffer *buffer);
gboolean gegl_buffer_try_lock (GeglBuffer *buffer);
+gboolean gegl_buffer_lock (GeglBuffer *buffer);
gboolean gegl_buffer_unlock (GeglBuffer *buffer);
+typedef struct GeglBufferTileIterator
+{
+ GeglBuffer *buffer;
+ GeglTile *tile;
+ GeglRectangle roi;
+ gint col;
+ gint row;
+ gboolean write; /* perhaps in a subclass struct? */
+ GeglRectangle subrect; /* has negative x when entire tile is valid */
+ gpointer data;
+ gpointer sub_data;
+ gint rowstride;
+} GeglBufferTileIterator;
+
+typedef struct GeglBufferScanIterator {
+ GeglBufferTileIterator tile_iterator;
+ gint max_size; /* in bytes */
+ gint width;
+ gint row;
+ gpointer data;
+} GeglBufferScanIterator;
+
+gboolean gegl_buffer_tile_iterator_next (GeglBufferTileIterator *i);
+gboolean gegl_buffer_scan_iterator_next (GeglBufferScanIterator *i);
+GeglBufferTileIterator *gegl_buffer_tile_iterator_new (GeglBuffer *buffer,
+ GeglRectangle roi,
+ gboolean write);
+void gegl_buffer_tile_iterator_init (GeglBufferTileIterator *i,
+ GeglBuffer *buffer,
+ GeglRectangle roi,
+ gboolean write);
+
+void gegl_buffer_scan_iterator_init (GeglBufferScanIterator *i,
+ GeglBuffer *buffer,
+ GeglRectangle roi,
+ gboolean write);
+GeglBufferScanIterator *gegl_buffer_scan_iterator_new (GeglBuffer *buffer,
+ GeglRectangle roi,
+ gboolean write);
+gboolean gegl_buffer_scan_compatible (GeglBuffer *input,
+ GeglBuffer *output);
+
+
#endif
Modified: trunk/gegl/buffer/gegl-tile.c
==============================================================================
--- trunk/gegl/buffer/gegl-tile.c (original)
+++ trunk/gegl/buffer/gegl-tile.c Fri May 16 17:01:36 2008
@@ -106,6 +106,8 @@
}
}
+#include "gegl-utils.h"
+
static void
dispose (GObject *object)
{
@@ -118,7 +120,7 @@
{
if (tile->next_shared == tile)
{ /* no clones */
- g_free (tile->data);
+ gegl_free (tile->data);
tile->data = NULL;
}
else
@@ -211,7 +213,7 @@
{
GeglTile *tile = g_object_new (GEGL_TYPE_TILE, NULL);
- tile->data = g_malloc (size);
+ tile->data = gegl_malloc (size);
tile->size = size;
tile->stored_rev = 1;
@@ -219,6 +221,15 @@
return tile;
}
+static gpointer
+gegl_memdup (gpointer src, gsize size)
+{
+ gpointer ret;
+ ret = gegl_malloc (size);
+ memcpy (ret, src, size);
+ return ret;
+}
+
static void
gegl_tile_unclone (GeglTile *tile)
{
@@ -227,7 +238,7 @@
/* the tile data is shared with other tiles,
* create a local copy
*/
- tile->data = g_memdup (tile->data, tile->size);
+ tile->data = gegl_memdup (tile->data, tile->size);
tile->prev_shared->next_shared = tile->next_shared;
tile->next_shared->prev_shared = tile->prev_shared;
tile->prev_shared = tile;
@@ -243,7 +254,8 @@
{
if (tile->lock != 0)
{
- g_warning ("locking a tile for the second time");
+ g_print ("hm\n");
+ g_warning ("strange tile lock count: %i", tile->lock);
}
total_locks++;
@@ -327,7 +339,7 @@
{
gegl_tile_lock (dst);
- g_free (dst->data);
+ gegl_free (dst->data);
dst->data = NULL;
dst->next_shared = src->next_shared;
Modified: trunk/gegl/operation/gegl-operation-point-filter.c
==============================================================================
--- trunk/gegl/operation/gegl-operation-point-filter.c (original)
+++ trunk/gegl/operation/gegl-operation-point-filter.c Fri May 16 17:01:36 2008
@@ -28,6 +28,9 @@
#include "gegl-utils.h"
#include <string.h>
+#include "gegl-buffer-private.h"
+#include "gegl-tile-storage.h"
+
static gboolean process_inner (GeglOperation *operation,
GeglBuffer *input,
GeglBuffer *output,
@@ -56,6 +59,7 @@
{
}
+
static gboolean
process_inner (GeglOperation *operation,
GeglBuffer *input,
@@ -65,6 +69,9 @@
GeglPad *pad;
const Babl *in_format;
const Babl *out_format;
+ GeglOperationPointFilterClass *point_filter_class;
+
+ point_filter_class = GEGL_OPERATION_POINT_FILTER_GET_CLASS (operation);
pad = gegl_node_get_pad (operation->node, "input");
in_format = gegl_pad_get_format (pad);
@@ -84,6 +91,103 @@
if ((result->width > 0) && (result->height > 0))
{
+ if (gegl_buffer_scan_compatible (input, output))
+ /* We can use the fastest possible path with the least possible
+ * copies using paralell scan iteratator with possibly direct
+ * read write access to buffers.
+ */
+ {
+ GTimer *timer = g_timer_new ();
+ gint input_bpp = in_format->format.bytes_per_pixel;
+ gint output_bpp = output->format->format.bytes_per_pixel;
+ gpointer *in_buf = NULL;
+ gpointer *out_buf = NULL;
+ Babl *infish;
+ Babl *outfish;
+
+ GeglBufferScanIterator read;
+ GeglBufferScanIterator write;
+ gegl_buffer_scan_iterator_init (&read, input, *result, FALSE);
+ gegl_buffer_scan_iterator_init (&write, output, *result, TRUE);
+
+ g_assert (input->tile_storage->tile_width == output->tile_storage->tile_width);
+
+ in_buf = gegl_malloc (input_bpp * input->tile_storage->tile_width *
+ input->tile_storage->tile_height);
+ out_buf = gegl_malloc (output_bpp * output->tile_storage->tile_width *
+ output->tile_storage->tile_height);
+
+ infish = babl_fish (input->format, in_format);
+ outfish = babl_fish (out_format, output->format);
+
+ gegl_buffer_lock (output);
+ {
+ gboolean a = FALSE, b = FALSE;
+ if (in_format == input->format &&
+ out_format == output->format)
+ {
+ while ( (a = gegl_buffer_scan_iterator_next (&read)) &&
+ (b = gegl_buffer_scan_iterator_next (&write)))
+ {
+ g_assert (read.width == write.width);
+ point_filter_class->process (operation, read.data, write.data, write.width);
+ }
+ }
+ else if (in_format == input->format &&
+ out_format != output->format)
+ {
+ while ( (a = gegl_buffer_scan_iterator_next (&read)) &&
+ (b = gegl_buffer_scan_iterator_next (&write)))
+ {
+ g_assert (read.width == write.width);
+ point_filter_class->process (operation, read.data, out_buf, read.width);
+ babl_process (outfish, out_buf, write.data, write.width);
+ }
+ }
+ else if (in_format != input->format &&
+ out_format == output->format)
+ {
+ while ( (a = gegl_buffer_scan_iterator_next (&read)) &&
+ (b = gegl_buffer_scan_iterator_next (&write)))
+ {
+ if (read.width < 0)
+ continue;
+ g_assert (read.width == write.width);
+ babl_process (infish, read.data, in_buf, read.width);
+ point_filter_class->process (operation, in_buf, write.data, read.width);
+ }
+ }
+ else if (in_format != input->format &&
+ out_format != output->format)
+ {
+ while ( (a = gegl_buffer_scan_iterator_next (&read)) &&
+ (b = gegl_buffer_scan_iterator_next (&write)))
+ {
+ g_assert (read.width == write.width);
+ babl_process (infish, read.data, in_buf, read.width);
+ point_filter_class->process (operation, in_buf, out_buf, read.width);
+ babl_process (outfish, out_buf, write.data, write.width);
+ }
+ }
+
+ if (a)
+ while (gegl_buffer_scan_iterator_next (&read));
+ if (b)
+ while (gegl_buffer_scan_iterator_next (&write));
+ }
+
+ gegl_free (in_buf);
+ gegl_free (out_buf);
+ gegl_buffer_unlock (output);
+
+ g_printerr ("%s: %d x %d %g Mpixels/sec\n",
+ G_STRFUNC,
+ output->extent.width,
+ output->extent.height,
+ ( output->extent.width* output->extent.height) /
+ (1000000 * g_timer_elapsed (timer, NULL)));
+ g_timer_destroy (timer);
+ }
/* eek: this fails,..
if (!(input->width == output->width &&
input->height == output->height))
@@ -93,23 +197,8 @@
g_assert (input->width == output->width &&
input->height == output->height);
*/
- if (in_format == out_format)
- {
- gfloat *buf;
- buf = gegl_malloc (in_format->format.bytes_per_pixel *
- output->extent.width * output->extent.height);
-
- gegl_buffer_get (input, 1.0, result, in_format, buf, GEGL_AUTO_ROWSTRIDE);
-
- GEGL_OPERATION_POINT_FILTER_GET_CLASS (operation)->process (
- operation,
- buf,
- buf,
- output->extent.width * output->extent.height);
- gegl_buffer_set (output, result, out_format, buf, GEGL_AUTO_ROWSTRIDE);
- gegl_free (buf);
- }
+#if 0
else
{
gfloat *in_buf;
@@ -130,7 +219,41 @@
gegl_buffer_set (output, result, out_format, out_buf, GEGL_AUTO_ROWSTRIDE);
gegl_free (in_buf);
gegl_free (out_buf);
+#else
+ else
+ {
+ gfloat *in_buf;
+ GeglRectangle roi;
+ gint skip = 32;
+ gfloat *out_buf;
+ in_buf = gegl_malloc (in_format->format.bytes_per_pixel * result->width * skip);
+ out_buf = gegl_malloc (out_format->format.bytes_per_pixel * result->width * skip);
+
+
+ roi = *result;
+ while (roi.y < result->y + result->height && skip >0 )
+ {
+ for (roi.height=skip; (roi.y + skip <= result->y + result->height);
+ roi.y+=skip)
+ {
+ gegl_buffer_get (input, 1.0, &roi, in_format, in_buf, GEGL_AUTO_ROWSTRIDE);
+
+ GEGL_OPERATION_POINT_FILTER_GET_CLASS (operation)->process (
+ operation,
+ in_buf,
+ out_buf,
+ result->width * skip);
+
+ gegl_buffer_set (output, &roi, out_format, out_buf, GEGL_AUTO_ROWSTRIDE);
+ }
+ skip /= 2;
+ }
+
+
+ gegl_free (in_buf);
+ gegl_free (out_buf);
}
+#endif
}
return TRUE;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]