From b2298db5c59ed2378aa56095bfdfac8523a7ef77 Mon Sep 17 00:00:00 2001 From: Ivan Molodetskikh Date: Tue, 6 Feb 2024 11:24:50 +0400 Subject: Split render_helpers.rs --- src/render_helpers/mod.rs | 3 + src/render_helpers/primary_gpu_texture.rs | 99 +++++++++++++++++++++++ src/render_helpers/render_elements.rs | 126 ++++++++++++++++++++++++++++++ src/render_helpers/renderer.rs | 73 +++++++++++++++++ 4 files changed, 301 insertions(+) create mode 100644 src/render_helpers/mod.rs create mode 100644 src/render_helpers/primary_gpu_texture.rs create mode 100644 src/render_helpers/render_elements.rs create mode 100644 src/render_helpers/renderer.rs (limited to 'src/render_helpers') diff --git a/src/render_helpers/mod.rs b/src/render_helpers/mod.rs new file mode 100644 index 00000000..fc7a9c85 --- /dev/null +++ b/src/render_helpers/mod.rs @@ -0,0 +1,3 @@ +pub mod primary_gpu_texture; +pub mod render_elements; +pub mod renderer; diff --git a/src/render_helpers/primary_gpu_texture.rs b/src/render_helpers/primary_gpu_texture.rs new file mode 100644 index 00000000..a3835c49 --- /dev/null +++ b/src/render_helpers/primary_gpu_texture.rs @@ -0,0 +1,99 @@ +use smithay::backend::renderer::element::texture::TextureRenderElement; +use smithay::backend::renderer::element::{Element, Id, Kind, RenderElement, UnderlyingStorage}; +use smithay::backend::renderer::gles::{GlesError, GlesFrame, GlesRenderer, GlesTexture}; +use smithay::backend::renderer::utils::CommitCounter; +use smithay::utils::{Buffer, Physical, Rectangle, Scale, Transform}; + +use super::renderer::AsGlesFrame; +use crate::backend::tty::{TtyFrame, TtyRenderer, TtyRendererError}; + +/// Wrapper for a texture from the primary GPU for rendering with the primary GPU. +#[derive(Debug)] +pub struct PrimaryGpuTextureRenderElement(pub TextureRenderElement); + +impl Element for PrimaryGpuTextureRenderElement { + fn id(&self) -> &Id { + self.0.id() + } + + fn current_commit(&self) -> CommitCounter { + self.0.current_commit() + } + + fn geometry(&self, scale: Scale) -> Rectangle { + self.0.geometry(scale) + } + + fn transform(&self) -> Transform { + self.0.transform() + } + + fn src(&self) -> Rectangle { + self.0.src() + } + + fn damage_since( + &self, + scale: Scale, + commit: Option, + ) -> Vec> { + self.0.damage_since(scale, commit) + } + + fn opaque_regions(&self, scale: Scale) -> Vec> { + self.0.opaque_regions(scale) + } + + fn alpha(&self) -> f32 { + self.0.alpha() + } + + fn kind(&self) -> Kind { + self.0.kind() + } +} + +impl RenderElement for PrimaryGpuTextureRenderElement { + fn draw( + &self, + frame: &mut GlesFrame<'_>, + src: Rectangle, + dst: Rectangle, + damage: &[Rectangle], + ) -> Result<(), GlesError> { + let gles_frame = frame.as_gles_frame(); + RenderElement::::draw(&self.0, gles_frame, src, dst, damage)?; + Ok(()) + } + + fn underlying_storage(&self, _renderer: &mut GlesRenderer) -> Option { + // If scanout for things other than Wayland buffers is implemented, this will need to take + // the target GPU into account. + None + } +} + +impl<'render, 'alloc> RenderElement> + for PrimaryGpuTextureRenderElement +{ + fn draw( + &self, + frame: &mut TtyFrame<'_, '_, '_>, + src: Rectangle, + dst: Rectangle, + damage: &[Rectangle], + ) -> Result<(), TtyRendererError<'render, 'alloc>> { + let gles_frame = frame.as_gles_frame(); + RenderElement::::draw(&self.0, gles_frame, src, dst, damage)?; + Ok(()) + } + + fn underlying_storage( + &self, + _renderer: &mut TtyRenderer<'render, 'alloc>, + ) -> Option { + // If scanout for things other than Wayland buffers is implemented, this will need to take + // the target GPU into account. + None + } +} diff --git a/src/render_helpers/render_elements.rs b/src/render_helpers/render_elements.rs new file mode 100644 index 00000000..d6423bff --- /dev/null +++ b/src/render_helpers/render_elements.rs @@ -0,0 +1,126 @@ +// We need to implement RenderElement manually due to AsGlesFrame requirement. +// This macro does it for us. +#[macro_export] +macro_rules! niri_render_elements { + ($name:ident => { $($variant:ident = $type:ty),+ $(,)? }) => { + #[derive(Debug)] + pub enum $name { + $($variant($type)),+ + } + + impl smithay::backend::renderer::element::Element for $name { + fn id(&self) -> &smithay::backend::renderer::element::Id { + match self { + $($name::$variant(elem) => elem.id()),+ + } + } + + fn current_commit(&self) -> smithay::backend::renderer::utils::CommitCounter { + match self { + $($name::$variant(elem) => elem.current_commit()),+ + } + } + + fn geometry(&self, scale: smithay::utils::Scale) -> Rectangle { + match self { + $($name::$variant(elem) => elem.geometry(scale)),+ + } + } + + fn transform(&self) -> smithay::utils::Transform { + match self { + $($name::$variant(elem) => elem.transform()),+ + } + } + + fn src(&self) -> smithay::utils::Rectangle { + match self { + $($name::$variant(elem) => elem.src()),+ + } + } + + fn damage_since( + &self, + scale: smithay::utils::Scale, + commit: Option, + ) -> Vec> { + match self { + $($name::$variant(elem) => elem.damage_since(scale, commit)),+ + } + } + + fn opaque_regions(&self, scale: smithay::utils::Scale) -> Vec> { + match self { + $($name::$variant(elem) => elem.opaque_regions(scale)),+ + } + } + + fn alpha(&self) -> f32 { + match self { + $($name::$variant(elem) => elem.alpha()),+ + } + } + + fn kind(&self) -> smithay::backend::renderer::element::Kind { + match self { + $($name::$variant(elem) => elem.kind()),+ + } + } + } + + impl smithay::backend::renderer::element::RenderElement for $name { + fn draw( + &self, + frame: &mut smithay::backend::renderer::gles::GlesFrame<'_>, + src: smithay::utils::Rectangle, + dst: smithay::utils::Rectangle, + damage: &[smithay::utils::Rectangle], + ) -> Result<(), smithay::backend::renderer::gles::GlesError> { + match self { + $($name::$variant(elem) => { + smithay::backend::renderer::element::RenderElement::::draw(elem, frame, src, dst, damage) + })+ + } + } + + fn underlying_storage(&self, renderer: &mut smithay::backend::renderer::gles::GlesRenderer) -> Option { + match self { + $($name::$variant(elem) => elem.underlying_storage(renderer)),+ + } + } + } + + impl<'render, 'alloc> smithay::backend::renderer::element::RenderElement<$crate::backend::tty::TtyRenderer<'render, 'alloc>> + for $name<$crate::backend::tty::TtyRenderer<'render, 'alloc>> + { + fn draw( + &self, + frame: &mut $crate::backend::tty::TtyFrame<'render, 'alloc, '_>, + src: smithay::utils::Rectangle, + dst: smithay::utils::Rectangle, + damage: &[smithay::utils::Rectangle], + ) -> Result<(), $crate::backend::tty::TtyRendererError<'render, 'alloc>> { + match self { + $($name::$variant(elem) => { + smithay::backend::renderer::element::RenderElement::<$crate::backend::tty::TtyRenderer<'render, 'alloc>>::draw(elem, frame, src, dst, damage) + })+ + } + } + + fn underlying_storage( + &self, + renderer: &mut $crate::backend::tty::TtyRenderer<'render, 'alloc>, + ) -> Option { + match self { + $($name::$variant(elem) => elem.underlying_storage(renderer)),+ + } + } + } + + $(impl From<$type> for $name { + fn from(x: $type) -> Self { + Self::$variant(x) + } + })+ + }; +} diff --git a/src/render_helpers/renderer.rs b/src/render_helpers/renderer.rs new file mode 100644 index 00000000..7f85b66d --- /dev/null +++ b/src/render_helpers/renderer.rs @@ -0,0 +1,73 @@ +use smithay::backend::allocator::dmabuf::Dmabuf; +use smithay::backend::renderer::gles::{GlesFrame, GlesRenderer, GlesTexture}; +use smithay::backend::renderer::{ + Bind, ExportMem, ImportAll, ImportMem, Offscreen, Renderer, Texture, +}; + +use crate::backend::tty::{TtyFrame, TtyRenderer}; + +/// Trait with our main renderer requirements to save on the typing. +pub trait NiriRenderer: + ImportAll + + ImportMem + + ExportMem + + Bind + + Offscreen + + Renderer + + AsGlesRenderer +{ + // Associated types to work around the instability of associated type bounds. + type NiriTextureId: Texture + Clone + 'static; + type NiriError: std::error::Error + + Send + + Sync + + From<::Error> + + 'static; +} + +impl NiriRenderer for R +where + R: ImportAll + ImportMem + ExportMem + Bind + Offscreen + AsGlesRenderer, + R::TextureId: Texture + Clone + 'static, + R::Error: std::error::Error + Send + Sync + From<::Error> + 'static, +{ + type NiriTextureId = R::TextureId; + type NiriError = R::Error; +} + +/// Trait for getting the underlying `GlesRenderer`. +pub trait AsGlesRenderer { + fn as_gles_renderer(&mut self) -> &mut GlesRenderer; +} + +impl AsGlesRenderer for GlesRenderer { + fn as_gles_renderer(&mut self) -> &mut GlesRenderer { + self + } +} + +impl<'render, 'alloc> AsGlesRenderer for TtyRenderer<'render, 'alloc> { + fn as_gles_renderer(&mut self) -> &mut GlesRenderer { + self.as_mut() + } +} + +/// Trait for getting the underlying `GlesFrame`. +pub trait AsGlesFrame<'frame> +where + Self: 'frame, +{ + fn as_gles_frame(&mut self) -> &mut GlesFrame<'frame>; +} + +impl<'frame> AsGlesFrame<'frame> for GlesFrame<'frame> { + fn as_gles_frame(&mut self) -> &mut GlesFrame<'frame> { + self + } +} + +impl<'render, 'alloc, 'frame> AsGlesFrame<'frame> for TtyFrame<'render, 'alloc, 'frame> { + fn as_gles_frame(&mut self) -> &mut GlesFrame<'frame> { + self.as_mut() + } +} -- cgit