FastLED 3.9.15
Loading...
Searching...
No Matches

◆ getOrCreate()

fl::shared_ptr< const Gamma8 > fl::Gamma8::getOrCreate ( float gamma)
static

Definition at line 459 of file ease.cpp.hpp.

459 {
460 // Clamp gamma to the cache-key domain BEFORE deriving the key and
461 // before feeding it to s8x24. `GammaKey` is `ufixed_point<4, 12>`,
462 // so its representable range is [0, ~16). A negative input would
463 // wrap unsigned in the GammaKey ctor; an input ≥ 16 would either
464 // saturate or wrap. Clamping up-front also keeps the s8x24 bit
465 // budget safe: `exp * log2_fp(1/255) ≈ -7.994 * gamma` must stay
466 // within s8x24's signed [-128, 128) integer range — gamma ≤ 16
467 // gives -127.9, right at the edge.
468 constexpr float kGammaMax = 15.99975f; // just under 4.12 ufixed max
469 const float gamma_clamped = (gamma < 0.0f) ? 0.0f
470 : (gamma > kGammaMax) ? kGammaMax
471 : gamma;
472 GammaKey key(gamma_clamped);
473
474 // Fast path: gamma 2.8 is the canonical default (every legacy
475 // `addLeds<NEOPIXEL>` flow, every WS281x chipset). We have a
476 // precomputed `GAMMA_2_8_LUT` already in .rodata (used by the
477 // free function `fl::gamma_2_8`). Construct a Gamma8 instance
478 // that copies that table directly instead of recomputing 256
479 // fixed-point pow operations (which would diverge from the
480 // precomputed values by ~30-50 LSB). Cached via weak_ptr to
481 // match the documented `getOrCreate` lifetime contract — the
482 // instance disappears once all callers drop their shared_ptr,
483 // and the next call rebuilds it.
484 constexpr GammaKey k28(2.8f);
485 if (key == k28) {
486 static fl::weak_ptr<const Gamma8> s28_weak;
487 if (auto existing = s28_weak.lock()) {
488 return existing;
489 }
491 Gamma8Impl::from_progmem_lut_tag{}, GAMMA_2_8_LUT);
492 s28_weak = ptr;
493 return ptr;
494 }
495
496 // Slow path: arbitrary gamma. Single-entry weak_ptr cache. Users
497 // who switch gamma values at runtime pay one extra `Gamma8Impl`
498 // reconstruction per switch (256 fixed-point pow operations +
499 // ~512 B alloc). See #2928 / #2886.
500 static GammaKey sCachedKey{};
501 static fl::weak_ptr<const Gamma8> sCachedPtr;
502 static bool sCacheValid = false;
503
504 if (sCacheValid && key == sCachedKey) {
505 if (auto existing = sCachedPtr.lock()) {
506 return existing;
507 }
508 }
509
510 // Use the clamped gamma so the LUT we build matches the cache key
511 // (otherwise out-of-range inputs would keep missing the cache).
512 fl::shared_ptr<const Gamma8> ptr =
513 fl::make_shared<Gamma8Impl>(gamma_clamped);
514 sCachedKey = key;
515 sCachedPtr = ptr;
516 sCacheValid = true;
517 return ptr;
518}
shared_ptr< T > lock() const FL_NOEXCEPT
Definition weak_ptr.h:140
fl::ufixed_point< 4, 12 > GammaKey
Definition ease.cpp.hpp:351
const u16 GAMMA_2_8_LUT[256]
shared_ptr< T > make_shared(Args &&... args) FL_NOEXCEPT
Definition shared_ptr.h:414
constexpr u32 gamma(float g) FL_NOEXCEPT
Definition gamma_lut.h:36

References fl::gamma(), fl::GAMMA_2_8_LUT, getOrCreate(), fl::weak_ptr< T >::lock(), and fl::make_shared().

Referenced by buildExpectedUCS7604(), fl::encodeUCS7604(), getOrCreate(), fl::UCS7604ControllerT< DATA_PIN, RGB_ORDER, fl::UCS7604Mode::UCS7604_MODE_8BIT_800KHZ, fl::TIMING_UCS7604_800KHZ, CLOCKLESS_CONTROLLER >::showPixels(), and fl::anonymous_namespace{channel.cpp.hpp}::writeUCS7604().

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