diff --git a/crates/apps/mirada-compositor/README.md b/crates/apps/mirada-compositor/README.md index 3ea2426..eaa1fcc 100644 --- a/crates/apps/mirada-compositor/README.md +++ b/crates/apps/mirada-compositor/README.md @@ -169,10 +169,12 @@ En modo enlazado el socket de control lo abre el Cerebro (la app `wl_compositor`, `xdg_shell` (toplevels y popups), `wl_shm`, `wl_seat` (teclado, y ratón en el backend DRM), `wl_output`, `wl_data_device` -(selección) y `xdg-decoration` — fuerza decoración del servidor y no -dibuja ninguna, así las ventanas van sin barra de título. Composición -con `GlesRenderer` — en `winit` sobre la ventana, en `drm` con un -`DrmCompositor` por salida. +(selección), `xdg-decoration` — fuerza decoración del servidor y no +dibuja ninguna, así las ventanas van sin barra de título — y +`zwp_linux_dmabuf`, que deja conectarse a los clientes que pintan por +GPU (apps GPUI, navegadores acelerados). Composición con `GlesRenderer` +— en `winit` sobre la ventana, en `drm` con un `DrmCompositor` por +salida. Reusa `mirada-body` para la contabilidad de salidas y superficies, y `mirada-link` para el cable hacia un Cerebro externo. Toda la lógica diff --git a/crates/apps/mirada-compositor/src/drm_backend.rs b/crates/apps/mirada-compositor/src/drm_backend.rs index 065a53b..0cac095 100644 --- a/crates/apps/mirada-compositor/src/drm_backend.rs +++ b/crates/apps/mirada-compositor/src/drm_backend.rs @@ -710,6 +710,9 @@ pub fn run() -> Result<(), Box> { // 7 · El estado Wayland (Cerebro, teclado, keymap, control). println!("[7/8] armando el estado Wayland …"); let Setup { mut display, mut app, keymap_path, keymap_watch, ctl } = crate::build_app()?; + // Con el renderer ya creado, anuncia dmabuf — sin esto las apps que + // pintan por GPU (GPUI, navegadores acelerados) no pueden conectarse. + crate::announce_dmabuf(&mut app, &display.handle(), &renderer); // La salida del Cerebro = el modo del monitor. let ev = app.body.add_output(0, mode_w as i32, mode_h as i32); app.brain_feed(ev); diff --git a/crates/apps/mirada-compositor/src/main.rs b/crates/apps/mirada-compositor/src/main.rs index e3fd7a5..6c3804d 100644 --- a/crates/apps/mirada-compositor/src/main.rs +++ b/crates/apps/mirada-compositor/src/main.rs @@ -20,6 +20,7 @@ use std::sync::Arc; use std::time::Instant; +use smithay::backend::allocator::dmabuf::Dmabuf; use smithay::backend::input::{InputEvent, KeyState, KeyboardKeyEvent}; use smithay::backend::renderer::element::surface::{ render_elements_from_surface_tree, WaylandSurfaceRenderElement, @@ -30,7 +31,7 @@ use smithay::backend::renderer::gles::GlesRenderer; use smithay::backend::renderer::utils::{ draw_render_elements, on_commit_buffer_handler, with_renderer_surface_state, }; -use smithay::backend::renderer::{Color32F, Frame, Renderer}; +use smithay::backend::renderer::{Color32F, Frame, ImportDma, Renderer}; use smithay::backend::winit::{self, WinitEvent}; use smithay::input::keyboard::{xkb, FilterResult, KeyboardHandle, Keysym, ModifiersState}; use smithay::input::pointer::{CursorImageStatus, CursorImageSurfaceData, PointerHandle}; @@ -47,6 +48,7 @@ use smithay::reexports::winit::platform::pump_events::PumpStatus; use smithay::utils::{Rectangle, SERIAL_COUNTER}; use smithay::utils::{Serial, Transform}; use smithay::wayland::buffer::BufferHandler; +use smithay::wayland::dmabuf::{DmabufGlobal, DmabufHandler, DmabufState, ImportNotifier}; use smithay::wayland::compositor::{ with_states, with_surface_tree_downward, CompositorClientState, CompositorHandler, CompositorState, SurfaceAttributes, TraversalAction, @@ -63,8 +65,8 @@ use smithay::wayland::shell::xdg::{ use smithay::wayland::output::OutputHandler; use smithay::wayland::shm::{ShmHandler, ShmState}; use smithay::{ - delegate_compositor, delegate_data_device, delegate_output, delegate_seat, delegate_shm, - delegate_xdg_decoration, delegate_xdg_shell, + delegate_compositor, delegate_data_device, delegate_dmabuf, delegate_output, delegate_seat, + delegate_shm, delegate_xdg_decoration, delegate_xdg_shell, }; use mirada_body::{BodyOp, BodyState}; @@ -133,6 +135,9 @@ struct App { compositor_state: CompositorState, xdg_shell_state: XdgShellState, shm_state: ShmState, + /// Estado de `zwp_linux_dmabuf` — deja que los clientes con GPU + /// (apps GPUI, navegadores acelerados) compartan búferes de vídeo. + dmabuf_state: DmabufState, seat_state: SeatState, data_device_state: DataDeviceState, seat: Seat, @@ -340,6 +345,24 @@ impl BufferHandler for App { fn buffer_destroyed(&mut self, _buffer: &wl_buffer::WlBuffer) {} } +impl DmabufHandler for App { + fn dmabuf_state(&mut self) -> &mut DmabufState { + &mut self.dmabuf_state + } + + /// Un cliente importó un DMA-BUF. El `GlesRenderer` lo importará de + /// verdad al componer; aquí basta con aceptarlo — un búfer inválido + /// sólo dejará en blanco ese cuadro de esa ventana. + fn dmabuf_imported( + &mut self, + _global: &DmabufGlobal, + _dmabuf: Dmabuf, + notifier: ImportNotifier, + ) { + let _ = notifier.successful::(); + } +} + impl ShmHandler for App { fn shm_state(&self) -> &ShmState { &self.shm_state @@ -494,6 +517,7 @@ impl OutputHandler for App {} delegate_compositor!(App); delegate_xdg_shell!(App); delegate_xdg_decoration!(App); +delegate_dmabuf!(App); delegate_shm!(App); delegate_seat!(App); delegate_data_device!(App); @@ -714,6 +738,19 @@ fn announce_output( output } +/// Anuncia el global `zwp_linux_dmabuf` con los formatos que el +/// `GlesRenderer` admite. Hay que llamarlo una vez creado el renderer +/// (no antes: los formatos salen de él) — así las apps que pintan por +/// GPU (GPUI, navegadores acelerados) pueden ser clientes del compositor. +fn announce_dmabuf(app: &mut App, dh: &DisplayHandle, renderer: &GlesRenderer) { + let formats: Vec<_> = renderer.dmabuf_formats().into_iter().collect(); + println!( + "mirada-compositor · dmabuf: {} formato(s) anunciado(s).", + formats.len() + ); + app.dmabuf_state.create_global::(dh, formats); +} + /// Lo que comparten los dos backends gráficos: el `Display` de Wayland, /// el `App` ya armado y la maquinaria de keymap y control. struct Setup { @@ -767,6 +804,7 @@ fn build_app() -> Result> { compositor_state: CompositorState::new::(&dh), xdg_shell_state: XdgShellState::new::(&dh), shm_state: ShmState::new::(&dh, Vec::new()), + dmabuf_state: DmabufState::new(), seat_state, data_device_state: DataDeviceState::new::(&dh), seat, @@ -878,6 +916,9 @@ fn run_winit() -> Result<(), Box> { let start = Instant::now(); let mut clients = Vec::new(); + // Con el renderer ya creado, anuncia dmabuf (clientes con GPU). + announce_dmabuf(&mut state, &display.handle(), backend.renderer()); + // Salida inicial = el tamaño de la ventana winit. let win_size = backend.window_size(); let _wl_output = announce_output(&display.handle(), "winit", win_size.w, win_size.h, 60_000); diff --git a/crates/modules/mirada/SDD.md b/crates/modules/mirada/SDD.md index 00aca47..5619e8a 100644 --- a/crates/modules/mirada/SDD.md +++ b/crates/modules/mirada/SDD.md @@ -193,10 +193,13 @@ manual) y `mirada-ctl` (CLI, probado vía el ejemplo `headless-ctl`). El **Cuerpo** ya existe: `mirada-compositor` es un compositor Wayland teselante real sobre `smithay`. Habla `wl_compositor`/`xdg_shell`/ -`wl_shm`/`wl_seat`/`wl_output`/`wl_data_device`/`xdg-decoration`, compone -las superficies de los clientes con `GlesRenderer` y aplica la geometría -del Cerebro. Fuerza decoración `ServerSide` y no dibuja ninguna: las -ventanas teseladas van sin marco (nada de barras de título de cliente). +`wl_shm`/`wl_seat`/`wl_output`/`wl_data_device`/`xdg-decoration`/ +`zwp_linux_dmabuf`, compone las superficies de los clientes con +`GlesRenderer` y aplica la geometría del Cerebro. Fuerza decoración +`ServerSide` y no dibuja ninguna: las ventanas teseladas van sin marco +(nada de barras de título de cliente). Con `zwp_linux_dmabuf` los +clientes que pintan por GPU (apps GPUI, navegadores acelerados) pueden +conectarse — el `GlesRenderer` importa sus búferes DMA-BUF al componer. Reusa `mirada-body` (contabilidad) y `mirada-link` (cable). Dos modos de Cerebro: **autónomo** (`Desktop` embebido) o **enlazado** (`MIRADA_SOCKET` → la app `mirada`). diff --git a/vamos.txt b/vamos.txt index 592958f..7b42fd7 100644 --- a/vamos.txt +++ b/vamos.txt @@ -1000,7 +1000,8 @@ WAYLAND_DISPLAY=wayland-1 foot # lanza clientes contra él (imprime su WAYLAND_DISPLAY al arrancar) MIRADA_SOCKET=/tmp/mirada.sock cargo run -p mirada-compositor # enlazado: la app mirada (Cerebro GPUI) decide la geometría cargo run -p mirada-compositor -- --drm # nativo sobre TTY (MIRADA_STARTUP=foot lanza un cliente al arrancar) - Habla wl_compositor/xdg_shell/wl_shm/wl_seat/wl_data_device; compone con GlesRenderer. Reusa mirada-body y mirada-link. + Habla wl_compositor/xdg_shell/wl_shm/wl_seat/wl_data_device/xdg-decoration/zwp_linux_dmabuf; compone con GlesRenderer. + dmabuf permite clientes que pintan por GPU (apps GPUI, navegadores acelerados). Reusa mirada-body y mirada-link. En --drm el foco sigue al puntero y clics/rueda van a la ventana debajo; el cursor toma la forma del cliente. Cada ventana lleva un marco fino: azul la enfocada, gris las demás. Super+arrastre mueve la ventana (botón izq.) o la redimensiona (der.) — al arrastrarla pasa a flotar.