diff --git a/wled00/FX.h b/wled00/FX.h index a2f51cf4..4ab04a9f 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -439,6 +439,7 @@ typedef struct Segment { #ifdef WLEDMM_FASTPATH // WLEDMM cache some values that won't change while drawing a frame bool _isSimpleSegment = false; + bool _isSuperSimpleSegment = false; bool _isValid2D = false; uint8_t _brightness = 255; // final pixel brightness - including transitions and segment opacity bool _firstFill = true; // dirty HACK support diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index 9660df63..b7e5357a 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -241,6 +241,7 @@ void Segment::startFrame(void) { _isValid2D = isActive() && is2D(); _brightness = currentBri(on ? opacity : 0); _isSimpleSegment = (grouping == 1) && (spacing == 0); // we can handle pixels faster when no grouping or spacing is involved + _isSuperSimpleSegment = !mirror && !mirror_y && (grouping == 1) && (spacing == 0); // fastest - we only draw one pixel per call // if (reverse_y) _isSimpleSegment = false; // for A/B testing _2dWidth = is2D() ? calc_virtualWidth() : virtualLength(); _2dHeight = calc_virtualHeight(); @@ -279,7 +280,8 @@ void IRAM_ATTR __attribute__((hot)) Segment::setPixelColorXY_fast(int x, int y, // set the requested pixel strip.setPixelColorXY_fast(start + x, startY + y, scaled_col); - bool simpleSegment = !mirror && !mirror_y; + //bool simpleSegment = !mirror && !mirror_y; + bool simpleSegment = _isSuperSimpleSegment; if (simpleSegment) return; // WLEDMM shortcut when no mirroring needed // handle mirroring @@ -306,7 +308,7 @@ void IRAM_ATTR_YN Segment::setPixelColorXY_slow(int x, int y, uint32_t col) //WL void IRAM_ATTR_YN Segment::setPixelColorXY(int x, int y, uint32_t col) //WLEDMM: IRAM_ATTR conditionally #endif { - if (Segment::maxHeight==1) return; // not a matrix set-up + if ((Segment::maxHeight==1) || !isActive()) return; // not a matrix set-up const int_fast16_t cols = virtualWidth(); // WLEDMM optimization const int_fast16_t rows = virtualHeight(); @@ -335,7 +337,8 @@ void IRAM_ATTR_YN Segment::setPixelColorXY(int x, int y, uint32_t col) //WLEDMM: if (transpose) { uint16_t t = x; x = y; y = t; } // swap X & Y if segment transposed // WLEDMM shortcut when no grouping/spacing used - bool simpleSegment = !mirror && !mirror_y && (grouping == 1) && (spacing == 0); + //bool simpleSegment = !mirror && !mirror_y && (grouping == 1) && (spacing == 0); + bool simpleSegment = _isSuperSimpleSegment; if (simpleSegment) { strip.setPixelColorXY(start + x, startY + y, col); return; @@ -441,20 +444,21 @@ uint32_t IRAM_ATTR_YN Segment::getPixelColorXY(int x, int y) const { // Blends the specified color with the existing pixel color. void Segment::blendPixelColorXY(uint16_t x, uint16_t y, uint32_t color, uint8_t blend) { - setPixelColorXY(x, y, color_blend(getPixelColorXY(x,y), color, blend)); + if (blend == UINT8_MAX) setPixelColorXY(x, y, color); + else setPixelColorXY(x, y, color_blend(getPixelColorXY(x,y), color, blend)); } // Adds the specified color with the existing pixel color perserving color balance. void IRAM_ATTR_YN Segment::addPixelColorXY(int x, int y, uint32_t color, bool fast) { - if (!isActive()) return; // not active - if (x >= virtualWidth() || y >= virtualHeight() || x<0 || y<0) return; // if pixel would fall out of virtual segment just exit + // if (!isActive()) return; // not active //WLEDMM sanity check is repeated in getPixelColorXY / setPixelColorXY + // if (x >= virtualWidth() || y >= virtualHeight() || x<0 || y<0) return; // if pixel would fall out of virtual segment just exit //WLEDMM uint32_t col = getPixelColorXY(x,y); col = color_add(col, color, fast); setPixelColorXY(x, y, col); } void Segment::fadePixelColorXY(uint16_t x, uint16_t y, uint8_t fade) { - if (!isActive()) return; // not active + // if (!isActive()) return; // not active //WLEDMM sanity check is repeated in getPixelColorXY / setPixelColorXY CRGB pix = CRGB(getPixelColorXY(x,y)).nscale8_video(fade); setPixelColorXY(x, y, pix); } diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 0f6eb6da..b5e84039 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -102,6 +102,12 @@ Segment::Segment(const Segment &orig) { DEBUG_PRINTLN(F("-- Copy segment constructor --")); memcpy((void*)this, (void*)&orig, sizeof(Segment)); //WLEDMM copy to this transitional = false; // copied segment cannot be in transition +#ifdef WLEDMM_FASTPATH + // WLEDMM temporarily prevent any fast draw calls to the new segment + // _isValid2D = false; + _isSimpleSegment = false; + _isSuperSimpleSegment = false; +#endif name = nullptr; data = nullptr; _dataLen = 0; @@ -143,8 +149,17 @@ void Segment::allocLeds() { // move constructor --> moves everything (including buffer) from orig to this Segment::Segment(Segment &&orig) noexcept { DEBUG_PRINTLN(F("-- Move segment constructor --")); +#ifdef WLEDMM_FASTPATH + // WLEDMM temporarily prevent any fast draw calls to old and new segment + orig._isSimpleSegment = false; + orig._isSuperSimpleSegment = false; +#endif memcpy((void*)this, (void*)&orig, sizeof(Segment)); orig.transitional = false; // old segment cannot be in transition any more +#ifdef WLEDMM_FASTPATH + // WLEDMM prevent any draw calls to old segment + orig._isValid2D = false; +#endif orig.name = nullptr; orig.data = nullptr; orig._dataLen = 0; @@ -169,6 +184,12 @@ Segment& Segment::operator= (const Segment &orig) { // copy source memcpy((void*)this, (void*)&orig, sizeof(Segment)); transitional = false; +#ifdef WLEDMM_FASTPATH + // WLEDMM prevent any fast draw calls to this segment until the next frame starts + //_isValid2D = false; + _isSimpleSegment = false; + _isSuperSimpleSegment = false; +#endif // erase pointers to allocated data name = nullptr; data = nullptr; @@ -196,7 +217,16 @@ Segment& Segment::operator= (Segment &&orig) noexcept { deallocateData(); // free old runtime data if (_t) { delete _t; _t = nullptr; } if (ledsrgb && !Segment::_globalLeds) free(ledsrgb); //WLEDMM: not needed anymore as we will use leds from copy. no need to nullify ledsrgb as it gets new value in memcpy +#ifdef WLEDMM_FASTPATH + // WLEDMM temporarily prevent any fast draw calls to old and new segment + orig._isSimpleSegment = false; + orig._isSuperSimpleSegment = false; +#endif memcpy((void*)this, (void*)&orig, sizeof(Segment)); +#ifdef WLEDMM_FASTPATH + // WLEDMM temporarily prevent any draw calls to old segment + orig._isValid2D = false; +#endif orig.name = nullptr; orig.data = nullptr; orig._dataLen = 0; @@ -956,8 +986,8 @@ void IRAM_ATTR_YN __attribute__((hot)) Segment::setPixelColor(int i, uint32_t co float rad = 0.0f; for (unsigned count = 0; count < numSteps; count++) { // may want to try float version as well (with or without antialiasing) - int x = roundf(sinf(rad) * radius); - int y = roundf(cosf(rad) * radius); + int x = max(0, min(vW-1, (int)roundf(sinf(rad) * radius))); + int y = max(0, min(vH-1, (int)roundf(cosf(rad) * radius))); setPixelColorXY(x, y, col); if(useSymmetry) setPixelColorXY(y, x, col);// WLEDMM rad += step; @@ -1388,7 +1418,8 @@ void __attribute__((hot)) Segment::fill(uint32_t c) { // Blends the specified color with the existing pixel color. void Segment::blendPixelColor(int n, uint32_t color, uint8_t blend) { - setPixelColor(n, color_blend(getPixelColor(n), color, blend)); + if (blend == UINT8_MAX) setPixelColor(n, color); + else setPixelColor(n, color_blend(getPixelColor(n), color, blend)); } // Adds the specified color with the existing pixel color perserving color balance. @@ -1420,7 +1451,7 @@ void Segment::fadePixelColor(uint16_t n, uint8_t fade) { /* * fade out function, higher rate = quicker fade */ -void Segment::fade_out(uint8_t rate) { +void __attribute__((hot)) Segment::fade_out(uint8_t rate) { if (!isActive()) return; // not active const uint_fast16_t cols = is2D() ? virtualWidth() : virtualLength(); // WLEDMM use fast int types const uint_fast16_t rows = virtualHeight(); // will be 1 for 1D diff --git a/wled00/wled.h b/wled00/wled.h index c185bc46..ed232910 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -8,7 +8,7 @@ */ // version code in format yymmddb (b = daily build) -#define VERSION 2408150 +#define VERSION 2408160 // WLEDMM - you can check for this define in usermods, to only enabled WLEDMM specific code in the "right" fork. Its not defined in AC WLED. #define _MoonModules_WLED_