Repository navigation
display_driver: present DIRECT frames without waiting inside the flush - #353
Conversation
On a framebuffer that can split its present (FBDisplay.show_nowait and wait_shown, over DotClockFramebuffer.present/wait), the last area starts the present and LVGL's flush_wait_cb finishes it just before LVGL paints again. The LVGL pass no longer blocks up to a scanout frame per present, and the loop's slow-pass yield no longer counts that wait as work. Panels without the split keep presenting with show().
|
The remaining runs are done, on the other ESP32-S3-Touch-LCD-4.3 with PyDevices/micropython-pydevices#226 merged onto current main and this branch merged onto main, driven over WebREPL only. Same probe and
All three full-screen runs finished on this path. 20-minute run of |
On a DIRECT panel, the last flush called
FBDisplay.show(), which waits up to a scanout frame for the new buffer to take over. The event loop's slow-pass rule then counted that wait as work and stayed off just as long afterwards. On an ESP32-S3-Touch-LCD-4.3 that meant a 46 ms pass, of which 29 ms was the wait, then about 46 ms off: 10.6 fps, where CircuitPython on the same board draws 23.6.With this change, a panel that can split its present no longer waits inside the flush:
FBDisplaygainsshow_nowait()andwait_shown(), overDotClockFramebuffer.present()/wait()(displayif: DotClockFramebuffer.present() and wait() split refresh() in two micropython-pydevices#226).display_driverstarts the present from the last flush and leaves that flush unfinished.flush_wait_cb, which LVGL calls before it paints a framebuffer again. The wait lands there, usually after the 33 ms refresh period has already covered it.A panel without the split, including the same board on firmware without #226, keeps the old
show()path. The meter still counts one frame per present.Only excluding the wait from the slow-pass rule was measured too: 15.8 fps, but LVGL then held 73% of the thread, mostly asleep in the wait. So that alternative was dropped.
Tests:
tests/test_lvgl_display_driver.pygainsTestAsyncPresent. A planted fault (always callingflush_ready) fails it.Measured on the same board with PyDevices/micropython-pydevices#226 firmware running
lv_test_timer, 30 s runs:show()in the flush)flush_wait_cbProved on hardware: all three full-screen runs on each path and a 20-minute run of this path finished with no hang (results in the comments). The earlier stop was the board's USB serial link.