Skip to content

LVGL renderer backend + unified control-affordance vocabulary#38

Merged
MarsDoge merged 6 commits into
mainfrom
experimental/lvgl-spike
Jun 5, 2026
Merged

LVGL renderer backend + unified control-affordance vocabulary#38
MarsDoge merged 6 commits into
mainfrom
experimental/lvgl-spike

Conversation

@MarsDoge

@MarsDoge MarsDoge commented Jun 5, 2026

Copy link
Copy Markdown
Owner

Summary

Four-part standardization batch plus the experimental LVGL renderer backend. Net +714 / −1183 (dedup and dead-code removal dominate).

  1. Renderer dedup + shape primitive — split ModernUiRendererLib into a thin GOP backend and a shared backend-agnostic surface (ModernUiRendererCommon.c / ModernUiRendererInternal.h) compiled verbatim by both backends. New ModernUiFillTriangle primitive replaces per-consumer magic-pixel chevrons. A backend now provides only ModernUiRendererInit / ModernUiFillRect / ModernUiDrawText.
  2. Experimental LVGL backendModernUiLvglRendererLib (MODERN_SETUP_DISPLAY_ENGINE=lvgl) composites through LVGL's software renderer into a shadow canvas, BLTing only touched regions. External/lvgl bumped v9.5.0 → v9.5.0-1-g4cdddfe4a for the pristine upstream loongarch64/riscv64 UEFI-build commit (no local patching). Adds LvglSpikePkg + build-lvgl-spike-{loongarch,riscv}.sh; experimental pieces stay out of default overlays.
  3. Unified control affordances — per-control cue shapes defined once in ModernUiEngineDrawControlCue keyed on MODERN_UI_VALUE_TYPE. The front-page App value lane and the in-setup DisplayEngine row (via ModernDisplayKindToValueType) both delegate, so a control type reads identically in each surface. Removes the DisplayEngine's private ModernDisplayCueTriangle / ModernDisplayDrawKindCue copies. Cue path classifies materialized statement data only — no HII/config/storage access.
  4. Docs + smoke — new "Control-affordance vocabulary" section in MODULE_BOUNDARIES.md, CHANGELOG entries, and smoke rules asserting the delegation contract and the no-config-token guard on the shared cue helper.

Validation

  • python3 Tests/Smoke/smoke_validate.pyPASS
  • OVMF X64 modern build — clean; ModernSetupApp X64 build — clean; OVMF X64 lvgl-mode build — clean (confirms shared surface compiles into the LVGL backend)
  • LoongArchVirt modern FD — built clean (DXEFV 99% full)
  • Screenshot: App Preferences page value lane renders OneOf / Numeric + / String caret / Checkbox box correctly via the unified vocabulary

Notes

  • External/edk2 baseline is intentionally not bumped in this PR.
  • Whole batch is one feature branch per the batch-commits-one-PR workflow.

🤖 Generated with Claude Code

MarsDoge and others added 6 commits June 3, 2026 11:18
Open-source-rendering-backend evaluation spike. Pins lvgl/lvgl at the
v9.5.0 release tag (85aa60d) under External/lvgl, alongside the existing
External/edk2 baseline.

Scope/discipline (experimental tier, like ModernUiHiiBridgeLib):
  - Lives only on experimental/lvgl-spike; not for default overlays,
    not for ModernSetupApp, not wired into any shipped firmware.
  - Bootstrap does not pull it by default (separate opt-in init).
  - Goal of the spike: answer the one question that actually gates a
    backend switch -- does LVGL build + render under edk2 on a hard
    arch (LoongArch), not just X64 where LvglPkg already works.

License: LVGL is MIT (compatible). Aptio-styled chrome/wallpaper from
downstream LVGL-UEFI ports is intentionally NOT used (AMI brand asset).
…e primitive

Split ModernUiRendererLib into a thin GOP backend plus a shared,
backend-agnostic surface (ModernUiRendererCommon.c / ModernUiRendererInternal.h)
that both the GOP and the experimental LVGL backend compile verbatim. The
shared surface owns geometry compositions, text measurement, themed widgets,
and the new ModernUiFillTriangle shape primitive (down/up/right apex) so
chevron/arrow cues are a single renderer primitive rather than per-consumer
magic-pixel shapes. A backend now provides only the three irreducible
primitives: ModernUiRendererInit, ModernUiFillRect, ModernUiDrawText.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add ModernUiLvglRendererLib, a second ModernUiRendererLib implementation
(selected by MODERN_SETUP_DISPLAY_ENGINE=lvgl) that composites every primitive
through LVGL's software renderer into a persistent XRGB8888 shadow canvas, then
BLTs only the touched region to GOP. ASCII text uses lv_draw_label (Montserrat);
CJK runs fall back to the package's embedded bitmap glyphs. It shares the
backend-agnostic surface and triangle primitive verbatim with the GOP backend.

Bump External/lvgl v9.5.0 -> v9.5.0-1-g4cdddfe4a to pick up the pristine
upstream "feat(uefi): support loongarch64 and riscv64 building" commit (no local
patching of the submodule). Add LvglSpikePkg plus build-lvgl-spike-{loongarch,
riscv}.sh as the experimental harness, and teach build-ovmf-x64.sh /
build-loongarchvirt.sh the lvgl display-engine mode (force-linking compiler
intrinsics for the LVGL-backed app shell and display engine). All experimental
pieces stay out of the default modern/native overlays.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Define the per-control cue shapes (checkbox box, one-of down chevron,
ordered-list up/down, numeric plus, date/time ticks, password dots, string
caret, action right arrow) once in ModernUiEngineDrawControlCue, keyed on
MODERN_UI_VALUE_TYPE and built only from renderer primitives. Both surfaces now
delegate to it so a given control type reads identically in each:

- Front-page App value lane: ModernUiEngineDrawValue paints the cue just left
  of the value box.
- In-setup DisplayEngine row: ModernDisplayDrawStatementRowCue maps its
  MODERN_DISPLAY_FORM_ROW_KIND via ModernDisplayKindToValueType and overlays the
  cue at the row's right edge AFTER native FormBrowser prints the row text, so it
  composites on top instead of being overpainted.

Removes the DisplayEngine's private duplicate shape code (ModernDisplayCueTriangle
/ ModernDisplayDrawKindCue). The cue path classifies already-materialized
statement data only and never touches HII/config/storage.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Document the renderer-backend split and the single control-affordance
vocabulary in MODULE_BOUNDARIES.md (new "Control-affordance vocabulary" section,
"Do not add a second copy" rule), record the user-visible changes in CHANGELOG,
and update smoke_validate.py to assert the new contract: ModernUiEngineDrawValue
delegates to ModernUiEngineDrawControlCue, the DisplayEngine row cue uses
ModernDisplayKindToValueType, the kind->value-type mapping is present, and the
shared cue helper carries no config/storage tokens.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@MarsDoge MarsDoge merged commit 0070fa7 into main Jun 5, 2026
1 check passed
MarsDoge added a commit that referenced this pull request Jun 5, 2026
PR #38 pinned External/lvgl at 4cdddfe, a local PR-branch SHA that does
not exist on upstream lvgl/lvgl, so fresh clones can't fetch the submodule.
Re-pin to the upstream merged commit 0b1ea312d (v9.5.0-273, PR #10221).

That commit carries unrelated v9.5.0->273 churn, handled edk2-side without
patching the submodule: drop dead wayland sources from LvglCoreLib.inf,
add a documented empty efi.h shim for PR #10041's unconditional gnu-efi
include, and switch spike sources to the <lvgl/lvgl.h> umbrella instead of
deprecated lvgl/src/drivers/uefi/* headers.

Validated: OVMF X64 lvgl-mode build, LoongArch lvgl spike build, smoke.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.

1 participant