another small speedup, and segment stability improvement

* removed a few sanity check that are done again later in getPixelColor
* stability: prevent crashes when changing segments settings or effect options
This commit is contained in:
Frank
2024-08-16 17:54:11 +02:00
parent 1ae8a62cf5
commit 030a7cee53
4 changed files with 48 additions and 12 deletions

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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_