Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LVGL fix memory allocation of flush buffers #21256

Merged
merged 1 commit into from
Apr 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ All notable changes to this project will be documented in this file.
- HASPmota `align` attribute and expand PNG cache
- LVGL restore `lv_palette` functions
- IPv6 support in safeboot
- LVGL fix memory allocation of flush buffers

### Removed
- LVGL disabled vector graphics
Expand Down
2 changes: 1 addition & 1 deletion lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
// b. textcolor,textbgcolor => public;

typedef struct LVGL_PARAMS {
uint16_t fluslines;
uint16_t flushlines;
union {
uint8_t data;
struct {
Expand Down
4 changes: 2 additions & 2 deletions lib/lib_display/UDisplay/uDisplay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ uDisplay::uDisplay(char *lp) : Renderer(800, 600) {
epc_full_cnt = 0;
lut_num = 0;
lvgl_param.data = 0;
lvgl_param.fluslines = 40;
lvgl_param.flushlines = 40;
rot_t[0] = 0;
rot_t[1] = 1;
rot_t[2] = 2;
Expand Down Expand Up @@ -590,7 +590,7 @@ uDisplay::uDisplay(char *lp) : Renderer(800, 600) {
lut3time = next_val(&lp1);
break;
case 'B':
lvgl_param.fluslines = next_val(&lp1);
lvgl_param.flushlines = next_val(&lp1);
lvgl_param.data = next_val(&lp1);
break;
case 'M':
Expand Down
2 changes: 1 addition & 1 deletion lib/lib_display/Xlatb_RA8876-gemu-1.0/RA8876.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ void RA8876::DisplayInit(int8_t p,int8_t size,int8_t rot,int8_t font) {

bool RA8876::initDisplay() {

lvgl_param.fluslines = 10;
lvgl_param.flushlines = 10;

SPI.beginTransaction(m_spiSettings);

Expand Down
2 changes: 1 addition & 1 deletion lib/libesp32_eink/epdiy/src/epd4in7.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ int32_t Epd47::Init(void) {
hl = epd_hl_init(WAVEFORM);
epd47_buffer = epd_hl_get_framebuffer(&hl);
framebuffer = epd47_buffer;
lvgl_param.fluslines = 10;
lvgl_param.flushlines = 10;
return 0;
}

Expand Down
35 changes: 12 additions & 23 deletions tasmota/tasmota_xdrv_driver/xdrv_54_lvgl.ino
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,10 @@
struct LVGL_Glue {
lv_display_t *lv_display = nullptr;
lv_indev_t *lv_indev = nullptr;
lv_color_t *lv_pixel_buf = nullptr;
lv_color_t *lv_pixel_buf2 = nullptr;
void *lv_pixel_buf = nullptr;
void *lv_pixel_buf2 = nullptr;
Ticker tick;
File * screenshot = nullptr;
bool first_frame = true; // Tracks if a call to `lv_flush_callback` needs to wait for DMA transfer to complete
};
LVGL_Glue * lvgl_glue;

Expand Down Expand Up @@ -70,10 +69,6 @@ void lv_flush_callback(lv_display_t *disp, const lv_area_t *area, uint8_t *color
// save pixels to file
int32_t btw = (width * height * LV_COLOR_DEPTH + 7) / 8;
while (btw > 0) {
#if (LV_COLOR_DEPTH == 16) && (LV_COLOR_16_SWAP == 1)
uint16_t * pix = (uint16_t*) color_p;
for (uint32_t i = 0; i < btw / 2; i++) (pix[i] = pix[i] << 8 | pix[i] >> 8);
#endif
if (btw > 0) { // if we had a previous error (ex disk full) don't try to write anymore
int32_t ret = lvgl_glue->screenshot->write((const uint8_t*) color_p, btw);
if (ret >= 0) {
Expand All @@ -87,13 +82,6 @@ void lv_flush_callback(lv_display_t *disp, const lv_area_t *area, uint8_t *color
return; // ok
}

if (!lvgl_glue->first_frame) {
//renderer->dmaWait(); // Wait for prior DMA transfer to complete
//disrendererplay->endWrite(); // End transaction from any prior call
} else {
lvgl_glue->first_frame = false;
}

uint32_t pixels_len = width * height;
uint32_t chrono_start = millis();
renderer->setAddrWindow(area->x1, area->y1, area->x1+width, area->y1+height);
Expand Down Expand Up @@ -407,25 +395,26 @@ void start_lvgl(const char * uconfig) {
bool status_ok = true;
size_t lvgl_buffer_size;
do {
//lvgl_buffer_size = LV_HOR_RES_MAX * LV_BUFFER_ROWS;
uint32_t flushlines = renderer->lvgl_pars()->fluslines;
uint32_t flushlines = renderer->lvgl_pars()->flushlines;
if (0 == flushlines) flushlines = LV_BUFFER_ROWS;

lvgl_buffer_size = renderer->width() * flushlines;
if (renderer->lvgl_pars()->use_dma) {
lvgl_buffer_size /= 2;
if (lvgl_buffer_size < 1000000) {
AddLog(LOG_LEVEL_ERROR, "LVG: Allocating buffer2 %i bytes in main memory (flushlines %i)", lvgl_buffer_size * sizeof(lv_color_t), flushlines);
lvgl_glue->lv_pixel_buf2 = new lv_color_t[lvgl_buffer_size];
// allocate preferably in internal memory which is faster than PSRAM
AddLog(LOG_LEVEL_DEBUG, "LVG: Allocating buffer2 %i bytes in main memory (flushlines %i)", (lvgl_buffer_size * (LV_COLOR_DEPTH / 8)) / 1024, flushlines);
lvgl_glue->lv_pixel_buf2 = heap_caps_malloc_prefer(lvgl_buffer_size * (LV_COLOR_DEPTH / 8), 2, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL, MALLOC_CAP_8BIT);
}
if (!lvgl_glue->lv_pixel_buf2) {
status_ok = false;
break;
}
}

AddLog(LOG_LEVEL_ERROR, "LVG: Allocating buffer1 %i KB in main memory (flushlines %i)", (lvgl_buffer_size * sizeof(lv_color_t)) / 1024, flushlines);
lvgl_glue->lv_pixel_buf = new lv_color_t[lvgl_buffer_size];
// allocate preferably in internal memory which is faster than PSRAM
AddLog(LOG_LEVEL_DEBUG, "LVG: Allocating buffer1 %i KB in main memory (flushlines %i)", (lvgl_buffer_size * (LV_COLOR_DEPTH / 8)) / 1024, flushlines);
lvgl_glue->lv_pixel_buf = heap_caps_malloc_prefer(lvgl_buffer_size * (LV_COLOR_DEPTH / 8), 2, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL, MALLOC_CAP_8BIT);
if (!lvgl_glue->lv_pixel_buf) {
status_ok = false;
break;
Expand All @@ -434,11 +423,11 @@ void start_lvgl(const char * uconfig) {

if (!status_ok) {
if (lvgl_glue->lv_pixel_buf) {
delete[] lvgl_glue->lv_pixel_buf;
free(lvgl_glue->lv_pixel_buf);
lvgl_glue->lv_pixel_buf = NULL;
}
if (lvgl_glue->lv_pixel_buf2) {
delete[] lvgl_glue->lv_pixel_buf2;
free(lvgl_glue->lv_pixel_buf2);
lvgl_glue->lv_pixel_buf2 = NULL;
}
delete lvgl_glue;
Expand All @@ -450,7 +439,7 @@ void start_lvgl(const char * uconfig) {
// Initialize LvGL display driver
lvgl_glue->lv_display = lv_display_create(renderer->width(), renderer->height());
lv_display_set_flush_cb(lvgl_glue->lv_display, lv_flush_callback);
lv_display_set_buffers(lvgl_glue->lv_display, lvgl_glue->lv_pixel_buf, lvgl_glue->lv_pixel_buf2, lvgl_buffer_size, LV_DISPLAY_RENDER_MODE_PARTIAL);
lv_display_set_buffers(lvgl_glue->lv_display, lvgl_glue->lv_pixel_buf, lvgl_glue->lv_pixel_buf2, lvgl_buffer_size * (LV_COLOR_DEPTH / 8), LV_DISPLAY_RENDER_MODE_PARTIAL);

// Initialize LvGL input device (touchscreen already started)
lvgl_glue->lv_indev = lv_indev_create();
Expand Down