From 2934739ebf3156eb69b4471adadd61d2cee52bd2 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 9 Aug 2024 17:46:14 +0200 Subject: [PATCH] HUB75 cleanup, double buffer improvement * code cleanup, removing some unneeded sanity checks * use dirty bits in double buffer mode, too -> only not-black pixels are drawn into the back-buffer (20%-30% faster) --- wled00/bus_manager.cpp | 39 +++++++++++++++++++++------------------ wled00/bus_manager.h | 1 - 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index ced434a4..f5ecb5d6 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -19,7 +19,7 @@ bool getBitFromArray(const uint8_t* byteArray, size_t position) { // get bit val } void setBitInArray(uint8_t* byteArray, size_t position, bool value) { // set bit - with error handling for nullptr - if (byteArray == nullptr) return; + //if (byteArray == nullptr) return; size_t byteIndex = position / 8; unsigned bitIndex = position % 8; if (value) @@ -526,7 +526,6 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh _valid = false; mxconfig.double_buff = false; // default to off, known to cause issue with some effects but needs more memory - isBlack = false; fourScanPanel = nullptr; @@ -700,14 +699,20 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh if (_ledBuffer) free(_ledBuffer); // should not happen if (_ledsDirty) free(_ledsDirty); // should not happen - if(mxconfig.double_buff == false) { - _ledBuffer = (CRGB*) calloc(_len, sizeof(CRGB)); // create LEDs buffer (initialized to BLACK) - _ledsDirty = (byte*) malloc(getBitArrayBytes(_len)); // create LEDs dirty bits - //_ledsDirty = nullptr; - setBitArray(_ledsDirty, _len, false); // reset dirty bits - } + _ledsDirty = (byte*) malloc(getBitArrayBytes(_len)); // create LEDs dirty bits - isBlack = true; + if (_ledsDirty == nullptr) { + display->stopDMAoutput(); + delete display; display = nullptr; + _valid = false; + USER_PRINTLN(F("MatrixPanel_I2S_DMA not started - not enough memory for dirty bits!")); + return; // fail is we cannot get memory for the buffer + } + setBitArray(_ledsDirty, _len, false); // reset dirty bits + + if (mxconfig.double_buff == false) { + _ledBuffer = (CRGB*) calloc(_len, sizeof(CRGB)); // create LEDs buffer (initialized to BLACK) + } } switch(bc.type) { @@ -753,11 +758,12 @@ void __attribute__((hot)) BusHub75Matrix::setPixelColor(uint16_t pix, uint32_t c if (_ledBuffer[pix] != fastled_col) { _ledBuffer[pix] = fastled_col; setBitInArray(_ledsDirty, pix, true); // flag pixel as "dirty" - isBlack = false; } } else { - if (isBlack && (c == BLACK)) return; // reject black pixels directly after clearScreen() + if ((c == BLACK) && (getBitFromArray(_ledsDirty, pix) == false)) return; // ignore black if pixel is already black + setBitInArray(_ledsDirty, pix, c != BLACK); // dirty = true means "color is not BLACK" + #ifndef NO_CIE1931 c = unGamma24(c); // to use the driver linear brightness feature, we first need to undo WLED gamma correction #endif @@ -776,7 +782,6 @@ void __attribute__((hot)) BusHub75Matrix::setPixelColor(uint16_t pix, uint32_t c int y = pix / width; display->drawPixelRGB888(int16_t(x), int16_t(y), r, g, b); } - isBlack = false; } } @@ -785,7 +790,7 @@ uint32_t BusHub75Matrix::getPixelColor(uint16_t pix) const { if (_ledBuffer) return uint32_t(_ledBuffer[pix].scale8(_bri)) & 0x00FFFFFF; // scale8() is needed to mimic NeoPixelBus, which returns scaled-down colours else - return BLACK; + return getBitFromArray(_ledsDirty, pix) ? DARKGREY: BLACK; // just a hack - we only know if the pixel is black or not } void BusHub75Matrix::setBrightness(uint8_t b, bool immediate) { @@ -797,7 +802,6 @@ void __attribute__((hot)) BusHub75Matrix::show(void) { if (!_valid) return; if (_ledBuffer) { // write out buffered LEDs - bool haveDirtyBits = (_ledsDirty != nullptr); bool isFourScan = (fourScanPanel != nullptr); unsigned width = isFourScan ? fourScanPanel->width() : display->width(); unsigned height = isFourScan ? fourScanPanel->height() : display->height(); @@ -806,7 +810,7 @@ void __attribute__((hot)) BusHub75Matrix::show(void) { size_t pix = 0; // running pixel index for (int y=0; yflipDMABuffer(); // Show the back buffer, set current output buffer to the back (i.e. no longer being sent to LED panels) // while(!previousBufferFree) delay(1); // experimental - Wait before we allow any writing to the buffer. Stop flicker. display->clearScreen(); // Now clear the back-buffer - isBlack = true; + setBitArray(_ledsDirty, _len, false); // dislay buffer is blank - reset all dirty bits } } @@ -840,7 +844,6 @@ void BusHub75Matrix::cleanup() { delete display; display = nullptr; fourScanPanel = nullptr; - isBlack = false; if (_ledBuffer != nullptr) free(_ledBuffer); _ledBuffer = nullptr; if (_ledsDirty != nullptr) free(_ledsDirty); _ledsDirty = nullptr; } diff --git a/wled00/bus_manager.h b/wled00/bus_manager.h index 93d5eb46..96aba376 100644 --- a/wled00/bus_manager.h +++ b/wled00/bus_manager.h @@ -389,7 +389,6 @@ class BusHub75Matrix : public Bus { MatrixPanel_I2S_DMA *display = nullptr; VirtualMatrixPanel *fourScanPanel = nullptr; HUB75_I2S_CFG mxconfig; - bool isBlack = false; CRGB *_ledBuffer = nullptr; byte *_ledsDirty = nullptr; };