[gegl] buffer: stack frame overhead optimizations
- From: Øyvind Kolås <ok src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] buffer: stack frame overhead optimizations
- Date: Wed, 18 Jun 2014 17:25:58 +0000 (UTC)
commit 07dc61e1a9ff994ea9b58ab0cf0cc8f7d557f82d
Author: Øyvind Kolås <pippin gimp org>
Date: Wed Jun 18 18:27:30 2014 +0200
buffer: stack frame overhead optimizations
When using gegl_buffer_get / gegl_buffer_set and gegl_buffer_sample for
small/1x1px sized rectangles the overhead of each involved function call
amounts to more than 2% of time spend processing.
This refactoring involves moving gegl_buffer_sample from gegl-buffer.c to
gegl-sampler.c to make them live in the same compilation unit. Replacing
internal nested chains of function calls with added complexity with an
inlinable implementation using switches.
gegl/buffer/gegl-buffer-access.c | 332 ++++++++++++++++++++++++++----------
gegl/buffer/gegl-buffer-iterator.c | 1 +
gegl/buffer/gegl-buffer-private.h | 7 +-
gegl/buffer/gegl-buffer.c | 5 +-
gegl/buffer/gegl-buffer.h | 11 --
gegl/buffer/gegl-sampler-nearest.c | 52 ++++---
gegl/buffer/gegl-sampler.c | 51 ++++++-
7 files changed, 328 insertions(+), 131 deletions(-)
---
diff --git a/gegl/buffer/gegl-buffer-access.c b/gegl/buffer/gegl-buffer-access.c
index aa1474c..5158254 100644
--- a/gegl/buffer/gegl-buffer-access.c
+++ b/gegl/buffer/gegl-buffer-access.c
@@ -56,7 +56,7 @@ static void gegl_buffer_iterate_read_dispatch (GeglBuffer *buffer,
gint level,
GeglAbyssPolicy repeat_mode);
-static void
+static void inline
gegl_buffer_get_pixel (GeglBuffer *buffer,
gint x,
gint y,
@@ -162,6 +162,130 @@ gegl_buffer_get_pixel (GeglBuffer *buffer,
}
}
+static inline void
+__gegl_buffer_set_pixel (GeglBuffer *buffer,
+ gint x,
+ gint y,
+ const Babl *format,
+ gconstpointer data)
+{
+ const GeglRectangle *abyss = &buffer->abyss;
+ const guchar *buf = data;
+
+ if (y < abyss->y ||
+ x < abyss->x ||
+ y >= abyss->y + abyss->height ||
+ x >= abyss->x + abyss->width)
+ return;
+
+ {
+ gint tile_width = buffer->tile_width;
+ gint tile_height = buffer->tile_height;
+ gint tiledy = y + buffer->shift_y;
+ gint tiledx = x + buffer->shift_x;
+ gint indice_x = gegl_tile_indice (tiledx, tile_width);
+ gint indice_y = gegl_tile_indice (tiledy, tile_height);
+
+ GeglTile *tile = buffer->tile_storage->hot_tile;
+ const Babl *fish = NULL;
+ gint px_size;
+
+ if (format != buffer->soft_format)
+ {
+ fish = babl_fish (format, buffer->soft_format);
+ px_size = babl_format_get_bytes_per_pixel (buffer->soft_format);
+ }
+ else
+ {
+ px_size = babl_format_get_bytes_per_pixel (buffer->soft_format);
+ }
+
+ if (!(tile &&
+ tile->x == indice_x &&
+ tile->y == indice_y))
+ {
+ _gegl_buffer_drop_hot_tile (buffer);
+ tile = gegl_tile_source_get_tile ((GeglTileSource *) (buffer),
+ indice_x, indice_y,
+ 0);
+ buffer->tile_storage->hot_tile = tile;
+ }
+
+ if (tile)
+ {
+ gint tile_origin_x = indice_x * tile_width;
+ gint tile_origin_y = indice_y * tile_height;
+ gint offsetx = tiledx - tile_origin_x;
+ gint offsety = tiledy - tile_origin_y;
+
+ guchar *tp;
+ gegl_tile_lock (tile);
+ tp = gegl_tile_get_data (tile) + (offsety * tile_width + offsetx) * px_size;
+
+ if (fish)
+ babl_process (fish, buf, tp, 1);
+ else
+ memcpy (tp, buf, px_size);
+
+ gegl_tile_unlock (tile);
+ }
+ }
+}
+
+enum _GeglBufferSetFlag {
+ GEGL_BUFFER_SET_FLAG_FAST = 0,
+ GEGL_BUFFER_SET_FLAG_LOCK = 1<<0,
+ GEGL_BUFFER_SET_FLAG_NOTIFY = 1<<2,
+ GEGL_BUFFER_SET_FLAG_FULL = GEGL_BUFFER_SET_FLAG_LOCK |
+ GEGL_BUFFER_SET_FLAG_NOTIFY
+};
+
+typedef enum _GeglBufferSetFlag GeglBufferSetFlag;
+
+void
+gegl_buffer_set_with_flags (GeglBuffer *buffer,
+ const GeglRectangle *rect,
+ gint level,
+ const Babl *format,
+ const void *src,
+ gint rowstride,
+ GeglBufferSetFlag set_flags);
+
+
+static inline void
+_gegl_buffer_set_pixel (GeglBuffer *buffer,
+ gint x,
+ gint y,
+ const Babl *format,
+ gconstpointer data,
+ GeglBufferSetFlag flags)
+{
+ GeglRectangle rect = {x,y,1,1};
+ switch (flags)
+ {
+ case GEGL_BUFFER_SET_FLAG_FAST:
+ __gegl_buffer_set_pixel (buffer, x, y, format, data);
+ break;
+ case GEGL_BUFFER_SET_FLAG_LOCK:
+ gegl_buffer_lock (buffer);
+ __gegl_buffer_set_pixel (buffer, x, y, format, data);
+ gegl_buffer_unlock (buffer);
+ break;
+ case GEGL_BUFFER_SET_FLAG_NOTIFY:
+ __gegl_buffer_set_pixel (buffer, x, y, format, data);
+ if (flags & GEGL_BUFFER_SET_FLAG_NOTIFY)
+ gegl_buffer_emit_changed_signal(buffer, &rect);
+ break;
+ case GEGL_BUFFER_SET_FLAG_LOCK|GEGL_BUFFER_SET_FLAG_NOTIFY:
+ default:
+ gegl_buffer_lock (buffer);
+ __gegl_buffer_set_pixel (buffer, x, y, format, data);
+ gegl_buffer_unlock (buffer);
+ gegl_buffer_emit_changed_signal(buffer, &rect);
+ break;
+ }
+}
+
/* flush any unwritten data (flushes the hot-cache of a single
* tile used by gegl_buffer_set for 1x1 pixel sized rectangles
*/
@@ -182,8 +306,6 @@ gegl_buffer_flush (GeglBuffer *buffer)
GEGL_TILE_FLUSH, 0,0,0,NULL);
}
-
-
static inline void
gegl_buffer_iterate_write (GeglBuffer *buffer,
const GeglRectangle *roi,
@@ -346,6 +468,76 @@ gegl_buffer_iterate_write (GeglBuffer *buffer,
}
}
+static inline void
+gegl_buffer_set_internal (GeglBuffer *buffer,
+ const GeglRectangle *rect,
+ gint level,
+ const Babl *format,
+ const void *src,
+ gint rowstride)
+{
+ if (gegl_cl_is_accelerated ())
+ {
+ gegl_buffer_cl_cache_flush (buffer, rect);
+ }
+
+ gegl_buffer_iterate_write (buffer, rect, (void *) src, rowstride, format, 0);
+
+ if (gegl_buffer_is_shared (buffer))
+ {
+ gegl_buffer_flush (buffer);
+ }
+}
+
+static void inline
+_gegl_buffer_set_with_flags (GeglBuffer *buffer,
+ const GeglRectangle *rect,
+ gint level,
+ const Babl *format,
+ const void *src,
+ gint rowstride,
+ GeglBufferSetFlag flags)
+{
+ switch (flags)
+ {
+ case GEGL_BUFFER_SET_FLAG_FAST:
+ gegl_buffer_set_internal (buffer, rect, level, format, src, rowstride);
+ break;
+ case GEGL_BUFFER_SET_FLAG_LOCK:
+ gegl_buffer_lock (buffer);
+ gegl_buffer_set_internal (buffer, rect, level, format, src, rowstride);
+ gegl_buffer_unlock (buffer);
+ break;
+ case GEGL_BUFFER_SET_FLAG_NOTIFY:
+ gegl_buffer_set_internal (buffer, rect, level, format, src, rowstride);
+ if (flags & GEGL_BUFFER_SET_FLAG_NOTIFY)
+ gegl_buffer_emit_changed_signal(buffer, rect);
+ break;
+ case GEGL_BUFFER_SET_FLAG_LOCK|GEGL_BUFFER_SET_FLAG_NOTIFY:
+ default:
+ gegl_buffer_lock (buffer);
+ gegl_buffer_set_internal (buffer, rect, level, format, src, rowstride);
+ gegl_buffer_unlock (buffer);
+ gegl_buffer_emit_changed_signal(buffer, rect);
+ break;
+ }
+}
+
+void
+gegl_buffer_set_with_flags (GeglBuffer *buffer,
+ const GeglRectangle *rect,
+ gint level,
+ const Babl *format,
+ const void *src,
+ gint rowstride,
+ GeglBufferSetFlag flags)
+{
+ g_return_if_fail (GEGL_IS_BUFFER (buffer));
+ if (format == NULL)
+ format = buffer->soft_format;
+ _gegl_buffer_set_with_flags (buffer, rect, level, format, src, rowstride, flags);
+}
+
static void
gegl_buffer_iterate_read_simple (GeglBuffer *buffer,
const GeglRectangle *roi,
@@ -1089,38 +1281,28 @@ gegl_buffer_iterate_read_dispatch (GeglBuffer *buffer,
void
gegl_buffer_set_unlocked (GeglBuffer *buffer,
const GeglRectangle *rect,
+ gint level,
const Babl *format,
const void *src,
gint rowstride)
{
- gegl_buffer_set_unlocked_no_notify(buffer, rect, format, src, rowstride);
- gegl_buffer_emit_changed_signal(buffer, rect);
+ _gegl_buffer_set_with_flags (buffer, rect, level, format, src, rowstride,
+ GEGL_BUFFER_SET_FLAG_NOTIFY);
}
-
void
gegl_buffer_set_unlocked_no_notify (GeglBuffer *buffer,
const GeglRectangle *rect,
+ gint level,
const Babl *format,
const void *src,
gint rowstride)
{
- if (format == NULL)
- format = buffer->soft_format;
-
- if (gegl_cl_is_accelerated ())
- {
- gegl_buffer_cl_cache_flush (buffer, rect);
- }
-
- gegl_buffer_iterate_write (buffer, rect, (void *) src, rowstride, format, 0);
-
- if (gegl_buffer_is_shared (buffer))
- {
- gegl_buffer_flush (buffer);
- }
+ _gegl_buffer_set_with_flags (buffer, rect, level, format, src, rowstride,
+ GEGL_BUFFER_SET_FLAG_FAST);
}
+
void
gegl_buffer_set (GeglBuffer *buffer,
const GeglRectangle *rect,
@@ -1130,10 +1312,16 @@ gegl_buffer_set (GeglBuffer *buffer,
gint rowstride)
{
g_return_if_fail (GEGL_IS_BUFFER (buffer));
+ if (format == NULL)
+ format = buffer->soft_format;
- gegl_buffer_lock (buffer);
- gegl_buffer_set_unlocked (buffer, rect, format, src, rowstride);
- gegl_buffer_unlock (buffer);
+ if (rect && (rect->width == 1 && rect->height == 1))
+ _gegl_buffer_set_pixel (buffer, rect->x, rect->y, format, src,
+ GEGL_BUFFER_SET_FLAG_LOCK|GEGL_BUFFER_SET_FLAG_NOTIFY);
+ else
+ _gegl_buffer_set_with_flags (buffer, rect, level, format, src, rowstride,
+ GEGL_BUFFER_SET_FLAG_LOCK|
+ GEGL_BUFFER_SET_FLAG_NOTIFY);
}
/* Expand roi by scale so it uncludes all pixels needed
@@ -1172,36 +1360,33 @@ _gegl_get_required_for_scale (const Babl *format,
}
}
-void
-gegl_buffer_get_unlocked (GeglBuffer *buffer,
- gdouble scale,
- const GeglRectangle *rect,
- const Babl *format,
- gpointer dest_buf,
- gint rowstride,
- GeglAbyssPolicy repeat_mode)
+static inline void
+_gegl_buffer_get_unlocked (GeglBuffer *buffer,
+ gdouble scale,
+ const GeglRectangle *rect,
+ const Babl *format,
+ gpointer dest_buf,
+ gint rowstride,
+ GeglAbyssPolicy repeat_mode)
{
g_return_if_fail (scale > 0.0);
if (format == NULL)
format = buffer->soft_format;
-#if 1
- /* not thread-safe */
+ if (gegl_cl_is_accelerated ())
+ {
+ gegl_buffer_cl_cache_flush (buffer, rect);
+ }
+
if (scale == 1.0 &&
rect &&
rect->width == 1 &&
- rect->height == 1) /* fast path */
+ rect->height == 1)
{
gegl_buffer_get_pixel (buffer, rect->x, rect->y, format, dest_buf, repeat_mode);
return;
}
-#endif
-
- if (gegl_cl_is_accelerated ())
- {
- gegl_buffer_cl_cache_flush (buffer, rect);
- }
if (!rect && scale == 1.0)
{
@@ -1314,6 +1499,18 @@ gegl_buffer_get_unlocked (GeglBuffer *buffer,
}
void
+gegl_buffer_get_unlocked (GeglBuffer *buffer,
+ gdouble scale,
+ const GeglRectangle *rect,
+ const Babl *format,
+ gpointer dest_buf,
+ gint rowstride,
+ GeglAbyssPolicy repeat_mode)
+{
+ return _gegl_buffer_get_unlocked (buffer, scale, rect, format, dest_buf, rowstride, repeat_mode);
+}
+
+void
gegl_buffer_get (GeglBuffer *buffer,
const GeglRectangle *rect,
gdouble scale,
@@ -1323,58 +1520,9 @@ gegl_buffer_get (GeglBuffer *buffer,
GeglAbyssPolicy repeat_mode)
{
g_return_if_fail (GEGL_IS_BUFFER (buffer));
- gegl_buffer_get_unlocked (buffer, scale, rect, format, dest_buf, rowstride, repeat_mode);
-}
-
-GType
-gegl_sampler_gtype_from_enum (GeglSamplerType sampler_type);
-
-void
-gegl_buffer_sample (GeglBuffer *buffer,
- gdouble x,
- gdouble y,
- GeglMatrix2 *scale,
- gpointer dest,
- const Babl *format,
- GeglSamplerType sampler_type,
- GeglAbyssPolicy repeat_mode)
-{
- GType desired_type;
-
- if (!format)
- format = buffer->soft_format;
-
- if (sampler_type == GEGL_SAMPLER_NEAREST)
- {
- /* XXX: not thread safe */
- gegl_buffer_get_pixel (buffer, x, y, format, dest, repeat_mode);
- return;
- }
-
- desired_type = gegl_sampler_gtype_from_enum (sampler_type);
-
- /* unset the cached sampler if it dosn't match the needs */
- if (buffer->sampler != NULL &&
- (!G_TYPE_CHECK_INSTANCE_TYPE (buffer->sampler, desired_type) ||
- buffer->sampler_format != format
- ))
- {
- g_object_unref (buffer->sampler);
- buffer->sampler = NULL;
- }
-
- /* look up appropriate sampler,. */
- if (buffer->sampler == NULL)
- {
- buffer->sampler = g_object_new (desired_type,
- "buffer", buffer,
- "format", format,
- NULL);
- buffer->sampler_format = format;
- gegl_sampler_prepare (buffer->sampler);
- }
-
- gegl_sampler_get (buffer->sampler, x, y, scale, dest, repeat_mode);
+ gegl_buffer_lock (buffer);
+ _gegl_buffer_get_unlocked (buffer, scale, rect, format, dest_buf, rowstride, repeat_mode);
+ gegl_buffer_unlock (buffer);
}
void
diff --git a/gegl/buffer/gegl-buffer-iterator.c b/gegl/buffer/gegl-buffer-iterator.c
index 6510d30..456e805 100644
--- a/gegl/buffer/gegl-buffer-iterator.c
+++ b/gegl/buffer/gegl-buffer-iterator.c
@@ -183,6 +183,7 @@ release_tile (GeglBufferIterator *iter,
{
gegl_buffer_set_unlocked_no_notify (sub->buffer,
&sub->real_roi,
+ 0, /* level */
sub->format,
sub->real_data,
GEGL_AUTO_ROWSTRIDE);
diff --git a/gegl/buffer/gegl-buffer-private.h b/gegl/buffer/gegl-buffer-private.h
index b5dbd71..d51394d 100644
--- a/gegl/buffer/gegl-buffer-private.h
+++ b/gegl/buffer/gegl-buffer-private.h
@@ -71,9 +71,10 @@ struct _GeglBuffer
useful for debugging */
gint alloc_stack_size;
- GeglTileBackend *backend;
+ gint changed_signal_connections; /* to avoid firing changed signals
+ with no listeners */
- gint changed_signal_connections;
+ GeglTileBackend *backend;
};
struct _GeglBufferClass
@@ -105,12 +106,14 @@ gboolean gegl_buffer_unlock (GeglBuffer *buffer);
void gegl_buffer_set_unlocked (GeglBuffer *buffer,
const GeglRectangle *rect,
+ gint level,
const Babl *format,
const void *src,
gint rowstride);
void gegl_buffer_set_unlocked_no_notify (GeglBuffer *buffer,
const GeglRectangle *rect,
+ gint level,
const Babl *format,
const void *src,
gint rowstride);
diff --git a/gegl/buffer/gegl-buffer.c b/gegl/buffer/gegl-buffer.c
index 4124816..5a3db18 100644
--- a/gegl/buffer/gegl-buffer.c
+++ b/gegl/buffer/gegl-buffer.c
@@ -91,7 +91,7 @@ enum
LAST_SIGNAL
};
-guint gegl_buffer_signals[LAST_SIGNAL] = { 0 };
+static guint gegl_buffer_signals[LAST_SIGNAL] = { 0 };
static void
gegl_buffer_get_property (GObject *gobject,
@@ -1179,5 +1179,4 @@ glong gegl_buffer_signal_connect (GeglBuffer *buffer,
{
buffer->changed_signal_connections++;
return g_signal_connect(buffer, detailed_signal, c_handler, data);
-}
-
+}
diff --git a/gegl/buffer/gegl-buffer.h b/gegl/buffer/gegl-buffer.h
index 22f9f06..1d9ff47 100644
--- a/gegl/buffer/gegl-buffer.h
+++ b/gegl/buffer/gegl-buffer.h
@@ -431,17 +431,6 @@ void gegl_buffer_sample (GeglBuffer *buffer,
*/
void gegl_buffer_sample_cleanup (GeglBuffer *buffer);
-
-
-/**
- * gegl_sampler_type_from_string:
- * @string: the string to look up
- *
- * Looks up the GeglInterpolation corresponding to a string, if no matching
- * interpolation is found GEGL_SAMPLER_NEAREST is returned.
- */
-GeglSamplerType gegl_sampler_type_from_string (const gchar *string);
-
typedef void (*GeglSamplerGetFun) (GeglSampler *self,
gdouble x,
gdouble y,
diff --git a/gegl/buffer/gegl-sampler-nearest.c b/gegl/buffer/gegl-sampler-nearest.c
index e40a495..44eb5c7 100644
--- a/gegl/buffer/gegl-sampler-nearest.c
+++ b/gegl/buffer/gegl-sampler-nearest.c
@@ -84,6 +84,8 @@ gegl_sampler_get_pixel (GeglSampler *sampler,
const GeglRectangle *abyss = &buffer->abyss;
guchar *buf = data;
+ gegl_buffer_lock (sampler->buffer);
+
if (y < abyss->y ||
x < abyss->x ||
y >= abyss->y + abyss->height ||
@@ -162,19 +164,22 @@ gegl_sampler_get_pixel (GeglSampler *sampler,
babl_process (sampler->fish, tp, buf, 1);
}
}
+ gegl_buffer_unlock (sampler->buffer);
}
static void
-gegl_sampler_nearest_prepare (GeglSampler* restrict sampler)
+gegl_sampler_nearest_get_same_format ( GeglSampler* restrict sampler,
+ const gdouble absolute_x,
+ const gdouble absolute_y,
+ GeglMatrix2 *scale,
+ void* restrict output,
+ GeglAbyssPolicy repeat_mode)
{
- if (!sampler->buffer) /* this happens when querying the extent of a sampler */
- return;
- GEGL_SAMPLER_NEAREST (sampler)->buffer_bpp = babl_format_get_bytes_per_pixel (sampler->buffer->format);
-
- sampler->fish = babl_fish (sampler->buffer->soft_format, sampler->format);
+ GeglRectangle rectangle = {floorf(absolute_x), floorf(absolute_y), 1, 1};
+ gegl_buffer_get (sampler->buffer, &rectangle, 1.0, NULL, output, GEGL_AUTO_ROWSTRIDE, repeat_mode);
}
-void
+static void
gegl_sampler_nearest_get ( GeglSampler* restrict sampler,
const gdouble absolute_x,
const gdouble absolute_y,
@@ -182,24 +187,11 @@ gegl_sampler_nearest_get ( GeglSampler* restrict sampler,
void* restrict output,
GeglAbyssPolicy repeat_mode)
{
- /*
- * The reason why floor of the absolute position gives the nearest
- * pixel (with ties resolved toward -infinity) is that the absolute
- * position is corner-based (origin at the top left corner of the
- * pixel labeled (0,0)) so that the center of the top left pixel is
- * located at (.5,.5) (instead of (0,0) as it would be if absolute
- * positions were center-based).
- */
#if 1
- return gegl_sampler_get_pixel (sampler,
+ gegl_sampler_get_pixel (sampler,
floorf(absolute_x), floorf(absolute_y),
output, repeat_mode);
#else
-
- /* this left in here; to make it easy to manually verify that the
- * sampler framework behaves correctly.
- */
-
const gfloat* restrict in_bptr =
gegl_sampler_get_ptr (sampler,
(gint) floor ((double) absolute_x),
@@ -208,3 +200,21 @@ gegl_sampler_nearest_get ( GeglSampler* restrict sampler,
babl_process (sampler->fish, in_bptr, output, 1);
#endif
}
+
+
+static void
+gegl_sampler_nearest_prepare (GeglSampler* restrict sampler)
+{
+ if (!sampler->buffer) /* this happens when querying the extent of a sampler */
+ return;
+ GEGL_SAMPLER_NEAREST (sampler)->buffer_bpp = babl_format_get_bytes_per_pixel (sampler->buffer->format);
+
+ if (sampler->format == sampler->buffer->soft_format)
+ {
+ sampler->get = gegl_sampler_nearest_get_same_format;
+ }
+ else
+ {
+ sampler->fish = babl_fish (sampler->buffer->soft_format, sampler->format);
+ }
+}
diff --git a/gegl/buffer/gegl-sampler.c b/gegl/buffer/gegl-sampler.c
index 7a117c4..d4e9aa5 100644
--- a/gegl/buffer/gegl-sampler.c
+++ b/gegl/buffer/gegl-sampler.c
@@ -72,7 +72,7 @@ static void buffer_contents_changed (GeglBuffer *buffer,
const GeglRectangle *changed_rect,
gpointer userdata);
-GType gegl_sampler_gtype_from_enum (GeglSamplerType sampler_type);
+static GType gegl_sampler_gtype_from_enum (GeglSamplerType sampler_type);
G_DEFINE_TYPE (GeglSampler, gegl_sampler, G_TYPE_OBJECT)
@@ -455,7 +455,7 @@ gegl_sampler_type_from_string (const gchar *string)
return GEGL_SAMPLER_LINEAR;
}
-GType
+static inline GType
gegl_sampler_gtype_from_enum (GeglSamplerType sampler_type)
{
switch (sampler_type)
@@ -475,6 +475,53 @@ gegl_sampler_gtype_from_enum (GeglSamplerType sampler_type)
}
}
+void
+gegl_buffer_sample (GeglBuffer *buffer,
+ gdouble x,
+ gdouble y,
+ GeglMatrix2 *scale,
+ gpointer dest,
+ const Babl *format,
+ GeglSamplerType sampler_type,
+ GeglAbyssPolicy repeat_mode)
+{
+ GType desired_type;
+ if (sampler_type == GEGL_SAMPLER_NEAREST && format == buffer->soft_format)
+ {
+ GeglRectangle rect = {floorf (x), floorf(y), 1, 1};
+ gegl_buffer_get (buffer, &rect, 1, NULL, dest, GEGL_AUTO_ROWSTRIDE, repeat_mode);
+ return;
+ }
+
+ if (!format)
+ format = buffer->soft_format;
+
+ desired_type = gegl_sampler_gtype_from_enum (sampler_type);
+
+ /* unset the cached sampler if it dosn't match the needs */
+ if (buffer->sampler != NULL &&
+ (!G_TYPE_CHECK_INSTANCE_TYPE (buffer->sampler, desired_type) ||
+ buffer->sampler_format != format
+ ))
+ {
+ g_object_unref (buffer->sampler);
+ buffer->sampler = NULL;
+ }
+
+ /* look up appropriate sampler,. */
+ if (buffer->sampler == NULL)
+ {
+ buffer->sampler = g_object_new (desired_type,
+ "buffer", buffer,
+ "format", format,
+ NULL);
+ buffer->sampler_format = format;
+ gegl_sampler_prepare (buffer->sampler);
+ }
+
+ buffer->sampler->get(buffer->sampler, x, y, scale, dest, repeat_mode);
+}
+
GeglSampler *
gegl_buffer_sampler_new (GeglBuffer *buffer,
const Babl *format,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]