#![allow(missing_docs)] #[cfg(all( feature = "wayland_frontend", feature = "use_system_lib", feature = "backend_egl" ))] use crate::backend::renderer::ImportEgl; #[cfg(feature = "wayland_frontend")] use crate::{ backend::renderer::{ImportDmaWl, ImportMemWl}, reexports::wayland_server::protocol::wl_buffer, wayland::{self, compositor::SurfaceData, shm::BufferAccessError}, }; use crate::{ backend::{ allocator::{dmabuf::Dmabuf, Fourcc}, renderer::{ sync::SyncPoint, DebugFlags, Frame, ImportDma, ImportMem, Renderer, RendererSuper, Texture, TextureFilter, }, SwapBuffersError, }, utils::{Buffer, Physical, Rectangle, Size, Transform}, }; #[cfg(feature = "wayland_frontend")] use std::cell::Cell; use std::sync::LazyLock; use super::{Color32F, ContextId}; /// All [`DummyRenderer`] instances share the same static [`ContextId`]. static CONTEXT_ID: LazyLock> = LazyLock::new(ContextId::new); #[derive(Debug, Default)] pub struct DummyRenderer; /// Error returned by the DummyRenderer #[derive(thiserror::Error, Debug)] pub enum DummyError { /// Error accessing shm buffer #[cfg(feature = "wayland_frontend")] #[error("Error accessing buffer ({0:?})")] BufferAccessError(BufferAccessError), /// Blocking for a synchronization primitive failed #[error("Blocking for a synchronization primitive got interrupted")] SyncInterrupted, } impl From for SwapBuffersError { #[inline] fn from(value: DummyError) -> Self { SwapBuffersError::TemporaryFailure(Box::new(value)) } } impl RendererSuper for DummyRenderer { type Error = DummyError; type TextureId = DummyTexture; type Framebuffer<'buffer> = DummyFramebuffer; type Frame<'frame, 'buffer> = DummyFrame where 'buffer: 'frame, Self: 'frame; } impl Renderer for DummyRenderer { fn context_id(&self) -> ContextId { CONTEXT_ID.clone() } fn downscale_filter(&mut self, _filter: TextureFilter) -> Result<(), Self::Error> { Ok(()) } fn upscale_filter(&mut self, _filter: TextureFilter) -> Result<(), Self::Error> { Ok(()) } fn set_debug_flags(&mut self, _flags: DebugFlags) {} fn debug_flags(&self) -> DebugFlags { DebugFlags::empty() } fn render<'frame, 'buffer>( &'frame mut self, _target: &'frame mut DummyFramebuffer, _size: Size, _dst_transform: Transform, ) -> Result where 'buffer: 'frame, { Ok(DummyFrame) } fn wait(&mut self, sync: &SyncPoint) -> Result<(), Self::Error> { sync.wait().map_err(|_| DummyError::SyncInterrupted) } } impl ImportMem for DummyRenderer { fn import_memory( &mut self, _data: &[u8], _format: Fourcc, _size: Size, _flipped: bool, ) -> Result { unimplemented!() } fn update_memory( &mut self, _texture: &Self::TextureId, _data: &[u8], _region: Rectangle, ) -> Result<(), Self::Error> { unimplemented!() } fn mem_formats(&self) -> Box> { Box::new([Fourcc::Argb8888, Fourcc::Xrgb8888].iter().copied()) } } #[cfg(feature = "wayland_frontend")] impl ImportMemWl for DummyRenderer { fn import_shm_buffer( &mut self, buffer: &wl_buffer::WlBuffer, surface: Option<&SurfaceData>, _damage: &[Rectangle], ) -> Result { use std::ptr; use wayland::shm::with_buffer_contents; let ret = with_buffer_contents(buffer, |ptr, len, data| { let offset = data.offset as u32; let width = data.width as u32; let height = data.height as u32; let stride = data.stride as u32; let mut x = 0; for h in 0..height { for w in 0..width { let idx = (offset + w + h * stride) as usize; assert!(idx < len); x |= unsafe { ptr::read(ptr.add(idx)) }; } } if let Some(data) = surface { data.data_map.insert_if_missing(|| Cell::new(0u8)); data.data_map.get::>().unwrap().set(x); } (width, height) }); match ret { Ok((width, height)) => Ok(DummyTexture { width, height }), Err(e) => Err(DummyError::BufferAccessError(e)), } } } impl ImportDma for DummyRenderer { fn import_dmabuf( &mut self, _dmabuf: &Dmabuf, _damage: Option<&[Rectangle]>, ) -> Result { unimplemented!() } } #[cfg(all( feature = "wayland_frontend", feature = "use_system_lib", feature = "backend_egl" ))] impl ImportEgl for DummyRenderer { fn bind_wl_display( &mut self, _display: &::wayland_server::DisplayHandle, ) -> Result<(), crate::backend::egl::Error> { unimplemented!() } fn unbind_wl_display(&mut self) { unimplemented!() } fn egl_reader(&self) -> Option<&crate::backend::egl::display::EGLBufferReader> { unimplemented!() } fn import_egl_buffer( &mut self, _buffer: &wl_buffer::WlBuffer, _surface: Option<&wayland::compositor::SurfaceData>, _damage: &[Rectangle], ) -> Result { unimplemented!() } } #[cfg(feature = "wayland_frontend")] impl ImportDmaWl for DummyRenderer {} #[derive(Debug)] pub struct DummyFramebuffer; impl Texture for DummyFramebuffer { fn width(&self) -> u32 { 0 } fn height(&self) -> u32 { 0 } fn format(&self) -> Option { None } } #[derive(Debug)] pub struct DummyFrame; impl Frame for DummyFrame { type Error = DummyError; type TextureId = DummyTexture; fn context_id(&self) -> ContextId { CONTEXT_ID.clone() } fn clear(&mut self, _color: Color32F, _damage: &[Rectangle]) -> Result<(), Self::Error> { Ok(()) } fn draw_solid( &mut self, _dst: Rectangle, _damage: &[Rectangle], _color: Color32F, ) -> Result<(), Self::Error> { Ok(()) } fn render_texture_from_to( &mut self, _texture: &Self::TextureId, _src: Rectangle, _dst: Rectangle, _damage: &[Rectangle], _opaque_regions: &[Rectangle], _src_transform: Transform, _alpha: f32, ) -> Result<(), Self::Error> { Ok(()) } fn transformation(&self) -> Transform { Transform::Normal } fn wait(&mut self, sync: &SyncPoint) -> Result<(), Self::Error> { sync.wait().map_err(|_| DummyError::SyncInterrupted) } fn finish(self) -> Result { Ok(SyncPoint::default()) } } #[derive(Clone, Debug)] pub struct DummyTexture { width: u32, height: u32, } impl Texture for DummyTexture { fn width(&self) -> u32 { self.width } fn height(&self) -> u32 { self.height } fn format(&self) -> Option { None } }