FastLED 3.10.8
Loading...
Searching...
No Matches
fl::gfx::blur_detail Namespace Reference

Classes

struct  interior_row
 
struct  interior_row< 0, RGB_T, acc_t >
 
struct  interior_row< 1, RGB_T, acc_t >
 
struct  interior_row< 2, RGB_T, acc_t >
 
struct  interior_row< 3, RGB_T, acc_t >
 
struct  interior_row< 4, RGB_T, acc_t >
 
struct  pixel_ops
 
struct  pixel_ops< CRGB >
 
struct  pixel_ops< CRGB16 >
 
struct  simd_hconv_dispatch
 
struct  simd_hconv_dispatch< 0 >
 
struct  simd_hconv_dispatch< 1 >
 
struct  simd_hconv_dispatch< 2 >
 
struct  simd_hconv_dispatch< 3 >
 
struct  simd_hconv_dispatch< 4 >
 
struct  simd_vconv_dispatch
 
struct  simd_vconv_dispatch< 0 >
 
struct  simd_vconv_dispatch< 1 >
 
struct  simd_vconv_dispatch< 2 >
 
struct  simd_vconv_dispatch< 3 >
 
struct  simd_vconv_dispatch< 4 >
 
struct  vpass_pixel_kernel
 
struct  vpass_pixel_kernel< 0, RGB_T, acc_t >
 
struct  vpass_pixel_kernel< 1, RGB_T, acc_t >
 
struct  vpass_pixel_kernel< 2, RGB_T, acc_t >
 
struct  vpass_pixel_kernel< 3, RGB_T, acc_t >
 
struct  vpass_pixel_kernel< 4, RGB_T, acc_t >
 

Functions

template<typename AlphaT>
constexpr AlphaT alpha_identity () FL_NO_EXCEPT
 
template<>
constexpr alpha16 alpha_identity< alpha16 > () FL_NO_EXCEPT
 
template<>
constexpr alpha8 alpha_identity< alpha8 > () FL_NO_EXCEPT
 
template<int R, typename RGB_T, typename acc_t>
FL_NO_INLINE_IF_AVR static FL_OPTIMIZE_FUNCTION void apply_pass (const RGB_T *pad, RGB_T *out, int count, int stride) FL_NO_EXCEPT
 
template<int R, typename RGB_T, typename acc_t, typename AlphaT>
FL_NO_INLINE_IF_AVR static FL_OPTIMIZE_FUNCTION void apply_pass_alpha (const RGB_T *pad, RGB_T *out, int count, int stride, AlphaT alpha) FL_NO_EXCEPT
 
template<int hR, int vR, typename RGB_T>
static int compute_pad_size (int w, int h) FL_NO_EXCEPT
 
template<typename RGB_T>
static fl::span< RGB_T > get_padbuf (int minSize) FL_NO_EXCEPT
 
template<int R, typename RGB_T, typename acc_t, bool ApplyAlpha, typename AlphaT>
FL_ALWAYS_INLINE void hpass_row (RGB_T *pad, RGB_T *out, int w, AlphaT alpha) FL_NO_EXCEPT
 
static void simd_conv_121 (const u8 *FL_RESTRICT_PARAM a, const u8 *FL_RESTRICT_PARAM b, const u8 *FL_RESTRICT_PARAM c, u8 *FL_RESTRICT_PARAM out, int nbytes) FL_NO_EXCEPT
 
static void simd_conv_14641 (const u8 *p0, const u8 *p1, const u8 *p2, const u8 *p3, const u8 *p4, u8 *out, int nbytes) FL_NO_EXCEPT
 
static void simd_conv_r3 (const u8 *p0, const u8 *p1, const u8 *p2, const u8 *p3, const u8 *p4, const u8 *p5, const u8 *p6, u8 *out, int nbytes) FL_NO_EXCEPT
 
static void simd_conv_r4 (const u8 *p0, const u8 *p1, const u8 *p2, const u8 *p3, const u8 *p4, const u8 *p5, const u8 *p6, const u8 *p7, const u8 *p8, u8 *out, int nbytes) FL_NO_EXCEPT
 
template<int R, typename RGB_T, typename acc_t, bool ApplyAlpha, typename AlphaT>
static void vpass_full (RGB_T *pixels, int w, int h, RGB_T *scratch, AlphaT alpha) FL_NO_EXCEPT
 
template<int R, typename RGB_T, typename acc_t, bool ApplyAlpha, typename AlphaT>
static FL_OPTIMIZE_FUNCTION void vpass_rowmajor_impl (RGB_T *pixels, int w, int h, RGB_T *scratch, AlphaT alpha) FL_NO_EXCEPT
 

◆ fl::gfx::blur_detail::pixel_ops

struct fl::gfx::blur_detail::pixel_ops
+ Inheritance diagram for fl::gfx::blur_detail::pixel_ops< RGB_T >:

◆ fl::gfx::blur_detail::simd_hconv_dispatch

struct fl::gfx::blur_detail::simd_hconv_dispatch
+ Inheritance diagram for fl::gfx::blur_detail::simd_hconv_dispatch< R >:

◆ fl::gfx::blur_detail::simd_vconv_dispatch

struct fl::gfx::blur_detail::simd_vconv_dispatch
+ Inheritance diagram for fl::gfx::blur_detail::simd_vconv_dispatch< R >:

◆ fl::gfx::blur_detail::vpass_pixel_kernel

struct fl::gfx::blur_detail::vpass_pixel_kernel
+ Inheritance diagram for fl::gfx::blur_detail::vpass_pixel_kernel< R, RGB_T, acc_t >:

Function Documentation

◆ alpha_identity()

template<typename AlphaT>
AlphaT fl::gfx::blur_detail::alpha_identity ( )
constexpr

References fl::FL_NO_EXCEPT.

Referenced by alpha_identity< alpha8 >(), fl::gfx::blurGaussianImpl(), and fl::gfx::blurGaussianMappedImpl().

+ Here is the caller graph for this function:

◆ alpha_identity< alpha16 >()

template<>
alpha16 fl::gfx::blur_detail::alpha_identity< alpha16 > ( )
constexpr

Definition at line 291 of file blur.cpp.hpp.

291{ return alpha16(65535); }
Unsigned 16-bit alpha / brightness — UNORM16.
Definition alpha.h:87

References fl::FL_NO_EXCEPT.

◆ alpha_identity< alpha8 >()

template<>
alpha8 fl::gfx::blur_detail::alpha_identity< alpha8 > ( )
constexpr

Definition at line 290 of file blur.cpp.hpp.

290{ return alpha8(255); }
Unsigned 8-bit alpha / brightness — UNORM8.
Definition alpha.h:42

References alpha_identity(), constexpr, and fl::FL_NO_EXCEPT.

+ Here is the call graph for this function:

◆ apply_pass()

template<int R, typename RGB_T, typename acc_t>
FL_NO_INLINE_IF_AVR static FL_OPTIMIZE_FUNCTION void fl::gfx::blur_detail::apply_pass ( const RGB_T * pad,
RGB_T * out,
int count,
int stride )
static

Definition at line 564 of file blur.cpp.hpp.

564 {
565 constexpr int shift = 2 * R;
566 using P = pixel_ops<RGB_T>;
567 for (int i = 0; i < count; ++i) {
568 acc_t r, g, b;
569 interior_row<R, RGB_T, acc_t>::apply(pad, R + i, r, g, b);
570 *out = P::make(static_cast<acc_t>(r >> shift),
571 static_cast<acc_t>(g >> shift),
572 static_cast<acc_t>(b >> shift));
573 out += stride;
574 }
575}
FASTLED_FORCE_INLINE fl::u8 P(fl::u8 x) FL_NO_EXCEPT
InputGamut g
Definition rgbw.h:125

References fl::FL_NO_EXCEPT, fl::g, and fl::P().

Referenced by hpass_row().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ apply_pass_alpha()

template<int R, typename RGB_T, typename acc_t, typename AlphaT>
FL_NO_INLINE_IF_AVR static FL_OPTIMIZE_FUNCTION void fl::gfx::blur_detail::apply_pass_alpha ( const RGB_T * pad,
RGB_T * out,
int count,
int stride,
AlphaT alpha )
static

Definition at line 579 of file blur.cpp.hpp.

580 {
581 constexpr int shift = 2 * R;
582 using P = pixel_ops<RGB_T>;
583 for (int i = 0; i < count; ++i) {
584 acc_t r, g, b;
585 interior_row<R, RGB_T, acc_t>::apply(pad, R + i, r, g, b);
586 *out = P::make(static_cast<acc_t>(r >> shift),
587 static_cast<acc_t>(g >> shift),
588 static_cast<acc_t>(b >> shift), alpha);
589 out += stride;
590 }
591}

References fl::FL_NO_EXCEPT, fl::g, and fl::P().

Referenced by hpass_row().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ compute_pad_size()

template<int hR, int vR, typename RGB_T>
static int fl::gfx::blur_detail::compute_pad_size ( int w,
int h )
static

Definition at line 1050 of file blur.cpp.hpp.

1050 {
1051 int hPad = 2 * hR + w;
1052#if defined(FL_IS_AVR)
1053 int vPad = 2 * vR + h;
1054#else
1055 int vPad = vR > 0 ? (vR + 2) * w : 0;
1056#endif
1057 return hPad > vPad ? hPad : vPad;
1058}

References fl::FL_NO_EXCEPT.

Referenced by fl::gfx::blurGaussianImpl(), and fl::gfx::blurGaussianMappedImpl().

+ Here is the caller graph for this function:

◆ get_padbuf()

template<typename RGB_T>
static fl::span< RGB_T > fl::gfx::blur_detail::get_padbuf ( int minSize)
static

Definition at line 350 of file blur.cpp.hpp.

350 {
352 if (static_cast<int>(buf.size()) < minSize) {
353 buf.resize(minSize);
354 }
355 return buf;
356}
fl::size size() const FL_NO_EXCEPT
void resize(fl::size n) FL_NO_EXCEPT
Definition vector.h:593

References fl::FL_NO_EXCEPT, fl::vector< T >::resize(), and fl::vector_basic::size().

Referenced by fl::gfx::blurGaussianImpl(), and fl::gfx::blurGaussianMappedImpl().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ hpass_row()

template<int R, typename RGB_T, typename acc_t, bool ApplyAlpha, typename AlphaT>
FL_ALWAYS_INLINE void fl::gfx::blur_detail::hpass_row ( RGB_T * pad,
RGB_T * out,
int w,
AlphaT alpha )

Definition at line 1064 of file blur.cpp.hpp.

1064 {
1065#if defined(FL_IS_AVR)
1066 if (ApplyAlpha)
1067 apply_pass_alpha_1ch<R>(pad, out, w, 1, alpha);
1068 else
1069 apply_pass_1ch<R>(pad, out, w, 1);
1070#else
1071 // SIMD fast path: u8-channel (CRGB), no alpha on this pass.
1072 if (sizeof(typename RGB_T::fp) == 1 && !ApplyAlpha) {
1073 constexpr int S = (int)sizeof(RGB_T);
1074 const int nbytes = w * S;
1075 const u8 *pb = (const u8 *)pad;
1076 u8 *ob = (u8 *)out;
1078 pb, S, ob, nbytes, (u8 *)(pad + 2 * R + w), w);
1079 } else if (ApplyAlpha) {
1080 apply_pass_alpha<R, RGB_T, acc_t>(pad, out, w, 1, alpha);
1081 } else {
1082 apply_pass<R, RGB_T, acc_t>(pad, out, w, 1);
1083 }
1084#endif
1085}
FL_NO_INLINE_IF_AVR static FL_OPTIMIZE_FUNCTION void apply_pass_alpha(const RGB_T *pad, RGB_T *out, int count, int stride, AlphaT alpha) FL_NO_EXCEPT
Definition blur.cpp.hpp:579
FL_NO_INLINE_IF_AVR static FL_OPTIMIZE_FUNCTION void apply_pass(const RGB_T *pad, RGB_T *out, int count, int stride) FL_NO_EXCEPT
Definition blur.cpp.hpp:564
unsigned char u8
Definition stdint.h:131

References apply_pass(), apply_pass_alpha(), and fl::FL_NO_EXCEPT.

Referenced by fl::gfx::blurGaussianImpl().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ simd_conv_121()

static void fl::gfx::blur_detail::simd_conv_121 ( const u8 *FL_RESTRICT_PARAM a,
const u8 *FL_RESTRICT_PARAM b,
const u8 *FL_RESTRICT_PARAM c,
u8 *FL_RESTRICT_PARAM out,
int nbytes )
static

Definition at line 606 of file blur.cpp.hpp.

609 {
610 namespace fsimd = fl::simd; // ok bare using
611 int i = 0;
612 for (; i + 63 < nbytes; i += 64) {
613 auto va0 = fsimd::load_u8_32(a+i), vb0 = fsimd::load_u8_32(b+i), vc0 = fsimd::load_u8_32(c+i);
614 auto va1 = fsimd::load_u8_32(a+i+32), vb1 = fsimd::load_u8_32(b+i+32), vc1 = fsimd::load_u8_32(c+i+32);
615 fsimd::store_u8_32(out+i, fsimd::avg_round_u8_32(fsimd::avg_round_u8_32(va0, vc0), vb0));
616 fsimd::store_u8_32(out+i+32, fsimd::avg_round_u8_32(fsimd::avg_round_u8_32(va1, vc1), vb1));
617 }
618 for (; i + 31 < nbytes; i += 32) {
619 auto va = fsimd::load_u8_32(a+i), vb = fsimd::load_u8_32(b+i), vc = fsimd::load_u8_32(c+i);
620 fsimd::store_u8_32(out+i, fsimd::avg_round_u8_32(fsimd::avg_round_u8_32(va, vc), vb));
621 }
622 for (; i + 15 < nbytes; i += 16) {
623 auto va = fsimd::load_u8_16(a+i), vb = fsimd::load_u8_16(b+i), vc = fsimd::load_u8_16(c+i);
624 fsimd::store_u8_16(out+i, fsimd::avg_round_u8_16(fsimd::avg_round_u8_16(va, vc), vb));
625 }
626 for (; i < nbytes; ++i)
627 out[i] = (u8)(((u16)a[i] + ((u16)b[i] << 1) + (u16)c[i]) >> 2);
628}

References fl::FL_NO_EXCEPT, and FL_RESTRICT_PARAM.

Referenced by fl::gfx::blur_detail::simd_hconv_dispatch< 1 >::apply(), and fl::gfx::blur_detail::simd_vconv_dispatch< 1 >::apply().

+ Here is the caller graph for this function:

◆ simd_conv_14641()

static void fl::gfx::blur_detail::simd_conv_14641 ( const u8 * p0,
const u8 * p1,
const u8 * p2,
const u8 * p3,
const u8 * p4,
u8 * out,
int nbytes )
static

Definition at line 634 of file blur.cpp.hpp.

636 {
637 namespace fsimd = fl::simd; // ok bare using
638 const auto w4w = fsimd::set1_u16_16(4), w6w = fsimd::set1_u16_16(6);
639 const auto w4 = fsimd::set1_u16_8(4), w6 = fsimd::set1_u16_8(6);
640 int i = 0;
641 for (; i + 31 < nbytes; i += 32) {
642 auto v0 = fsimd::load_u8_32(p0+i), v1 = fsimd::load_u8_32(p1+i);
643 auto v2 = fsimd::load_u8_32(p2+i), v3 = fsimd::load_u8_32(p3+i), v4 = fsimd::load_u8_32(p4+i);
644 auto s04 = fsimd::add_u16_16(fsimd::widen_lo_u8x32_to_u16(v0), fsimd::widen_lo_u8x32_to_u16(v4));
645 auto s13 = fsimd::add_u16_16(fsimd::widen_lo_u8x32_to_u16(v1), fsimd::widen_lo_u8x32_to_u16(v3));
646 auto lo = fsimd::add_u16_16(s04, fsimd::add_u16_16(fsimd::mullo_u16_16(s13, w4w), fsimd::mullo_u16_16(fsimd::widen_lo_u8x32_to_u16(v2), w6w)));
647 lo = fsimd::srli_u16_16(lo, 4);
648 auto s04h = fsimd::add_u16_16(fsimd::widen_hi_u8x32_to_u16(v0), fsimd::widen_hi_u8x32_to_u16(v4));
649 auto s13h = fsimd::add_u16_16(fsimd::widen_hi_u8x32_to_u16(v1), fsimd::widen_hi_u8x32_to_u16(v3));
650 auto hi = fsimd::add_u16_16(s04h, fsimd::add_u16_16(fsimd::mullo_u16_16(s13h, w4w), fsimd::mullo_u16_16(fsimd::widen_hi_u8x32_to_u16(v2), w6w)));
651 hi = fsimd::srli_u16_16(hi, 4);
652 fsimd::store_u8_32(out+i, fsimd::narrow_u16x16_to_u8(lo, hi));
653 }
654 for (; i + 15 < nbytes; i += 16) {
655 auto v0 = fsimd::load_u8_16(p0+i), v1 = fsimd::load_u8_16(p1+i);
656 auto v2 = fsimd::load_u8_16(p2+i), v3 = fsimd::load_u8_16(p3+i), v4 = fsimd::load_u8_16(p4+i);
657 auto s04 = fsimd::add_u16_8(fsimd::widen_lo_u8_to_u16(v0), fsimd::widen_lo_u8_to_u16(v4));
658 auto s13 = fsimd::add_u16_8(fsimd::widen_lo_u8_to_u16(v1), fsimd::widen_lo_u8_to_u16(v3));
659 auto lo = fsimd::add_u16_8(s04, fsimd::add_u16_8(fsimd::mullo_u16_8(s13, w4), fsimd::mullo_u16_8(fsimd::widen_lo_u8_to_u16(v2), w6)));
660 lo = fsimd::srli_u16_8(lo, 4);
661 auto s04h = fsimd::add_u16_8(fsimd::widen_hi_u8_to_u16(v0), fsimd::widen_hi_u8_to_u16(v4));
662 auto s13h = fsimd::add_u16_8(fsimd::widen_hi_u8_to_u16(v1), fsimd::widen_hi_u8_to_u16(v3));
663 auto hi = fsimd::add_u16_8(s04h, fsimd::add_u16_8(fsimd::mullo_u16_8(s13h, w4), fsimd::mullo_u16_8(fsimd::widen_hi_u8_to_u16(v2), w6)));
664 hi = fsimd::srli_u16_8(hi, 4);
665 fsimd::store_u8_16(out+i, fsimd::narrow_u16_to_u8(lo, hi));
666 }
667 for (; i < nbytes; ++i) {
668 u16 s04 = (u16)p0[i] + (u16)p4[i];
669 u16 s13 = (u16)p1[i] + (u16)p3[i];
670 out[i] = (u8)((s04 + s13 * 4 + (u16)p2[i] * 6) >> 4);
671 }
672}

References fl::FL_NO_EXCEPT.

Referenced by fl::gfx::blur_detail::simd_hconv_dispatch< 2 >::apply(), and fl::gfx::blur_detail::simd_vconv_dispatch< 2 >::apply().

+ Here is the caller graph for this function:

◆ simd_conv_r3()

static void fl::gfx::blur_detail::simd_conv_r3 ( const u8 * p0,
const u8 * p1,
const u8 * p2,
const u8 * p3,
const u8 * p4,
const u8 * p5,
const u8 * p6,
u8 * out,
int nbytes )
static

Definition at line 675 of file blur.cpp.hpp.

677 {
678 namespace fsimd = fl::simd; // ok bare using
679 const auto w6w = fsimd::set1_u16_16(6), w15w = fsimd::set1_u16_16(15), w20w = fsimd::set1_u16_16(20);
680 const auto w6 = fsimd::set1_u16_8(6), w15 = fsimd::set1_u16_8(15), w20 = fsimd::set1_u16_8(20);
681 int i = 0;
682 for (; i + 31 < nbytes; i += 32) {
683 auto v0 = fsimd::load_u8_32(p0+i), v1 = fsimd::load_u8_32(p1+i), v2 = fsimd::load_u8_32(p2+i);
684 auto v3 = fsimd::load_u8_32(p3+i), v4 = fsimd::load_u8_32(p4+i), v5 = fsimd::load_u8_32(p5+i);
685 auto v6v = fsimd::load_u8_32(p6+i);
686 auto s06 = fsimd::add_u16_16(fsimd::widen_lo_u8x32_to_u16(v0), fsimd::widen_lo_u8x32_to_u16(v6v));
687 auto s15 = fsimd::add_u16_16(fsimd::widen_lo_u8x32_to_u16(v1), fsimd::widen_lo_u8x32_to_u16(v5));
688 auto s24 = fsimd::add_u16_16(fsimd::widen_lo_u8x32_to_u16(v2), fsimd::widen_lo_u8x32_to_u16(v4));
689 auto lo = fsimd::add_u16_16(s06, fsimd::add_u16_16(fsimd::mullo_u16_16(s15, w6w),
690 fsimd::add_u16_16(fsimd::mullo_u16_16(s24, w15w), fsimd::mullo_u16_16(fsimd::widen_lo_u8x32_to_u16(v3), w20w))));
691 lo = fsimd::srli_u16_16(lo, 6);
692 auto s06h = fsimd::add_u16_16(fsimd::widen_hi_u8x32_to_u16(v0), fsimd::widen_hi_u8x32_to_u16(v6v));
693 auto s15h = fsimd::add_u16_16(fsimd::widen_hi_u8x32_to_u16(v1), fsimd::widen_hi_u8x32_to_u16(v5));
694 auto s24h = fsimd::add_u16_16(fsimd::widen_hi_u8x32_to_u16(v2), fsimd::widen_hi_u8x32_to_u16(v4));
695 auto hi = fsimd::add_u16_16(s06h, fsimd::add_u16_16(fsimd::mullo_u16_16(s15h, w6w),
696 fsimd::add_u16_16(fsimd::mullo_u16_16(s24h, w15w), fsimd::mullo_u16_16(fsimd::widen_hi_u8x32_to_u16(v3), w20w))));
697 hi = fsimd::srli_u16_16(hi, 6);
698 fsimd::store_u8_32(out+i, fsimd::narrow_u16x16_to_u8(lo, hi));
699 }
700 for (; i + 15 < nbytes; i += 16) {
701 auto v0 = fsimd::load_u8_16(p0+i), v1 = fsimd::load_u8_16(p1+i), v2 = fsimd::load_u8_16(p2+i);
702 auto v3 = fsimd::load_u8_16(p3+i), v4 = fsimd::load_u8_16(p4+i), v5 = fsimd::load_u8_16(p5+i);
703 auto v6v = fsimd::load_u8_16(p6+i);
704 auto s06 = fsimd::add_u16_8(fsimd::widen_lo_u8_to_u16(v0), fsimd::widen_lo_u8_to_u16(v6v));
705 auto s15 = fsimd::add_u16_8(fsimd::widen_lo_u8_to_u16(v1), fsimd::widen_lo_u8_to_u16(v5));
706 auto s24 = fsimd::add_u16_8(fsimd::widen_lo_u8_to_u16(v2), fsimd::widen_lo_u8_to_u16(v4));
707 auto lo = fsimd::add_u16_8(s06, fsimd::add_u16_8(fsimd::mullo_u16_8(s15, w6),
708 fsimd::add_u16_8(fsimd::mullo_u16_8(s24, w15), fsimd::mullo_u16_8(fsimd::widen_lo_u8_to_u16(v3), w20))));
709 lo = fsimd::srli_u16_8(lo, 6);
710 auto s06h = fsimd::add_u16_8(fsimd::widen_hi_u8_to_u16(v0), fsimd::widen_hi_u8_to_u16(v6v));
711 auto s15h = fsimd::add_u16_8(fsimd::widen_hi_u8_to_u16(v1), fsimd::widen_hi_u8_to_u16(v5));
712 auto s24h = fsimd::add_u16_8(fsimd::widen_hi_u8_to_u16(v2), fsimd::widen_hi_u8_to_u16(v4));
713 auto hi = fsimd::add_u16_8(s06h, fsimd::add_u16_8(fsimd::mullo_u16_8(s15h, w6),
714 fsimd::add_u16_8(fsimd::mullo_u16_8(s24h, w15), fsimd::mullo_u16_8(fsimd::widen_hi_u8_to_u16(v3), w20))));
715 hi = fsimd::srli_u16_8(hi, 6);
716 fsimd::store_u8_16(out+i, fsimd::narrow_u16_to_u8(lo, hi));
717 }
718 for (; i < nbytes; ++i) {
719 u16 s06=(u16)p0[i]+(u16)p6[i], s15=(u16)p1[i]+(u16)p5[i], s24=(u16)p2[i]+(u16)p4[i];
720 out[i]=(u8)((s06+s15*6+s24*15+(u16)p3[i]*20)>>6);
721 }
722}

References fl::FL_NO_EXCEPT.

Referenced by fl::gfx::blur_detail::simd_hconv_dispatch< 3 >::apply(), and fl::gfx::blur_detail::simd_vconv_dispatch< 3 >::apply().

+ Here is the caller graph for this function:

◆ simd_conv_r4()

static void fl::gfx::blur_detail::simd_conv_r4 ( const u8 * p0,
const u8 * p1,
const u8 * p2,
const u8 * p3,
const u8 * p4,
const u8 * p5,
const u8 * p6,
const u8 * p7,
const u8 * p8,
u8 * out,
int nbytes )
static

Definition at line 725 of file blur.cpp.hpp.

727 {
728 namespace fsimd = fl::simd; // ok bare using
729 const auto w8w = fsimd::set1_u16_16(8), w28w = fsimd::set1_u16_16(28);
730 const auto w56w = fsimd::set1_u16_16(56), w70w = fsimd::set1_u16_16(70);
731 const auto w8 = fsimd::set1_u16_8(8), w28 = fsimd::set1_u16_8(28);
732 const auto w56 = fsimd::set1_u16_8(56), w70 = fsimd::set1_u16_8(70);
733 int i = 0;
734 for (; i + 31 < nbytes; i += 32) {
735 auto v0 = fsimd::load_u8_32(p0+i), v1 = fsimd::load_u8_32(p1+i), v2 = fsimd::load_u8_32(p2+i);
736 auto v3 = fsimd::load_u8_32(p3+i), v4 = fsimd::load_u8_32(p4+i), v5 = fsimd::load_u8_32(p5+i);
737 auto v6v = fsimd::load_u8_32(p6+i), v7 = fsimd::load_u8_32(p7+i), v8v = fsimd::load_u8_32(p8+i);
738 auto s08 = fsimd::add_u16_16(fsimd::widen_lo_u8x32_to_u16(v0), fsimd::widen_lo_u8x32_to_u16(v8v));
739 auto s17 = fsimd::add_u16_16(fsimd::widen_lo_u8x32_to_u16(v1), fsimd::widen_lo_u8x32_to_u16(v7));
740 auto s26 = fsimd::add_u16_16(fsimd::widen_lo_u8x32_to_u16(v2), fsimd::widen_lo_u8x32_to_u16(v6v));
741 auto s35 = fsimd::add_u16_16(fsimd::widen_lo_u8x32_to_u16(v3), fsimd::widen_lo_u8x32_to_u16(v5));
742 auto lo = fsimd::add_u16_16(s08, fsimd::add_u16_16(fsimd::mullo_u16_16(s17, w8w),
743 fsimd::add_u16_16(fsimd::mullo_u16_16(s26, w28w),
744 fsimd::add_u16_16(fsimd::mullo_u16_16(s35, w56w), fsimd::mullo_u16_16(fsimd::widen_lo_u8x32_to_u16(v4), w70w)))));
745 lo = fsimd::srli_u16_16(lo, 8);
746 auto s08h = fsimd::add_u16_16(fsimd::widen_hi_u8x32_to_u16(v0), fsimd::widen_hi_u8x32_to_u16(v8v));
747 auto s17h = fsimd::add_u16_16(fsimd::widen_hi_u8x32_to_u16(v1), fsimd::widen_hi_u8x32_to_u16(v7));
748 auto s26h = fsimd::add_u16_16(fsimd::widen_hi_u8x32_to_u16(v2), fsimd::widen_hi_u8x32_to_u16(v6v));
749 auto s35h = fsimd::add_u16_16(fsimd::widen_hi_u8x32_to_u16(v3), fsimd::widen_hi_u8x32_to_u16(v5));
750 auto hi = fsimd::add_u16_16(s08h, fsimd::add_u16_16(fsimd::mullo_u16_16(s17h, w8w),
751 fsimd::add_u16_16(fsimd::mullo_u16_16(s26h, w28w),
752 fsimd::add_u16_16(fsimd::mullo_u16_16(s35h, w56w), fsimd::mullo_u16_16(fsimd::widen_hi_u8x32_to_u16(v4), w70w)))));
753 hi = fsimd::srli_u16_16(hi, 8);
754 fsimd::store_u8_32(out+i, fsimd::narrow_u16x16_to_u8(lo, hi));
755 }
756 for (; i + 15 < nbytes; i += 16) {
757 auto v0 = fsimd::load_u8_16(p0+i), v1 = fsimd::load_u8_16(p1+i), v2 = fsimd::load_u8_16(p2+i);
758 auto v3 = fsimd::load_u8_16(p3+i), v4 = fsimd::load_u8_16(p4+i), v5 = fsimd::load_u8_16(p5+i);
759 auto v6v = fsimd::load_u8_16(p6+i), v7 = fsimd::load_u8_16(p7+i), v8v = fsimd::load_u8_16(p8+i);
760 auto s08 = fsimd::add_u16_8(fsimd::widen_lo_u8_to_u16(v0), fsimd::widen_lo_u8_to_u16(v8v));
761 auto s17 = fsimd::add_u16_8(fsimd::widen_lo_u8_to_u16(v1), fsimd::widen_lo_u8_to_u16(v7));
762 auto s26 = fsimd::add_u16_8(fsimd::widen_lo_u8_to_u16(v2), fsimd::widen_lo_u8_to_u16(v6v));
763 auto s35 = fsimd::add_u16_8(fsimd::widen_lo_u8_to_u16(v3), fsimd::widen_lo_u8_to_u16(v5));
764 auto lo = fsimd::add_u16_8(s08, fsimd::add_u16_8(fsimd::mullo_u16_8(s17, w8),
765 fsimd::add_u16_8(fsimd::mullo_u16_8(s26, w28),
766 fsimd::add_u16_8(fsimd::mullo_u16_8(s35, w56), fsimd::mullo_u16_8(fsimd::widen_lo_u8_to_u16(v4), w70)))));
767 lo = fsimd::srli_u16_8(lo, 8);
768 auto s08h = fsimd::add_u16_8(fsimd::widen_hi_u8_to_u16(v0), fsimd::widen_hi_u8_to_u16(v8v));
769 auto s17h = fsimd::add_u16_8(fsimd::widen_hi_u8_to_u16(v1), fsimd::widen_hi_u8_to_u16(v7));
770 auto s26h = fsimd::add_u16_8(fsimd::widen_hi_u8_to_u16(v2), fsimd::widen_hi_u8_to_u16(v6v));
771 auto s35h = fsimd::add_u16_8(fsimd::widen_hi_u8_to_u16(v3), fsimd::widen_hi_u8_to_u16(v5));
772 auto hi = fsimd::add_u16_8(s08h, fsimd::add_u16_8(fsimd::mullo_u16_8(s17h, w8),
773 fsimd::add_u16_8(fsimd::mullo_u16_8(s26h, w28),
774 fsimd::add_u16_8(fsimd::mullo_u16_8(s35h, w56), fsimd::mullo_u16_8(fsimd::widen_hi_u8_to_u16(v4), w70)))));
775 hi = fsimd::srli_u16_8(hi, 8);
776 fsimd::store_u8_16(out+i, fsimd::narrow_u16_to_u8(lo, hi));
777 }
778 for (; i < nbytes; ++i) {
779 u16 s08=(u16)p0[i]+(u16)p8[i], s17=(u16)p1[i]+(u16)p7[i];
780 u16 s26=(u16)p2[i]+(u16)p6[i], s35=(u16)p3[i]+(u16)p5[i];
781 out[i]=(u8)((s08+s17*8+s26*28+s35*56+(u16)p4[i]*70)>>8);
782 }
783}

References fl::FL_NO_EXCEPT.

Referenced by fl::gfx::blur_detail::simd_hconv_dispatch< 4 >::apply(), and fl::gfx::blur_detail::simd_vconv_dispatch< 4 >::apply().

+ Here is the caller graph for this function:

◆ vpass_full()

template<int R, typename RGB_T, typename acc_t, bool ApplyAlpha, typename AlphaT>
static void fl::gfx::blur_detail::vpass_full ( RGB_T * pixels,
int w,
int h,
RGB_T * scratch,
AlphaT alpha )
static

Definition at line 1089 of file blur.cpp.hpp.

1089 {
1090#if defined(FL_IS_AVR)
1091 // AVR: column-by-column with per-channel noinline + O3.
1092 FL_BUILTIN_MEMSET(scratch, 0, R * sizeof(RGB_T));
1093 FL_BUILTIN_MEMSET(scratch + R + h, 0, R * sizeof(RGB_T));
1094
1095 for (int x = 0; x < w; ++x) {
1096 // Linearize column into padded region.
1097 {
1098 const RGB_T *src = pixels + x;
1099 RGB_T *dst = scratch + R;
1100 for (int i = 0; i < h; ++i) {
1101 *dst++ = *src;
1102 src += w;
1103 }
1104 }
1105 if (ApplyAlpha)
1106 apply_pass_alpha_1ch<R>(scratch, pixels + x, h, w, alpha);
1107 else
1108 apply_pass_1ch<R>(scratch, pixels + x, h, w);
1109 }
1110#else
1111 // Non-AVR: row-major vertical pass for cache efficiency.
1112 // Direct R=2 V-pass using exact [1,4,6,4,1] kernel (no cascaded R=1).
1113 if (ApplyAlpha) {
1115 pixels, w, h, scratch, alpha);
1116 } else {
1118 pixels, w, h, scratch, alpha);
1119 }
1120#endif
1121}
#define FL_BUILTIN_MEMSET(dest, val, n)
static FL_OPTIMIZE_FUNCTION void vpass_rowmajor_impl(RGB_T *pixels, int w, int h, RGB_T *scratch, AlphaT alpha) FL_NO_EXCEPT
Definition blur.cpp.hpp:968

References FL_BUILTIN_MEMSET, fl::FL_NO_EXCEPT, vpass_rowmajor_impl(), and fl::x.

Referenced by fl::gfx::blurGaussianImpl().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ vpass_rowmajor_impl()

template<int R, typename RGB_T, typename acc_t, bool ApplyAlpha, typename AlphaT>
static FL_OPTIMIZE_FUNCTION void fl::gfx::blur_detail::vpass_rowmajor_impl ( RGB_T * pixels,
int w,
int h,
RGB_T * scratch,
AlphaT alpha )
static

Definition at line 968 of file blur.cpp.hpp.

971 {
972 constexpr int shift = 2 * R;
973 using P = pixel_ops<RGB_T>;
974
975 // Ring buffer: bufs[0..R-1] = saved previous rows, bufs[R] = save slot.
976 // Extra zero_row for bottom-boundary padding.
977 RGB_T *bufs[5] = {nullptr, nullptr, nullptr, nullptr, nullptr};
978 for (int i = 0; i <= R; ++i)
979 bufs[i] = scratch + i * w;
980 RGB_T *zero_row = scratch + (R + 1) * w;
981
982 // Zero all: first R buffers (top-boundary padding) + zero_row.
983 FL_BUILTIN_MEMSET(scratch, 0, (R + 2) * w * sizeof(RGB_T));
984
985 for (int y = 0; y < h; ++y) {
986 RGB_T *out_row = pixels + y * w;
987
988 // Save current row before we overwrite it.
989 FL_BUILTIN_MEMCPY(bufs[R], out_row, w * sizeof(RGB_T));
990
991 // Forward row pointers (rows y+1 .. y+R, or zero_row if OOB).
992 const RGB_T *fwd[4] = {zero_row, zero_row, zero_row, zero_row};
993 for (int k = 0; k < R; ++k)
994 fwd[k] = (y + 1 + k < h) ? (pixels + (y + 1 + k) * w) : zero_row;
995
996 // Prefetch the furthest-ahead row needed by the NEXT iteration.
997 // At row y, next iteration needs fwd[R-1] = row y+1+R.
998 // Prefetching 2 rows ahead gives the memory subsystem time to fetch.
999 {
1000 const int prefetch_y = y + R + 2;
1001 if (prefetch_y < h) {
1002 const char *pf = (const char *)(pixels + prefetch_y * w);
1003 const int row_bytes = w * (int)sizeof(RGB_T);
1004 for (int off = 0; off < row_bytes; off += 64)
1005 __builtin_prefetch(pf + off, 0, 3);
1006 }
1007 }
1008
1009 // Process all pixels in this output row.
1010 // For u8-channel types (CRGB), process as raw byte stream — all
1011 // channels use the same kernel weights, so we treat the row as a
1012 // flat u8 array of w*sizeof(RGB_T) bytes. This produces a simpler
1013 // loop that the compiler can optimize better at low -O levels.
1014 if (sizeof(typename RGB_T::fp) == 1 && !ApplyAlpha) {
1015 // Raw byte fast path (CRGB without alpha).
1016 const int nbytes = w * (int)sizeof(RGB_T);
1017 u8 *ob = (u8 *)out_row;
1018
1019 simd_vconv_dispatch<R>::apply(bufs, fwd, ob, nbytes);
1020 } else {
1021 // Generic path: per-pixel struct access (CRGB16 or alpha case).
1022 for (int x = 0; x < w; ++x) {
1023 acc_t r, g, b;
1024
1026
1027 if (ApplyAlpha) {
1028 out_row[x] = P::make(static_cast<acc_t>(r >> shift),
1029 static_cast<acc_t>(g >> shift),
1030 static_cast<acc_t>(b >> shift), alpha);
1031 } else {
1032 out_row[x] = P::make(static_cast<acc_t>(r >> shift),
1033 static_cast<acc_t>(g >> shift),
1034 static_cast<acc_t>(b >> shift));
1035 }
1036 }
1037 }
1038
1039 // Rotate ring buffer: discard oldest, current becomes newest saved.
1040 RGB_T *recycled = bufs[0];
1041 for (int i = 0; i < R; ++i) bufs[i] = bufs[i + 1];
1042 bufs[R] = recycled;
1043 }
1044}
#define FL_BUILTIN_MEMCPY(dest, src, n)

References FL_BUILTIN_MEMCPY, FL_BUILTIN_MEMSET, fl::FL_NO_EXCEPT, fl::g, fl::P(), fl::x, and fl::y.

Referenced by vpass_full().

+ Here is the call graph for this function:
+ Here is the caller graph for this function: