Reverting addition of bool unScale, added new improvements and fixes

- Added pre-calculation for segment brightness: stored in _segBri. The impact on FPS is not huge but measurable (~1-2FPS in my test conditions)
- Removed `bool unScaled` from `setPixelColor()` function again (it has no/minimal impact on speed but huge impact on flash usage: +850 bytes)
- Removed negative checking in `setPixelColorXY()` and replaced it with a local typecast to unsigned, saves a few instructions (tested and working)
- Changed int8_t to int in `moveX()` and `moveY()`
- Removed a few functions from IRAM as they are now not called for every pixel but only once per segment update
- Removed a `virtualWidth()` call from `ripple_base()`
- Bugfix in `mode_colortwinkle()`
This commit is contained in:
Damian Schneider 2024-09-29 13:55:00 +02:00
parent 9114867578
commit ffbc8c5f70
4 changed files with 55 additions and 62 deletions

View File

@ -2294,7 +2294,7 @@ uint16_t mode_colortwinkle() {
bool fadeUp = bitRead(SEGENV.data[index], bitNum);
if (fadeUp) {
CRGBW incrementalColor = color_fade(col, fadeUpAmount, true);
CRGBW incrementalColor = color_fade(cur, fadeUpAmount, true);
col = color_add(cur, incrementalColor);
if (col.r == 255 || col.g == 255 || col.b == 255) {
@ -2528,7 +2528,7 @@ static uint16_t ripple_base() {
} else {//randomly create new wave
if (random16(IBN + 10000) <= (SEGMENT.intensity >> (SEGMENT.is2D()*3))) {
ripples[i].state = 1;
ripples[i].pos = SEGMENT.is2D() ? ((random8(SEGENV.virtualWidth())<<8) | (random8(SEGENV.virtualHeight()))) : random16(SEGLEN);
ripples[i].pos = SEGMENT.is2D() ? ((random8(SEG_W)<<8) | (random8(SEG_H))) : random16(SEGLEN);
ripples[i].color = random8(); //color
}
}

View File

@ -420,8 +420,8 @@ typedef struct Segment {
};
uint16_t _dataLen;
static uint16_t _usedSegmentData;
static unsigned _vLength; // 1D dimension used for current effect
static uint8_t _segBri; // Current brightness of segment
static unsigned _vLength; // 1D dimension used for current effect
static unsigned _vWidth, _vHeight; // 2D dimensions used for current effect
static uint32_t _currentColors[NUM_COLORS]; // colors used for current effect
static CRGBPalette16 _currentPalette; // palette used for current effect (includes transition, used in color_from_palette())
@ -546,7 +546,7 @@ typedef struct Segment {
inline static unsigned vHeight() { return Segment::_vHeight; }
inline static uint32_t getCurrentColor(unsigned i) { return Segment::_currentColors[i]; } // { return i < 3 ? Segment::_currentColors[i] : 0; }
inline static const CRGBPalette16 &getCurrentPalette() { return Segment::_currentPalette; }
inline static uint8_t getCurrentBrightness() { return Segment::_segBri; }
static void handleRandomPalette();
void beginDraw(); // set up parameters for current effect
@ -589,8 +589,8 @@ typedef struct Segment {
// 1D strip
[[gnu::hot]] uint16_t virtualLength() const;
[[gnu::hot]] void setPixelColor(int n, uint32_t c, bool unScaled = true); // set relative pixel within segment with color
inline void setPixelColor(unsigned n, uint32_t c, bool unScaled = true) { setPixelColor(int(n), c, unScaled); }
[[gnu::hot]] void setPixelColor(int n, uint32_t c); // set relative pixel within segment with color
inline void setPixelColor(unsigned n, uint32_t c) { setPixelColor(int(n), c); }
inline void setPixelColor(int n, byte r, byte g, byte b, byte w = 0) { setPixelColor(n, RGBW32(r,g,b,w)); }
inline void setPixelColor(int n, CRGB c) { setPixelColor(n, RGBW32(c.r,c.g,c.b,0)); }
#ifdef WLED_USE_AA_PIXELS
@ -629,8 +629,8 @@ typedef struct Segment {
uint16_t nrOfVStrips() const; // returns number of virtual vertical strips in 2D matrix (used to expand 1D effects into 2D)
#ifndef WLED_DISABLE_2D
[[gnu::hot]] uint16_t XY(int x, int y); // support function to get relative index within segment
[[gnu::hot]] void setPixelColorXY(int x, int y, uint32_t c, bool unScaled = true); // set relative pixel within segment with color
inline void setPixelColorXY(unsigned x, unsigned y, uint32_t c, bool unScaled = true) { setPixelColorXY(int(x), int(y), c, unScaled); }
[[gnu::hot]] void setPixelColorXY(int x, int y, uint32_t c); // set relative pixel within segment with color
inline void setPixelColorXY(unsigned x, unsigned y, uint32_t c) { setPixelColorXY(int(x), int(y), c); }
inline void setPixelColorXY(int x, int y, byte r, byte g, byte b, byte w = 0) { setPixelColorXY(x, y, RGBW32(r,g,b,w)); }
inline void setPixelColorXY(int x, int y, CRGB c) { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0)); }
inline void setPixelColorXY(unsigned x, unsigned y, CRGB c) { setPixelColorXY(int(x), int(y), RGBW32(c.r,c.g,c.b,0)); }
@ -651,8 +651,8 @@ typedef struct Segment {
void blur2D(uint8_t blur_amount, bool smear = false);
void blurRow(int row, fract8 blur_amount, bool smear = false);
void blurCol(int col, fract8 blur_amount, bool smear = false);
void moveX(int8_t delta, bool wrap = false);
void moveY(int8_t delta, bool wrap = false);
void moveX(int delta, bool wrap = false);
void moveY(int delta, bool wrap = false);
void move(uint8_t dir, uint8_t delta, bool wrap = false);
void drawCircle(uint16_t cx, uint16_t cy, uint8_t radius, uint32_t c, bool soft = false);
inline void drawCircle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c, bool soft = false) { drawCircle(cx, cy, radius, RGBW32(c.r,c.g,c.b,0), soft); }
@ -668,8 +668,8 @@ typedef struct Segment {
inline void fill_solid(CRGB c) { fill(RGBW32(c.r,c.g,c.b,0)); }
#else
inline uint16_t XY(int x, int y) { return x; }
inline void setPixelColorXY(int x, int y, uint32_t c, bool unScaled = true) { setPixelColor(x, c, unScaled); }
inline void setPixelColorXY(unsigned x, unsigned y, uint32_t c, bool unScaled = true) { setPixelColor(int(x), c, unScaled); }
inline void setPixelColorXY(int x, int y, uint32_t c) { setPixelColor(x, c); }
inline void setPixelColorXY(unsigned x, unsigned y, uint32_t c) { setPixelColor(int(x), c); }
inline void setPixelColorXY(int x, int y, byte r, byte g, byte b, byte w = 0) { setPixelColor(x, RGBW32(r,g,b,w)); }
inline void setPixelColorXY(int x, int y, CRGB c) { setPixelColor(x, RGBW32(c.r,c.g,c.b,0)); }
inline void setPixelColorXY(unsigned x, unsigned y, CRGB c) { setPixelColor(int(x), RGBW32(c.r,c.g,c.b,0)); }
@ -689,8 +689,8 @@ typedef struct Segment {
inline void blur2D(uint8_t blur_amount, bool smear = false) {}
inline void blurRow(int row, fract8 blur_amount, bool smear = false) {}
inline void blurCol(int col, fract8 blur_amount, bool smear = false) {}
inline void moveX(int8_t delta, bool wrap = false) {}
inline void moveY(int8_t delta, bool wrap = false) {}
inline void moveX(int delta, bool wrap = false) {}
inline void moveY(int delta, bool wrap = false) {}
inline void move(uint8_t dir, uint8_t delta, bool wrap = false) {}
inline void drawCircle(uint16_t cx, uint16_t cy, uint8_t radius, uint32_t c, bool soft = false) {}
inline void drawCircle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c, bool soft = false) {}

View File

@ -168,16 +168,16 @@ uint16_t IRAM_ATTR_YN Segment::XY(int x, int y)
return isActive() ? (x%vW) + (y%vH) * vW : 0;
}
void IRAM_ATTR_YN Segment::setPixelColorXY(int x, int y, uint32_t col, bool unScaled)
void IRAM_ATTR_YN Segment::setPixelColorXY(int x, int y, uint32_t col)
{
if (!isActive()) return; // not active
const int vW = vWidth(); // segment width in logical pixels (can be 0 if segment is inactive)
const int vH = vHeight(); // segment height in logical pixels (is always >= 1)
if (x >= vW|| y >= vH || x<0 || y<0) return; // if pixel would fall out of virtual segment just exit
if (unsigned(x) >= vW || unsigned(y) >= vH) return; // if pixel would fall out of virtual segment just exit
// if color is unscaled
if (unScaled) col = color_fade(col, currentBri());
if(getCurrentBrightness() < 255)
col = color_fade(col, getCurrentBrightness()); // scale brightness
if (reverse ) x = vW - x - 1;
if (reverse_y) y = vH - y - 1;
@ -459,7 +459,7 @@ void Segment::box_blur(unsigned radius, bool smear) {
delete[] tmpWSum;
}
void Segment::moveX(int8_t delta, bool wrap) {
void Segment::moveX(int delta, bool wrap) {
if (!isActive()) return; // not active
const int vW = vWidth(); // segment width in logical pixels (can be 0 if segment is inactive)
const int vH = vHeight(); // segment height in logical pixels (is always >= 1)
@ -477,7 +477,7 @@ void Segment::moveX(int8_t delta, bool wrap) {
}
}
void Segment::moveY(int8_t delta, bool wrap) {
void Segment::moveY(int delta, bool wrap) {
if (!isActive()) return; // not active
const int vW = vWidth(); // segment width in logical pixels (can be 0 if segment is inactive)
const int vH = vHeight(); // segment height in logical pixels (is always >= 1)
@ -545,20 +545,18 @@ void Segment::drawCircle(uint16_t cx, uint16_t cy, uint8_t radius, uint32_t col,
x++;
}
} else {
// pre-scale color for all pixels
col = color_fade(col, currentBri());
// Bresenhams Algorithm
int d = 3 - (2*radius);
int y = radius, x = 0;
while (y >= x) {
setPixelColorXY(cx+x, cy+y, col, false);
setPixelColorXY(cx-x, cy+y, col, false);
setPixelColorXY(cx+x, cy-y, col, false);
setPixelColorXY(cx-x, cy-y, col, false);
setPixelColorXY(cx+y, cy+x, col, false);
setPixelColorXY(cx-y, cy+x, col, false);
setPixelColorXY(cx+y, cy-x, col, false);
setPixelColorXY(cx-y, cy-x, col, false);
setPixelColorXY(cx+x, cy+y, col);
setPixelColorXY(cx-x, cy+y, col);
setPixelColorXY(cx+x, cy-y, col);
setPixelColorXY(cx-x, cy-y, col);
setPixelColorXY(cx+y, cy+x, col);
setPixelColorXY(cx-y, cy+x, col);
setPixelColorXY(cx+y, cy-x, col);
setPixelColorXY(cx-y, cy-x, col);
x++;
if (d > 0) {
y--;
@ -577,15 +575,13 @@ void Segment::fillCircle(uint16_t cx, uint16_t cy, uint8_t radius, uint32_t col,
const int vH = vHeight(); // segment height in logical pixels (is always >= 1)
// draw soft bounding circle
if (soft) drawCircle(cx, cy, radius, col, soft);
// pre-scale color for all pixels
col = color_fade(col, currentBri());
// fill it
for (int y = -radius; y <= radius; y++) {
for (int x = -radius; x <= radius; x++) {
if (x * x + y * y <= radius * radius &&
int(cx)+x >= 0 && int(cy)+y >= 0 &&
int(cx)+x < vW && int(cy)+y < vH)
setPixelColorXY(cx + x, cy + y, col, false);
setPixelColorXY(cx + x, cy + y, col);
}
}
}
@ -633,12 +629,10 @@ void Segment::drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint3
if (steep) std::swap(x,y); // restore if steep
}
} else {
// pre-scale color for all pixels
c = color_fade(c, currentBri());
// Bresenham's algorithm
int err = (dx>dy ? dx : -dy)/2; // error direction
for (;;) {
setPixelColorXY(x0, y0, c, false);
setPixelColorXY(x0, y0, c);
if (x0==x1 && y0==y1) break;
int e2 = err;
if (e2 >-dx) { err -= dy; x0 += sx; }

View File

@ -86,6 +86,9 @@ uint16_t Segment::maxHeight = 1;
unsigned Segment::_vLength = 0;
unsigned Segment::_vWidth = 0;
unsigned Segment::_vHeight = 0;
uint8_t Segment::_segBri = 0;
//uint8_t Segment::_currentBrightness2 = 0;
//uint8_t Segment::_currentBrightness3 = 0;
uint32_t Segment::_currentColors[NUM_COLORS] = {0,0,0};
CRGBPalette16 Segment::_currentPalette = CRGBPalette16(CRGB::Black);
CRGBPalette16 Segment::_randomPalette = generateRandomPalette(); // was CRGBPalette16(DEFAULT_COLOR);
@ -413,7 +416,7 @@ void Segment::restoreSegenv(tmpsegd_t &tmpSeg) {
}
#endif
uint8_t IRAM_ATTR Segment::currentBri(bool useCct) const {
uint8_t Segment::currentBri(bool useCct) const {
unsigned prog = progress();
if (prog < 0xFFFFU) {
unsigned curBri = (useCct ? cct : (on ? opacity : 0)) * prog;
@ -445,6 +448,7 @@ void Segment::beginDraw() {
_vWidth = virtualWidth();
_vHeight = virtualHeight();
_vLength = virtualLength();
_segBri = currentBri();
// adjust gamma for effects
for (unsigned i = 0; i < NUM_COLORS; i++) {
#ifndef WLED_DISABLE_MODE_BLEND
@ -624,21 +628,21 @@ void Segment::setPalette(uint8_t pal) {
}
// 2D matrix
uint16_t IRAM_ATTR Segment::virtualWidth() const {
uint16_t Segment::virtualWidth() const {
unsigned groupLen = groupLength();
unsigned vWidth = ((transpose ? height() : width()) + groupLen - 1) / groupLen;
if (mirror) vWidth = (vWidth + 1) /2; // divide by 2 if mirror, leave at least a single LED
return vWidth;
}
uint16_t IRAM_ATTR Segment::virtualHeight() const {
uint16_t Segment::virtualHeight() const {
unsigned groupLen = groupLength();
unsigned vHeight = ((transpose ? width() : height()) + groupLen - 1) / groupLen;
if (mirror_y) vHeight = (vHeight + 1) /2; // divide by 2 if mirror, leave at least a single LED
return vHeight;
}
uint16_t IRAM_ATTR_YN Segment::nrOfVStrips() const {
uint16_t Segment::nrOfVStrips() const {
unsigned vLen = 1;
#ifndef WLED_DISABLE_2D
if (is2D() && map1D2D == M12_pBar) vLen = virtualWidth();
@ -683,7 +687,7 @@ static int getPinwheelLength(int vW, int vH) {
#endif
// 1D strip
uint16_t IRAM_ATTR Segment::virtualLength() const {
uint16_t Segment::virtualLength() const {
#ifndef WLED_DISABLE_2D
if (is2D()) {
unsigned vW = virtualWidth();
@ -715,7 +719,7 @@ uint16_t IRAM_ATTR Segment::virtualLength() const {
return vLength;
}
void IRAM_ATTR_YN Segment::setPixelColor(int i, uint32_t col, bool unScaled)
void IRAM_ATTR_YN Segment::setPixelColor(int i, uint32_t col)
{
if (!isActive() || i < 0) return; // not active or invalid index
#ifndef WLED_DISABLE_2D
@ -739,22 +743,20 @@ void IRAM_ATTR_YN Segment::setPixelColor(int i, uint32_t col, bool unScaled)
if (is2D()) {
const int vW = vWidth(); // segment width in logical pixels (can be 0 if segment is inactive)
const int vH = vHeight(); // segment height in logical pixels (is always >= 1)
// pre-scale color for all pixels
col = color_fade(col, currentBri());
switch (map1D2D) {
case M12_Pixels:
// use all available pixels as a long strip
setPixelColorXY(i % vW, i / vW, col, false);
setPixelColorXY(i % vW, i / vW, col);
break;
case M12_pBar:
// expand 1D effect vertically or have it play on virtual strips
if (vStrip > 0) setPixelColorXY(vStrip - 1, vH - i - 1, col, false);
else for (int x = 0; x < vW; x++) setPixelColorXY(x, vH - i - 1, col, false);
if (vStrip > 0) setPixelColorXY(vStrip - 1, vH - i - 1, col);
else for (int x = 0; x < vW; x++) setPixelColorXY(x, vH - i - 1, col);
break;
case M12_pArc:
// expand in circular fashion from center
if (i == 0)
setPixelColorXY(0, 0, col, false);
setPixelColorXY(0, 0, col);
else {
float r = i;
float step = HALF_PI / (2.8284f * r + 4); // we only need (PI/4)/(r/sqrt(2)+1) steps
@ -762,8 +764,8 @@ void IRAM_ATTR_YN Segment::setPixelColor(int i, uint32_t col, bool unScaled)
int x = roundf(sin_t(rad) * r);
int y = roundf(cos_t(rad) * r);
// exploit symmetry
setPixelColorXY(x, y, col, false);
setPixelColorXY(y, x, col, false);
setPixelColorXY(x, y, col);
setPixelColorXY(y, x, col);
}
// Bresenhams Algorithm (may not fill every pixel)
//int d = 3 - (2*i);
@ -782,8 +784,8 @@ void IRAM_ATTR_YN Segment::setPixelColor(int i, uint32_t col, bool unScaled)
}
break;
case M12_pCorner:
for (int x = 0; x <= i; x++) setPixelColorXY(x, i, col, false);
for (int y = 0; y < i; y++) setPixelColorXY(i, y, col, false);
for (int x = 0; x <= i; x++) setPixelColorXY(x, i, col);
for (int y = 0; y < i; y++) setPixelColorXY(i, y, col);
break;
case M12_sPinwheel: {
// i = angle --> 0 - 296 (Big), 0 - 192 (Medium), 0 - 72 (Small)
@ -822,7 +824,7 @@ void IRAM_ATTR_YN Segment::setPixelColor(int i, uint32_t col, bool unScaled)
int x = posx / Fixed_Scale;
int y = posy / Fixed_Scale;
// set pixel
if (x != lastX || y != lastY) setPixelColorXY(x, y, col, false); // only paint if pixel position is different
if (x != lastX || y != lastY) setPixelColorXY(x, y, col); // only paint if pixel position is different
lastX = x;
lastY = y;
// advance to next position
@ -846,9 +848,8 @@ void IRAM_ATTR_YN Segment::setPixelColor(int i, uint32_t col, bool unScaled)
#endif
unsigned len = length();
// if color is unscaled
if (unScaled) col = color_fade(col, currentBri());
if(getCurrentBrightness() < 255) //!!! test without this if
col = color_fade(col, getCurrentBrightness()); // scale brightness
// expand pixel (taking into account start, grouping, spacing [and offset])
i = i * groupLength();
if (reverse) { // is segment reversed?
@ -1070,11 +1071,9 @@ void Segment::fill(uint32_t c) {
if (!isActive()) return; // not active
const int cols = is2D() ? vWidth() : vLength();
const int rows = vHeight(); // will be 1 for 1D
// pre-scale color for all pixels
c = color_fade(c, currentBri());
for (int y = 0; y < rows; y++) for (int x = 0; x < cols; x++) {
if (is2D()) setPixelColorXY(x, y, c, false);
else setPixelColor(x, c, false);
if (is2D()) setPixelColorXY(x, y, c);
else setPixelColor(x, c);
}
}