Skip to content

lvgl: build against LVGL 9.6 - #20

Draft
bdbarnett wants to merge 6 commits into
mainfrom
lvgl-9.6
Draft

bdbarnett wants to merge 6 commits into
mainfrom
lvgl-9.6

Conversation

@bdbarnett

@bdbarnett bdbarnett commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor

Builds the binding against LVGL 9.6 (release/v9.6 at d8a4e1d: 9.6.0 and 24 fixes since; there is no 9.6.1 tag yet). Draft: whether main moves to 9.6 is still open, and the measurements on boards are being gathered against 9.5.54 with the same firmware.

What changed:

  • lv_conf.h uses 9.6's option names (LV_COLOR_FORMAT_DEFAULT, no LV_MEM_POOL_EXPAND_SIZE, the calendar names and the external ThorVG and LZ4 switches gone), so no deprecation #warning stops a -Werror build.
  • Asserts: 9.6 makes LV_USE_ASSERT a master switch that is off by default, which would silently drop the NULL and malloc checks the ports' assert handlers report. It's set on here, with the same checks as before. LV_USE_CHECK_ARG, which 9.6 adds and enables by default, is set explicitly. Several of 9.5's asserts became these argument checks, which return quietly. On MicroPython a failed check also goes to the assert handler, so a bad argument still raises RuntimeError (the smoke test's set_tile_cnt(256)). CircuitPython's handler reboots into safe mode and CPython's halts, so there a failed check just returns.
  • The ports and scripts read 9.6's headers from include/lvgl/ and fall back to the 9.5 paths. The opt-in TLSF pool switches on LV_USE_TLSF itself, because 9.6 derives it before our override applies.
  • The generated C wraps LVGL's own LV_DEPRECATIONS_IGNORE_BEGIN, because the binding still binds 36 functions that 9.6 marks deprecated.
  • The CPython jpegio decoder is synced from micropython-pydevices, whose decoder now includes lvgl_private.h rather than the private header that moved.
  • The API baseline records 9.6's renames and additions as upstream changes. verify_bindings.sh allows the CircuitPython file to reach 60,000 lines, up from 52,000; it is 53,495.
  • scripts/generate_font_bins.py runs LVGL's font generator from scripts/generators/built_in_font/, where 9.6 moved it. The two CJK fonts gain the eight glyphs 9.6 added.
  • The CircuitPython Unix job applies micropython-pydevices' two qstr offset patches, at a pinned commit, on CircuitPython 11.0.0-alpha.2. With 9.6's names the coverage build's qstr pool is past the 64 KB that 2-byte offsets address, and the port already asks for 4.
  • tools/lvgl_bench.py measures heap use and refresh time the same way on every interpreter, so two builds can be compared.

Python names that go away. LVGL renamed these and keeps the old names only as C macros, which the binding can't see:

9.5 9.6
lv.draw_sw_rgb565_swap lv.draw_rgb565_swap
lv.draw_sw_rotate lv.draw_rotate
lv.draw_sw_i1_* lv.draw_i1_*
display.delete_event display.remove_event
obj.is_valid obj.is_in_widget_tree
observer.remove observer.delete
subject.copy_string subject.set_string

The API grows from 2,156 functions to 2,317. LVGL 9.6's private headers also add 164 *_internal helpers. All but one back a public function of the same name, so the binding leaves them out. That saves 17.7 KB on an ESP32-S3 and 15.3 KB on the GIGA.

Checked: regenerate_all.sh is deterministic. verify_bindings.sh passes, including MicroPython, CircuitPython and CPython namespace parity and a mypy-clean stub. The generator tests pass (112), and so do the CPython extension tests (30 passed, 2 skipped) and the smoke test (28 checks), which match 9.5.54.

Needs the micropython-pydevices change that fetches LVGL's include/ directory and moves the jpegio include.

Pin LVGL to release/v9.6 (d8a4e1d, 9.6.0 plus 24 fixes) and bring the
binding up on it:

- lv_conf.h uses 9.6's option names, so no deprecation #warning breaks a
  -Werror build. Asserts are now off unless LV_USE_ASSERT is set; it is
  set here, with the same NULL and malloc checks as before, and
  LV_USE_CHECK_ARG is set explicitly.
- Ports and scripts read 9.6's headers from include/lvgl/, falling back
  to the 9.5 paths, and the TLSF pool turns on LV_USE_TLSF itself.
- The generated C tolerates the deprecated functions it still binds.
- The CPython jpegio decoder follows micropython-pydevices' moved
  include.
- The API baseline records 9.6's renames and additions as upstream
  changes.
- tools/lvgl_bench.py measures heap and refresh time the same way on
  every interpreter, to compare LVGL versions.

Removed from Python, renamed upstream: draw_sw_rgb565_swap is now
draw_rgb565_swap, draw_sw_rotate is draw_rotate, draw_sw_i1_* is
draw_i1_*, display.delete_event is display.remove_event, obj.is_valid is
obj.is_in_widget_tree, observer.remove is observer.delete and
subject.copy_string is subject.set_string.
LVGL 9.6 turned several asserts into argument checks, which return
quietly by default. On MicroPython a failed check now also goes to the
assert handler, so Python still gets RuntimeError, as the smoke test's
set_tile_cnt(256) expects. CircuitPython's handler reboots into safe
mode and CPython's halts, so there a failed check just returns.
LVGL 9.6 moved built_in_font_gen.py and its font files to
scripts/generators/built_in_font/, leaving the recipe list in
scripts/built_in_font/generate_all.py. The script reads the recipes
where they are and runs the generator where it now lives. The two CJK
fonts gain the eight glyphs 9.6 added for the 24 solar terms.
LVGL 9.6's private headers add 164 inline helpers named *_internal,
mostly lv_obj_get_style_*_internal. All but one back a public function
of the same name without the suffix, so Python gains nothing from them.
Leaving them out takes 17.7 KB off an ESP32-S3 image and 15.3 KB off
the Arduino GIGA's, and about 6 KB of names off CircuitPython's qstr
pool. The API is 2,317 functions.
With LVGL 9.6's names, the coverage build's sorted qstr pool is 65,895
bytes, past the 64 KB that 2-byte offsets address. CircuitPython
11.0.0-alpha.2, the release the firmware builds on, can use 4-byte
offsets, so the coverage build asks for them.
Vanilla CircuitPython can't take 4-byte qstr offsets, so the setting
alone didn't help: the coverage build's pool was 66,042 bytes. The job
now applies the two patches micropython-pydevices builds CircuitPython
with (pinned at its commit), which make the offset size a setting for
the firmware's pools and mpy-tool's frozen ones.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant