Skip to content

feat(esp_lvgl_port): Out-of-tree PPA and DMA2D LVGL draw units#806

Open
uLipe wants to merge 13 commits into
espressif:masterfrom
uLipe:feature/esp_ppa_dma2d_draw
Open

feat(esp_lvgl_port): Out-of-tree PPA and DMA2D LVGL draw units#806
uLipe wants to merge 13 commits into
espressif:masterfrom
uLipe:feature/esp_ppa_dma2d_draw

Conversation

@uLipe

@uLipe uLipe commented Jul 15, 2026

Copy link
Copy Markdown

Summary

  • Host Espressif PPA and DMA2D LVGL draw units in esp_lvgl_port (LVGL 9+, ESP32-P4), registered after lv_init() via CONFIG_ESP_LVGL_PORT_* (keep stock CONFIG_LV_USE_PPA unset).
  • Small LVGL9/IDF 5.5 build fixes for P4 BSP display rotation and DPI avoid-tearing.
  • Docs + ESP32-P4 CI config (test_apps/lvgl_port / ppa_dma2d) so the draw-unit path is compiled in CI.

Test plan

  • Build/flash LVGL benchmark on ESP32-P4 with PPA+DMA2D enabled (hardware)
  • Build components/esp_lvgl_port/test_apps/lvgl_port for esp32p4 with sdkconfig.ci.ppa_dma2d (LVGL 9.5.0 from Component Registry)
  • Run LVGL demo benchmark on ESP32P4 EV Function Board.
  • Version of modified component bumped
  • CI passing

Board output log:

I (1826) GT911: TouchPad_ID:0x39,0x31,0x31
I (1828) GT911: TouchPad_Config_Version:89
I (1832) ESP32_P4_EV: Setting LCD backlight: 100%
I (1836) lvgl_benchmark: Iniciando teste de triangle
I (1841) tri_test: triangle test done
I (1844) lvgl_benchmark: triangle test PPA totals: tasks=0 ops=0 failed=0
I (1850) lvgl_benchmark: Iniciando benchmark LVGL
I (1858) main_task: Returned from app_main()
I (6859) PPA: tasks=664 (+664) ops=664 (+664) failed=0 peak_pending=1
I (11859) PPA: tasks=1526 (+862) ops=1472 (+808) failed=0 peak_pending=1
I (16859) PPA: tasks=3846 (+2320) ops=3669 (+2197) failed=0 peak_pending=1
I (21859) PPA: tasks=6123 (+2277) ops=5945 (+2276) failed=0 peak_pending=1
I (26859) PPA: tasks=7634 (+1511) ops=7457 (+1512) failed=0 peak_pending=1
I (31859) PPA: tasks=7944 (+310) ops=7766 (+309) failed=0 peak_pending=1
I (36859) PPA: tasks=8964 (+1020) ops=17290 (+9524) failed=0 peak_pending=21
I (41859) PPA: tasks=10518 (+1554) ops=37497 (+20207) failed=0 peak_pending=23
I (46859) PPA: tasks=11814 (+1296) ops=51819 (+14322) failed=0 peak_pending=23
[Warn]	(50.145, +50145)	 lv_group_add_obj: Check failed: group != NULL  lv_group.c:128
[Warn]	(50.170, +25)	 lv_group_add_obj: Check failed: group != NULL  lv_group.c:128
I (51859) PPA: tasks=13025 (+1211) ops=65994 (+14175) failed=0 peak_pending=23
I (56859) PPA: tasks=16628 (+3603) ops=82582 (+16588) failed=0 peak_pending=23
I (61859) PPA: tasks=19575 (+2947) ops=93355 (+10773) failed=0 peak_pending=23
I (66859) PPA: tasks=23964 (+4389) ops=115184 (+21829) failed=0 peak_pending=23
Benchmark Summary (9.6.0 dev)
Name, Avg. CPU, Avg. FPS, Avg. time, render time, flush time
Empty screen, 84%, 57, 14, 5, 9
Moving wallpaper, 97%, 20, 45, 38, 7
Single rectangle, 94%, 60, 13, 0, 13
Multiple rectangles, 93%, 60, 11, 5, 6
Multiple RGB images, 96%, 30, 25, 15, 10
Multiple ARGB images, 97%, 28, 26, 21, 5
Rotated ARGB images, 96%, 26, 31, 28, 3
Multiple labels, 97%, 19, 33, 27, 6
Screen sized text, 98%, 19, 46, 44, 2
Multiple arcs, 97%, 29, 23, 17, 6
Containers, 89%, 41, 20, 12, 8
Containers with overlay, 94%, 15, 49, 40, 9
Containers with opa, 96%, 25, 32, 24, 8
Containers with opa_layer, 97%, 22, 37, 30, 7
Containers with scrolling, 99%, 10, 77, 71, 6
Widgets demo, 99%, 8, 73, 65, 8
All scenes avg.,95%, 29, 34, 27, 7

Note

Medium Risk
Large new rendering path touches cache coherency, async PPA completion, and hardware fallbacks; misconfiguration (e.g. duplicate CONFIG_LV_USE_PPA) is caught at build time but runtime draw bugs could still affect UI correctness on P4.

Overview
Adds out-of-tree LVGL 9 hardware draw units for ESP32-P4: optional PPA (fills, blends, images/layers, borders, gradients, tile composer, async, stats/tuning) and DMA2D (blit/convert), wired through new Kconfig (CONFIG_ESP_LVGL_PORT_*), CMake (esp_lvgl_port_draw_units.cmake), and registration from lvgl_port right after lv_init().

Robustness and integration: shared esp_cache draw-buffer handlers, SW fallbacks when PPA/DMA2D cannot handle or fails a task, DPI avoid-tearing keeps on_refresh_done on IDF 5.5 (not RGB’s on_frame_buf_complete), P4 BSP bsp_display_rotate uses lv_display_rotation_t, plus README/CHANGELOG and CI sdkconfig.ci.ppa_dma2d for test_apps/lvgl_port.

Reviewed by Cursor Bugbot for commit 22c9521. Bugbot is set up for automated code reviews on this repo. Configure here.

uLipe added 7 commits July 15, 2026 10:13
lv_disp_rotation_t was renamed to lv_display_rotation_t in LVGL 9, so the
BSP rotate API failed to build against current LVGL headers.
… 5.5

esp_lcd_dpi_panel_event_callbacks_t still exposes on_refresh_done on IDF
5.5; on_frame_buf_complete belongs to the RGB panel API and broke P4 DSI
builds when gated only by IDF version.
Host the Espressif PPA/DMA2D draw units in esp_lvgl_port for LVGL 9+,
register them after lv_init(), and gate them with ESP_LVGL_PORT_* Kconfig
so the full composer path does not wait on upstream LVGL merges.
…ions

Replace LVGL section banners and include guards with the port layout
(#pragma once, esp-bsp section headers, quoted IDF includes, extern "C"
around declarations only) so the imported units match the rest of the tree.
Add an lvgl_public.h shim, include the mask rect descriptor definition,
and widen set_pending_trans to uint16_t so the units compile with LVGL
from the Component Registry (validated with 9.5.0).
Describe the ESP_LVGL_PORT_* menuconfig path, buffer alignment and
stock LV_USE_PPA conflict, and record the docs/CI notes in CHANGELOG.
Add a ppa_dma2d sdkconfig.ci variant for test_apps/lvgl_port and restrict
it to esp32p4 / IDF >= 5.4 so CI compiles the out-of-tree draw unit path.
@CLAassistant

CLAassistant commented Jul 15, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

Comment thread components/esp_lvgl_port/src/lvgl9/draw/ppa/lv_draw_ppa.c
Comment thread components/esp_lvgl_port/src/lvgl9/draw/ppa/lv_draw_ppa_layer.c Outdated
Comment thread components/esp_lvgl_port/src/lvgl9/esp_lvgl_port.c
Comment thread components/esp_lvgl_port/src/lvgl9/draw/dma2d/lv_draw_dma2d.c
Comment thread components/esp_lvgl_port/src/lvgl9/draw/ppa/lv_draw_ppa_runtime.c Outdated
Reject oversized tile-composer layers in evaluate, release tiles on
composite early-exit, finalize active tasks during runtime retune,
share cache handlers for DMA2D-only builds, and disable a half-initialized
DMA2D unit instead of leaving it registered.
Comment thread components/esp_lvgl_port/src/lvgl9/draw/ppa/lv_draw_ppa.c
Comment thread components/esp_lvgl_port/src/lvgl9/draw/ppa/lv_draw_ppa.c Outdated
#include "lv_draw_esp_dma2d_private.h"

#if LV_USE_ESP_DMA2D

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

FYI, maybe we can reuse the async color convert driver in the esp-idf? https://docs.espressif.com/projects/esp-idf/en/latest/esp32p4/api-reference/peripherals/async_color_convert.html The driver can be used to do either color conversion or 2D window copy.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

@suda-morris this would be great, is this feature also present on IDF5.5? When I made the DMA2D I was using what IDF oferred in terms of its driver.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I can backport the feature to 5.5. Currently it's available on 6.x

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

It would be great then the DMA2D draw can benefit from this driver

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

sorry, it's not easy to backport the driver to v5.5 because there's no esp_color_fourcc_t definitions. Feel free to continue your original solution.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Directly calling esp_private APIs from external components is not recommended because there's no assurance in compatibility. Can we apply this PPA and DMA2D enhancement for IDF v6.x only? @uLipe

Drain leftover binary-semaphore tokens when the last ISR completes before
pending_ops is sampled, and stop calling vSemaphoreDelete on the statically
allocated done_sem.
Comment thread components/esp_lvgl_port/src/lvgl9/draw/dma2d/lv_draw_dma2d.c
Comment thread components/esp_lvgl_port/src/lvgl9/draw/dma2d/lv_draw_dma2d_img.c
Write back the decoded source buffer before DMA2D reads it, and fall
back to lv_draw_sw_image when enqueue/transfer fails so preferred-unit
tasks are not left blank.
Comment thread components/esp_lvgl_port/src/lvgl9/draw/ppa/lv_draw_ppa_layer.c
Comment thread components/esp_lvgl_port/src/lvgl9/draw/dma2d/lv_draw_dma2d_copy.c
Preferred-unit tasks already mark FINISHED on return; empty tile pool or
a failed pass left blank holes. Recover with lv_draw_sw_layer instead.
Comment thread components/esp_lvgl_port/src/lvgl9/draw/dma2d/lv_draw_dma2d.c
Comment thread components/esp_lvgl_port/src/lvgl9/draw/ppa/lv_draw_ppa_img.c
uLipe added 2 commits July 15, 2026 11:16
Copy the child layer draw_buf header before DMA2D image blit, and redraw
with software when PPA blend/SRM enqueue fails on a claimed task.
Call dma2d_force_end when the completion wait times out so an in-flight
transfer cannot overwrite the destination after lv_draw_sw_image redraws it.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 22c9521. Configure here.

Comment thread components/esp_lvgl_port/src/lvgl9/draw/ppa/lv_draw_ppa.c
@suda-morris
suda-morris requested a review from espzav July 16, 2026 03:56
@tore-espressif
tore-espressif self-requested a review July 16, 2026 06:02

@espzav espzav left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@uLipe Thank you very much for this PR. Only for clarification:

  • Is this same like CONFIG_LV_USE_PPA ? Or these changes are for better performance?
  • What is the recommended settings? Is it safe to enable this recommended settings in P4 BSP - in examples sdkconfig.bsp.esp32_p4_function_ev_board?
  • Please, Could you bump LVGL port version (+changelog) for release it after merge?

LGTM

#else
/* IDF DPI API still exposes on_refresh_done (vsync). Do not use
* on_frame_buf_complete here — that name belongs to the RGB panel
* callbacks, not esp_lcd_dpi_panel_event_callbacks_t on IDF 5.5. */

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I see this warning in CI:

/__w/esp-bsp/esp-bsp/components/esp_lvgl_port/src/lvgl9/esp_lvgl_port_disp.c:162:13: warning: 'on_refresh_done' is deprecated: Deprecated, use on_frame_buf_complete instead [-Wdeprecated-declarations]
  162 |             cbs.on_refresh_done = lvgl_port_flush_dpi_vsync_ready_callback;
      |             ^~~
In file included from /__w/esp-bsp/esp-bsp/components/esp_lvgl_port/src/lvgl9/esp_lvgl_port_disp.c:33:
/opt/esp/idf/components/esp_lcd/dsi/include/esp_lcd_mipi_dsi.h:205:45: note: declared here
  205 |         esp_lcd_dpi_panel_refresh_done_cb_t on_refresh_done __attribute__((deprecated("Deprecated, use on_frame_buf_complete instead"))); /*!< Deprecated, use on_frame_buf_complete instead */
      |                                             ^~~~~~~~~~~~~~~

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants