Skip to content

Commit

Permalink
const const const
Browse files Browse the repository at this point in the history
adding hints for the compiler for optimization.
In case your custom build complains about "const", just remove the keyword. based on Aircoookie@e82f38e, but going further :-)

* "const" class functions : function does not modify any class attributes ( --> "this" becomes const)

* __attribute__((pure)) :  function return value depends only on the parameters and/or global variables. The function does not modify any global or static variables.
* __attribute__((const)) : function only examines arguments (no globals), and has no effects except the return value. This slightly more strict than "pure"
* hot: tells the compiler "this functions is called very often"
* cold: the opposite of hot
  • Loading branch information
softhack007 committed Aug 7, 2024
1 parent 273154d commit 7f9da30
Show file tree
Hide file tree
Showing 14 changed files with 148 additions and 145 deletions.
2 changes: 1 addition & 1 deletion usermods/audioreactive/audio_reactive.h
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ static volatile float micReal_max2 = 0.0f; // MicIn data max afte
// some prototypes, to ensure consistent interfaces
static float mapf(float x, float in_min, float in_max, float out_min, float out_max); // map function for float
static float fftAddAvg(int from, int to); // average of several FFT result bins
void FFTcode(void * parameter); // audio processing task: read samples, run FFT, fill GEQ channels from FFT results
void FFTcode(void * parameter) __attribute__((noreturn)); // audio processing task: read samples, run FFT, fill GEQ channels from FFT results
static void runMicFilter(uint16_t numSamples, float *sampleBuffer); // pre-filtering of raw samples (band-pass)
static void postProcessFFTResults(bool noiseGateOpen, int numberOfChannels, bool i2sFastpath); // post-processing and post-amp of GEQ channels

Expand Down
74 changes: 37 additions & 37 deletions wled00/FX.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@

bool canUseSerial(void); // WLEDMM implemented in wled_serial.cpp
void strip_wait_until_idle(String whoCalledMe); // WLEDMM implemented in FX_fcn.cpp
bool strip_uses_global_leds(void); // WLEDMM implemented in FX_fcn.cpp
bool strip_uses_global_leds(void) __attribute__((pure)); // WLEDMM implemented in FX_fcn.cpp

#define FASTLED_INTERNAL //remove annoying pragma messages
#define USE_GET_MILLISECOND_TIMER
Expand Down Expand Up @@ -640,7 +640,7 @@ typedef struct Segment {
void setPixelColor(float i, uint32_t c, bool aa = true);
inline void setPixelColor(float i, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0, bool aa = true) { setPixelColor(i, RGBW32(r,g,b,w), aa); }
inline void setPixelColor(float i, CRGB c, bool aa = true) { setPixelColor(i, RGBW32(c.r,c.g,c.b,0), aa); }
uint32_t __attribute__((pure)) getPixelColor(int i); // WLEDMM attribute added
uint32_t __attribute__((pure)) getPixelColor(int i) const; // WLEDMM attribute added
// 1D support functions (some implement 2D as well)
void blur(uint8_t, bool smear = false);
void fill(uint32_t c);
Expand All @@ -652,7 +652,7 @@ typedef struct Segment {
inline void addPixelColor(int n, byte r, byte g, byte b, byte w = 0, bool fast = false) { addPixelColor(n, RGBW32(r,g,b,w), fast); } // automatically inline
inline void addPixelColor(int n, CRGB c, bool fast = false) { addPixelColor(n, RGBW32(c.r,c.g,c.b,0), fast); } // automatically inline
void fadePixelColor(uint16_t n, uint8_t fade);
uint8_t get_random_wheel_index(uint8_t pos);
uint8_t get_random_wheel_index(uint8_t pos) const;
uint32_t __attribute__((pure)) color_from_palette(uint_fast16_t, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri = 255);
uint32_t __attribute__((pure)) color_wheel(uint8_t pos);

Expand Down Expand Up @@ -693,7 +693,7 @@ typedef struct Segment {
void deletejMap(); //WLEDMM jMap

#ifndef WLED_DISABLE_2D
inline uint16_t XY(uint_fast16_t x, uint_fast16_t y) { // support function to get relative index within segment (for leds[]) // WLEDMM inline for speed
inline uint16_t XY(uint_fast16_t x, uint_fast16_t y) const { // support function to get relative index within segment (for leds[]) // WLEDMM inline for speed
uint_fast16_t width = max(uint16_t(1), virtualWidth()); // segment width in logical pixels -- softhack007 avoid div/0
uint_fast16_t height = max(uint16_t(1), virtualHeight()); // segment height in logical pixels -- softhack007 avoid div/0
return (x%width) + (y%height) * width;
Expand Down Expand Up @@ -726,7 +726,7 @@ typedef struct Segment {
inline void setPixelColorXY(float x, float y, byte r, byte g, byte b, byte w = 0, bool aa = true) { setPixelColorXY(x, y, RGBW32(r,g,b,w), aa); }
inline void setPixelColorXY(float x, float y, CRGB c, bool aa = true) { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0), aa); }
//#endif
uint32_t __attribute__((pure)) getPixelColorXY(int x, int y);
uint32_t __attribute__((pure)) getPixelColorXY(int x, int y) const;
// 2D support functions
void blendPixelColorXY(uint16_t x, uint16_t y, uint32_t color, uint8_t blend);
inline void blendPixelColorXY(uint16_t x, uint16_t y, CRGB c, uint8_t blend) { blendPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0), blend); }
Expand Down Expand Up @@ -792,7 +792,7 @@ typedef struct Segment {
inline void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, CRGB c, CRGB c2, int8_t rotate = 0) {}
inline void wu_pixel(uint32_t x, uint32_t y, CRGB c) {}
#endif
uint8_t * getAudioPalette(int pal); //WLEDMM netmindz ar palette
uint8_t * getAudioPalette(int pal) const; //WLEDMM netmindz ar palette
} segment;
//static int segSize = sizeof(Segment);

Expand Down Expand Up @@ -915,64 +915,64 @@ class WS2812FX { // 96 bytes

bool
checkSegmentAlignment(void),
hasRGBWBus(void),
hasCCTBus(void),
hasRGBWBus(void) const,
hasCCTBus(void) const,
// return true if the strip is being sent pixel updates
isUpdating(void),
isUpdating(void) const,
deserializeMap(uint8_t n=0),
useLedsArray = false;

inline bool isServicing(void) { return _isServicing; }
inline bool hasWhiteChannel(void) {return _hasWhiteChannel;}
inline bool isOffRefreshRequired(void) {return _isOffRefreshRequired;}
inline bool isServicing(void) const { return _isServicing; }
inline bool hasWhiteChannel(void) const {return _hasWhiteChannel;}
inline bool isOffRefreshRequired(void) const {return _isOffRefreshRequired;}

uint8_t
paletteFade,
paletteBlend,
milliampsPerLed,
cctBlending,
getActiveSegmentsNum(void),
getFirstSelectedSegId(void),
getLastActiveSegmentId(void),
getActiveSegsLightCapabilities(bool selectedOnly = false),
getActiveSegmentsNum(void) const,
getFirstSelectedSegId(void) __attribute__((pure)),
getLastActiveSegmentId(void) const,
getActiveSegsLightCapabilities(bool selectedOnly = false) __attribute__((pure)),
setPixelSegment(uint8_t n);

inline uint8_t getBrightness(void) { return _brightness; }
inline uint8_t getMaxSegments(void) { return MAX_NUM_SEGMENTS; } // returns maximum number of supported segments (fixed value)
inline uint8_t getSegmentsNum(void) { return _segments.size(); } // returns currently present segments
inline uint8_t getCurrSegmentId(void) { return _segment_index; }
inline uint8_t getMainSegmentId(void) { return _mainSegment; }
inline uint8_t getPaletteCount() { return 13 + GRADIENT_PALETTE_COUNT; } // will only return built-in palette count
inline uint8_t getTargetFps() { return _targetFps; }
inline uint8_t getModeCount() { return _modeCount; }
inline uint8_t getBrightness(void) const { return _brightness; }
inline uint8_t getMaxSegments(void) const { return MAX_NUM_SEGMENTS; } // returns maximum number of supported segments (fixed value)
inline uint8_t getSegmentsNum(void) const { return _segments.size(); } // returns currently present segments
inline uint8_t getCurrSegmentId(void) const { return _segment_index; }
inline uint8_t getMainSegmentId(void) const { return _mainSegment; }
inline uint8_t getPaletteCount() const { return 13 + GRADIENT_PALETTE_COUNT; } // will only return built-in palette count
inline uint8_t getTargetFps() const { return _targetFps; }
inline uint8_t getModeCount() const { return _modeCount; }

uint16_t
ablMilliampsMax,
currentMilliamps,
getLengthPhysical(void),
__attribute__((pure)) getLengthTotal(void), // will include virtual/nonexistent pixels in matrix //WLEDMM attribute added
getFps();
getLengthPhysical(void) const,
__attribute__((pure)) getLengthTotal(void) const, // will include virtual/nonexistent pixels in matrix //WLEDMM attribute added
getFps() const;

inline uint16_t getFrameTime(void) { return _frametime; }
inline uint16_t getMinShowDelay(void) { return MIN_SHOW_DELAY; }
inline uint16_t getLength(void) { return _length; } // 2D matrix may have less pixels than W*H
inline uint16_t getTransition(void) { return _transitionDur; }
inline uint16_t getFrameTime(void) const { return _frametime; }
inline uint16_t getMinShowDelay(void) const { return MIN_SHOW_DELAY; }
inline uint16_t getLength(void) const { return _length; } // 2D matrix may have less pixels than W*H
inline uint16_t getTransition(void) const { return _transitionDur; }

uint32_t
now,
timebase;
uint32_t __attribute__((pure)) getPixelColor(uint_fast16_t); // WLEDMM attribute pure = does not have side-effects
uint32_t __attribute__((pure)) getPixelColor(uint_fast16_t) const; // WLEDMM attribute pure = does not have side-effects

inline uint32_t getLastShow(void) { return _lastShow; }
inline uint32_t segColor(uint8_t i) { return _colors_t[i]; }
inline uint32_t getLastShow(void) const { return _lastShow; }
inline uint32_t segColor(uint8_t i) const { return _colors_t[i]; }

const char *
getModeData(uint8_t id = 0) { return (id && id<_modeCount) ? _modeData[id] : PSTR("Solid"); }
getModeData(uint8_t id = 0) const { return (id && id<_modeCount) ? _modeData[id] : PSTR("Solid"); }

const char **
getModeDataSrc(void) { return &(_modeData[0]); } // vectors use arrays for underlying data

Segment& getSegment(uint8_t id);
Segment& getSegment(uint8_t id) __attribute__((pure));
inline Segment& getFirstSelectedSeg(void) { return _segments[getFirstSelectedSegId()]; }
inline Segment& getMainSegment(void) { return _segments[getMainSegmentId()]; }
inline Segment* getSegments(void) { return &(_segments[0]); }
Expand Down Expand Up @@ -1039,7 +1039,7 @@ class WS2812FX { // 96 bytes
inline void setPixelColorXY(int x, int y, CRGB c) { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0)); }

uint32_t
getPixelColorXY(uint16_t, uint16_t);
getPixelColorXY(uint16_t, uint16_t) const;

// end 2D support

Expand Down
8 changes: 4 additions & 4 deletions wled00/FX_2Dfcn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ void WS2812FX::setUpMatrix() {
}

// absolute matrix version of setPixelColor(), without error checking
void IRAM_ATTR WS2812FX::setPixelColorXY_fast(int x, int y, uint32_t col) //WLEDMM: IRAM_ATTR conditionally
void IRAM_ATTR __attribute__((hot)) WS2812FX::setPixelColorXY_fast(int x, int y, uint32_t col) //WLEDMM: IRAM_ATTR conditionally
{
uint_fast16_t index = y * Segment::maxWidth + x;
if (index < customMappingSize) index = customMappingTable[index];
Expand All @@ -200,7 +200,7 @@ void IRAM_ATTR_YN WS2812FX::setPixelColorXY(int x, int y, uint32_t col) //WLEDMM
}

// returns RGBW values of pixel
uint32_t WS2812FX::getPixelColorXY(uint16_t x, uint16_t y) {
uint32_t __attribute__((hot)) WS2812FX::getPixelColorXY(uint16_t x, uint16_t y) const {
#ifndef WLED_DISABLE_2D
uint_fast16_t index = (y * Segment::maxWidth + x); //WLEDMM: use fast types
#else
Expand Down Expand Up @@ -239,7 +239,7 @@ void Segment::startFrame(void) {

// Simplified version of Segment::setPixelColorXY - without error checking. Does not support grouping or spacing
// * expects scaled color (final brightness) as additional input parameter, plus segment virtualWidth() and virtualHeight()
void IRAM_ATTR Segment::setPixelColorXY_fast(int x, int y, uint32_t col, uint32_t scaled_col, int cols, int rows) //WLEDMM
void IRAM_ATTR __attribute__((hot)) Segment::setPixelColorXY_fast(int x, int y, uint32_t col, uint32_t scaled_col, int cols, int rows) //WLEDMM
{
unsigned i = UINT_MAX;
bool sameColor = false;
Expand Down Expand Up @@ -406,7 +406,7 @@ void Segment::setPixelColorXY(float x, float y, uint32_t col, bool aa, bool fast
}

// returns RGBW values of pixel
uint32_t IRAM_ATTR_YN Segment::getPixelColorXY(int x, int y) {
uint32_t IRAM_ATTR_YN Segment::getPixelColorXY(int x, int y) const {
if (x<0 || y<0 || !isActive()) return 0; // not active or out-of range
if (ledsrgb) {
int i = XY(x,y);
Expand Down
36 changes: 18 additions & 18 deletions wled00/FX_fcn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -882,7 +882,7 @@ uint16_t Segment::virtualLength() const {
}

//WLEDMM used for M12_sBlock
void xyFromBlock(uint16_t &x,uint16_t &y, uint16_t i, uint16_t vW, uint16_t vH, uint16_t vStrip) {
static void xyFromBlock(uint16_t &x,uint16_t &y, uint16_t i, uint16_t vW, uint16_t vH, uint16_t vStrip) {
float i2;
if (i<=SEGLEN*0.25) { //top, left to right
i2 = i/(SEGLEN*0.25);
Expand All @@ -907,7 +907,7 @@ void xyFromBlock(uint16_t &x,uint16_t &y, uint16_t i, uint16_t vW, uint16_t vH,

}

void IRAM_ATTR_YN Segment::setPixelColor(int i, uint32_t col) //WLEDMM: IRAM_ATTR conditionally
void IRAM_ATTR_YN __attribute__((hot)) Segment::setPixelColor(int i, uint32_t col) //WLEDMM: IRAM_ATTR conditionally
{
if (!isActive()) return; // not active
#ifndef WLED_DISABLE_2D
Expand Down Expand Up @@ -1171,7 +1171,7 @@ void Segment::setPixelColor(float i, uint32_t col, bool aa)
}
}

uint32_t Segment::getPixelColor(int i)
uint32_t __attribute__((hot)) Segment::getPixelColor(int i) const
{
if (!isActive()) return 0; // not active
#ifndef WLED_DISABLE_2D
Expand Down Expand Up @@ -1345,7 +1345,7 @@ void Segment::refreshLightCapabilities() {
/*
* Fills segment with color - WLEDMM using faster sPC if possible
*/
void Segment::fill(uint32_t c) {
void __attribute__((hot)) Segment::fill(uint32_t c) {
if (!isActive()) return; // not active

#if 0 && defined(WLED_ENABLE_HUB75MATRIX) && defined(WLEDMM_FASTPATH)
Expand Down Expand Up @@ -1457,7 +1457,7 @@ void Segment::fade_out(uint8_t rate) {
}

// fades all pixels to black using nscale8()
void Segment::fadeToBlackBy(uint8_t fadeBy) {
void __attribute__((hot)) Segment::fadeToBlackBy(uint8_t fadeBy) {
if (!isActive() || fadeBy == 0) return; // optimization - no scaling to apply
const uint_fast16_t cols = is2D() ? virtualWidth() : virtualLength(); // WLEDMM use fast int types
const uint_fast16_t rows = virtualHeight(); // will be 1 for 1D
Expand All @@ -1480,7 +1480,7 @@ void Segment::fadeToBlackBy(uint8_t fadeBy) {
/*
* blurs segment content, source: FastLED colorutils.cpp
*/
void Segment::blur(uint8_t blur_amount, bool smear) {
void __attribute__((hot)) Segment::blur(uint8_t blur_amount, bool smear) {
if (!isActive() || blur_amount == 0) return; // optimization: 0 means "don't blur"
#ifndef WLED_DISABLE_2D
if (is2D()) {
Expand Down Expand Up @@ -1541,7 +1541,7 @@ uint32_t Segment::color_wheel(uint8_t pos) {
/*
* Returns a new, random wheel index with a minimum distance of 42 from pos.
*/
uint8_t Segment::get_random_wheel_index(uint8_t pos) { // WLEDMM use fast int types, use native min/max
uint8_t Segment::get_random_wheel_index(uint8_t pos) const { // WLEDMM use fast int types, use native min/max
uint_fast8_t r = 0, x = 0, y = 0, d = 0;

while(d < 42) {
Expand All @@ -1562,7 +1562,7 @@ uint8_t Segment::get_random_wheel_index(uint8_t pos) { // WLEDMM use fast int ty
* @param pbri Value to scale the brightness of the returned color by. Default is 255. (no scaling)
* @returns Single color from palette
*/
uint32_t Segment::color_from_palette(uint_fast16_t i, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri) // WLEDMM use fast int types
uint32_t __attribute__((hot)) Segment::color_from_palette(uint_fast16_t i, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri) // WLEDMM use fast int types
{
// default palette or no RGB support on segment
if ((palette == 0 && mcol < NUM_COLORS) || !_isRGB) {
Expand All @@ -1582,7 +1582,7 @@ uint32_t Segment::color_from_palette(uint_fast16_t i, bool mapping, bool wrap, u
}

//WLEDMM netmindz ar palette
uint8_t * Segment::getAudioPalette(int pal) {
uint8_t * Segment::getAudioPalette(int pal) const {
// https://forum.makerforums.info/t/hi-is-it-possible-to-define-a-gradient-palette-at-runtime-the-define-gradient-palette-uses-the/63339

um_data_t *um_data;
Expand Down Expand Up @@ -1891,7 +1891,7 @@ void IRAM_ATTR WS2812FX::setPixelColor(int i, uint32_t col)
busses.setPixelColor(i, col);
}

uint32_t WS2812FX::getPixelColor(uint_fast16_t i) // WLEDMM fast int types
uint32_t WS2812FX::getPixelColor(uint_fast16_t i) const // WLEDMM fast int types
{
if (i < customMappingSize) i = customMappingTable[i];
if (i >= _length) return 0;
Expand Down Expand Up @@ -2029,15 +2029,15 @@ void WS2812FX::show(void) {
* Returns a true value if any of the strips are still being updated.
* On some hardware (ESP32), strip updates are done asynchronously.
*/
bool WS2812FX::isUpdating() {
bool WS2812FX::isUpdating() const {
return !busses.canAllShow();
}

/**
* Returns the refresh rate of the LED strip. Useful for finding out whether a given setup is fast enough.
* Only updates on show() or is set to 0 fps if last show is more than 2 secs ago, so accuracy varies
*/
uint16_t WS2812FX::getFps() {
uint16_t WS2812FX::getFps() const {
if (millis() - _lastShow > 2000) return 0;
#ifdef ARDUINO_ARCH_ESP32
return ((_cumulativeFps500 + 250) / 500); // +250 for proper rounding
Expand Down Expand Up @@ -2128,28 +2128,28 @@ void WS2812FX::setMainSegmentId(uint8_t n) {
return;
}

uint8_t WS2812FX::getLastActiveSegmentId(void) {
uint8_t WS2812FX::getLastActiveSegmentId(void) const {
for (size_t i = _segments.size() -1; i > 0; i--) {
if (_segments[i].isActive()) return i;
}
return 0;
}

uint8_t WS2812FX::getActiveSegmentsNum(void) {
uint8_t WS2812FX::getActiveSegmentsNum(void) const {
uint8_t c = 0;
for (size_t i = 0; i < _segments.size(); i++) {
if (_segments[i].isActive()) c++;
}
return c;
}

uint16_t WS2812FX::getLengthTotal(void) { // WLEDMM fast int types
uint16_t WS2812FX::getLengthTotal(void) const { // WLEDMM fast int types
uint_fast16_t len = Segment::maxWidth * Segment::maxHeight; // will be _length for 1D (see finalizeInit()) but should cover whole matrix for 2D
if (isMatrix && _length > len) len = _length; // for 2D with trailing strip
return len;
}

uint16_t WS2812FX::getLengthPhysical(void) { // WLEDMM fast int types
uint16_t WS2812FX::getLengthPhysical(void) const { // WLEDMM fast int types
uint_fast16_t len = 0;
for (unsigned b = 0; b < busses.getNumBusses(); b++) { // WLEDMM use native (fast) types
Bus *bus = busses.getBus(b);
Expand All @@ -2162,7 +2162,7 @@ uint16_t WS2812FX::getLengthPhysical(void) { // WLEDMM fast int types
//used for JSON API info.leds.rgbw. Little practical use, deprecate with info.leds.rgbw.
//returns if there is an RGBW bus (supports RGB and White, not only white)
//not influenced by auto-white mode, also true if white slider does not affect output white channel
bool WS2812FX::hasRGBWBus(void) {
bool WS2812FX::hasRGBWBus(void) const {
for (unsigned b = 0; b < busses.getNumBusses(); b++) { // WLEDMM use native (fast) types
Bus *bus = busses.getBus(b);
if (bus == nullptr || bus->getLength()==0) break;
Expand All @@ -2171,7 +2171,7 @@ bool WS2812FX::hasRGBWBus(void) {
return false;
}

bool WS2812FX::hasCCTBus(void) {
bool WS2812FX::hasCCTBus(void) const {
if (cctFromRgb && !correctWB) return false;
for (unsigned b = 0; b < busses.getNumBusses(); b++) { // WLEDMM use native (fast) types
Bus *bus = busses.getBus(b);
Expand Down
Loading

4 comments on commit 7f9da30

@blazoncek
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a shame really that you take freely but don't give back.
You could've done this upstream as well.

I do understand MIT and GPLv3 issue, but still... Even though it shouldn't, it does sadden me.

@softhack007
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a shame really that you take freely but don't give back.
You could've done this upstream as well.

Oh c'mon, you know that MM is doing experiments, and I often prefer to expose stuff to a limited audience first. In this case, I was not sure if spreading "const" throughout the busmanager will have bad side-effects.

About "taking freely" - its not much different to what other forks to - for example https://github.com/SteveEisner/WLEDtubes. I'm just cherry-picking because MM is no longer in sync with upstream so "update from upstream" does not work. We still have this "license barrier", however if you tell me what you like to have, we'll make that happen... you have my e-mail.

Just FYI, I have recently made some effect fixes and minor improvements in AC WLED first, then pulled it into MM.

@blazoncek
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Experiments and MM have nothing that would inseparably tie them. You can branch and experiment in AC as well with no cost or danger to anyone.
There is only benefit as we can merge those branches into other branches without any real wok. If they turn out to be dead end we can simply delete them.
I've opened several such branches (and later PRs).

I was/am sad because I thought you would know and commit "universal" benefits to upstream first (as it is easier then to merge/cherry-pick then downstream including license-wise).

As for others, yes I know many, many just take and give little or nothing back (or that their solutions are of little value in general). But they are "others" and we are "us". If you know what I mean.

Still, I am in now way offended or think less of your contributions. I just wanted to let you know that I care.

@softhack007
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I know what you mean.

You're a bit right, even when I will always do some (general) improvements in MM first. Especially when I'm working in MM any way, for example to improve HUB75 performance, then its just too much effort to first switch to upstream, branch, code, cherry-pick, etc. But in general I agree that we could bring more improvements to upstream.

Licensing is actually a problem for me, because I don't want to publish our "diamonds" under MIT any more. But for this, a solution is "in the making" (you know what I mean).

Please sign in to comment.