CouchDeckSeptember 14, 2026

22 fps, then 7, then smooth — LVGL on a TV CPU

Three live iterations on an LG TV and the one rule that came out of them.

The webOS client for CouchDeck is C and LVGL, forked from moonlight-tv, running on the TV’s own CPU. The first build of the game carousel ran at 20–22 fps. Fine for a prototype, not for something that should feel like a console.

The second build added per-frame scaling so cards could grow when focused. It ran at 7–12 fps. Worse, and now I knew why: LVGL was recomputing rounded corners and blending a full-screen scrim on every frame, on a chip that was never meant to do either.

The third build is smooth, and it follows one rule: no zoom transforms, no full-screen alpha blends inside animations. Everything that can be baked is baked — in worker threads, ahead of time, into textures. Rounded corners are in the texture. The scrim over the hero art is in the texture. The focus ring, which morphs between seven sizes, is seven pre-rendered PNGs, one per size, and the “animation” swaps between them.

The Android client, on a real GPU, does none of this and animates position and size freely. Both clients follow one spec document and share no code, which is what let the webOS one cheat like this without holding the Android one back.