perf(l2): screen sent by DMA while the next part is drawn

The panel takes each 24-line band by DMA while LVGL draws the next one
into the other buffer (two 15 KB buffers in internal RAM; LovyanGFX's
4092-byte DMA descriptors leave PSRAM unaligned for the S3's DMA, which
showed as shifted and smeared bands). LVGL draws in the panel's byte
order, and so do map tiles and the frozen screen under a popup, so
nothing is swapped on the way out. Full frames ~10-25% faster (page1
19.9 -> 14.7 ms, Home 21.4 -> 18.2 ms). Without the internal RAM the
screen is sent as before. The arduino2 env keeps the old way.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Jakub
2026-10-01 20:56:13 +02:00
co-authored by Claude Opus 5.5
parent ca5e66a4a1
commit 0a07dc3deb
5 changed files with 123 additions and 15 deletions
@@ -90,7 +90,11 @@ public:
s->present = true;
memset(&s->dsc, 0, sizeof(s->dsc));
s->dsc.header.magic = LV_IMAGE_HEADER_MAGIC;
#ifdef UI_FLUSH_DMA
s->dsc.header.cf = LV_COLOR_FORMAT_RGB565_SWAPPED;
#else
s->dsc.header.cf = LV_COLOR_FORMAT_RGB565;
#endif
s->dsc.header.w = TILE_PX;
s->dsc.header.h = TILE_PX;
s->dsc.header.stride = TILE_PX * 2;
@@ -151,6 +155,9 @@ private:
uint32_t t0 = micros();
#endif
_job.present = _spare && _job.src->renderTile(_job.z, _job.x, _job.y, _spare);
#ifdef UI_FLUSH_DMA // in the display's byte order: drawn as a plain copy (LvglPort.h)
if (_job.present) lv_draw_sw_rgb565_swap(_spare, TILE_PX * TILE_PX);
#endif
#ifdef UI_PERF_TEST
uint32_t dt = micros() - t0;
if (_job.present) { s_perf_tile_us += dt; s_perf_tile_n++; if (dt > s_perf_tile_max) s_perf_tile_max = dt; }