tawasuyu

tawasuyu/llimphi

Sovereign retained-mode GPU UI framework in Rust (wgpu+vello+taffy+parley), Elm loop, 40+ widgets.

Rust 660Markdown 302TOML 157RON 312382 Definiciones

⎇ main llimphi-jaula/LEEME.md Markdown · 105 líneas · 4.1 KB Historia crudo

chore: refresco desde el monorepo — vello 0.9 / wgpu 29, 120 miembros d251eb32b · Sergio ·

1# llimphi-jaula
2
3La cáscara del lado **app**: corre el ciclo de Llimphi dentro de una jaula WASM y
4emite una [`EscenaWire`](../llimphi-wire-escena/LEEME.md) en vez de rasterizar.
5
6Es el gemelo de [`llimphi-wawa`](../llimphi-wawa/LEEME.md), del otro lado de la
7frontera: aquélla recibe y ejecuta, ésta compone y manda.
8
9W4 de [`03_ukupacha/wawa/PLAN-LLIMPHI.md`](../../../03_ukupacha/wawa/PLAN-LLIMPHI.md).
10
11```
12View<Msg> → mount → layout → paint → EscenaWire → postcard → …
13…………………………… frontera WASM ……………………………
14                                   … → shapear nativo → rasterizar
15```
16
17## Lo que hay que entender de acá
18
19Las dos cáscaras corren el **mismo `llimphi-compositor`** — el mismo mount, el
20mismo layout de taffy, el mismo `render.rs` de 4.000 líneas. Lo único que cambia
21es el alias `Lienzo` y, con él, el `Typesetter`.
22
23Eso es el resultado de W4 que vale decir en voz alta: **no hay un compositor para
24apps y otro para el kernel.** Un widget escrito una vez sirve en Linux, adentro
25del kernel, y adentro de una jaula.
26
27## Las dos cosas que ésta hace y la del kernel no
28
29### Pregunta las medidas
30
31taffy no puede dimensionar una etiqueta sin saber cuánto mide, y medir es
32shapear — justo lo que no debe pasar adentro de la jaula: el 30,3x del intérprete
33se comería el 72% del fotograma (W4.1). Así que el medidor es un **argumento**:
34
35```rust
36let mut jaula = Jaula::new(320.0, 72.0, |p: &Peticion| {
37    // En wawa: un `sys_medir_texto` que cruza a parley del lado nativo.
38    // En un test: un `Typesetter` de parley de verdad.
39    medir_del_otro_lado(p)
40});
41let montado = jaula.fotograma(vista());
42let bytes = postcard::to_allocvec(jaula.escena())?;
43```
44
45Sin medidor no se devuelve cero — un cero silencioso colapsaría el layout entero
46y la pantalla saldría vacía «funcionando». Se estima grosero **y se cuenta**:
47`jaula.medidas_estimadas()` distinto de cero significa que ese layout es
48aproximado.
49
50En wawa, ese medidor ya viene hecho — es [`medidor::wawa`](src/medidor.rs), que
51envuelve el syscall `sys_medir_texto`:
52
53```rust
54let mut jaula = Jaula::new(ancho, alto, llimphi_jaula::medidor::wawa);
55```
56
57`sys_medir_texto` **no está gateado por permiso**: medir texto no es un
58privilegio, es aritmética sobre una fuente, y toda app que dibuje la necesita. Lo
59que sí lleva es cuota, porque el shaping lo paga el kernel fuera del `fuel` de la
60app. Fuera de wasm el medidor devuelve `None` en vez de un número inventado.
61
62### Se queda con el árbol
63
64El `Mounted` no cruza la frontera, así que el hit-test se resuelve de este lado:
65el kernel manda una coordenada y la app contesta qué se tocó.
66
67```rust
68if let Some(msg) = jaula.click(&montado, x, y) {
69    modelo = App::update(modelo, msg);
70}
71```
72
73Es lo contrario de la cáscara del kernel, que **no puede** hacer hit-test
74justamente porque el árbol se quedó acá.
75
76## Por qué está fuera del workspace
77
78Enciende `llimphi-text/wire`, que es un backend excluyente de `vello` (el que usa
79todo el resto del repo por default). La unificación de features de cargo los
80juntaría y dispararía el `compile_error!` que `llimphi-text` tiene puesto para
81delatarlo — es la misma trampa que ya mordió con `llimphi-wawa`.
82
83Que las dos estén afuera no es una molestia: es el diseño. Son dos procesos en
84dos lados de una frontera.
85
86```bash
87cargo test  --manifest-path 02_ruway/llimphi/llimphi-jaula/Cargo.toml \
88  --no-default-features --features std
89cargo check --manifest-path 02_ruway/llimphi/llimphi-jaula/Cargo.toml \
90  --target wasm32-unknown-unknown --no-default-features --features libm
91```
92
93## El fixture
94
95Como el encoder y el reproductor no pueden compilarse juntos, la costura del test
96es la misma que la de producción: **bytes**.
97
98```bash
99cargo run --example emitir_fixture --no-default-features --features std
100```
101
102Compone una vista con el compositor de verdad y deja los bytes en
103`../llimphi-wawa/pruebas/fixture_jaula.postcard`, donde los levantan el test
104`la_escena_que_emitio_el_compositor_llega_a_pixeles` **y el arranque del kernel**.
105Si alguien cambia el formato del cable de un solo lado, esos dos lo dicen.

LEEME.md

llimphi-jaula

La cáscara del lado app: corre el ciclo de Llimphi dentro de una jaula WASM y emite una EscenaWire en vez de rasterizar.

Es el gemelo de llimphi-wawa, del otro lado de la frontera: aquélla recibe y ejecuta, ésta compone y manda.

W4 de 03_ukupacha/wawa/PLAN-LLIMPHI.md.

View<Msg> → mount → layout → paint → EscenaWire → postcard → …
…………………………… frontera WASM ……………………………
                                   … → shapear nativo → rasterizar

Lo que hay que entender de acá

Las dos cáscaras corren el mismo llimphi-compositor — el mismo mount, el mismo layout de taffy, el mismo render.rs de 4.000 líneas. Lo único que cambia es el alias Lienzo y, con él, el Typesetter.

Eso es el resultado de W4 que vale decir en voz alta: no hay un compositor para apps y otro para el kernel. Un widget escrito una vez sirve en Linux, adentro del kernel, y adentro de una jaula.

Las dos cosas que ésta hace y la del kernel no

Pregunta las medidas

taffy no puede dimensionar una etiqueta sin saber cuánto mide, y medir es shapear — justo lo que no debe pasar adentro de la jaula: el 30,3x del intérprete se comería el 72% del fotograma (W4.1). Así que el medidor es un argumento:

let mut jaula = Jaula::new(320.0, 72.0, |p: &Peticion| {
    // En wawa: un `sys_medir_texto` que cruza a parley del lado nativo.
    // En un test: un `Typesetter` de parley de verdad.
    medir_del_otro_lado(p)
});
let montado = jaula.fotograma(vista());
let bytes = postcard::to_allocvec(jaula.escena())?;

Sin medidor no se devuelve cero — un cero silencioso colapsaría el layout entero y la pantalla saldría vacía «funcionando». Se estima grosero y se cuenta: jaula.medidas_estimadas() distinto de cero significa que ese layout es aproximado.

En wawa, ese medidor ya viene hecho — es medidor::wawa, que envuelve el syscall sys_medir_texto:

let mut jaula = Jaula::new(ancho, alto, llimphi_jaula::medidor::wawa);

sys_medir_texto no está gateado por permiso: medir texto no es un privilegio, es aritmética sobre una fuente, y toda app que dibuje la necesita. Lo que sí lleva es cuota, porque el shaping lo paga el kernel fuera del fuel de la app. Fuera de wasm el medidor devuelve None en vez de un número inventado.

Se queda con el árbol

El Mounted no cruza la frontera, así que el hit-test se resuelve de este lado: el kernel manda una coordenada y la app contesta qué se tocó.

if let Some(msg) = jaula.click(&montado, x, y) {
    modelo = App::update(modelo, msg);
}

Es lo contrario de la cáscara del kernel, que no puede hacer hit-test justamente porque el árbol se quedó acá.

Por qué está fuera del workspace

Enciende llimphi-text/wire, que es un backend excluyente de vello (el que usa todo el resto del repo por default). La unificación de features de cargo los juntaría y dispararía el compile_error! que llimphi-text tiene puesto para delatarlo — es la misma trampa que ya mordió con llimphi-wawa.

Que las dos estén afuera no es una molestia: es el diseño. Son dos procesos en dos lados de una frontera.

cargo test  --manifest-path 02_ruway/llimphi/llimphi-jaula/Cargo.toml \
  --no-default-features --features std
cargo check --manifest-path 02_ruway/llimphi/llimphi-jaula/Cargo.toml \
  --target wasm32-unknown-unknown --no-default-features --features libm

El fixture

Como el encoder y el reproductor no pueden compilarse juntos, la costura del test es la misma que la de producción: bytes.

cargo run --example emitir_fixture --no-default-features --features std

Compone una vista con el compositor de verdad y deja los bytes en ../llimphi-wawa/pruebas/fixture_jaula.postcard, donde los levantan el test la_escena_que_emitio_el_compositor_llega_a_pixeles y el arranque del kernel. Si alguien cambia el formato del cable de un solo lado, esos dos lo dicen.