[gegl/abyss] abyss: initial abyss policy in gegl_buffer_iterate
- From: Ville Sokk <villesokk src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl/abyss] abyss: initial abyss policy in gegl_buffer_iterate
- Date: Wed, 20 Jun 2012 18:39:14 +0000 (UTC)
commit 8feace47dbb85ecc51387d8a5bf9e8d84a41ead0
Author: Ville Sokk <ville sokk gmail com>
Date: Wed Jun 20 21:34:06 2012 +0300
abyss: initial abyss policy in gegl_buffer_iterate
gegl/buffer/gegl-buffer-access.c | 410 ++++++++++++++++++++++++++------------
1 files changed, 282 insertions(+), 128 deletions(-)
---
diff --git a/gegl/buffer/gegl-buffer-access.c b/gegl/buffer/gegl-buffer-access.c
index 3338ccb..6f9ad55 100644
--- a/gegl/buffer/gegl-buffer-access.c
+++ b/gegl/buffer/gegl-buffer-access.c
@@ -331,16 +331,13 @@ gegl_buffer_flush (GeglBuffer *buffer)
GEGL_TILE_FLUSH, 0,0,0,NULL);
}
-
-
static inline void
-gegl_buffer_iterate (GeglBuffer *buffer,
- const GeglRectangle *roi, /* or NULL for extent */
- guchar *buf,
- gint rowstride,
- gboolean write,
- const Babl *format,
- gint level)
+gegl_buffer_iterate_write (GeglBuffer *buffer,
+ const GeglRectangle *roi, /* or NULL for extent */
+ guchar *buf,
+ gint rowstride,
+ const Babl *format,
+ gint level)
{
gint tile_width = buffer->tile_storage->tile_width;
gint tile_height = buffer->tile_storage->tile_height;
@@ -388,50 +385,194 @@ gegl_buffer_iterate (GeglBuffer *buffer,
buf_stride = rowstride;
if (format == buffer->soft_format)
- {
fish = NULL;
- }
else
- {
- if (write)
- {
- fish = babl_fish ((gpointer) format,
- (gpointer) buffer->soft_format);
- }
- else
- {
- fish = babl_fish ((gpointer) buffer->soft_format,
- (gpointer) format);
- }
- }
+ fish = babl_fish ((gpointer) format,
+ (gpointer) buffer->soft_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)
+ while (bufx < width)
+ {
+ gint tiledx = buffer_x + bufx;
+ gint offsetx = gegl_tile_offset (tiledx, tile_width);
+ gint y = bufy;
+ gint lskip, rskip, pixels, row;
+ guchar *bp, *tile_base, *tp;
+ GeglTile *tile;
+
+ bp = buf + bufy * buf_stride + bufx * bpx_size;
+
+ if (width + offsetx - bufx < tile_width)
+ pixels = (width + offsetx - bufx) - offsetx;
+ else
+ pixels = tile_width - offsetx;
+
+ tile = gegl_tile_source_get_tile ((GeglTileSource *) (buffer),
+ gegl_tile_indice (tiledx, tile_width),
+ gegl_tile_indice (tiledy, tile_height),
+ level);
+
+ lskip = (buffer_abyss_x) - (buffer_x + bufx);
+ /* gap between left side of tile, and abyss */
+ 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)
{
- gint row;
- gint y = bufy;
- guchar *bp = buf + ((bufy) * width) * bpx_size;
+ g_warning ("didn't get tile, trying to continue");
+ bufx += (tile_width - offsetx);
+ continue;
+ }
+ gegl_tile_lock (tile);
+
+ tile_base = gegl_tile_get_data (tile);
+ tp = ((guchar *) tile_base) + (offsety * tile_width + offsetx) * px_size;
+
+ 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++)
{
- memset (bp, 0x00, buf_stride);
+
+ 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);
+ gegl_tile_unref (tile);
+ bufx += (tile_width - offsetx);
}
- else
+ bufy += (tile_height - offsety);
+ }
+}
+
+static inline void
+gegl_buffer_iterate_read (GeglBuffer *buffer,
+ const GeglRectangle *roi, /* or NULL for extent */
+ guchar *buf,
+ gint rowstride,
+ const Babl *format,
+ gint level,
+ GeglAbyssPolicy repeat_mode)
+{
+ gint tile_width = buffer->tile_storage->tile_width;
+ gint tile_height = buffer->tile_storage->tile_height;
+ gint px_size = babl_format_get_bytes_per_pixel (buffer->soft_format);
+ gint bpx_size = babl_format_get_bytes_per_pixel (format);
+ gint tile_stride = px_size * tile_width;
+ gint buf_stride;
+ gint bufy = 0;
+
+ gint buffer_shift_x = buffer->shift_x;
+ gint buffer_shift_y = buffer->shift_y;
+
+ gint width = buffer->extent.width;
+ gint height = buffer->extent.height;
+ 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 factor = 1<<level;
+ const Babl *fish;
+
+ /* roi specified, override buffers extent */
+ if (roi)
+ {
+ width = roi->width;
+ height = roi->height;
+ buffer_x = roi->x + buffer_shift_x;
+ buffer_y = roi->y + buffer_shift_y;
+ }
+ 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->soft_format)
+ fish = NULL;
+ else
+ fish = babl_fish ((gpointer) buffer->soft_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 */
+ 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;
@@ -446,35 +587,32 @@ gegl_buffer_iterate (GeglBuffer *buffer,
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;
+ gint row;
+ gint y = bufy;
- for (row = offsety;
- row < tile_height && y < height;
- row++, y++)
- {
- memset (bp, 0x00, pixels * bpx_size);
- bp += buf_stride;
- }
+ for (row = offsety;
+ row < tile_height && y < height;
+ row++, y++)
+ {
+ memset (bp, 0x00, pixels * bpx_size);
+ bp += buf_stride;
}
}
else
{
guchar *tile_base, *tp;
+ gint row, y, lskip, rskip;
GeglTile *tile = gegl_tile_source_get_tile ((GeglTileSource *) (buffer),
- gegl_tile_indice (tiledx, tile_width),
- gegl_tile_indice (tiledy, tile_height),
- level);
+ gegl_tile_indice (tiledx, tile_width),
+ gegl_tile_indice (tiledy, tile_height),
+ level);
- gint lskip = (buffer_abyss_x) - (buffer_x + bufx);
+ lskip = (buffer_abyss_x) - (buffer_x + bufx);
/* gap between left side of tile, and abyss */
- gint rskip = (buffer_x + bufx + pixels) - abyss_x_total;
+ rskip = (buffer_x + bufx + pixels) - abyss_x_total;
/* gap between right side of tile, and abyss */
if (lskip < 0)
@@ -493,97 +631,112 @@ gegl_buffer_iterate (GeglBuffer *buffer,
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)
+ y = bufy;
+ for (row = offsety;
+ row < tile_height && y < height;
+ row++, y++)
{
- gint row;
- gint y = bufy;
-
-
- if (fish)
+ if (buffer_y + y >= buffer_abyss_y &&
+ buffer_y + y < abyss_y_total)
{
- 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;
- }
+ if (fish)
+ babl_process (fish, tp, bp, pixels);
+ else
+ memcpy (bp, tp, pixels * px_size);
}
else
{
- for (row = offsety;
- row < tile_height && y < height;
- row++, y++)
- {
-
- if (buffer_y + y >= buffer_abyss_y &&
- buffer_y + y < abyss_y_total)
- {
+ /* entire row in abyss */
- 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
+ if (repeat_mode == GEGL_ABYSS_NONE)
{
- /* entire row in abyss */
memset (bp, 0x00, pixels * bpx_size);
}
-
- /* left hand zeroing of abyss in tile */
- if (lskip)
+ else if (repeat_mode == GEGL_ABYSS_WHITE ||
+ repeat_mode == GEGL_ABYSS_BLACK)
{
- memset (bp, 0x00, bpx_size * lskip);
+ gfloat color_a[4] = {0.0, 0.0, 0.0, 1.0};
+ guchar color[128];
+ gint i;
+
+ if (repeat_mode == GEGL_ABYSS_WHITE)
+ for (i = 0; i < 3; i++)
+ color_a[i] = 1.0;
+ babl_process (babl_fish (babl_format ("RGBA float"), format),
+ color_a, color, 1);
+
+ for (i = 0; i < pixels * bpx_size; i += bpx_size)
+ memcpy (bp + i, color, bpx_size);
}
-
- /* right side zeroing of abyss in tile */
- if (rskip)
+ else
{
- memset (bp + (pixels - rskip) * bpx_size, 0x00, bpx_size * rskip);
+ gint i, atiledx, atiledy, aoffsetx, aoffsety;
+ GeglTile *abysstile;
+ guchar *data;
+
+ if (repeat_mode == GEGL_ABYSS_LOOP)
+ {
+ atiledx = buffer_abyss_x + (buffer_x + bufx - buffer_abyss_x) % buffer->abyss.width;
+ atiledy = buffer_abyss_y + (buffer_y + y - buffer_abyss_y) % buffer->abyss.height;
+ }
+ else
+ {
+ atiledx = CLAMP (buffer_x + bufx, buffer_abyss_x, abyss_x_total - 1);
+ atiledy = CLAMP (buffer_y + y, buffer_abyss_y, abyss_y_total - 1);
+ }
+ aoffsetx = gegl_tile_offset (atiledx, tile_width);
+ aoffsety = gegl_tile_offset (atiledy, tile_height);
+ abysstile = gegl_tile_source_get_tile ((GeglTileSource *) (buffer),
+ gegl_tile_indice (atiledx, tile_width),
+ gegl_tile_indice (atiledy, tile_height),
+ level);
+ data = gegl_tile_get_data (abysstile) + (aoffsety * tile_width + aoffsetx) * px_size;
+ if (repeat_mode == GEGL_ABYSS_LOOP)
+ {
+ if (fish)
+ babl_process (fish, data, bp, pixels);
+ else
+ memcpy (bp, data, pixels * bpx_size);
+ }
+ else
+ {
+ /* if x was clamped, copy a single pixel repeatedly */
+ if (atiledx != buffer_x + bufx)
+ {
+ guchar color[128];
+
+ if (fish)
+ babl_process (fish, data, color, 1);
+ else
+ memcpy (color, data, px_size);
+ for (i = 0; i < pixels * bpx_size; i += bpx_size)
+ memcpy (bp + i, color, bpx_size);
+ }
+ else
+ {
+ if (fish)
+ babl_process (fish, data, bp, pixels);
+ else
+ memcpy (bp, data, pixels * bpx_size);
+ }
+ }
+ gegl_tile_unref (abysstile);
}
- tp += tile_stride;
- bp += buf_stride;
}
+
+ /* 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;
}
gegl_tile_unref (tile);
}
@@ -627,7 +780,7 @@ gegl_buffer_set_unlocked_no_notify (GeglBuffer *buffer,
}
else
#endif
- gegl_buffer_iterate (buffer, rect, (void *) src, rowstride, TRUE, format, 0);
+ gegl_buffer_iterate_write (buffer, rect, (void *) src, rowstride, format, 0);
if (gegl_buffer_is_shared(buffer))
{
@@ -997,7 +1150,7 @@ gegl_buffer_get_unlocked (GeglBuffer *buffer,
if (!rect && scale == 1.0)
{
- gegl_buffer_iterate (buffer, NULL, dest_buf, rowstride, FALSE, format, 0);
+ gegl_buffer_iterate_read (buffer, NULL, dest_buf, rowstride, format, 0, repeat_mode);
return;
}
@@ -1009,7 +1162,7 @@ gegl_buffer_get_unlocked (GeglBuffer *buffer,
}
if (GEGL_FLOAT_EQUAL (scale, 1.0))
{
- gegl_buffer_iterate (buffer, rect, dest_buf, rowstride, FALSE, format, 0);
+ gegl_buffer_iterate_read (buffer, rect, dest_buf, rowstride, format, 0, repeat_mode);
return;
}
else
@@ -1049,7 +1202,8 @@ gegl_buffer_get_unlocked (GeglBuffer *buffer,
offset_y = rect->y-floor(rect->y/scale) * scale;
sample_buf = g_malloc (buf_width * buf_height * bpp);
- gegl_buffer_iterate (buffer, &sample_rect, sample_buf, GEGL_AUTO_ROWSTRIDE, FALSE, format, level);
+ gegl_buffer_iterate_read (buffer, &sample_rect, sample_buf, GEGL_AUTO_ROWSTRIDE,
+ format, level, repeat_mode);
#if 1
/* slows testing of rendering code speed too much for now and
* no time to make a fast implementation
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]