tawasuyu

tawasuyu/llimphi

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

Rust 238TOML 102Markdown 83Shell 24178 Sutichaykuna

⎇ main llimphi-hal/examples/canvas_clear.rs Rust · 101 siq'ikuna · 3.9 KB Ñawpa willay Pi imata llamkarqan ch'uya

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

1//! El `clear_screen` del navegador: pinta un `<canvas>` de gris plomo con
2//! [`CanvasSurface`], el HAL de wasm32.
3//!
4//! Es el gemelo web de `clear_screen.rs` y cumple la misma función que aquel:
5//! ser el consumidor mínimo del HAL, para que un cambio de API rompa acá y no
6//! meses después en una app. Ejercita el camino entero —canvas del DOM →
7//! `Hal::for_canvas` → `resize_to_css` → `acquire` → render pass → `present`—
8//! sin depender del event loop de `llimphi-ui`, que todavía no cruzó a web.
9//!
10//! Verificación (no linkea, no necesita navegador ni wasm-bindgen-cli):
11//!
12//! ```sh
13//! cargo check -p llimphi-hal --target wasm32-unknown-unknown --examples
14//! ```
15//!
16//! Para correrlo de verdad hace falta empaquetarlo con `wasm-bindgen-cli` y
17//! servir un HTML con un `<canvas id="llimphi">`. No hay script de eso todavía
18//! — ver `PORTING.md` §wasm32.
19
20// En cualquier target nativo este example no aplica: la `CanvasSurface` sólo
21// existe en wasm32. Un `main` vacío deja que `--examples` lo compile en el
22// smoke test del workspace sin ensuciar la salida.
23#[cfg(not(target_arch = "wasm32"))]
24fn main() {
25    eprintln!(
26        "llimphi · canvas_clear — este example es sólo para wasm32-unknown-unknown \
27         (usa CanvasSurface). En escritorio el equivalente es `clear_screen`."
28    );
29}
30
31#[cfg(target_arch = "wasm32")]
32fn main() {
33    wasm_bindgen_futures::spawn_local(async {
34        if let Err(e) = correr().await {
35            web_sys::console::error_1(&format!("llimphi · canvas_clear: {e}").into());
36        }
37    });
38}
39
40#[cfg(target_arch = "wasm32")]
41const LEAD_GRAY: llimphi_hal::wgpu::Color = llimphi_hal::wgpu::Color {
42    r: 0.235,
43    g: 0.239,
44    b: 0.247,
45    a: 1.0,
46};
47
48#[cfg(target_arch = "wasm32")]
49async fn correr() -> Result<(), String> {
50    use llimphi_hal::{wgpu, Hal, Surface};
51    use wasm_bindgen::JsCast;
52
53    let canvas: web_sys::HtmlCanvasElement = web_sys::window()
54        .ok_or("sin `window`")?
55        .document()
56        .ok_or("sin `document`")?
57        .get_element_by_id("llimphi")
58        .ok_or("no hay ningún elemento con id=\"llimphi\"")?
59        .dyn_into()
60        .map_err(|_| "el elemento #llimphi no es un <canvas>")?;
61
62    // Surface-first, igual que en Android: el adapter se pide contra ESTA
63    // surface. `for_canvas` es async porque en el main thread del navegador no
64    // se puede bloquear.
65    let (hal, mut surface) = Hal::for_canvas(canvas).await.map_err(|e| e.to_string())?;
66
67    // El backing store del canvas por `devicePixelRatio`. Sin esto el canvas se
68    // ve borroso en HiDPI (el navegador escala un buffer chico).
69    let (w, h) = surface.resize_to_css();
70    web_sys::console::log_1(&format!("llimphi · canvas_clear — surface {w}×{h} px físicos").into());
71
72    let frame = surface.acquire().map_err(|e| e.to_string())?;
73    let mut encoder = hal
74        .device
75        .create_command_encoder(&wgpu::CommandEncoderDescriptor {
76            label: Some("canvas_clear-encoder"),
77        });
78    {
79        let _pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
80            label: Some("canvas_clear-pass"),
81            color_attachments: &[Some(wgpu::RenderPassColorAttachment {
82                // La intermedia, no el swapchain: es el mismo contrato que en
83                // escritorio (vello pinta acá y `present` blittea).
84                view: frame.view(),
85                resolve_target: None,
86                depth_slice: None,
87                ops: wgpu::Operations {
88                    load: wgpu::LoadOp::Clear(LEAD_GRAY),
89                    store: wgpu::StoreOp::Store,
90                },
91            })],
92            depth_stencil_attachment: None,
93            timestamp_writes: None,
94            occlusion_query_set: None,
95            multiview_mask: None,
96        });
97    }
98    hal.queue.submit(std::iter::once(encoder.finish()));
99    surface.present(frame, &hal);
100    Ok(())
101}