From bba9ca1fa273ec57748f2bfabcbf6b19e9200512 Mon Sep 17 00:00:00 2001 From: Ivan Molodetskikh Date: Tue, 12 Aug 2025 22:34:13 +0300 Subject: headless: Add a renderer To be used for animation tests that need animation snapshots. The renderer is optional to avoid creating it thousands of times in tests when it's not needed, plus it can deadlock in mesa apparently. --- src/backend/headless.rs | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/backend/headless.rs b/src/backend/headless.rs index e961daa2..51381168 100644 --- a/src/backend/headless.rs +++ b/src/backend/headless.rs @@ -1,13 +1,16 @@ //! Headless backend for tests. //! //! This can eventually grow into a more complete backend if needed, but for now it's missing some -//! crucial parts like rendering. +//! crucial parts like dmabufs. use std::mem; use std::sync::{Arc, Mutex}; +use anyhow::Context as _; use niri_config::OutputName; use smithay::backend::allocator::dmabuf::Dmabuf; +use smithay::backend::egl::native::EGLSurfacelessDisplay; +use smithay::backend::egl::{EGLContext, EGLDisplay}; use smithay::backend::renderer::element::RenderElementStates; use smithay::backend::renderer::gles::GlesRenderer; use smithay::output::{Mode, Output, PhysicalProperties, Subpixel}; @@ -17,21 +20,44 @@ use smithay::wayland::presentation::Refresh; use super::{IpcOutputMap, OutputId, RenderResult}; use crate::niri::{Niri, RedrawState}; +use crate::render_helpers::{resources, shaders}; use crate::utils::{get_monotonic_time, logical_output}; pub struct Headless { + renderer: Option, ipc_outputs: Arc>, } impl Headless { pub fn new() -> Self { Self { + renderer: None, ipc_outputs: Default::default(), } } pub fn init(&mut self, _niri: &mut Niri) {} + pub fn add_renderer(&mut self) -> anyhow::Result<()> { + if self.renderer.is_some() { + error!("add_renderer: renderer must not already exist"); + return Ok(()); + } + + let mut renderer = unsafe { + let display = + EGLDisplay::new(EGLSurfacelessDisplay).context("error creating EGL display")?; + let context = EGLContext::new(&display).context("error creating EGL context")?; + GlesRenderer::new(context).context("error creating renderer")? + }; + + resources::init(&mut renderer); + shaders::init(&mut renderer); + + self.renderer = Some(renderer); + Ok(()) + } + pub fn add_output(&mut self, niri: &mut Niri, n: u8, size: (u16, u16)) { let connector = format!("headless-{n}"); let make = "niri".to_string(); @@ -94,9 +120,9 @@ impl Headless { pub fn with_primary_renderer( &mut self, - _f: impl FnOnce(&mut GlesRenderer) -> T, + f: impl FnOnce(&mut GlesRenderer) -> T, ) -> Option { - None + self.renderer.as_mut().map(f) } pub fn render(&mut self, niri: &mut Niri, output: &Output) -> RenderResult { -- cgit