Memory allocation fixes.

Whitespace.
Cleanup.
This commit is contained in:
Blaz Kristan 2022-08-06 12:39:12 +02:00
parent aa36e04250
commit a8785570df
5 changed files with 80 additions and 90 deletions

View File

@ -449,7 +449,7 @@ typedef struct Segment {
uint16_t _dataLen;
static uint16_t _usedSegmentData;
// transition data, valid only if getOption(SEG_OPTION_TRANSITIONAL)==true, holds values during transition
// transition data, valid only if transitional==true, holds values during transition
struct Transition {
uint32_t _colorT[NUM_COLORS];
uint8_t _briT; // temporary brightness
@ -526,11 +526,11 @@ typedef struct Segment {
Segment& operator= (Segment &&orig) noexcept; // move assignment
#ifdef WLED_DEBUG
size_t getSize() { return sizeof(Segment) + (data?_dataLen:0) + (name?strlen(name):0) + (_t?sizeof(Transition):0) + (leds?sizeof(CRGB)*length():0); }
size_t getSize() { return sizeof(Segment) + (data?_dataLen:0) + (name?strlen(name):0) + (_t?sizeof(Transition):0) + (!Segment::_globalLeds && leds?sizeof(CRGB)*length():0); }
#endif
inline bool getOption(uint8_t n) { return ((options >> n) & 0x01); }
inline bool isSelected(void) { return getOption(0); }
inline bool isSelected(void) { return selected; }
inline bool isActive(void) { return stop > start; }
inline bool is2D(void) { return !(startY == 0 && stopY == 1); }
inline uint16_t width(void) { return stop - start; } // segment width in physical pixels (length if 1D)
@ -737,6 +737,7 @@ class WS2812FX { // 96 bytes
_modeData.clear();
_segments.clear();
customPalettes.clear();
if (useLedsArray && Segment::_globalLeds) free(Segment::_globalLeds);
}
static WS2812FX* getInstance(void) { return instance; }

View File

@ -153,7 +153,7 @@ void IRAM_ATTR Segment::setPixelColorXY(int x, int y, uint32_t col)
if (leds) leds[XY(x,y)] = col;
uint8_t _bri_t = currentBri(getOption(SEG_OPTION_ON) ? opacity : 0);
uint8_t _bri_t = currentBri(on ? opacity : 0);
if (_bri_t < 255) {
byte r = scale8(R(col), _bri_t);
byte g = scale8(G(col), _bri_t);
@ -162,9 +162,9 @@ void IRAM_ATTR Segment::setPixelColorXY(int x, int y, uint32_t col)
col = RGBW32(r, g, b, w);
}
if (getOption(SEG_OPTION_REVERSED) ) x = virtualWidth() - x - 1;
if (getOption(SEG_OPTION_REVERSED_Y)) y = virtualHeight() - y - 1;
if (getOption(SEG_OPTION_TRANSPOSED)) { uint16_t t = x; x = y; y = t; } // swap X & Y if segment transposed
if (reverse ) x = virtualWidth() - x - 1;
if (reverse_y) y = virtualHeight() - y - 1;
if (transpose) { uint16_t t = x; x = y; y = t; } // swap X & Y if segment transposed
x *= groupLength(); // expand to physical pixels
y *= groupLength(); // expand to physical pixels
@ -177,15 +177,15 @@ void IRAM_ATTR Segment::setPixelColorXY(int x, int y, uint32_t col)
strip.setPixelColorXY(start + xX, startY + yY, col);
if (getOption(SEG_OPTION_MIRROR)) { //set the corresponding horizontally mirrored pixel
if (getOption(SEG_OPTION_TRANSPOSED)) strip.setPixelColorXY(start + xX, startY + height() - yY - 1, col);
else strip.setPixelColorXY(start + width() - xX - 1, startY + yY, col);
if (mirror) { //set the corresponding horizontally mirrored pixel
if (transpose) strip.setPixelColorXY(start + xX, startY + height() - yY - 1, col);
else strip.setPixelColorXY(start + width() - xX - 1, startY + yY, col);
}
if (getOption(SEG_OPTION_MIRROR_Y)) { //set the corresponding vertically mirrored pixel
if (getOption(SEG_OPTION_TRANSPOSED)) strip.setPixelColorXY(start + width() - xX - 1, startY + yY, col);
else strip.setPixelColorXY(start + xX, startY + height() - yY - 1, col);
if (mirror_y) { //set the corresponding vertically mirrored pixel
if (transpose) strip.setPixelColorXY(start + width() - xX - 1, startY + yY, col);
else strip.setPixelColorXY(start + xX, startY + height() - yY - 1, col);
}
if (getOption(SEG_OPTION_MIRROR_Y) && getOption(SEG_OPTION_MIRROR)) { //set the corresponding vertically AND horizontally mirrored pixel
if (mirror_y && mirror) { //set the corresponding vertically AND horizontally mirrored pixel
strip.setPixelColorXY(width() - xX - 1, height() - yY - 1, col);
}
}
@ -240,9 +240,9 @@ void Segment::setPixelColorXY(float x, float y, uint32_t col, bool aa)
uint32_t Segment::getPixelColorXY(uint16_t x, uint16_t y) {
int i = XY(x,y);
if (leds) return RGBW32(leds[i].r, leds[i].g, leds[i].b, 0);
if (getOption(SEG_OPTION_REVERSED) ) x = virtualWidth() - x - 1;
if (getOption(SEG_OPTION_REVERSED_Y)) y = virtualHeight() - y - 1;
if (getOption(SEG_OPTION_TRANSPOSED)) { uint16_t t = x; x = y; y = t; } // swap X & Y if segment transposed
if (reverse ) x = virtualWidth() - x - 1;
if (reverse_y) y = virtualHeight() - y - 1;
if (transpose) { uint16_t t = x; x = y; y = t; } // swap X & Y if segment transposed
x *= groupLength(); // expand to physical pixels
y *= groupLength(); // expand to physical pixels
if (x >= width() || y >= height()) return 0;

View File

@ -78,23 +78,22 @@ CRGB *Segment::_globalLeds = nullptr;
// copy constructor
Segment::Segment(const Segment &orig) {
DEBUG_PRINTLN(F("-- Segment duplicated --"));
DEBUG_PRINTLN(F("-- Copy segment constructor --"));
memcpy(this, &orig, sizeof(Segment));
name = nullptr;
data = nullptr;
_dataLen = 0;
_t = nullptr;
if (leds && !Segment::_globalLeds) leds = nullptr;
if (orig.name) { name = new char[strlen(orig.name)+1]; if (name) strcpy(name, orig.name); }
if (orig.data) { if (allocateData(orig._dataLen)) memcpy(data, orig.data, orig._dataLen); }
if (orig._t) { _t = new Transition(orig._t->_dur, orig._t->_briT, orig._t->_cctT, orig._t->_colorT); }
if (orig.leds) { leds = (CRGB*)malloc(sizeof(CRGB)*length()); }
DEBUG_PRINTF(" Original data: %p (%d)\n", orig.data, (int)orig._dataLen);
DEBUG_PRINTF(" Constructed data: %p (%d)\n", data, (int)_dataLen);
if (orig.leds && !Segment::_globalLeds) { leds = (CRGB*)malloc(sizeof(CRGB)*length()); if (leds) memcpy(leds, orig.leds, sizeof(CRGB)*length()); }
}
// move constructor
Segment::Segment(Segment &&orig) noexcept {
DEBUG_PRINTLN(F("-- Move constructor --"));
DEBUG_PRINTLN(F("-- Move segment constructor --"));
memcpy(this, &orig, sizeof(Segment));
orig.name = nullptr;
orig.data = nullptr;
@ -105,27 +104,26 @@ Segment::Segment(Segment &&orig) noexcept {
// copy assignment
Segment& Segment::operator= (const Segment &orig) {
DEBUG_PRINTLN(F("-- Segment copied --"));
DEBUG_PRINTLN(F("-- Copying segment --"));
if (this != &orig) {
if (name) {
DEBUG_PRINTF(" Copy Deleting %s (%p)\n", name, name);
delete[] name;
}
if (_t) delete _t;
if (leds) free(leds);
// clean destination
if (name) delete[] name;
if (_t) delete _t;
if (leds && !Segment::_globalLeds) free(leds);
deallocateData();
// copy source
memcpy(this, &orig, sizeof(Segment));
// erase pointers to allocated data
name = nullptr;
data = nullptr;
_dataLen = 0;
_t = nullptr;
leds = nullptr;
if (!Segment::_globalLeds) leds = nullptr;
// copy source data
if (orig.name) { name = new char[strlen(orig.name)+1]; if (name) strcpy(name, orig.name); }
if (orig.data) { if (allocateData(orig._dataLen)) memcpy(data, orig.data, orig._dataLen); }
if (orig._t) { _t = new Transition(orig._t->_dur, orig._t->_briT, orig._t->_cctT, orig._t->_colorT); }
if (orig.leds) { leds = (CRGB*)malloc(sizeof(CRGB)*length()); if (leds) memcpy(leds, orig.leds, sizeof(CRGB)*length()); }
DEBUG_PRINTF(" Original data: %p (%d)\n", orig.data, (int)orig._dataLen);
DEBUG_PRINTF(" Copied data: %p (%d)\n", data, (int)_dataLen);
if (orig._t) { _t = new Transition(orig._t->_dur, orig._t->_briT, orig._t->_cctT, orig._t->_colorT); }
if (orig.leds && !Segment::_globalLeds) { leds = (CRGB*)malloc(sizeof(CRGB)*length()); if (leds) memcpy(leds, orig.leds, sizeof(CRGB)*length()); }
}
return *this;
}
@ -134,13 +132,10 @@ Segment& Segment::operator= (const Segment &orig) {
Segment& Segment::operator= (Segment &&orig) noexcept {
DEBUG_PRINTLN(F("-- Moving segment --"));
if (this != &orig) {
if (name) {
DEBUG_PRINTF(" Move Deleting %s (%p)\n", name, name);
delete[] name; // free old name
}
if (name) delete[] name; // free old name
deallocateData(); // free old runtime data
if (_t) delete _t;
if (leds) free(leds);
if (leds && !Segment::_globalLeds) free(leds);
memcpy(this, &orig, sizeof(Segment));
orig.name = nullptr;
orig.data = nullptr;
@ -166,19 +161,15 @@ bool Segment::allocateData(size_t len) {
Segment::addUsedSegmentData(len);
_dataLen = len;
memset(data, 0, len);
DEBUG_PRINTF("-- Allocated data %p (%d)\n", data, (int)len);
return true;
}
void Segment::deallocateData() {
if (!data) return;
DEBUG_PRINTF("-- Deallocating data: %p (%d)\n", data, (int)_dataLen);
free(data);
DEBUG_PRINTLN(F("-- Data freed."));
data = nullptr;
Segment::addUsedSegmentData(-_dataLen);
_dataLen = 0;
DEBUG_PRINTLN(F("-- Dealocated data."));
}
/**
@ -189,8 +180,8 @@ void Segment::deallocateData() {
* may free that data buffer.
*/
void Segment::resetIfRequired() {
if (reset) { // (getOption(SEG_OPTION_RESET))
if (leds) { free(leds); leds = nullptr; DEBUG_PRINTLN(F("Freeing leds.")); }
if (reset) {
if (leds && !Segment::_globalLeds) { free(leds); leds = nullptr; }
if (_t) _t->_dur = 0;
next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0;
reset = false; // setOption(SEG_OPTION_RESET, false);
@ -198,6 +189,7 @@ void Segment::resetIfRequired() {
}
void Segment::setUpLeds() {
// deallocation happens in resetIfRequired() as it is called when segment changes or in destructor
if (Segment::_globalLeds)
#ifndef WLED_DISABLE_2D
leds = &Segment::_globalLeds[start + startY*strip.matrixWidth]; // TODO: remove this hack
@ -209,17 +201,16 @@ void Segment::setUpLeds() {
}
void Segment::startTransition(uint16_t dur) {
if (transitional || _t) return; // already in transition
if (transitional || _t) return; // already in transition no need to store anything
// starting a transition has to occur before change so we get current values 1st
uint8_t _briT = currentBri(getOption(SEG_OPTION_ON) ? opacity : 0); // comment out uint8_t if not using Transition struct
uint8_t _cctT = currentBri(cct, true); // comment out uint8_t if not using Transition struct
uint8_t _briT = currentBri(on ? opacity : 0);
uint8_t _cctT = currentBri(cct, true);
CRGBPalette16 _palT; loadPalette(_palT, palette);
uint8_t _modeP = mode; // comment out uint8_t if not using Transition struct
uint32_t _colorT[NUM_COLORS]; // comment out if not using Transition struct
uint8_t _modeP = mode;
uint32_t _colorT[NUM_COLORS];
for (size_t i=0; i<NUM_COLORS; i++) _colorT[i] = currentColor(i, colors[i]);
// using transition struct
if (!_t) _t = new Transition(dur); // no previous transition running
if (!_t) return; // failed to allocate data
_t->_briT = _briT;
@ -227,14 +218,11 @@ void Segment::startTransition(uint16_t dur) {
_t->_palT = _palT;
_t->_modeP = _modeP;
for (size_t i=0; i<NUM_COLORS; i++) _t->_colorT[i] = _colorT[i];
// comment out if using transition struct as it is done in constructor
//_dur = dur;
//_start = millis();
setOption(SEG_OPTION_TRANSITIONAL, true);
transitional = true; // setOption(SEG_OPTION_TRANSITIONAL, true);
}
uint16_t Segment::progress() { //transition progression between 0-65535
// transition progression between 0-65535
uint16_t Segment::progress() {
if (!transitional || !_t) return 0xFFFFU;
uint32_t timeNow = millis();
if (timeNow - _t->_start > _t->_dur) return 0xFFFFU;
@ -391,7 +379,7 @@ void Segment::setOpacity(uint8_t o) {
}
void Segment::setOption(uint8_t n, bool val) {
bool prevOn = getOption(SEG_OPTION_ON);
bool prevOn = on;
if (fadeTransition && n == SEG_OPTION_ON && val != prevOn) startTransition(strip.getTransition()); // start transition prior to change
if (val) options |= 0x01 << n;
else options &= ~(0x01 << n);
@ -400,15 +388,15 @@ void Segment::setOption(uint8_t n, bool val) {
// 2D matrix
uint16_t Segment::virtualWidth() {
uint16_t groupLen = groupLength();
uint16_t vWidth = ((getOption(SEG_OPTION_TRANSPOSED) ? height() : width()) + groupLen - 1) / groupLen;
if (getOption(SEG_OPTION_MIRROR)) vWidth = (vWidth + 1) /2; // divide by 2 if mirror, leave at least a single LED
uint16_t 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 Segment::virtualHeight() {
uint16_t groupLen = groupLength();
uint16_t vHeight = ((getOption(SEG_OPTION_TRANSPOSED) ? width() : height()) + groupLen - 1) / groupLen;
if (getOption(SEG_OPTION_MIRROR_Y)) vHeight = (vHeight + 1) /2; // divide by 2 if mirror, leave at least a single LED
uint16_t 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;
}
@ -433,7 +421,7 @@ uint16_t Segment::virtualLength() {
#endif
uint16_t groupLen = groupLength();
uint16_t vLength = (length() + groupLen - 1) / groupLen;
if (getOption(SEG_OPTION_MIRROR)) vLength = (vLength + 1) /2; // divide by 2 if mirror, leave at least a single LED
if (mirror) vLength = (vLength + 1) /2; // divide by 2 if mirror, leave at least a single LED
return vLength;
}
@ -473,7 +461,7 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col)
if (leds) leds[i] = col;
uint16_t len = length();
uint8_t _bri_t = currentBri(getOption(SEG_OPTION_ON) ? opacity : 0);
uint8_t _bri_t = currentBri(on ? opacity : 0);
if (_bri_t < 255) {
byte r = scale8(R(col), _bri_t);
byte g = scale8(G(col), _bri_t);
@ -484,8 +472,8 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col)
// expand pixel (taking into account start, grouping, spacing [and offset])
i = i * groupLength();
if (getOption(SEG_OPTION_REVERSED)) { // is segment reversed?
if (getOption(SEG_OPTION_MIRROR)) { // is segment mirrored?
if (reverse) { // is segment reversed?
if (mirror) { // is segment mirrored?
i = (len - 1) / 2 - i; //only need to index half the pixels
} else {
i = (len - 1) - i;
@ -495,9 +483,9 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col)
// set all the pixels in the group
for (int j = 0; j < grouping; j++) {
uint16_t indexSet = i + ((getOption(SEG_OPTION_REVERSED)) ? -j : j);
uint16_t indexSet = i + ((reverse) ? -j : j);
if (indexSet >= start && indexSet < stop) {
if (getOption(SEG_OPTION_MIRROR)) { //set the corresponding mirrored pixel
if (mirror) { //set the corresponding mirrored pixel
uint16_t indexMir = stop - indexSet + start - 1;
indexMir += offset; // offset/phase
if (indexMir >= stop) indexMir -= len; // wrap
@ -564,7 +552,7 @@ uint32_t Segment::getPixelColor(uint16_t i)
if (leds) return RGBW32(leds[i].r, leds[i].g, leds[i].b, 0);
if (getOption(SEG_OPTION_REVERSED)) i = virtualLength() - i - 1;
if (reverse) i = virtualLength() - i - 1;
i *= groupLength();
i += start;
/* offset/phase */
@ -862,12 +850,12 @@ void WS2812FX::finalizeInit(void)
}
//initialize leds array. TBD: realloc if nr of leds change
if (Segment::_globalLeds) {
purgeSegments(true);
free(Segment::_globalLeds);
Segment::_globalLeds = nullptr;
}
if (useLedsArray) {
if (Segment::_globalLeds) {
for (Segment seg : _segments) if (seg.leds) { free(seg.leds); seg.leds = nullptr; }
free(Segment::_globalLeds);
Segment::_globalLeds = nullptr;
}
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM)
if (psramFound())
Segment::_globalLeds = (CRGB*) ps_malloc(sizeof(CRGB) * _length);
@ -902,7 +890,7 @@ void WS2812FX::service() {
doShow = true;
uint16_t delay = FRAMETIME;
if (!seg.getOption(SEG_OPTION_FREEZE)) { //only run effect function if not frozen
if (!seg.freeze) { //only run effect function if not frozen
_virtualSegmentLength = seg.virtualLength();
_colors_t[0] = seg.currentColor(0, seg.colors[0]);
_colors_t[1] = seg.currentColor(1, seg.colors[1]);
@ -914,7 +902,7 @@ void WS2812FX::service() {
// effect blending (execute previous effect)
// actual code may be a bit more involved as effects have runtime data including allocated memory
//if (getOption(SEG_OPTION_TRANSITIONAL) && seg._modeP) (*_mode[seg._modeP])(progress());
//if (seg.transitional && seg._modeP) (*_mode[seg._modeP])(progress());
delay = (*_mode[seg.currentMode(seg.mode)])();
if (seg.mode != FX_MODE_HALLOWEEN_EYES) seg.call++;
if (seg.transitional && delay > FRAMETIME) delay = FRAMETIME; // foce faster updates during transition
@ -1406,6 +1394,7 @@ void WS2812FX::printSize()
DEBUG_PRINTF("Modes: %d*%d=%uB\n", sizeof(mode_ptr), _mode.size(), (_mode.capacity()*sizeof(mode_ptr)));
DEBUG_PRINTF("Data: %d*%d=%uB\n", sizeof(const char *), _modeData.size(), (_modeData.capacity()*sizeof(const char *)));
DEBUG_PRINTF("Map: %d*%d=%uB\n", sizeof(uint16_t), (int)customMappingSize, customMappingSize*sizeof(uint16_t));
if (useLedsArray) DEBUG_PRINTF("Buffer: %d*%d=%uB\n", sizeof(CRGB), (int)_length, _length*sizeof(CRGB));
}
#endif

View File

@ -23,7 +23,7 @@
}
setCanvas();
// Check for canvas support
var ctx = c.getContext('2d');
var ctx = c.getContext('2d');
if (ctx) { // Access the rendering context
// use parent WS or open new
var ws;
@ -44,18 +44,18 @@
if (toString.call(e.data) === '[object ArrayBuffer]') {
let leds = new Uint8Array(event.data);
if (leds[0] != 76 || !ctx) return; //'L', set in ws.cpp
let mW = leds[2]; // matrix width
let mH = leds[3]; // matrix height
let pPL = Math.min(c.width / mW, c.height / mH); // pixels per LED (width of circle)
let lOf = Math.floor((c.width - pPL*mW)/2); //left offeset (to center matrix)
var i = 4;
for (y=0.5;y<mH;y++) for (x=0.5; x<mW; x++) {
ctx.fillStyle = `rgb(${leds[i]},${leds[i+1]},${leds[i+2]})`;
ctx.beginPath();
ctx.arc(x*pPL+lOf, y*pPL, pPL*0.4, 0, 2 * Math.PI);
ctx.fill();
i+=3;
}
let mW = leds[2]; // matrix width
let mH = leds[3]; // matrix height
let pPL = Math.min(c.width / mW, c.height / mH); // pixels per LED (width of circle)
let lOf = Math.floor((c.width - pPL*mW)/2); //left offeset (to center matrix)
var i = 4;
for (y=0.5;y<mH;y++) for (x=0.5; x<mW; x++) {
ctx.fillStyle = `rgb(${leds[i]},${leds[i+1]},${leds[i+2]})`;
ctx.beginPath();
ctx.arc(x*pPL+lOf, y*pPL, pPL*0.4, 0, 2 * Math.PI);
ctx.fill();
i+=3;
}
}
} catch (err) {
console.error("Peek WS error:",err);

View File

@ -8,7 +8,7 @@
*/
// version code in format yymmddb (b = daily build)
#define VERSION 2208051
#define VERSION 2208061
//uncomment this if you have a "my_config.h" file you'd like to use
//#define WLED_USE_MY_CONFIG