Watch
1
0
Fork
You've already forked SouveraineOS
0

59: phase 1 passes on hardware, ~58fps with the rig drawing

This commit is contained in:
Fimeg 2026-08-05 16:10:41 -04:00
commit ec552a82a2
2 changed files with 49 additions and 3 deletions

View file

@ -1,7 +1,9 @@
# TASK 59 — her face on the glass: a Live2D presence for Annie
**Status: open — scoped 2026-08-05, nothing built.** From Casey, after finding a
Live2D board-girl on a blog he had cloned: *"I want to take a peek at how it
**Status: 2026-08-05 — phase 1 PASSED on hardware. Cubism renders on blueline at
~58 fps in the engine wry wraps.** The gate this task set for itself is cleared;
what remains is building the host and making her Annie. From Casey, after
finding a Live2D board-girl on a blog he had cloned: *"I want to take a peek at how it
functions and see if there's a crossover event to where it could exist on the
phone as a character of Annie. We already have something called the ani-avatar
a godot program but this thing I just saw looked better and more complete."*
@ -135,6 +137,50 @@ free Cubism Editor targets **4/5**, which is a *different loader*. Shipping 2.x
now is fine; just know that the swap to her own rig is a runtime change, not a
file swap.
## Phase 1, measured on blueline 2026-08-05 — it works
Run on the phone itself, WebKit2GTK 2.52.5 (`webkit2gtk-4.1`, already installed
— the same engine wry binds on Linux), Wayland/viewtop, freedreno `card0`.
Harness: the real `live2d.js` and the real Histoire rig, served over
`127.0.0.1`, sampling `requestAnimationFrame` for 10 s after a 3 s warmup.
| | |
|---|---|
| WebGL | **present** |
| Cubism runtime | initialised — `Live2D 2.1.00_1` |
| Frame rate | **57.9 / 58.7 / 61.0 fps** across runs (panel is 60 Hz — vsync-bound) |
| Worst frame | 3788 ms, one hitch per run, during texture upload |
| Actually drawing | **`painted_px` 23,617 and 23,668 of 24,000 sampled** |
| WebKit RSS | **283 MB** (`WebKitWebProcess` 224 + `WebKitNetworkProcess` 59) |
| Phone total during run | 1,736 MB of 3,550 |
**The `painted_px` check is the load-bearing part of this result, not the fps.**
The first run reported a healthy 58.3 fps while `model.json` had failed to load
— a vsync-capped empty loop is indistinguishable from a working one by frame
rate alone. So the harness reads the framebuffer back and counts non-transparent
pixels in a 120×200 window at the rig's centre. 98% painted is the rig; the fps
number is only meaningful beside it. **Any future re-measure must keep that
check** or it will cheerfully report success for a blank canvas.
Two things the run cost that are worth knowing before the host is built:
- **283 MB for the webview** is real on a 3.5 GB device, and it sits beside a
`qs` that was already measured at 610 MB RSS in the same snapshot. An
always-on face is not free; Q0's "summoned, not always-on" is now a memory
argument as well as a design one.
- **file:// is not enough.** `XMLHttpRequest` for `model.json` is blocked from
`file://` even with `allow-file-access-from-file-urls` and
`allow-universal-access-from-file-urls` set — it failed with status 0. The
spike used a local HTTP server; a real host wants a **custom URI scheme
handler** (wry has one) rather than shipping an HTTP server to serve its own
assets.
Reproduce: `/tmp/l2d/` on the phone holds the rig, `fps.html` and `spike.py`;
`systemd-run --user --unit=l2dspike --working-directory=/tmp/l2d python3 -m
http.server 8899 --bind 127.0.0.1` (a backgrounded server does *not* survive the
ssh session that started it), then
`GDK_BACKEND=wayland python3 spike.py http://127.0.0.1:8899/fps.html`.
## Open questions
### Q0. How is she summoned?

View file

@ -59,7 +59,7 @@ Four that are cheap relative to what they unblock:
| # | Task | What's left |
|---|------|-------------|
| 59 | [Her face on the glass: a Live2D presence](59-her-face-on-the-glass.md) | Scoped from a Live2D board-girl found in a cloned blog. The reference streams its chat over **SSE terminated by `[DONE]`** — the contract souveraine's server already speaks, so the integration is accidentally done. Base layer is **wry**, not the Chromium already on the phone; the first deliverable is a measured frame rate for the Cubism runtime in WebKit on freedreno, and if that fails the task stops there. Replaces ani-avatar's 2.5 GB of sprite states with one rig. Reference rig ships as the working placeholder and gets edited toward Annie — it just stays out of any public repo. Summoned by app launch and/or the radial dial, not always-on. |
| 59 | [Her face on the glass: a Live2D presence](59-her-face-on-the-glass.md) | **Phase 1 passed on hardware 2026-08-05: ~58 fps, rig verified drawing (`painted_px` 23.6k/24k), 283 MB WebKit RSS.** Scoped from a Live2D board-girl found in a cloned blog. The reference streams its chat over **SSE terminated by `[DONE]`** — the contract souveraine's server already speaks, so the integration is accidentally done. Base layer is **wry**, not the Chromium already on the phone; the first deliverable is a measured frame rate for the Cubism runtime in WebKit on freedreno, and if that fails the task stops there. Replaces ani-avatar's 2.5 GB of sprite states with one rig. Reference rig ships as the working placeholder and gets edited toward Annie — it just stays out of any public repo. Summoned by app launch and/or the radial dial, not always-on. |
| 58 | [Host power: the SMB2 OTG boost](58-host-power-smb2-boost.md) | Host data works; the boost isn't. The SMB2 5 V boost exists in silicon and mainline's `qcom-smbx-charger` never registers it. Investigation first (which tree builds the running kernel, does smb2 touch the boost, does `qcom_pmic_typec` bind pmi8998), then vbus-supply + regulator + typec. Unlocks host-mode power, power-bank mode, and the Pi without a wall wart. |
| 57 | [The Pi dock head](57-pi-dock-head.md) | Phone stays a gadget; the Pi 4 drives the monitor + dock. NCM link is default, Venus encoder is present, compositor capture landed — the unproven seams are `zwlr_screencopy` vs our own capture IPC, and the Pi's own bring-up ("major malfunctions TBD"). Four phases: Pi bring-up, static chain, real capture + udev trigger, input injection. |
| 56 | [The island, and the bar's honest face](56-island-and-the-bars-honest-face.md) | Bar clears a region for sprawling notification banners, agent-controlled (Part A: design questions). Part B is buildable now: drop the LTE suffix, tap-to-cycle the carrier name (Fido → Casey → Fimeg), and a network-type indicator that shows the live connection instead of a wifi glyph that never reflects cellular. |