[gegl] Unify buffer reads
- From: Daniel Sabo <daniels src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] Unify buffer reads
- Date: Tue, 19 Nov 2013 17:52:15 +0000 (UTC)
commit 1797af8d1d9a04c611634f39a62bc68ff53f4426
Author: Daniel Sabo <DanielSabo gmail com>
Date: Sun Oct 27 17:09:35 2013 -0700
Unify buffer reads
Define all of the iterate_read operations in terms of
iterate_read_simple. This cuts down on a lot of
duplicate logic and is also moderately faster when
the abyss area is small.
gegl/buffer/gegl-buffer-access.c | 816 ++++++++++++++------------------------
1 files changed, 297 insertions(+), 519 deletions(-)
---
diff --git a/gegl/buffer/gegl-buffer-access.c b/gegl/buffer/gegl-buffer-access.c
index e84eec1..0882f06 100644
--- a/gegl/buffer/gegl-buffer-access.c
+++ b/gegl/buffer/gegl-buffer-access.c
@@ -14,6 +14,7 @@
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2006-2008 Øyvind Kolås <pippin gimp org>
+ * 2013 Daniel Sabo
*/
#include "config.h"
@@ -498,7 +499,7 @@ gegl_buffer_iterate_write (GeglBuffer *buffer,
}
}
-static inline void
+static void
gegl_buffer_iterate_read_simple (GeglBuffer *buffer,
const GeglRectangle *roi,
guchar *buf,
@@ -583,164 +584,43 @@ gegl_buffer_iterate_read_simple (GeglBuffer *buffer,
}
}
-static inline void
-gegl_buffer_iterate_read_abyss_none (GeglBuffer *buffer,
- const GeglRectangle *roi,
- const GeglRectangle *abyss,
- guchar *buf,
- gint buf_stride,
- const Babl *format,
- gint level)
+static void
+fill_abyss_none (guchar *buf, gint width, gint height, gint buf_stride, gint pixel_size)
{
- 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 bufy = 0;
+ const int byte_width = width * pixel_size;
- gint width = roi->width;
- gint height = roi->height;
- gint buffer_x = roi->x;
- gint buffer_y = roi->y;
-
- gint buffer_abyss_x = abyss->x;
- gint buffer_abyss_y = abyss->y;
- gint abyss_x_total = buffer_abyss_x + abyss->width;
- gint abyss_y_total = buffer_abyss_y + abyss->height;
-
- const Babl *fish;
-
- if (format == buffer->soft_format)
- fish = NULL;
+ if (buf_stride == byte_width)
+ {
+ memset (buf, 0, byte_width * height);
+ }
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 * buf_stride;
-
- for (row = offsety;
- row < tile_height && y < height;
- row++, y++)
- {
- memset (bp, 0x00, width * bpx_size);
- bp += buf_stride;
- }
+ while (height--)
+ {
+ memset (buf, 0, byte_width);
+ buf += buf_stride;
}
- else
+ }
+}
- while (bufx < width)
- {
- gint tiledx = buffer_x + bufx;
- gint offsetx = gegl_tile_offset (tiledx, tile_width);
- gint pixels;
- guchar *bp;
-
- bp = buf + bufy * buf_stride + bufx * bpx_size;
-
- if (width + offsetx - bufx < tile_width)
- pixels = width - bufx;
- 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 */
- gint row;
- gint y = bufy;
-
- 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);
-
- 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)
- {
- g_warning ("didn't get tile, trying to continue");
- bufx += (tile_width - offsetx);
- continue;
- }
-
- tile_base = gegl_tile_get_data (tile);
- tp = ((guchar *) tile_base) + (offsety * tile_width + offsetx) * px_size;
-
- 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
- {
- /* entire row in abyss */
- memset (bp, 0x00, pixels * bpx_size);
- }
-
- /* 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);
- }
- bufx += (tile_width - offsetx);
- }
- bufy += (tile_height - offsety);
+static void
+fill_abyss_color (guchar *buf, gint width, gint height, gint buf_stride, guchar *pixel, gint pixel_size)
+{
+ if (buf_stride == width)
+ {
+ gegl_memset_pattern (buf, pixel, pixel_size, width * height);
+ }
+ else
+ {
+ while (height--)
+ {
+ gegl_memset_pattern (buf, pixel, pixel_size, width);
+ buf += buf_stride;
+ }
}
}
-static inline void
+static void
gegl_buffer_iterate_read_abyss_color (GeglBuffer *buffer,
const GeglRectangle *roi,
const GeglRectangle *abyss,
@@ -750,158 +630,97 @@ gegl_buffer_iterate_read_abyss_color (GeglBuffer *buffer,
gint level,
guchar *color)
{
- 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 bufy = 0;
+ GeglRectangle current_roi = *roi;
+ gint bpp = babl_format_get_bytes_per_pixel (format);
- gint width = roi->width;
- gint height = roi->height;
- gint buffer_x = roi->x;
- gint buffer_y = roi->y;
+ if (current_roi.y < abyss->y)
+ {
+ /* Abyss above image */
+ gint height = abyss->y - current_roi.y;
+ if (current_roi.height < height)
+ height = current_roi.height;
+ if (color)
+ fill_abyss_color (buf, current_roi.width, height, buf_stride, color, bpp);
+ else
+ fill_abyss_none (buf, current_roi.width, height, buf_stride, bpp);
+ buf += buf_stride * height;
+ current_roi.y += height;
+ current_roi.height -= height;
+ }
- gint buffer_abyss_x = abyss->x;
- gint buffer_abyss_y = abyss->y;
- gint abyss_x_total = buffer_abyss_x + abyss->width;
- gint abyss_y_total = buffer_abyss_y + abyss->height;
+ if (current_roi.height && (current_roi.y < abyss->y + abyss->height))
+ {
+ GeglRectangle inner_roi = current_roi;
+ guchar *inner_buf = buf;
- const Babl *fish;
+ if (inner_roi.height + inner_roi.y > abyss->height + abyss->y)
+ {
+ /* Clamp inner_roi to the in abyss height */
+ inner_roi.height -= (inner_roi.height + inner_roi.y) - (abyss->height + abyss->y);
+ }
- if (format == buffer->soft_format)
- fish = NULL;
- else
- fish = babl_fish ((gpointer) buffer->soft_format,
- (gpointer) format);
+ if (inner_roi.x < abyss->x)
+ {
+ /* Abyss left of image */
+ gint width = abyss->x - inner_roi.x;
+ if (width > inner_roi.width)
+ width = inner_roi.width;
- while (bufy < height)
- {
- gint tiledy = buffer_y + bufy;
- gint offsety = gegl_tile_offset (tiledy, tile_height);
- gint bufx = 0;
+ if (color)
+ fill_abyss_color (inner_buf, width, inner_roi.height, buf_stride, color, bpp);
+ else
+ fill_abyss_none (inner_buf, width, inner_roi.height, buf_stride, bpp);
+ inner_buf += width * bpp;
+ inner_roi.x += width;
+ inner_roi.width -= width;
+ }
- 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 * buf_stride;
+ if (inner_roi.width && (inner_roi.x < abyss->x + abyss->width))
+ {
+ gint full_width = inner_roi.width;
- for (row = offsety;
- row < tile_height && y < height;
- row++, y++)
+ if (inner_roi.width + inner_roi.x > abyss->width + abyss->x)
{
- gegl_memset_pattern (bp, color, bpx_size, width);
- bp += buf_stride;
+ /* Clamp inner_roi to the in abyss width */
+ inner_roi.width -= (inner_roi.width + inner_roi.x) - (abyss->width + abyss->x);
}
+
+ gegl_buffer_iterate_read_simple (buffer,
+ &inner_roi,
+ inner_buf,
+ buf_stride,
+ format,
+ level);
+
+ inner_buf += inner_roi.width * bpp;
+ inner_roi.width = full_width - inner_roi.width;
+ }
+
+ if (inner_roi.width)
+ {
+ /* Abyss right of image */
+ if (color)
+ fill_abyss_color (inner_buf, inner_roi.width, inner_roi.height, buf_stride, color, bpp);
+ else
+ fill_abyss_none (inner_buf, inner_roi.width, inner_roi.height, buf_stride, bpp);
}
+
+ buf += inner_roi.height * buf_stride;
+ current_roi.x += inner_roi.height;
+ current_roi.height -= inner_roi.height;
+ }
+
+ if (current_roi.height)
+ {
+ /* Abyss below image */
+ if (color)
+ fill_abyss_color (buf, current_roi.width, current_roi.height, buf_stride, color, bpp);
else
- while (bufx < width)
- {
- gint tiledx = buffer_x + bufx;
- gint offsetx = gegl_tile_offset (tiledx, tile_width);
- gint pixels;
- guchar *bp;
-
- bp = buf + bufy * buf_stride + bufx * bpx_size;
-
- if (width + offsetx - bufx < tile_width)
- pixels = width - bufx;
- 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 */
- gint row;
- gint y = bufy;
-
- for (row = offsety;
- row < tile_height && y < height;
- row++, y++)
- {
- gegl_memset_pattern (bp, color, bpx_size, pixels);
- 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);
-
- 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)
- {
- g_warning ("didn't get tile, trying to continue");
- bufx += (tile_width - offsetx);
- continue;
- }
-
- tile_base = gegl_tile_get_data (tile);
- tp = ((guchar *) tile_base) + (offsety * tile_width + offsetx) * px_size;
-
- 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
- {
- /* entire row in abyss */
- gegl_memset_pattern (bp, color, bpx_size, pixels);
- }
-
- /* left hand zeroing of abyss in tile */
- if (lskip)
- {
- gegl_memset_pattern (bp, color, bpx_size, lskip);
- }
-
- /* right side zeroing of abyss in tile */
- if (rskip)
- {
- guchar *bp_right = bp + (pixels - rskip) * bpx_size;
- gegl_memset_pattern (bp_right, color, bpx_size, rskip);
- }
-
- tp += tile_stride;
- bp += buf_stride;
- }
- gegl_tile_unref (tile);
- }
- bufx += (tile_width - offsetx);
- }
- bufy += (tile_height - offsety);
+ fill_abyss_none (buf, current_roi.width, current_roi.height, buf_stride, bpp);
}
}
-static inline void
+static void
gegl_buffer_iterate_read_abyss_clamp (GeglBuffer *buffer,
const GeglRectangle *roi,
const GeglRectangle *abyss,
@@ -910,149 +729,161 @@ gegl_buffer_iterate_read_abyss_clamp (GeglBuffer *buffer,
const Babl *format,
gint level)
{
- 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 bufy = 0;
-
- gint width = roi->width;
- gint height = roi->height;
- gint buffer_x = roi->x;
- gint buffer_y = roi->y;
-
- gint buffer_abyss_x = abyss->x;
- gint buffer_abyss_y = abyss->y;
- gint abyss_x_total = buffer_abyss_x + abyss->width;
- gint abyss_y_total = buffer_abyss_y + abyss->height;
-
- const Babl *fish;
+ GeglRectangle read_output_rect;
+ GeglRectangle read_input_rect;
+
+ gint bpp = babl_format_get_bytes_per_pixel (format);
+ gint x_read_offset = 0;
+ gint y_read_offset = 0;
+ gint buf_offset_cols;
+ gint buf_offset_rows;
+ gint top_rows, left_cols, right_cols, bottom_rows;
+ guchar *read_buf;
+
+ if (roi->x >= abyss->x + abyss->width) /* Right of */
+ x_read_offset = roi->x - (abyss->x + abyss->width) + 1;
+ else if (roi->x + roi->width <= abyss->x) /* Left of */
+ x_read_offset = (roi->x + roi->width) - abyss->x - 1;
+
+ if (roi->y >= abyss->y + abyss->height) /* Above */
+ y_read_offset = roi->y - (abyss->y + abyss->height) + 1;
+ else if (roi->y + roi->height <= abyss->y) /* Below of */
+ y_read_offset = (roi->y + roi->height) - abyss->y - 1;
+
+ /* Intersect our shifted abyss with the roi */
+ gegl_rectangle_intersect (&read_output_rect,
+ roi,
+ GEGL_RECTANGLE (abyss->x + x_read_offset,
+ abyss->y + y_read_offset,
+ abyss->width,
+ abyss->height));
+
+ /* Offset into *buf based on the intersected rect's x & y */
+ buf_offset_cols = read_output_rect.x - roi->x;
+ buf_offset_rows = read_output_rect.y - roi->y;
+ read_buf = buf + (buf_offset_cols * bpp + buf_offset_rows * buf_stride);
+
+ /* Convert the read output to a coresponding input */
+ read_input_rect.x = read_output_rect.x - x_read_offset;
+ read_input_rect.y = read_output_rect.y - y_read_offset;
+ read_input_rect.width = read_output_rect.width;
+ read_input_rect.height = read_output_rect.height;
+
+ gegl_buffer_iterate_read_simple (buffer,
+ &read_input_rect,
+ read_buf,
+ buf_stride,
+ format,
+ level);
- if (format == buffer->soft_format)
- fish = NULL;
- else
- fish = babl_fish ((gpointer) buffer->soft_format,
- (gpointer) format);
+ /* All calculations are done relative to read_output_rect because it is guranteed
+ * to be inside of the roi rect and none of these calculations can return a value
+ * less than 0.
+ */
+ top_rows = read_output_rect.y - roi->y;
+ left_cols = read_output_rect.x - roi->x;
+ right_cols = (roi->x + roi->width) - (read_output_rect.x + read_output_rect.width);
+ bottom_rows = (roi->y + roi->height) - (read_output_rect.y + read_output_rect.height);
- while (bufy < height)
+ if (top_rows)
{
- gint tiledy = CLAMP (buffer_y + bufy, buffer_abyss_y, abyss_y_total - 1);
- gint offsety = gegl_tile_offset (tiledy, tile_height);
- gint bufx = 0;
- gboolean row_in_abyss = !(buffer_y + bufy + (tile_height) >= buffer_abyss_y &&
- buffer_y + bufy < abyss_y_total);
-
- while (bufx < width)
+ guchar *fill_buf = buf;
+ /* Top left pixel */
+ if (left_cols)
{
- gint tiledx = CLAMP (buffer_x + bufx, buffer_abyss_x, abyss_x_total - 1);
- gint offsetx = gegl_tile_offset (tiledx, tile_width);
- gint row, y, pixels, lskip, rskip;
- guchar *bp, *tile_base, *tp;
- GeglTile *tile;
-
- bp = buf + bufy * buf_stride + bufx * bpx_size;
+ guchar *src_pixel = read_buf;
+ fill_abyss_color (fill_buf, left_cols, top_rows, buf_stride, src_pixel, bpp);
+ fill_buf += left_cols * bpp;
+ }
- tile = gegl_tile_source_get_tile ((GeglTileSource *) (buffer),
- gegl_tile_indice (tiledx, tile_width),
- gegl_tile_indice (tiledy, tile_height),
- level);
+ /* Top rows */
+ {
+ guchar *src_pixel = read_buf;
+ guchar *row_fill_buf = fill_buf;
+ gint byte_width = read_output_rect.width * bpp;
+ gint i;
+ for (i = 0; i < top_rows; ++i)
+ {
+ memcpy (row_fill_buf, src_pixel, byte_width);
+ row_fill_buf += buf_stride;
+ }
+ }
- if (!tile)
- {
- g_warning ("didn't get tile, trying to continue");
- bufx += (tile_width - offsetx);
- continue;
- }
+ fill_buf += (read_input_rect.width) * bpp;
+ /* Top right pixel */
+ if (right_cols)
+ {
+ guchar *src_pixel = read_buf + (read_input_rect.width - 1) * bpp;
+ fill_abyss_color (fill_buf, right_cols, top_rows, buf_stride, src_pixel, bpp);
+ }
+ }
- tile_base = gegl_tile_get_data (tile);
- tp = ((guchar *) tile_base) + (offsety * tile_width + offsetx) * px_size;
+ /* Left */
+ if (left_cols)
+ {
+ guchar *row_fill_buf = buf + (top_rows * buf_stride);
+ guchar *src_pixel = read_buf;
+ gint i;
- y = bufy;
- if (tiledx != buffer_x + bufx)
- { /* x was clamped. Copy a single color since x remains clamped in
- this iteration. */
- guchar *color = alloca (bpx_size);
-
- /* gap between current column and left side of abyss rect */
- lskip = (buffer_abyss_x) - (buffer_x + bufx);
- /* gap between current column and end of roi */
- rskip = width - bufx;
- pixels = (lskip > 0 && lskip < width) ? lskip : rskip;
-
- if (row_in_abyss)
- { /* y remains clamped in this iteration so don't change the color */
- if (fish)
- babl_process (fish, tp, color, 1);
- else
- memcpy (color, tp, px_size);
-
- for (row = 0;
- row < tile_height && y < height;
- row++, y++)
- {
- gegl_memset_pattern (bp, color, bpx_size, pixels);
- bp += buf_stride;
- }
- }
- else
- {
- for (row = offsety;
- row < tile_height && y < height;
- row++, y++)
- {
- if (fish)
- babl_process (fish, tp, color, 1);
- else
- memcpy (color, tp, px_size);
+ for (i = 0; i < read_output_rect.height; ++i)
+ {
+ gegl_memset_pattern (row_fill_buf, src_pixel, bpp, left_cols);
+ row_fill_buf += buf_stride;
+ src_pixel += buf_stride;
+ }
+ }
- gegl_memset_pattern (bp, color, bpx_size, pixels);
+ /* Right */
+ if (right_cols)
+ {
+ guchar *row_fill_buf = buf + (read_input_rect.width + left_cols) * bpp
+ + top_rows * buf_stride;
+ guchar *src_pixel = read_buf + (read_input_rect.width - 1) * bpp;
+ gint i;
- if (buffer_y + y >= buffer_abyss_y &&
- buffer_y + y < abyss_y_total - 1)
- tp += tile_stride;
- bp += buf_stride;
- }
- }
- }
- else
- {
- if (width + offsetx - bufx < tile_width)
- pixels = width - bufx;
- else
- pixels = tile_width - offsetx;
+ for (i = 0; i < read_output_rect.height; ++i)
+ {
+ gegl_memset_pattern (row_fill_buf, src_pixel, bpp, right_cols);
+ row_fill_buf += buf_stride;
+ src_pixel += buf_stride;
+ }
+ }
- /* gap between current column and right side of abyss rect */
- rskip = abyss_x_total - (buffer_x + bufx);
- if (rskip > 0 && rskip < pixels)
- pixels = rskip;
+ if (bottom_rows)
+ {
+ guchar *fill_buf = buf + (read_input_rect.height + top_rows) * buf_stride;
+ /* Bottom left */
+ if (left_cols)
+ {
+ guchar *src_pixel = read_buf + (read_input_rect.height - 1) * buf_stride;
+ fill_abyss_color (fill_buf, left_cols, bottom_rows, buf_stride, src_pixel, bpp);
+ fill_buf += left_cols * bpp;
+ }
- for (row = (row_in_abyss) ? 0 : offsety;
- row < tile_height && y < height;
- row++, y++)
- {
- if (fish)
- babl_process (fish, tp, bp, pixels);
- else
- memcpy (bp, tp, pixels * px_size);
+ /* Bottom rows */
+ {
+ guchar *src_pixel = read_buf + (read_input_rect.height - 1) * buf_stride;
+ guchar *row_fill_buf = fill_buf;
+ gint byte_width = read_output_rect.width * bpp;
+ gint i;
+ for (i = 0; i < bottom_rows; ++i)
+ {
+ memcpy (row_fill_buf, src_pixel, byte_width);
+ row_fill_buf += buf_stride;
+ }
+ }
- if (buffer_y + y >= buffer_abyss_y &&
- buffer_y + y < abyss_y_total - 1)
- tp += tile_stride;
- bp += buf_stride;
- }
- }
- gegl_tile_unref (tile);
- bufx += pixels;
+ fill_buf += read_input_rect.width * bpp;
+ /* Bottom right */
+ if (right_cols)
+ {
+ guchar *src_pixel = read_buf + (read_input_rect.width - 1) * bpp + (read_input_rect.height - 1) *
buf_stride;
+ fill_abyss_color (fill_buf, right_cols, bottom_rows, buf_stride, src_pixel, bpp);
}
- if (row_in_abyss)
- bufy += tile_height;
- else
- bufy += (tile_height - offsety);
}
}
-static inline void
+static void
gegl_buffer_iterate_read_abyss_loop (GeglBuffer *buffer,
const GeglRectangle *roi,
const GeglRectangle *abyss,
@@ -1061,113 +892,52 @@ gegl_buffer_iterate_read_abyss_loop (GeglBuffer *buffer,
const Babl *format,
gint level)
{
- 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 bufy = 0;
+ GeglRectangle current_roi;
+ gint bpp = babl_format_get_bytes_per_pixel (format);
+ gint origin_x;
- gint width = roi->width;
- gint height = roi->height;
- gint buffer_x = roi->x;
- gint buffer_y = roi->y;
+ /* Loop abyss works like iterating over a grid of tiles the size of the abyss */
+ gint loop_chunk_ix = gegl_tile_indice (roi->x - abyss->x, abyss->width);
+ gint loop_chunk_iy = gegl_tile_indice (roi->y - abyss->y, abyss->height);
- gint buffer_abyss_x = abyss->x;
- gint buffer_abyss_y = abyss->y;
- gint abyss_x_total = buffer_abyss_x + abyss->width;
- gint abyss_y_total = buffer_abyss_y + abyss->height;
+ current_roi.x = loop_chunk_ix * abyss->width + abyss->x;
+ current_roi.y = loop_chunk_iy * abyss->height + abyss->y;
- const Babl *fish;
+ current_roi.width = abyss->width;
+ current_roi.height = abyss->height;
- if (format == buffer->soft_format)
- fish = NULL;
- else
- fish = babl_fish ((gpointer) buffer->soft_format,
- (gpointer) format);
+ origin_x = current_roi.x;
- while (bufy < height)
+ while (current_roi.y < roi->y + roi->height)
{
- gint tiledy = buffer_abyss_y +
- GEGL_REMAINDER (buffer_y + bufy - buffer_abyss_y, abyss->height);
- gint offsety = gegl_tile_offset (tiledy, tile_height);
- gint bufx = 0;
- gint rows, topskip, bottomskip;
-
- if (height + offsety - bufy < tile_height)
- rows = height - bufy;
- else
- rows = tile_height - offsety;
+ guchar *inner_buf = buf;
+ gint row_height = 0;
- /* gap between current row and top of abyss rect */
- topskip = buffer_abyss_y - tiledy;
- /* gap between current row and bottom of abyss rect */
- bottomskip = abyss_y_total - tiledy;
-
- if (topskip > 0 && topskip < rows)
- rows = topskip;
- else if (bottomskip > 0 && bottomskip < rows)
- rows = bottomskip;
-
- while (bufx < width)
+ while (current_roi.x < roi->x + roi->width)
{
- gint tiledx = buffer_abyss_x +
- GEGL_REMAINDER (buffer_x + bufx - buffer_abyss_x, abyss->width);
- gint offsetx = gegl_tile_offset (tiledx, tile_width);
- guchar *bp, *tile_base, *tp;
- gint pixels, row, y, lskip, rskip;
- GeglTile *tile;
-
- bp = buf + bufy * buf_stride + bufx * bpx_size;
-
- if (width + offsetx - bufx < tile_width)
- pixels = width - bufx;
- 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);
-
- /* gap between current column and left side of abyss rect */
- lskip = buffer_abyss_x - tiledx;
- /* gap between current column and right side of abyss rect */
- rskip = abyss_x_total - tiledx;
-
- if (lskip > 0 && lskip < pixels)
- pixels = lskip;
- else if (rskip > 0 && rskip < pixels)
- pixels = rskip;
-
- if (!tile)
- {
- g_warning ("didn't get tile, trying to continue");
- bufx += pixels;
- continue;
- }
-
- tile_base = gegl_tile_get_data (tile);
- tp = ((guchar *) tile_base) + (offsety * tile_width + offsetx) * px_size;
+ GeglRectangle simple_roi;
+ gegl_rectangle_intersect (&simple_roi, ¤t_roi, roi);
+
+ gegl_buffer_iterate_read_simple (buffer,
+ GEGL_RECTANGLE (abyss->x + (simple_roi.x - current_roi.x),
+ abyss->y + (simple_roi.y - current_roi.y),
+ simple_roi.width,
+ simple_roi.height),
+ inner_buf,
+ buf_stride,
+ format,
+ level);
+
+ row_height = simple_roi.height;
+ inner_buf += simple_roi.width * bpp;
+
+ current_roi.x += abyss->width;
+ }
- y = bufy;
- for (row = 0;
- row < rows && y < height;
- row++, y++)
- {
- if (fish)
- babl_process (fish, tp, bp, pixels);
- else
- memcpy (bp, tp, pixels * px_size);
+ buf += buf_stride * row_height;
- tp += tile_stride;
- bp += buf_stride;
- }
-
- gegl_tile_unref (tile);
- bufx += pixels;
- }
- bufy += rows;
+ current_roi.x = origin_x;
+ current_roi.y += abyss->height;
}
}
@@ -1218,8 +988,8 @@ gegl_buffer_iterate_read_dispatch (GeglBuffer *buffer,
}
else if (repeat_mode == GEGL_ABYSS_NONE)
{
- gegl_buffer_iterate_read_abyss_none (buffer, &roi_factored, &abyss_factored,
- buf, rowstride, format, level);
+ gegl_buffer_iterate_read_abyss_color (buffer, &roi_factored, &abyss_factored,
+ buf, rowstride, format, level, NULL);
}
else if (repeat_mode == GEGL_ABYSS_WHITE)
{
@@ -1245,13 +1015,21 @@ gegl_buffer_iterate_read_dispatch (GeglBuffer *buffer,
}
else if (repeat_mode == GEGL_ABYSS_CLAMP)
{
- gegl_buffer_iterate_read_abyss_clamp (buffer, &roi_factored, &abyss_factored,
- buf, rowstride, format, level);
+ if (abyss_factored.width == 0 || abyss_factored.height == 0)
+ gegl_buffer_iterate_read_abyss_color (buffer, &roi_factored, &abyss_factored,
+ buf, rowstride, format, level, NULL);
+ else
+ gegl_buffer_iterate_read_abyss_clamp (buffer, &roi_factored, &abyss_factored,
+ buf, rowstride, format, level);
}
else
{
- gegl_buffer_iterate_read_abyss_loop (buffer, &roi_factored, &abyss_factored,
- buf, rowstride, format, level);
+ if (abyss_factored.width == 0 || abyss_factored.height == 0)
+ gegl_buffer_iterate_read_abyss_color (buffer, &roi_factored, &abyss_factored,
+ buf, rowstride, format, level, NULL);
+ else
+ gegl_buffer_iterate_read_abyss_loop (buffer, &roi_factored, &abyss_factored,
+ buf, rowstride, format, level);
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]