[gegl] sampler-nearest: make nearest sampler use hot tile directly
- From: Øyvind Kolås <ok src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] sampler-nearest: make nearest sampler use hot tile directly
- Date: Sun, 15 Jun 2014 02:16:23 +0000 (UTC)
commit c44ae23350732b129b4893f81a7dcac122412547
Author: Øyvind Kolås <pippin gimp org>
Date: Sun Jun 15 03:31:01 2014 +0200
sampler-nearest: make nearest sampler use hot tile directly
gegl/buffer/gegl-sampler-nearest.c | 144 +++++++++++++++++++++++++++++++++---
gegl/buffer/gegl-sampler.c | 11 +++
gegl/buffer/gegl-sampler.h | 21 +++++-
3 files changed, 164 insertions(+), 12 deletions(-)
---
diff --git a/gegl/buffer/gegl-sampler-nearest.c b/gegl/buffer/gegl-sampler-nearest.c
index 48da2d8..2058520 100644
--- a/gegl/buffer/gegl-sampler-nearest.c
+++ b/gegl/buffer/gegl-sampler-nearest.c
@@ -17,9 +17,16 @@
#include "config.h"
#include <math.h>
+#include <string.h>
#include "gegl.h"
#include "gegl-types-internal.h"
+#include "gegl-buffer-types.h"
+#include "gegl-buffer.h"
+#include "gegl-buffer-private.h"
+#include "gegl-tile-storage.h"
+#include "gegl-tile-backend.h"
+
#include "gegl-sampler-nearest.h"
enum
@@ -29,12 +36,15 @@ enum
};
static void
-gegl_sampler_nearest_get ( GeglSampler* restrict self,
- const gdouble absolute_x,
- const gdouble absolute_y,
- GeglMatrix2 *scale,
- void* restrict output,
- GeglAbyssPolicy repeat_mode);
+gegl_sampler_nearest_get (GeglSampler* restrict self,
+ const gdouble absolute_x,
+ const gdouble absolute_y,
+ GeglMatrix2 *scale,
+ void* restrict output,
+ GeglAbyssPolicy repeat_mode);
+
+static void
+gegl_sampler_nearest_prepare (GeglSampler* restrict self);
G_DEFINE_TYPE (GeglSamplerNearest, gegl_sampler_nearest, GEGL_TYPE_SAMPLER)
@@ -44,6 +54,7 @@ gegl_sampler_nearest_class_init (GeglSamplerNearestClass *klass)
GeglSamplerClass *sampler_class = GEGL_SAMPLER_CLASS (klass);
sampler_class->get = gegl_sampler_nearest_get;
+ sampler_class->prepare = gegl_sampler_nearest_prepare;
}
/*
@@ -61,6 +72,117 @@ gegl_sampler_nearest_init (GeglSamplerNearest *self)
GEGL_SAMPLER (self)->interpolate_format = babl_format ("RaGaBaA float");
}
+static void inline
+gegl_sampler_get_pixel (GeglSampler *sampler,
+ gint x,
+ gint y,
+ const Babl *format,
+ gpointer data,
+ GeglAbyssPolicy repeat_mode)
+{
+ GeglBuffer *buffer = sampler->buffer;
+ const GeglRectangle *abyss = &buffer->abyss;
+ guchar *buf = data;
+
+ if (y < abyss->y ||
+ x < abyss->x ||
+ y >= abyss->y + abyss->height ||
+ x >= abyss->x + abyss->width)
+ {
+ switch (repeat_mode)
+ {
+ case GEGL_ABYSS_CLAMP:
+ x = CLAMP (x, abyss->x, abyss->x+abyss->width-1);
+ y = CLAMP (y, abyss->y, abyss->y+abyss->height-1);
+ break;
+
+ case GEGL_ABYSS_LOOP:
+ x = abyss->x + GEGL_REMAINDER (x - abyss->x, abyss->width);
+ y = abyss->y + GEGL_REMAINDER (y - abyss->y, abyss->height);
+ break;
+
+ case GEGL_ABYSS_BLACK:
+ {
+ gfloat color[4] = {0.0, 0.0, 0.0, 1.0};
+ babl_process (babl_fish (babl_format ("RGBA float"), format),
+ color,
+ buf,
+ 1);
+ return;
+ }
+
+ case GEGL_ABYSS_WHITE:
+ {
+ gfloat color[4] = {1.0, 1.0, 1.0, 1.0};
+ babl_process (babl_fish (babl_format ("RGBA float"),
+ format),
+ color,
+ buf,
+ 1);
+ return;
+ }
+
+ default:
+ case GEGL_ABYSS_NONE:
+ memset (buf, 0x00, babl_format_get_bytes_per_pixel (format));
+ 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;
+ gint px_size;
+
+ if (format != buffer->soft_format)
+ {
+ px_size = babl_format_get_bytes_per_pixel (buffer->soft_format);
+ }
+ else
+ {
+ px_size = babl_format_get_bytes_per_pixel (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_get_data (tile) + (offsety * tile_width + offsetx) * px_size;
+
+ babl_process (sampler->fish, tp, buf, 1);
+ }
+ }
+}
+
+static void
+gegl_sampler_nearest_prepare (GeglSampler* restrict sampler)
+{
+ if (!sampler->buffer) /* this happens when querying the extent of a sampler */
+ return;
+
+ sampler->fish = babl_fish (sampler->buffer->soft_format, sampler->format);
+}
+
void
gegl_sampler_nearest_get ( GeglSampler* restrict sampler,
const gdouble absolute_x,
@@ -77,11 +199,11 @@ gegl_sampler_nearest_get ( GeglSampler* restrict sampler,
* located at (.5,.5) (instead of (0,0) as it would be if absolute
* positions were center-based).
*/
-
-#if 1 /* There probably is faster ways to do this, */
- GeglRectangle rect = {floorf(absolute_x), floorf(absolute_y), 1, 1};
- gegl_buffer_get (sampler->buffer, &rect, 1.0,
- sampler->format, output, 0, repeat_mode);
+#if 1
+ return gegl_sampler_get_pixel (sampler,
+ floorf(absolute_x), floorf(absolute_y),
+ sampler->format,
+ output, repeat_mode);
#else
/* this left in here; to make it easy to manually verify that the
diff --git a/gegl/buffer/gegl-sampler.c b/gegl/buffer/gegl-sampler.c
index da48688..f8370de 100644
--- a/gegl/buffer/gegl-sampler.c
+++ b/gegl/buffer/gegl-sampler.c
@@ -26,8 +26,12 @@
#include "gegl.h"
#include "gegl-types-internal.h"
+#include "gegl-buffer-types.h"
#include "gegl-buffer.h"
+#include "gegl-buffer-private.h"
+
+
#include "gegl-sampler-nearest.h"
#include "gegl-sampler-linear.h"
#include "gegl-sampler-cubic.h"
@@ -139,6 +143,11 @@ gegl_sampler_prepare (GeglSampler *self)
klass = GEGL_SAMPLER_GET_CLASS (self);
+ if (!self->buffer)
+ return;
+ if (!self->format)
+ self->format = self->buffer->soft_format;
+
if (klass->prepare)
klass->prepare (self);
@@ -174,6 +183,8 @@ gegl_sampler_set_buffer (GeglSampler *self, GeglBuffer *buffer)
if (klass->set_buffer)
klass->set_buffer (self, buffer);
+
+ gegl_sampler_prepare (self);
}
static void
diff --git a/gegl/buffer/gegl-sampler.h b/gegl/buffer/gegl-sampler.h
index 6446c16..69f9f64 100644
--- a/gegl/buffer/gegl-sampler.h
+++ b/gegl/buffer/gegl-sampler.h
@@ -39,7 +39,26 @@ G_BEGIN_DECLS
* Best thing to do seems to use rectangular buffer tiles that are
* twice as wide as they are tall.
*/
-#define GEGL_SAMPLER_MAXIMUM_HEIGHT (64)
+
+//128 20.42 23.23
+// 96 26.91 30.39
+// 64 34.32 41.52
+// 48 38.66 46.67
+// 32 43.17 53.78
+// 24 45.38 56.11
+// 20 45.18 56.70
+// 20 45.41 56.32
+// 19 45.75 57.81
+// 19 45.81 57.69
+// 18 47.16 60.02
+// 18 47.19 60.36
+// 17 46.43 58.73
+// 17 46.61 58.85
+// 16 46.44 58.73
+// 8 43.25 54
+// 4 33.11 39
+
+#define GEGL_SAMPLER_MAXIMUM_HEIGHT (27)
#define GEGL_SAMPLER_MAXIMUM_WIDTH (GEGL_SAMPLER_MAXIMUM_HEIGHT)
typedef struct _GeglSamplerClass GeglSamplerClass;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]