Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 37 additions & 1 deletion wled00/FX.h
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,8 @@ typedef struct Segment {
uint16_t startY; // start Y coodrinate 2D (top); there should be no more than 255 rows, but we cannot be sure.
uint16_t stopY; // stop Y coordinate 2D (bottom); there should be no more than 255 rows, but we cannot be sure.
char *name = nullptr; // WLEDMM initialize to nullptr
uint8_t maskId = 0; // WLEDMM segment mask ID (0 = none)
bool maskInvert = false; // WLEDMM invert mask bits (useful for "outside" masks)

// runtime data
unsigned long next_time; // millis() of next update
Expand All @@ -469,6 +471,12 @@ typedef struct Segment {
void *jMap = nullptr; //WLEDMM jMap

private:
uint8_t *_mask = nullptr; // WLEDMM bit-packed mask, 1 bit per virtual pixel
uint16_t _maskW = 0; // WLEDMM mask width in virtual pixels
uint16_t _maskH = 0; // WLEDMM mask height in virtual pixels
size_t _maskLen = 0; // WLEDMM total bits (w*h), not bytes
bool _maskValid = false; // WLEDMM cached dimension check vs virtual size

union {
uint8_t _capabilities;
struct {
Expand Down Expand Up @@ -563,6 +571,8 @@ typedef struct Segment {
startY(0),
stopY(1),
name(nullptr),
maskId(0), // WLEDMM
maskInvert(false), // WLEDMM
next_time(0),
step(0),
call(0),
Expand All @@ -571,6 +581,11 @@ typedef struct Segment {
data(nullptr),
ledsrgb(nullptr),
ledsrgbSize(0), //WLEDMM
_mask(nullptr), // WLEDMM
_maskW(0), // WLEDMM
_maskH(0), // WLEDMM
_maskLen(0), // WLEDMM
_maskValid(false), // WLEDMM
_capabilities(0),
_dataLen(0),
_t(nullptr)
Expand Down Expand Up @@ -612,6 +627,7 @@ typedef struct Segment {
if ((Segment::_globalLeds == nullptr) && !strip_uses_global_leds() && (ledsrgb != nullptr)) {free(ledsrgb); ledsrgb = nullptr;} // WLEDMM we need "!strip_uses_global_leds()" to avoid crashes (#104)
if (name) { delete[] name; name = nullptr; }
if (_t) { transitional = false; delete _t; _t = nullptr; }
clearMask(); // WLEDMM
deallocateData();
}

Expand Down Expand Up @@ -666,6 +682,8 @@ typedef struct Segment {
inline void markForReset(void) { reset = true; } // setOption(SEG_OPTION_RESET, true)
inline void markForBlank(void) { needsBlank = true; } // WLEDMM serialize "blank" requests, avoid parallel drawing from different task
void setUpLeds(void); // set up leds[] array for loseless getPixelColor()
bool setMask(uint8_t id); // WLEDMM
void clearMask(); // WLEDMM

// transition functions
void startTransition(uint16_t dur); // transition has to start before actual segment values change
Expand Down Expand Up @@ -704,6 +722,23 @@ typedef struct Segment {
#else
inline uint16_t virtualLength(void) const {return _virtuallength;}
#endif
[[gnu::hot]] inline bool hasMask(void) const { return _mask != nullptr; } // WLEDMM
[[gnu::hot]] inline bool maskAllows(uint16_t i) const { // WLEDMM
if (!_mask || !_maskValid) return true;
if (size_t(i) >= _maskLen) return false;
// WLEDMM: bit-packed mask (LSB-first): byte = i>>3, bit = i&7
bool bit = (_mask[i >> 3] >> (i & 7)) & 0x01;
return maskInvert ? !bit : bit;
}
[[gnu::hot]] inline bool maskAllowsXY(int x, int y) const { // WLEDMM
if (!_mask || !_maskValid) return true;
if (x < 0 || y < 0) return false;
size_t idx = size_t(x) + (size_t(y) * _maskW);
if (idx >= _maskLen) return false;
// WLEDMM: row-major (x + y*w), bit-packed mask (LSB-first in each byte)
bool bit = (_mask[idx >> 3] >> (idx & 7)) & 0x01;
return maskInvert ? !bit : bit;
}
void setPixelColor(int n, uint32_t c); // set relative pixel within segment with color
inline void setPixelColor(int n, byte r, byte g, byte b, byte w = 0) { setPixelColor(n, RGBW32(r,g,b,w)); } // automatically inline
inline void setPixelColor(int n, CRGB c) { setPixelColor(n, uint32_t(c) & 0x00FFFFFF); } // automatically inline
Expand Down Expand Up @@ -1044,7 +1079,8 @@ class WS2812FX { // 96 bytes
fixInvalidSegments(),
show(void),
setTargetFps(uint8_t fps),
enumerateLedmaps(); //WLEDMM (from fcn_declare)
enumerateLedmaps(), //WLEDMM (from fcn_declare)
enumerateSegmasks(); // WLEDMM

void setColor(uint8_t slot, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0) { setColor(slot, RGBW32(r,g,b,w)); }
void fill(uint32_t c) { for (int i = 0; i < getLengthTotal(); i++) setPixelColor(i, c); } // fill whole strip with color (inline)
Expand Down
11 changes: 11 additions & 0 deletions wled00/FX_2Dfcn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,15 @@ void Segment::startFrame(void) {
_2dWidth = _isValid2D ? calc_virtualWidth() : calc_virtualLength();
_virtuallength = calc_virtualLength();
#endif

// WLEDMM validate mask dimensions against current virtual size
if (_mask) {
uint16_t vW = calc_virtualWidth();
uint16_t vH = calc_virtualHeight();
_maskValid = (_maskW == vW && _maskH == vH);
} else {
_maskValid = false;
}
}
// WLEDMM end

Expand All @@ -245,6 +254,7 @@ void Segment::startFrame(void) {
// * expects scaled color (final brightness) as additional input parameter, plus segment virtualWidth() and virtualHeight()
void IRAM_ATTR __attribute__((hot)) Segment::setPixelColorXY_fast(int x, int y, uint32_t col, uint32_t scaled_col, int cols, int rows) const //WLEDMM
{
if (!maskAllowsXY(x, y)) return; // WLEDMM mask gate for 2D pixels
unsigned i = UINT_MAX;
bool sameColor = false;
if (ledsrgb) { // WLEDMM small optimization
Expand Down Expand Up @@ -301,6 +311,7 @@ void IRAM_ATTR_YN Segment::setPixelColorXY(int x, int y, uint32_t col) //WLEDMM:
const int_fast16_t rows = virtualHeight();

if (x<0 || y<0 || x >= cols || y >= rows) return; // if pixel would fall out of virtual segment just exit
if (!maskAllowsXY(x, y)) return; // WLEDMM mask gate for 2D pixels

unsigned i = UINT_MAX;
bool sameColor = false;
Expand Down
Loading