Skip to content

Commit 5b3b093

Browse files
DedeHainetmindz
authored andcommitted
speed optimisations, fix for restoreColorLossy, code cleanup (wled#4895)
- speed optimization in color_add, PS fast_color_add and blur functions - applying more bit and shift manipulation tricks to squeeze out just a bit more speed on color manipulation functions. - Optimization on blur is based on work by @blazoncek - Renamed PS fast_color_add() to fast_color_scaleAdd()
1 parent 3a60a52 commit 5b3b093

File tree

9 files changed

+140
-151
lines changed

9 files changed

+140
-151
lines changed

wled00/FX_2Dfcn.cpp

Lines changed: 25 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ void WS2812FX::setUpMatrix() {
145145
#ifndef WLED_DISABLE_2D
146146
// pixel is clipped if it falls outside clipping range
147147
// if clipping start > stop the clipping range is inverted
148-
bool IRAM_ATTR_YN Segment::isPixelXYClipped(int x, int y) const {
148+
bool Segment::isPixelXYClipped(int x, int y) const {
149149
if (blendingStyle != BLEND_STYLE_FADE && isInTransition() && _clipStart != _clipStop) {
150150
const bool invertX = _clipStart > _clipStop;
151151
const bool invertY = _clipStartY > _clipStopY;
@@ -185,7 +185,7 @@ bool IRAM_ATTR_YN Segment::isPixelXYClipped(int x, int y) const {
185185
void IRAM_ATTR_YN Segment::setPixelColorXY(int x, int y, uint32_t col) const
186186
{
187187
if (!isActive()) return; // not active
188-
if (x >= (int)vWidth() || y >= (int)vHeight() || x < 0 || y < 0) return; // if pixel would fall out of virtual segment just exit
188+
if ((unsigned)x >= vWidth() || (unsigned)y >= vHeight()) return; // if pixel would fall out of virtual segment just exit
189189
setPixelColorXYRaw(x, y, col);
190190
}
191191

@@ -235,7 +235,7 @@ void Segment::setPixelColorXY(float x, float y, uint32_t col, bool aa) const
235235
// returns RGBW values of pixel
236236
uint32_t IRAM_ATTR_YN Segment::getPixelColorXY(int x, int y) const {
237237
if (!isActive()) return 0; // not active
238-
if (x >= (int)vWidth() || y >= (int)vHeight() || x<0 || y<0) return 0; // if pixel would fall out of virtual segment just exit
238+
if ((unsigned)x >= vWidth() || (unsigned)y >= vHeight()) return 0; // if pixel would fall out of virtual segment just exit
239239
return getPixelColorXYRaw(x,y);
240240
}
241241

@@ -245,52 +245,42 @@ void Segment::blur2D(uint8_t blur_x, uint8_t blur_y, bool smear) const {
245245
const unsigned cols = vWidth();
246246
const unsigned rows = vHeight();
247247
const auto XY = [&](unsigned x, unsigned y){ return x + y*cols; };
248-
uint32_t lastnew; // not necessary to initialize lastnew and last, as both will be initialized by the first loop iteration
249-
uint32_t last;
250248
if (blur_x) {
251249
const uint8_t keepx = smear ? 255 : 255 - blur_x;
252250
const uint8_t seepx = blur_x >> 1;
253251
for (unsigned row = 0; row < rows; row++) { // blur rows (x direction)
254-
uint32_t carryover = BLACK;
255-
uint32_t curnew = BLACK;
256-
for (unsigned x = 0; x < cols; x++) {
257-
uint32_t cur = getPixelColorRaw(XY(x, row));
258-
uint32_t part = color_fade(cur, seepx);
259-
curnew = color_fade(cur, keepx);
260-
if (x > 0) {
261-
if (carryover) curnew = color_add(curnew, carryover);
262-
uint32_t prev = color_add(lastnew, part);
263-
// optimization: only set pixel if color has changed
264-
if (last != prev) setPixelColorRaw(XY(x - 1, row), prev);
265-
} else setPixelColorRaw(XY(x, row), curnew); // first pixel
266-
lastnew = curnew;
267-
last = cur; // save original value for comparison on next iteration
252+
// handle first pixel in row to avoid conditional in loop (faster)
253+
uint32_t cur = getPixelColorRaw(XY(0, row));
254+
uint32_t carryover = fast_color_scale(cur, seepx);
255+
setPixelColorRaw(XY(0, row), fast_color_scale(cur, keepx));
256+
for (unsigned x = 1; x < cols; x++) {
257+
cur = getPixelColorRaw(XY(x, row));
258+
uint32_t part = fast_color_scale(cur, seepx);
259+
cur = fast_color_scale(cur, keepx);
260+
cur = color_add(cur, carryover);
261+
setPixelColorRaw(XY(x - 1, row), color_add(getPixelColorRaw(XY(x-1, row)), part)); // previous pixel
262+
setPixelColorRaw(XY(x, row), cur); // current pixel
268263
carryover = part;
269264
}
270-
setPixelColorRaw(XY(cols-1, row), curnew); // set last pixel
271265
}
272266
}
273267
if (blur_y) {
274268
const uint8_t keepy = smear ? 255 : 255 - blur_y;
275269
const uint8_t seepy = blur_y >> 1;
276270
for (unsigned col = 0; col < cols; col++) {
277-
uint32_t carryover = BLACK;
278-
uint32_t curnew = BLACK;
279-
for (unsigned y = 0; y < rows; y++) {
280-
uint32_t cur = getPixelColorRaw(XY(col, y));
281-
uint32_t part = color_fade(cur, seepy);
282-
curnew = color_fade(cur, keepy);
283-
if (y > 0) {
284-
if (carryover) curnew = color_add(curnew, carryover);
285-
uint32_t prev = color_add(lastnew, part);
286-
// optimization: only set pixel if color has changed
287-
if (last != prev) setPixelColorRaw(XY(col, y - 1), prev);
288-
} else setPixelColorRaw(XY(col, y), curnew); // first pixel
289-
lastnew = curnew;
290-
last = cur; //save original value for comparison on next iteration
271+
// handle first pixel in column
272+
uint32_t cur = getPixelColorRaw(XY(col, 0));
273+
uint32_t carryover = fast_color_scale(cur, seepy);
274+
setPixelColorRaw(XY(col, 0), fast_color_scale(cur, keepy));
275+
for (unsigned y = 1; y < rows; y++) {
276+
cur = getPixelColorRaw(XY(col, y));
277+
uint32_t part = fast_color_scale(cur, seepy);
278+
cur = fast_color_scale(cur, keepy);
279+
cur = color_add(cur, carryover);
280+
setPixelColorRaw(XY(col, y - 1), color_add(getPixelColorRaw(XY(col, y-1)), part)); // previous pixel
281+
setPixelColorRaw(XY(col, y), cur); // current pixel
291282
carryover = part;
292283
}
293-
setPixelColorRaw(XY(col, rows - 1), curnew);
294284
}
295285
}
296286
}

wled00/FX_fcn.cpp

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -682,7 +682,7 @@ uint16_t Segment::maxMappingLength() const {
682682
#endif
683683
// pixel is clipped if it falls outside clipping range
684684
// if clipping start > stop the clipping range is inverted
685-
bool IRAM_ATTR_YN Segment::isPixelClipped(int i) const {
685+
bool Segment::isPixelClipped(int i) const {
686686
if (blendingStyle != BLEND_STYLE_FADE && isInTransition() && _clipStart != _clipStop) {
687687
bool invert = _clipStart > _clipStop; // ineverted start & stop
688688
int start = invert ? _clipStop : _clipStart;
@@ -700,7 +700,7 @@ bool IRAM_ATTR_YN Segment::isPixelClipped(int i) const {
700700
return false;
701701
}
702702

703-
void IRAM_ATTR_YN Segment::setPixelColor(int i, uint32_t col) const
703+
void WLED_O2_ATTR Segment::setPixelColor(int i, uint32_t col) const
704704
{
705705
if (!isActive() || i < 0) return; // not active or invalid index
706706
#ifndef WLED_DISABLE_2D
@@ -913,7 +913,7 @@ void Segment::setPixelColor(float i, uint32_t col, bool aa) const
913913
}
914914
#endif
915915

916-
uint32_t IRAM_ATTR_YN Segment::getPixelColor(int i) const
916+
uint32_t WLED_O2_ATTR Segment::getPixelColor(int i) const
917917
{
918918
if (!isActive() || i < 0) return 0; // not active or invalid index
919919

@@ -1052,7 +1052,7 @@ void Segment::fadeToSecondaryBy(uint8_t fadeBy) const {
10521052
void Segment::fadeToBlackBy(uint8_t fadeBy) const {
10531053
if (!isActive() || fadeBy == 0) return; // optimization - no scaling to apply
10541054
const size_t rlength = rawLength(); // calculate only once
1055-
for (unsigned i = 0; i < rlength; i++) setPixelColorRaw(i, color_fade(getPixelColorRaw(i), 255-fadeBy));
1055+
for (unsigned i = 0; i < rlength; i++) setPixelColorRaw(i, fast_color_scale(getPixelColorRaw(i), 255-fadeBy));
10561056
}
10571057

10581058
/*
@@ -1072,25 +1072,19 @@ void Segment::blur(uint8_t blur_amount, bool smear) const {
10721072
uint8_t keep = smear ? 255 : 255 - blur_amount;
10731073
uint8_t seep = blur_amount >> 1;
10741074
unsigned vlength = vLength();
1075-
uint32_t carryover = BLACK;
1076-
uint32_t lastnew; // not necessary to initialize lastnew and last, as both will be initialized by the first loop iteration
1077-
uint32_t last;
1078-
uint32_t curnew = BLACK;
1079-
for (unsigned i = 0; i < vlength; i++) {
1080-
uint32_t cur = getPixelColorRaw(i);
1081-
uint32_t part = color_fade(cur, seep);
1082-
curnew = color_fade(cur, keep);
1083-
if (i > 0) {
1084-
if (carryover) curnew = color_add(curnew, carryover);
1085-
uint32_t prev = color_add(lastnew, part);
1086-
// optimization: only set pixel if color has changed
1087-
if (last != prev) setPixelColorRaw(i - 1, prev);
1088-
} else setPixelColorRaw(i, curnew); // first pixel
1089-
lastnew = curnew;
1090-
last = cur; // save original value for comparison on next iteration
1075+
// handle first pixel to avoid conditional in loop (faster)
1076+
uint32_t cur = getPixelColorRaw(0);
1077+
uint32_t carryover = fast_color_scale(cur, seep);
1078+
setPixelColorRaw(0, fast_color_scale(cur, keep));
1079+
for (unsigned i = 1; i < vlength; i++) {
1080+
cur = getPixelColorRaw(i);
1081+
uint32_t part = fast_color_scale(cur, seep);
1082+
cur = fast_color_scale(cur, keep);
1083+
cur = color_add(cur, carryover);
1084+
setPixelColorRaw(i - 1, color_add(getPixelColorRaw(i - 1), part)); // previous pixel
1085+
setPixelColorRaw(i, cur); // current pixel
10911086
carryover = part;
10921087
}
1093-
setPixelColorRaw(vlength - 1, curnew);
10941088
}
10951089

10961090
/*

0 commit comments

Comments
 (0)