--- /dev/null
+/* @file blur_gaussian_rgba_.c
+ * Should define the functions:
+ * - _gaussian_blur_horiz_rgba_step
+ * - _gaussian_blur_vert_rgba_step
+ */
+
+#include "evas_common_private.h"
+#include "../evas_filter_private.h"
+
+#if !defined (FUNCTION_NAME) || !defined (STEP)
+# error Must define FUNCTION_NAME and STEP
+#endif
+
+static inline void
+FUNCTION_NAME(const DATA32* restrict srcdata, DATA32* restrict dstdata,
+ const int radius, const int len,
+ const int loops, const int loopstep,
+ const int* restrict weights, const int pow2_divider)
+{
+ const int diameter = 2 * radius + 1;
+ const int left = MIN(radius, len);
+ const int right = MIN(radius, (len - radius));
+ const DATA32* restrict src;
+ DATA32* restrict dst;
+ int i, j, k;
+
+ for (i = loops; i; --i)
+ {
+ src = srcdata;
+ dst = dstdata;
+
+ // left
+ for (k = 0; k < left; k++, dst += STEP)
+ {
+ int acc[4] = {0};
+ int divider = 0;
+ const DATA32* restrict s = src;
+ for (j = 0; j <= k + radius; j++, s += STEP)
+ {
+ const int weightidx = j + radius - k;
+ acc[ALPHA] += A_VAL(s) * weights[weightidx];
+ acc[RED] += R_VAL(s) * weights[weightidx];
+ acc[GREEN] += G_VAL(s) * weights[weightidx];
+ acc[BLUE] += B_VAL(s) * weights[weightidx];
+ divider += weights[weightidx];
+ }
+ //if (!divider) abort();
+ A_VAL(dst) = acc[ALPHA] / divider;
+ R_VAL(dst) = acc[RED] / divider;
+ G_VAL(dst) = acc[GREEN] / divider;
+ B_VAL(dst) = acc[BLUE] / divider;
+ }
+
+ // middle
+ for (k = len - (2 * radius); k > 0; k--, src += STEP, dst += STEP)
+ {
+ int acc[4] = {0};
+ const DATA32* restrict s = src;
+ for (j = 0; j < diameter; j++, s += STEP)
+ {
+ acc[ALPHA] += A_VAL(s) * weights[j];
+ acc[RED] += R_VAL(s) * weights[j];
+ acc[GREEN] += G_VAL(s) * weights[j];
+ acc[BLUE] += B_VAL(s) * weights[j];
+ }
+ A_VAL(dst) = acc[ALPHA] >> pow2_divider;
+ R_VAL(dst) = acc[RED] >> pow2_divider;
+ G_VAL(dst) = acc[GREEN] >> pow2_divider;
+ B_VAL(dst) = acc[BLUE] >> pow2_divider;
+ }
+
+ // right
+ for (k = 0; k < right; k++, dst += STEP, src += STEP)
+ {
+ int acc[4] = {0};
+ int divider = 0;
+ const DATA32* restrict s = src;
+ for (j = 0; j < 2 * radius - k; j++, s += STEP)
+ {
+ acc[ALPHA] += A_VAL(s) * weights[j];
+ acc[RED] += R_VAL(s) * weights[j];
+ acc[GREEN] += G_VAL(s) * weights[j];
+ acc[BLUE] += B_VAL(s) * weights[j];
+ divider += weights[j];
+ }
+ //if (!divider) abort();
+ A_VAL(dst) = acc[ALPHA] / divider;
+ R_VAL(dst) = acc[RED] / divider;
+ G_VAL(dst) = acc[GREEN] / divider;
+ B_VAL(dst) = acc[BLUE] / divider;
+ }
+
+ dstdata += loopstep;
+ srcdata += loopstep;
+ }
+}
+
+#undef FUNCTION_NAME
+#undef STEP
#include <time.h>
// Enable debug if you're working on optimizations
-#define DEBUG_TIME 0
+#define DEBUG_TIME 1
// Windows build will break if CLOCK_MONOTONIC is used
#if !defined(_POSIX_MONOTONIC_CLOCK) || (_POSIX_MONOTONIC_CLOCK < 0)
*pow2_divider = nextpow2;
}
-static void
-_gaussian_blur_step_rgba(DATA32 *src, DATA32 *dst, int radius, int len, int step,
- int *weights, int pow2_divider)
-{
- const int diameter = 2 * radius + 1;
- int left = MIN(radius, len);
- int right = MIN(radius, (len - radius));
- int j, k;
-
- // left
- for (k = 0; k < left; k++, dst += step)
- {
- int acc[4] = {0};
- int divider = 0;
- DATA32 *s = src;
- for (j = 0; j <= k + radius; j++, s += step)
- {
- const int weightidx = j + radius - k;
- acc[ALPHA] += A_VAL(s) * weights[weightidx];
- acc[RED] += R_VAL(s) * weights[weightidx];
- acc[GREEN] += G_VAL(s) * weights[weightidx];
- acc[BLUE] += B_VAL(s) * weights[weightidx];
- divider += weights[weightidx];
- }
- if (!divider) goto div_zero;
- A_VAL(dst) = acc[ALPHA] / divider;
- R_VAL(dst) = acc[RED] / divider;
- G_VAL(dst) = acc[GREEN] / divider;
- B_VAL(dst) = acc[BLUE] / divider;
- }
-
- // middle
- for (k = len - (2 * radius); k > 0; k--, src += step, dst += step)
- {
- int acc[4] = {0};
- DATA32 *s = src;
- for (j = 0; j < diameter; j++, s += step)
- {
- acc[ALPHA] += A_VAL(s) * weights[j];
- acc[RED] += R_VAL(s) * weights[j];
- acc[GREEN] += G_VAL(s) * weights[j];
- acc[BLUE] += B_VAL(s) * weights[j];
- }
- A_VAL(dst) = acc[ALPHA] >> pow2_divider;
- R_VAL(dst) = acc[RED] >> pow2_divider;
- G_VAL(dst) = acc[GREEN] >> pow2_divider;
- B_VAL(dst) = acc[BLUE] >> pow2_divider;
- }
-
- // right
- for (k = 0; k < right; k++, dst += step, src += step)
- {
- int acc[4] = {0};
- int divider = 0;
- DATA32 *s = src;
- for (j = 0; j < 2 * radius - k; j++, s += step)
- {
- acc[ALPHA] += A_VAL(s) * weights[j];
- acc[RED] += R_VAL(s) * weights[j];
- acc[GREEN] += G_VAL(s) * weights[j];
- acc[BLUE] += B_VAL(s) * weights[j];
- divider += weights[j];
- }
- if (!divider) goto div_zero;
- A_VAL(dst) = acc[ALPHA] / divider;
- R_VAL(dst) = acc[RED] / divider;
- G_VAL(dst) = acc[GREEN] / divider;
- B_VAL(dst) = acc[BLUE] / divider;
- }
-
- return;
-
-div_zero:
- CRI("Division by zero avoided! Something is very wrong here!");
-}
-
#define FUNCTION_NAME _gaussian_blur_horiz_alpha_step
#define STEP 1
#include "./blur/blur_gaussian_alpha_.c"
DEBUG_TIME_END();
}
-// w steps, loops = w --> STEP = loops
+// Step size is w (row by row), loops = w, so STEP = 'loops'
#define FUNCTION_NAME _gaussian_blur_vert_alpha_step
#define STEP loops
#include "./blur/blur_gaussian_alpha_.c"
DEBUG_TIME_END();
}
+#define FUNCTION_NAME _gaussian_blur_horiz_rgba_step
+#define STEP 1
+#include "./blur/blur_gaussian_rgba_.c"
+
static void
_gaussian_blur_horiz_rgba(DATA32 *src, DATA32 *dst, int radius, int w, int h)
{
int *weights;
- int k, pow2_div = 0;
+ int pow2_div = 0;
weights = alloca((2 * radius + 1) * sizeof(int));
_sin_blur_weights_get(weights, &pow2_div, radius);
DEBUG_TIME_BEGIN();
-
- for (k = h; k; k--)
- {
- _gaussian_blur_step_rgba(src, dst, radius, w, 1, weights, pow2_div);
- dst += w;
- src += w;
- }
-
+ _gaussian_blur_horiz_rgba_step(src, dst, radius, w, h, w, weights, pow2_div);
DEBUG_TIME_END();
}
+#define FUNCTION_NAME _gaussian_blur_vert_rgba_step
+#define STEP loops
+#include "./blur/blur_gaussian_rgba_.c"
+
static void
_gaussian_blur_vert_rgba(DATA32 *src, DATA32 *dst, int radius, int w, int h)
{
int *weights;
- int k, pow2_div = 0;
+ int pow2_div = 0;
weights = alloca((2 * radius + 1) * sizeof(int));
_sin_blur_weights_get(weights, &pow2_div, radius);
DEBUG_TIME_BEGIN();
-
- for (k = w; k; k--)
- {
- _gaussian_blur_step_rgba(src, dst, radius, h, w, weights, pow2_div);
- dst += 1;
- src += 1;
- }
-
+ _gaussian_blur_vert_rgba_step(src, dst, radius, h, w, 1, weights, pow2_div);
DEBUG_TIME_END();
}