[gegl] buffer: do COW for tiles during gegl_buffer_dup
- From: Ãyvind KolÃs <ok src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] buffer: do COW for tiles during gegl_buffer_dup
- Date: Thu, 22 Mar 2012 21:17:19 +0000 (UTC)
commit 72e784cbc8fd474123f85786b6d4895957a773d0
Author: Ãyvind KolÃs <pippin gimp org>
Date: Thu Mar 22 21:17:00 2012 +0000
buffer: do COW for tiles during gegl_buffer_dup
gegl/buffer/gegl-buffer-access.c | 85 ++++++++++++++++++++++++++++++------
gegl/buffer/gegl-buffer-iterator.c | 18 +++----
gegl/buffer/gegl-buffer-private.h | 6 +++
3 files changed, 86 insertions(+), 23 deletions(-)
---
diff --git a/gegl/buffer/gegl-buffer-access.c b/gegl/buffer/gegl-buffer-access.c
index fd5aae6..1f7b379 100644
--- a/gegl/buffer/gegl-buffer-access.c
+++ b/gegl/buffer/gegl-buffer-access.c
@@ -1139,6 +1139,36 @@ gegl_buffer_sample_cleanup (GeglBuffer *buffer)
}
}
+static void
+gegl_buffer_copy2 (GeglBuffer *src,
+ const GeglRectangle *src_rect,
+ GeglBuffer *dst,
+ const GeglRectangle *dst_rect)
+{
+ const Babl *fish;
+
+ g_return_if_fail (GEGL_IS_BUFFER (src));
+ g_return_if_fail (GEGL_IS_BUFFER (dst));
+ g_return_if_fail (src_rect);
+ g_return_if_fail (dst_rect);
+
+ fish = babl_fish (src->format, dst->format);
+
+ {
+ GeglRectangle dest_rect_r = *dst_rect;
+ GeglBufferIterator *i;
+ gint read;
+
+ dest_rect_r.width = src_rect->width;
+ dest_rect_r.height = src_rect->height;
+
+ i = gegl_buffer_iterator_new (dst, &dest_rect_r, dst->format, GEGL_BUFFER_WRITE);
+ read = gegl_buffer_iterator_add (i, src, src_rect, src->format, GEGL_BUFFER_READ);
+ while (gegl_buffer_iterator_next (i))
+ babl_process (fish, i->data[read], i->data[0], i->length);
+ }
+}
+
void
gegl_buffer_copy (GeglBuffer *src,
const GeglRectangle *src_rect,
@@ -1160,21 +1190,50 @@ gegl_buffer_copy (GeglBuffer *src,
dst_rect = src_rect;
}
- fish = babl_fish (src->format, dst->format);
-
+ /* for now, only doing the zero copy when we effectively are doing a buffer
+ * dup.
+ */
+ if (src->format == dst->format &&
+ _gegl_buffer_scan_compatible (src,
+ src_rect->x,
+ src_rect->y,
+ dst,
+ dst_rect->x,
+ dst_rect->y) &&
+ !memcmp (src_rect, dst_rect, sizeof (GeglRectangle)) &&
+ src_rect->x == 0 &&
+ src_rect->y == 0)
{
- GeglRectangle dest_rect_r = *dst_rect;
- GeglBufferIterator *i;
- gint read;
-
- dest_rect_r.width = src_rect->width;
- dest_rect_r.height = src_rect->height;
-
- i = gegl_buffer_iterator_new (dst, &dest_rect_r, dst->format, GEGL_BUFFER_WRITE);
- read = gegl_buffer_iterator_add (i, src, src_rect, src->format, GEGL_BUFFER_READ);
- while (gegl_buffer_iterator_next (i))
- babl_process (fish, i->data[read], i->data[0], i->length);
+ int i;
+ int x, y;
+ int tile_width = dst->tile_storage->tile_width;
+ int tile_height = dst->tile_storage->tile_height;
+ /* determine inner region that can definetly be shared */
+
+ /* share this inner region */
+ for (y = dst_rect->y; y < dst_rect->y + dst_rect->height; y += tile_height)
+ for (x = dst_rect->x; x < dst_rect->x + dst_rect->width; x += tile_width)
+ {
+ GeglTile *src_tile;
+ GeglTile *dst_tile;
+ int res;
+ src_tile = gegl_tile_source_get_tile ((GeglTileSource *)(src),
+ gegl_tile_indice (x, tile_width),
+ gegl_tile_indice (y, tile_height),
+ 0);
+ dst_tile = gegl_tile_dup (src_tile);
+ res = gegl_tile_source_set_tile ((GeglTileSource*)(dst),
+ gegl_tile_indice (x, tile_width),
+ gegl_tile_indice (y, tile_height),
+ 0,
+ dst_tile);
+ if (res) res = 0;
+ gegl_tile_unref (src_tile);
+ }
+ /* copy up to four regions around : NYI */
+ return;
}
+ gegl_buffer_copy2 (src, src_rect, dst, dst_rect);
}
void
diff --git a/gegl/buffer/gegl-buffer-iterator.c b/gegl/buffer/gegl-buffer-iterator.c
index 523b918..ec009f8 100644
--- a/gegl/buffer/gegl-buffer-iterator.c
+++ b/gegl/buffer/gegl-buffer-iterator.c
@@ -93,12 +93,12 @@ static gboolean gegl_buffer_tile_iterator_next (GeglBufferTileIterator *i);
* check whether iterations on two buffers starting from the given coordinates with
* the same width and height would be able to run parallell.
*/
-static gboolean gegl_buffer_scan_compatible (GeglBuffer *bufferA,
- gint xA,
- gint yA,
- GeglBuffer *bufferB,
- gint xB,
- gint yB)
+gboolean _gegl_buffer_scan_compatible (GeglBuffer *bufferA,
+ gint xA,
+ gint yA,
+ GeglBuffer *bufferB,
+ gint xB,
+ gint yB)
{
if (bufferA->tile_storage->tile_width !=
bufferB->tile_storage->tile_width)
@@ -244,8 +244,6 @@ static glong in_direct_read = 0;
static glong in_direct_write = 0;
#endif
-
-
gint
gegl_buffer_iterator_add (GeglBufferIterator *iterator,
GeglBuffer *buffer,
@@ -290,8 +288,8 @@ gegl_buffer_iterator_add (GeglBufferIterator *iterator,
i->rect[self].width = i->rect[0].width;
i->rect[self].height = i->rect[0].height;
- if (gegl_buffer_scan_compatible (i->buffer[0], i->rect[0].x, i->rect[0].y,
- i->buffer[self], i->rect[self].x, i->rect[self].y))
+ if (_gegl_buffer_scan_compatible (i->buffer[0], i->rect[0].x, i->rect[0].y,
+ i->buffer[self], i->rect[self].x, i->rect[self].y))
{
i->flags[self] |= GEGL_BUFFER_SCAN_COMPATIBLE;
gegl_buffer_tile_iterator_init (&i->i[self], i->buffer[self], i->rect[self], ((i->flags[self] & GEGL_BUFFER_WRITE) != 0));
diff --git a/gegl/buffer/gegl-buffer-private.h b/gegl/buffer/gegl-buffer-private.h
index 9cf188f..0780c13 100644
--- a/gegl/buffer/gegl-buffer-private.h
+++ b/gegl/buffer/gegl-buffer-private.h
@@ -174,6 +174,12 @@ struct _GeglTile
gpointer unlock_notify_data;
};
+gboolean _gegl_buffer_scan_compatible (GeglBuffer *bufferA,
+ gint xA,
+ gint yA,
+ GeglBuffer *bufferB,
+ gint xB,
+ gint yB);
#ifndef __GEGL_TILE_C
#define gegl_tile_get_data(tile) ((guchar*)((tile)->data))
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]