LVGL Benchmark — C
Source: apps/c/heap/lvgl_benchmark/src/app.c (and apps/c/zeroheap/lvgl_benchmark/).
The C port calls the LVGL C API directly through <ove/lvgl.h> — ove_lvgl_lock() / ove_lvgl_unlock() are the only oveRTOS-specific calls; everything else is upstream LVGL.
Build
make host.posix.lvgl_benchmark # POSIX host + browser dashboard
make qemu.freertos.lvgl_benchmark # QEMU + FreeRTOS
make # build
make run # run
Scene registration
Each scene is a function that builds a tree of LVGL widgets on lv_screen_active():
static void rectangle_create(void)
{
lv_obj_t *obj = lv_obj_create(lv_screen_active());
lv_obj_set_size(obj, 200, 200);
lv_obj_center(obj);
lv_obj_set_style_bg_color(obj, lv_color_hex(0xff0000), 0);
}
A static table pairs the scene name with its builder:
static scene_dsc_t scenes[] = {
{ "Empty screen", empty_create, 0, 0, 0, 0, 0, 0 },
{ "Rectangle", rectangle_create, 0, 0, 0, 0, 0, 0 },
{ "Rectangle, rounded", rectangle_rounded_create, 0, 0, 0, 0, 0, 0 },
/* … */
};
Scene rotation
A periodic LVGL timer fires every scene_time ms to record metrics and load the next scene:
static void next_scene_timer_cb(lv_timer_t *timer)
{
/* Record current scene's metrics from LVGL's perf monitor. */
scenes[current_scene].fps_avg = ...;
current_scene++;
if (current_scene >= ARRAY_SIZE(scenes)) {
summary_create();
lv_timer_del(timer);
return;
}
lv_obj_clean(lv_screen_active());
scenes[current_scene].create_cb();
}
lv_timer_* is LVGL's own timer engine, not ove_timer_* — LVGL timers run from lv_timer_handler() on the graphics thread, so they're already synchronised with the rest of LVGL.
Locking
The benchmark builds and tears down widgets from the graphics thread, so it doesn't need explicit ove_lvgl_lock() calls. If your own benchmark variation builds widgets from another thread (a network response, a sensor sample), wrap the construction:
ove_lvgl_lock();
lv_obj_t *card = lv_obj_create(parent);
ove_lvgl_unlock();
Assets
Image scenes use LVGL's compile-time image format. The C array is generated at build time from PNGs and listed in app.yaml:
sources:
- src/app.c
- src/benchmark_perf.c
- src/assets/benchmark_cogwheel_rgb.c
- src/assets/benchmark_cogwheel_argb.c
- src/assets/benchmark_avatar.c
The PNG-to-C conversion happens via scripts/lvgl_img_conv.py invoked by the build system.
Where to next
- The summary table at the end of the run pastes cleanly into
make benchmarksreports. - Compare numbers across bindings: C++, Rust, Zig.
- LVGL API: https://docs.lvgl.io/master/
- oveRTOS LVGL integration internals:
bindings/cpp/ove/lvgl.hpp(the highest-level wrapper still pairs to the raw C API used here).