Wayland y arquitectura de compositores

Idea central

Wayland no es un “servidor gráfico” al estilo de X11; es un protocolo que define cómo los clientes (apps) hablan con un compositor que hace de servidor, renderizador y gestor de ventanas a la vez. Hyprland es ese compositor, y desde ~0.42 usa aquamarine —su propio backend— para hablar directamente con el kernel y la GPU, sin depender de wlroots.


1. ¿Qué es un servidor gráfico?

Un servidor gráfico es el proceso que:

  1. Habla con el kernel para controlar la pantalla (modo, resolución, sincronía vertical).
  2. Recibe eventos de input (teclado, ratón, touchpad).
  3. Arbitra qué proceso puede dibujar en qué región.
  4. Compone los buffers de las apps en la imagen final y la manda al display.

En Linux el núcleo de este pipeline siempre ha sido el subsistema DRM/KMS del kernel.


2. X11 — el modelo clásico

App A ──┐
App B ──┤──► Servidor X (Xorg) ──► GPU (driver DRI/DRM) ──► pantalla
App C ──┘         │
                  └── Gestor de ventanas (proceso separado: i3, openbox…)
CaracterísticaX11
ProtocoloBidi TCP/IP (incluso en local via socket)
RenderingLa app puede pedir al servidor X que dibuje (X primitives) o dibujar ella misma (DRI)
Gestor de ventanasProceso separado; Xorg delega decoraciones y foco
SeguridadCualquier app puede leer eventos de teclado de otras (keylogging trivial)
Escalado HiDPIAfterthought; cada app escala por su cuenta → inconsistencias
TearingPosible; VSync opcional y complejo de coordinar
Pantallas múltiplesRANDR/XINERAMA, legacy y frágil

X11 lleva ~40 años de capas de compatibilidad. Es potente pero su modelo de seguridad es plano: todas las apps que abren una misma pantalla X pueden espiarse entre sí.


3. Wayland — el modelo moderno

App A ──► libwayland-client ──► socket Unix ──► Compositor (Hyprland)
App B ──► libwayland-client ──► socket Unix ──┘        │
                                                        ▼
                                               EGL/GBM ──► GPU ──► pantalla
                                               libinput ──► eventos

El compositor ES el servidor. No hay proceso Xorg separado: Hyprland habla directamente con DRM/KMS para controlar el display y con libinput para el input. Las apps solo ven su propio buffer; no pueden leer el de las demás.

Principios clave

PrincipioDetalle
Aislamiento de buffersCada cliente renderiza en su propio buffer (SHM o GBM/EGL). El compositor los combina.
Compositor = servidor + WMNo hay separación: Hyprland decide layout, decoraciones, foco y compositing.
Sin X primitivesEl protocolo solo mueve buffers y eventos; el dibujo es 100% responsabilidad del cliente.
Escalado nativoEl compositor comunica el scale factor al cliente; cada buffer ya llega a la resolución correcta.
Sin tearing por diseñoEl compositor sincroniza con el flip de pantalla (page flip DRM) antes de presentar.
SeguridadUn cliente no puede recibir eventos de teclado de otra ventana sin permiso explícito.

4. Pipeline completo: app → compositor → GPU → pantalla

┌──────────────────────────────────────────────────────────────────┐
│  ESPACIO DE USUARIO                                              │
│                                                                  │
│  ┌─────────┐  wl_surface  ┌──────────────────────────────────┐  │
│  │   App   │─────────────►│         HYPRLAND (compositor)    │  │
│  │ (GTK4 / │  wl_buffer   │  ┌────────────┐  ┌───────────┐  │  │
│  │  Qt6 /  │◄─────────────│  │ Protocolo  │  │  Layout   │  │  │
│  │  SDL2…) │              │  │  Wayland   │  │  (dwindle/│  │  │
│  └─────────┘              │  │ (negociado │  │   master) │  │  │
│                           │  │ en el boot)│  └───────────┘  │  │
│  ┌─────────┐              │  └────────────┘        │         │  │
│  │XWayland │──X11─►XWM───►│                        ▼         │  │
│  │(apps X) │              │  ┌─────────────────────────────┐ │  │
│  └─────────┘              │  │     aquamarine (backend)    │ │  │
│                           │  │  ┌──────────┐ ┌──────────┐  │ │  │
│                           │  │  │ DRM/KMS  │ │ libinput │  │ │  │
│                           │  └──┴────┬─────┴─┴────┬─────┘  │  │
│                           └──────────│─────────────│────────┘  │
└──────────────────────────────────────│─────────────│───────────┘
                                       ▼             ▼
                               ┌──────────────┐  ┌──────────┐
                               │  GPU (EGL /  │  │ /dev/    │
                               │  GBM / Mesa) │  │ input/*  │
                               └──────┬───────┘  └──────────┘
                                      │ page flip
                                      ▼
                               ┌──────────────┐
                               │  Pantalla    │
                               │  (CRTC/eDP-1)│
                               └──────────────┘

5. Cómo Hyprland habla con el kernel: DRM/KMS

DRM (Direct Rendering Manager) es el subsistema del kernel Linux que gestiona el acceso a la GPU y al display hardware. Se divide en dos partes:

  • DRM propiamente dicho: gestión de memoria de GPU, command submission, sincronización (fences).
  • KMS (Kernel Mode Setting): controla los conectores físicos (HDMI, eDP), CRTCs (scanout engines) y planos. Permite al compositor setear resolución/refresh sin pasar por Xorg.

Hyprland abre /dev/dri/cardN (acceso KMS) y /dev/dri/renderDN (acceso render). En tu sistema el GPU NVIDIA usa ambos nodos.

# ENVariables.conf (KooL/JaKooLit dotfiles)
# env = AQ_DRM_DEVICES,/dev/dri/card1:/dev/dri/card0
# card0 → Intel UHD (iGPU, scanout principal)
# card1 → RTX 4070 (dGPU, render on-demand)

6. Cómo habla con la GPU: EGL y GBM

CapaRol
MesaImplementación open-source de OpenGL/Vulkan/EGL para Intel y (parcialmente) NVIDIA
GBM (Generic Buffer Management)API de Mesa para asignar buffers gráficos en VRAM compatibles con KMS. Es el “malloc de la GPU”.
EGLAPI de Khronos que inicializa el contexto OpenGL/ES sobre un display nativo (aquí, un gbm_device).
DMA-BUFMecanismo del kernel para compartir buffers entre procesos/drivers sin copias (zero-copy).

Pipeline de render de un frame:

  1. Hyprland pide a GBM un buffer para el plano de pantalla.
  2. Importa ese buffer en EGL como EGLImage.
  3. Renderiza todos los wl_surface de los clientes sobre ese buffer (con shaders OpenGL).
  4. Llama a DRM page-flip: el kernel swapea el buffer activo al siguiente vsync.
  5. La pantalla escanea el nuevo buffer. Sin tearing.

7. Input: libinput

libinput es la biblioteca que abstrae todos los dispositivos de entrada en Linux (teclado, ratón, touchpad, stylus). Hyprland (vía aquamarine) abre los nodos /dev/input/eventN directamente, sin pasar por Xorg ni evdev manual.

libinput maneja:

  • Aceleración del puntero (configurable en Hyprland con input { accel_profile })
  • Gesto multitouch del touchpad
  • Tap-to-click, scroll natural, etc.
# Ejemplo de tu setup (UserSettings.conf puede incluir):
# input {
#     touchpad {
#         natural_scroll = true
#         tap-to-click = true
#     }
# }

8. aquamarine — el backend propio de Hyprland

Hasta ~0.41, Hyprland usaba wlroots (biblioteca C para construir compositores Wayland). Desde 0.42 (completado en 0.45+) Hyprland es completamente independiente y usa aquamarine.

¿Qué es aquamarine?

“A very light linux rendering backend library implementing only the low-level KMS/DRM/etc rendering backends.”

Comparaciónwlrootsaquamarine
ScopeCompositor completo (protocolos + backend)Solo backend de bajo nivel
IdiomaCC++
Protocolo WaylandIncluidoNo — Hyprland implementa los protocolos por su cuenta
DependenciasMuchasMínimas
PortabilidadDRM + backend Wayland (nested)DRM o nested Wayland

Aquamarine puede correr Hyprland en una TTY (modo DRM nativo) o dentro de otra sesión Wayland (modo nested, útil para debug). Tu configuración usa DRM nativo.

Variables de debug de aquamarine disponibles en tu ENVariables.conf:

# env = AQ_TRACE,1                          # log verboso
# env = AQ_DRM_DEVICES,/dev/dri/card1:...   # forzar orden de GPUs
# env = AQ_NO_MODIFIERS,1                   # deshabilitar DRM modifiers (debug)

9. XWayland — compatibilidad con apps X11

Las apps que solo hablan X11 (muchos juegos, apps legacy, algunas de desarrollo) no pueden conectarse directamente al socket Wayland. XWayland resuelve esto:

App X11 ──► XWayland (servidor X completo) ──► wl_surface ──► Hyprland
                    │
                    └── XWM (X Window Manager interno de Hyprland)
                        gestiona decoraciones y foco de ventanas X
  • XWayland arranca como cliente Wayland normal. Hyprland lo lanza automáticamente al detectar una app X11.
  • Internamente hay una dependencia circular: XWayland es cliente Wayland de Hyprland, pero Hyprland es cliente X11 de XWayland (para el XWM). Hyprland gestiona esto con cuidado.
  • Las apps X11 no saben que están en Wayland; ven un servidor X estándar.
  • Limitaciones: input de teclado global funciona distinto, escalado HiDPI es imperfecto (por eso existen las env = GDK_SCALE en tu ENVariables.conf).
# ENVariables.conf — fix de escala para apps XWayland con monitor scaling:
# env = GDK_SCALE,1
# env = QT_SCALE_FACTOR,1

10. Protocolos Wayland

Un “protocolo” Wayland es un conjunto de interfaces (en XML) que define los mensajes que pueden intercambiar cliente y compositor. Se negocian en el wl_registry al conectarse.

Capas de protocolos

CapaEjemplosQuién los define
Corewl_compositor, wl_surface, wl_shm, wl_seatfreedesktop.org (libwayland)
wayland-protocolsxdg-shell (ventanas normales), xdg-output, wp-presentation-timefreedesktop.org (oficial, lento)
wlr-protocolszwlr_layer_shell_v1 (barras, overlays), zwlr_screencopy_v1Originally wlroots; adoptados por Hyprland
hyprland-protocolshyprland_toplevel_export_v1, hyprland_global_keybinds_v1, hyprland_surface_v1Hyprland propio

El protocolo más importante para apps normales es xdg-shell, que define xdg_surface + xdg_toplevel (ventana normal) y xdg_popup (menús/tooltips).

zwlr_layer_shell_v1 es lo que usa tu barra (Waybar) para anclarse en un borde de pantalla sin que Hyprland la trate como ventana flotante.


11. xdg-desktop-portal y portals

En X11, una app podía abrir cualquier archivo del sistema o capturar cualquier ventana directamente. En Wayland esto está bloqueado. Los portals son la solución: procesos intermediarios con interfaz D-Bus que elevan permisos bajo consentimiento explícito del usuario.

App (p. ej. OBS) ──D-Bus──► xdg-desktop-portal (portal genérico)
                                    │
                             implementación específica del compositor
                                    │
                        xdg-desktop-portal-hyprland (XDPH)
                                    │
                    ┌───────────────┴───────────────┐
                    ▼                               ▼
            PipeWire (screen capture)     Qt picker (file open)

Portals que provee XDPH

PortalFuncionalidad
ScreenCastCaptura de pantalla/ventana vía PipeWire (OBS, Discord, Zoom)
RemoteDesktopControl remoto con acceso a input
FileChooserSelector de archivos nativo del sistema
ScreenshotCaptura estática

Por qué se necesita PipeWire: el compositor no puede dar acceso directo a su framebuffer a las apps. PipeWire actúa de bus multimedia: XDPH exporta el contenido de pantalla como un stream PipeWire, y la app (OBS, navegador para screenshare) consume ese stream.

XDPH arranca automáticamente por D-Bus cuando Hyprland inicia. Si no funciona:

# Verificar que corre:
systemctl --user status xdg-desktop-portal-hyprland
 
# Verificar PipeWire y wireplumber:
systemctl --user status pipewire wireplumber

12. X11 vs Wayland — tabla resumen

AspectoX11Wayland
ModeloCliente habla con servidor X separadoCliente habla directo con el compositor
Seguridad inputCualquier app puede leer teclado de otrasAislado; el compositor es árbitro
RenderingX puede dibujar por ti O el cliente (DRI)El cliente siempre dibuja su propio buffer
TearingPosible sin VSync explícitoEliminado por diseño (page flip en vsync)
Escalado HiDPIFrágil, por appNativo en el protocolo (wl_output.scale)
Network transparencySí (X11 por TCP)No (por diseño; screenshare vía PipeWire)
Captura de pantallaDirecta (cualquier app)Solo vía portals + PipeWire
CompositingOpcional (COMPOSITE extension)Obligatorio; el compositor es el renderer
Apps legacyNativasVia XWayland

Conexiones