Performance drop when displaying 3x3 matrix, I4 encoded images (256x256px) from SD card – ESP32 + LVGL + custom malloc/fs

Hi all!

For my project on ESP32-S3, I need to display a 3x3 matrix of images, each of 256x256 pixels, I4 encoded, stored as .bin files on an SD card.

I’ve successfully implemented:

  • LV_STDLIB_CUSTOM to use heap_caps_malloc on SPIRAM (ESP32) (because with standard mem allocator there where some overflow/allocation problems)
  • a custom file system driver based on SD_MMC (it is basically the stock lvgl SD fs already provided, with SD_MMC instead of SD).

Each cell of the matrix is placed using lv_obj_set_grid_dsc_array and lv_obj_set_grid_cell, then I load the image using lv_img_set_src() pointing to the .bin file path on the SD card.

I use double buffering (LV_DISPLAY_RENDER_MODE_FULL) and have a working disp_flush.

Even though lv_img_set_src() is only called once per image, the FPS drops from 40–45 to 3–6, making scrolling and interactivity almost unusable. If I replace images with standard lv_label_create, the fps remains stable.

In lv_bin_decoder.c, lv_bin_decoder_open is called every frame. I can successfully debug that image is added to cache, (LV_BIN_DECODER_RAM_LOAD is enabled and LV_CACHE_DEF_SIZE is 1024 * 1024). But I’m not sure about how cache hit works.


:mag: What I’m trying to figure out:

  • Why does FPS drop so drastically when loading these I4 images from the SD card?
  • Is there a better way to handle many large images from SD?
  • Any best practices for working with image matrices in LVGL with constrained RAM?
  • How cache hit works in lv_bin_decoder?

:wrench: Additional details:

  • Display: 320x480
  • LVGL Version: 9.2.2
  • Image Format: .bin, I4 format (256x256)
  • SD Card interface: Using SD_MMC at 60 MHz

Looking better at the source code, the cache hit can happen in lv_image_decoder_open in lv_image_decoder.c. Then I found that Image caching for BIN files can be enabled by setting in lv_conf.h the following params:

#define LV_CACHE_DEF_SIZE (256 * 256 * 8 * 9)
#define LV_IMAGE_HEADER_CACHE_DEF_CNT 9
#define LV_BIN_DECODER_RAM_LOAD 1

but after some calls of lv_img_set_src() (with different files) the performance decrease… I will investigate more and post here the cause…