FastLED 3.10.8
Loading...
Searching...
No Matches

◆ getOrCreate()

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

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

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

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

Referenced by 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: