From 595b7f750d6843476a37177e0e6a83d2f53a3f0b Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Tue, 23 Apr 2024 20:11:01 +0200 Subject: [PATCH] LVGL fix memory allocation of flush buffers (#21256) --- CHANGELOG.md | 1 + .../Display_Renderer-gemu-1.0/src/renderer.h | 2 +- lib/lib_display/UDisplay/uDisplay.cpp | 4 +-- .../Xlatb_RA8876-gemu-1.0/RA8876.cpp | 2 +- lib/libesp32_eink/epdiy/src/epd4in7.cpp | 2 +- tasmota/tasmota_xdrv_driver/xdrv_54_lvgl.ino | 35 +++++++------------ 6 files changed, 18 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d587b161..30bc238be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.h b/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.h index 7ef7d86ab..3abe7800b 100644 --- a/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.h +++ b/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.h @@ -28,7 +28,7 @@ // b. textcolor,textbgcolor => public; typedef struct LVGL_PARAMS { - uint16_t fluslines; + uint16_t flushlines; union { uint8_t data; struct { diff --git a/lib/lib_display/UDisplay/uDisplay.cpp b/lib/lib_display/UDisplay/uDisplay.cpp index 8ff1d9ff3..e54ee3834 100755 --- a/lib/lib_display/UDisplay/uDisplay.cpp +++ b/lib/lib_display/UDisplay/uDisplay.cpp @@ -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; @@ -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': diff --git a/lib/lib_display/Xlatb_RA8876-gemu-1.0/RA8876.cpp b/lib/lib_display/Xlatb_RA8876-gemu-1.0/RA8876.cpp index d050d83ac..77d48daa0 100644 --- a/lib/lib_display/Xlatb_RA8876-gemu-1.0/RA8876.cpp +++ b/lib/lib_display/Xlatb_RA8876-gemu-1.0/RA8876.cpp @@ -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); diff --git a/lib/libesp32_eink/epdiy/src/epd4in7.cpp b/lib/libesp32_eink/epdiy/src/epd4in7.cpp index bc0882e0f..252abfde5 100644 --- a/lib/libesp32_eink/epdiy/src/epd4in7.cpp +++ b/lib/libesp32_eink/epdiy/src/epd4in7.cpp @@ -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; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_54_lvgl.ino b/tasmota/tasmota_xdrv_driver/xdrv_54_lvgl.ino index 3dc0cd55b..4fc6df0aa 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_54_lvgl.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_54_lvgl.ino @@ -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; @@ -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) { @@ -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); @@ -407,16 +395,16 @@ 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; @@ -424,8 +412,9 @@ void start_lvgl(const char * uconfig) { } } - 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; @@ -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; @@ -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();