blur speedup
it seems that SEGMENT.blur() is the main bottleneck for many 2D effects. This change optimizes performance of the function: * avoid to re-write unchanged pixels * early exit when blur_amount == 0 (=nothing to do) * use _fast_ types where possible I've seen up to 20% speedup with this change.
This commit is contained in:
parent
fbbf2d5eb3
commit
42b247756a
@ -306,6 +306,7 @@ void Segment::blendPixelColorXY(uint16_t x, uint16_t y, uint32_t color, uint8_t
|
|||||||
|
|
||||||
// Adds the specified color with the existing pixel color perserving color balance.
|
// Adds the specified color with the existing pixel color perserving color balance.
|
||||||
void Segment::addPixelColorXY(int x, int y, uint32_t color, bool fast) {
|
void Segment::addPixelColorXY(int x, int y, uint32_t color, bool fast) {
|
||||||
|
if (x >= virtualWidth() || y >= virtualHeight() || x<0 || y<0) return; // if pixel would fall out of virtual segment just exit
|
||||||
uint32_t col = getPixelColorXY(x,y);
|
uint32_t col = getPixelColorXY(x,y);
|
||||||
uint8_t r = R(col);
|
uint8_t r = R(col);
|
||||||
uint8_t g = G(col);
|
uint8_t g = G(col);
|
||||||
@ -330,24 +331,26 @@ void Segment::fadePixelColorXY(uint16_t x, uint16_t y, uint8_t fade) {
|
|||||||
|
|
||||||
// blurRow: perform a blur on a row of a rectangular matrix
|
// blurRow: perform a blur on a row of a rectangular matrix
|
||||||
void Segment::blurRow(uint16_t row, fract8 blur_amount) {
|
void Segment::blurRow(uint16_t row, fract8 blur_amount) {
|
||||||
const uint16_t cols = virtualWidth();
|
const uint_fast16_t cols = virtualWidth();
|
||||||
const uint16_t rows = virtualHeight();
|
const uint_fast16_t rows = virtualHeight();
|
||||||
|
|
||||||
if (row >= rows) return;
|
if (row >= rows) return;
|
||||||
// blur one row
|
// blur one row
|
||||||
uint8_t keep = 255 - blur_amount;
|
uint8_t keep = 255 - blur_amount;
|
||||||
uint8_t seep = blur_amount >> 1;
|
uint8_t seep = blur_amount >> 1;
|
||||||
CRGB carryover = CRGB::Black;
|
CRGB carryover = CRGB::Black;
|
||||||
for (uint16_t x = 0; x < cols; x++) {
|
for (uint_fast16_t x = 0; x < cols; x++) {
|
||||||
CRGB cur = getPixelColorXY(x, row);
|
CRGB cur = getPixelColorXY(x, row);
|
||||||
|
uint32_t before = uint32_t(cur); // remember color before blur
|
||||||
CRGB part = cur;
|
CRGB part = cur;
|
||||||
part.nscale8(seep);
|
part.nscale8(seep);
|
||||||
cur.nscale8(keep);
|
cur.nscale8(keep);
|
||||||
cur += carryover;
|
cur += carryover;
|
||||||
if (x) {
|
if (x>0) {
|
||||||
CRGB prev = CRGB(getPixelColorXY(x-1, row)) + part;
|
CRGB prev = CRGB(getPixelColorXY(x-1, row)) + part;
|
||||||
setPixelColorXY(x-1, row, prev);
|
setPixelColorXY(x-1, row, prev);
|
||||||
}
|
}
|
||||||
|
if (before != uint32_t(cur)) // optimization: only set pixel if color has changed
|
||||||
setPixelColorXY(x, row, cur);
|
setPixelColorXY(x, row, cur);
|
||||||
carryover = part;
|
carryover = part;
|
||||||
}
|
}
|
||||||
@ -355,25 +358,27 @@ void Segment::blurRow(uint16_t row, fract8 blur_amount) {
|
|||||||
|
|
||||||
// blurCol: perform a blur on a column of a rectangular matrix
|
// blurCol: perform a blur on a column of a rectangular matrix
|
||||||
void Segment::blurCol(uint16_t col, fract8 blur_amount) {
|
void Segment::blurCol(uint16_t col, fract8 blur_amount) {
|
||||||
const uint16_t cols = virtualWidth();
|
const uint_fast16_t cols = virtualWidth();
|
||||||
const uint16_t rows = virtualHeight();
|
const uint_fast16_t rows = virtualHeight();
|
||||||
|
|
||||||
if (col >= cols) return;
|
if (col >= cols) return;
|
||||||
// blur one column
|
// blur one column
|
||||||
uint8_t keep = 255 - blur_amount;
|
uint8_t keep = 255 - blur_amount;
|
||||||
uint8_t seep = blur_amount >> 1;
|
uint8_t seep = blur_amount >> 1;
|
||||||
CRGB carryover = CRGB::Black;
|
CRGB carryover = CRGB::Black;
|
||||||
for (uint16_t i = 0; i < rows; i++) {
|
for (uint_fast16_t y = 0; y < rows; y++) {
|
||||||
CRGB cur = getPixelColorXY(col, i);
|
CRGB cur = getPixelColorXY(col, y);
|
||||||
CRGB part = cur;
|
CRGB part = cur;
|
||||||
|
uint32_t before = uint32_t(cur); // remember color before blur
|
||||||
part.nscale8(seep);
|
part.nscale8(seep);
|
||||||
cur.nscale8(keep);
|
cur.nscale8(keep);
|
||||||
cur += carryover;
|
cur += carryover;
|
||||||
if (i) {
|
if (y>0) {
|
||||||
CRGB prev = CRGB(getPixelColorXY(col, i-1)) + part;
|
CRGB prev = CRGB(getPixelColorXY(col, y-1)) + part;
|
||||||
setPixelColorXY(col, i-1, prev);
|
setPixelColorXY(col, y-1, prev);
|
||||||
}
|
}
|
||||||
setPixelColorXY(col, i, cur);
|
if (before != uint32_t(cur)) // optimization: only set pixel if color has changed
|
||||||
|
setPixelColorXY(col, y, cur);
|
||||||
carryover = part;
|
carryover = part;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -392,8 +397,8 @@ void Segment::box_blur(uint16_t i, bool vertical, fract8 blur_amount) {
|
|||||||
for (uint16_t j = 0; j < dim1; j++) {
|
for (uint16_t j = 0; j < dim1; j++) {
|
||||||
uint16_t x = vertical ? i : j;
|
uint16_t x = vertical ? i : j;
|
||||||
uint16_t y = vertical ? j : i;
|
uint16_t y = vertical ? j : i;
|
||||||
uint16_t xp = vertical ? x : x-1;
|
int16_t xp = vertical ? x : x-1; // "signed" to prevent underflow
|
||||||
uint16_t yp = vertical ? y-1 : y;
|
int16_t yp = vertical ? y-1 : y; // "signed" to prevent underflow
|
||||||
uint16_t xn = vertical ? x : x+1;
|
uint16_t xn = vertical ? x : x+1;
|
||||||
uint16_t yn = vertical ? y+1 : y;
|
uint16_t yn = vertical ? y+1 : y;
|
||||||
CRGB curr = getPixelColorXY(x,y);
|
CRGB curr = getPixelColorXY(x,y);
|
||||||
|
@ -887,6 +887,7 @@ void Segment::fade_out(uint8_t rate) {
|
|||||||
|
|
||||||
// fades all pixels to black using nscale8()
|
// fades all pixels to black using nscale8()
|
||||||
void Segment::fadeToBlackBy(uint8_t fadeBy) {
|
void Segment::fadeToBlackBy(uint8_t fadeBy) {
|
||||||
|
if (fadeBy == 0) return; // optimization - no scaling to apply
|
||||||
const uint16_t cols = is2D() ? virtualWidth() : virtualLength();
|
const uint16_t cols = is2D() ? virtualWidth() : virtualLength();
|
||||||
const uint16_t rows = virtualHeight(); // will be 1 for 1D
|
const uint16_t rows = virtualHeight(); // will be 1 for 1D
|
||||||
|
|
||||||
@ -901,23 +902,26 @@ void Segment::fadeToBlackBy(uint8_t fadeBy) {
|
|||||||
*/
|
*/
|
||||||
void Segment::blur(uint8_t blur_amount)
|
void Segment::blur(uint8_t blur_amount)
|
||||||
{
|
{
|
||||||
|
if (blur_amount == 0) return; // optimization: 0 means "don't blur"
|
||||||
#ifndef WLED_DISABLE_2D
|
#ifndef WLED_DISABLE_2D
|
||||||
if (is2D()) {
|
if (is2D()) {
|
||||||
// compatibility with 2D
|
// compatibility with 2D
|
||||||
const uint16_t cols = virtualWidth();
|
const uint_fast16_t cols = virtualWidth();
|
||||||
const uint16_t rows = virtualHeight();
|
const uint_fast16_t rows = virtualHeight();
|
||||||
for (uint16_t i = 0; i < rows; i++) blurRow(i, blur_amount); // blur all rows
|
for (uint_fast16_t i = 0; i < rows; i++) blurRow(i, blur_amount); // blur all rows
|
||||||
for (uint16_t k = 0; k < cols; k++) blurCol(k, blur_amount); // blur all columns
|
for (uint_fast16_t k = 0; k < cols; k++) blurCol(k, blur_amount); // blur all columns
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
uint8_t keep = 255 - blur_amount;
|
uint8_t keep = 255 - blur_amount;
|
||||||
uint8_t seep = blur_amount >> 1;
|
uint8_t seep = blur_amount >> 1;
|
||||||
CRGB carryover = CRGB::Black;
|
CRGB carryover = CRGB::Black;
|
||||||
for(uint16_t i = 0; i < virtualLength(); i++)
|
uint_fast16_t vlength = virtualLength();
|
||||||
|
for(uint_fast16_t i = 0; i < vlength; i++)
|
||||||
{
|
{
|
||||||
CRGB cur = CRGB(getPixelColor(i));
|
CRGB cur = CRGB(getPixelColor(i));
|
||||||
CRGB part = cur;
|
CRGB part = cur;
|
||||||
|
uint32_t before = uint32_t(cur); // remember color before blur
|
||||||
part.nscale8(seep);
|
part.nscale8(seep);
|
||||||
cur.nscale8(keep);
|
cur.nscale8(keep);
|
||||||
cur += carryover;
|
cur += carryover;
|
||||||
@ -926,9 +930,10 @@ void Segment::blur(uint8_t blur_amount)
|
|||||||
uint8_t r = R(c);
|
uint8_t r = R(c);
|
||||||
uint8_t g = G(c);
|
uint8_t g = G(c);
|
||||||
uint8_t b = B(c);
|
uint8_t b = B(c);
|
||||||
setPixelColor(i-1, qadd8(r, part.red), qadd8(g, part.green), qadd8(b, part.blue));
|
setPixelColor((uint16_t)(i-1), qadd8(r, part.red), qadd8(g, part.green), qadd8(b, part.blue));
|
||||||
}
|
}
|
||||||
setPixelColor(i,cur.red, cur.green, cur.blue);
|
if (before != uint32_t(cur)) // optimization: only set pixel if color has changed
|
||||||
|
setPixelColor((uint16_t)i,cur.red, cur.green, cur.blue);
|
||||||
carryover = part;
|
carryover = part;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user