render: Use custom render element macro

This commit is contained in:
Ottatop 2024-05-19 19:34:29 -05:00 committed by Ottatop
parent 4095abadf3
commit a251c96278
7 changed files with 411 additions and 8 deletions

View file

@ -108,7 +108,7 @@ const SUPPORTED_FORMATS: &[Fourcc] = &[
const SUPPORTED_FORMATS_8BIT_ONLY: &[Fourcc] = &[Fourcc::Abgr8888, Fourcc::Argb8888];
/// A [`MultiRenderer`] that uses the [`GbmGlesBackend`].
type UdevRenderer<'a> = MultiRenderer<
pub type UdevRenderer<'a> = MultiRenderer<
'a,
'a,
GbmGlesBackend<GlesRenderer, DrmDeviceFd>,
@ -866,6 +866,12 @@ fn render_frame<'a>(
}
impl Udev {
pub fn renderer(&mut self) -> UdevRenderer<'_> {
self.gpu_manager
.single_renderer(&self.primary_gpu)
.expect("failed to create multirenderer")
}
/// A GPU was plugged in.
fn device_added(
&mut self,

View file

@ -1,5 +1,7 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pub mod transaction;
use std::{collections::HashMap, time::Duration};
use pinnacle_api_defs::pinnacle::layout::v0alpha1::{layout_request::Geometries, LayoutResponse};

18
src/layout/transaction.rs Normal file
View file

@ -0,0 +1,18 @@
use std::collections::HashMap;
use smithay::{
backend::renderer::gles::GlesTexture,
utils::{Logical, Point, Serial},
};
use crate::window::WindowElement;
pub struct LayoutTransaction {
from: Vec<(GlesTexture)>,
to: HashMap<WindowElement, PendingLayoutState>,
}
pub struct PendingLayoutState {
serial: Serial,
loc: Point<i32, Logical>,
}

View file

@ -4,7 +4,10 @@ use std::{ops::Deref, sync::Mutex};
use smithay::{
backend::renderer::{
element::{surface::WaylandSurfaceRenderElement, AsRenderElements, RenderElementStates},
element::{
surface::WaylandSurfaceRenderElement, AsRenderElements, Element, RenderElementStates,
},
gles::{GlesRenderer, GlesTexture},
ImportAll, ImportMem, Renderer, Texture,
},
desktop::{
@ -26,21 +29,35 @@ use smithay::{
use crate::{
backend::Backend,
pinnacle_render_elements,
state::{State, WithState},
window::WindowElement,
};
use self::pointer::{PointerElement, PointerRenderElement};
use self::{
pointer::{PointerElement, PointerRenderElement},
texture::CommonTextureRenderElement,
};
pub mod pointer;
pub mod render_elements;
pub mod texture;
pub const CLEAR_COLOR: [f32; 4] = [0.6, 0.6, 0.6, 1.0];
pub const CLEAR_COLOR_LOCKED: [f32; 4] = [0.2, 0.0, 0.3, 1.0];
render_elements! {
pub OutputRenderElement<R> where R: ImportAll + ImportMem;
Surface = WaylandSurfaceRenderElement<R>,
Pointer = PointerRenderElement<R>,
// render_elements! {
// pub OutputRenderElement<R> where R: ImportAll + ImportMem;
// Surface = WaylandSurfaceRenderElement<R>,
// Pointer = PointerRenderElement<R>,
// }
pinnacle_render_elements! {
#[derive(Debug)]
pub enum OutputRenderElement<R> {
Surface = WaylandSurfaceRenderElement<R>,
Pointer = PointerRenderElement<R>,
}
}
impl<R> AsRenderElements<R> for WindowElement
@ -173,7 +190,7 @@ pub fn pointer_render_elements<R>(
pointer_element: &PointerElement<<R as Renderer>::TextureId>,
) -> Vec<OutputRenderElement<R>>
where
R: Renderer + ImportAll,
R: Renderer + ImportAll + ImportMem,
<R as Renderer>::TextureId: Clone + 'static,
{
let mut output_render_elements = Vec::new();
@ -349,3 +366,32 @@ impl State {
}
}
}
impl Backend {
pub fn render_to_texture(
&mut self,
window: &WindowElement,
scale: f64,
) -> Vec<(GlesTexture, Point<i32, Physical>)> {
let render_to_texture = |renderer: &mut GlesRenderer, window: &WindowElement| {
let elements = window.render_elements::<WaylandSurfaceRenderElement<GlesRenderer>>(
renderer,
(0, 0).into(),
scale.into(),
1.0,
);
elements
.into_iter()
.map(|elem| (elem.texture().clone(), elem.location(scale.into())))
.collect()
};
match self {
Backend::Winit(winit) => render_to_texture(winit.backend.renderer(), window),
Backend::Udev(udev) => render_to_texture(udev.renderer().as_mut(), window),
#[cfg(feature = "testing")]
Backend::Dummy(_) => Vec::new(),
}
}
}

View file

@ -50,6 +50,7 @@ impl<T: Texture> PointerElement<T> {
}
render_elements! {
#[derive(Debug)]
pub PointerRenderElement<R> where R: ImportAll;
Surface=WaylandSurfaceRenderElement<R>,
Texture=TextureRenderElement<<R as Renderer>::TextureId>,

View file

@ -0,0 +1,229 @@
/// A custom implementation of [`smithay::render_elements`] that is not generic but rather
/// implements over the three used renderers.
///
/// This is needed to allow GlesTextures to be easily rendered on winit and udev.
///
/// Also idea from Niri. Ya know this whole compositor is slowly inching towards
/// being a Niri clone lol
#[macro_export]
macro_rules! pinnacle_render_elements {
(
$(#[$attr:meta])*
$vis:vis enum $name:ident {
$($variant:ident = $type:ty),+ $(,)?
}
) => {
$(#[$attr])*
$vis enum $name {
$($variant($type)),+
}
$(impl From<$type> for $name {
fn from(x: $type) -> Self {
Self::$variant(x)
}
})+
$crate::pinnacle_render_elements! {
@impl $name ($name) () => { $($variant = $type),+ }
}
};
(
$(#[$attr:meta])*
$vis:vis enum $name:ident<$generic_name:ident> {
$($variant:ident = $type:ty),+ $(,)?
}
) => {
$(#[$attr])*
$vis enum $name<$generic_name>
where
$generic_name: ::smithay::backend::renderer::Renderer + ::smithay::backend::renderer::ImportAll + ::smithay::backend::renderer::ImportMem,
$generic_name::TextureId: 'static,
{
$($variant($type)),+
}
$(impl<$generic_name> From<$type> for $name<$generic_name>
where
$generic_name: ::smithay::backend::renderer::Renderer + ::smithay::backend::renderer::ImportAll + ::smithay::backend::renderer::ImportMem,
$generic_name::TextureId: 'static,
{
fn from(x: $type) -> Self {
Self::$variant(x)
}
})+
$crate::pinnacle_render_elements! {
@impl $name () ($name<$generic_name>) => { $($variant = $type),+ }
}
};
(@impl $name:ident ($($name_no_generic:ident)?) ($($name_generic:ident<$generic:ident>)?) => {
$($variant:ident = $type:ty),+
}) => {
impl$(<$generic>)? ::smithay::backend::renderer::element::Element for $name$(<$generic>)?
$(where
$generic: ::smithay::backend::renderer::Renderer + ::smithay::backend::renderer::ImportAll + ::smithay::backend::renderer::ImportMem,
$generic::TextureId: 'static,)?
{
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<f64>
) -> ::smithay::utils::Rectangle<i32, smithay::utils::Physical> {
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<f64, ::smithay::utils::Buffer> {
match self {
$($name::$variant(elem) => elem.src()),+
}
}
fn damage_since(
&self,
scale: ::smithay::utils::Scale<f64>,
commit: ::std::option::Option<::smithay::backend::renderer::utils::CommitCounter>,
) -> ::smithay::backend::renderer::utils::DamageSet<i32, ::smithay::utils::Physical> {
match self {
$($name::$variant(elem) => elem.damage_since(scale, commit)),+
}
}
fn opaque_regions(
&self,
scale: ::smithay::utils::Scale<f64>,
) -> ::smithay::backend::renderer::utils::OpaqueRegions<i32, ::smithay::utils::Physical> {
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<::smithay::backend::renderer::gles::GlesRenderer>
for $($name_generic<::smithay::backend::renderer::gles::GlesRenderer>)? $($name_no_generic)?
{
fn draw(
&self,
frame: &mut ::smithay::backend::renderer::gles::GlesFrame<'_>,
src: ::smithay::utils::Rectangle<f64, ::smithay::utils::Buffer>,
dst: ::smithay::utils::Rectangle<i32, ::smithay::utils::Physical>,
damage: &[::smithay::utils::Rectangle<i32, ::smithay::utils::Physical>],
) -> ::std::result::Result<(), ::smithay::backend::renderer::gles::GlesError> {
match self {
$($name::$variant(elem) => {
::smithay::backend::renderer::element::RenderElement::<
::smithay::backend::renderer::gles::GlesRenderer
>::draw(elem, frame, src, dst, damage)
})+
}
}
fn underlying_storage(
&self,
renderer: &mut ::smithay::backend::renderer::gles::GlesRenderer
) -> ::std::option::Option<::smithay::backend::renderer::element::UnderlyingStorage> {
match self {
$($name::$variant(elem) => elem.underlying_storage(renderer)),+
}
}
}
impl<'a> ::smithay::backend::renderer::element::RenderElement<$crate::backend::udev::UdevRenderer<'a>>
for $($name_generic<$crate::backend::udev::UdevRenderer<'a>>)? $($name_no_generic)?
{
fn draw(
&self,
frame: &mut <$crate::backend::udev::UdevRenderer<'a> as ::smithay::backend::renderer::Renderer>::Frame<'_>,
src: ::smithay::utils::Rectangle<f64, ::smithay::utils::Buffer>,
dst: ::smithay::utils::Rectangle<i32, ::smithay::utils::Physical>,
damage: &[::smithay::utils::Rectangle<i32, ::smithay::utils::Physical>],
) -> ::std::result::Result<
(),
<$crate::backend::udev::UdevRenderer as ::smithay::backend::renderer::Renderer>::Error,
> {
match self {
$($name::$variant(elem) => {
::smithay::backend::renderer::element::RenderElement::<
$crate::backend::udev::UdevRenderer
>::draw(elem, frame, src, dst, damage)
})+
}
}
fn underlying_storage(
&self,
renderer: &mut $crate::backend::udev::UdevRenderer<'a>,
) -> ::std::option::Option<::smithay::backend::renderer::element::UnderlyingStorage> {
match self {
$($name::$variant(elem) => elem.underlying_storage(renderer)),+
}
}
}
#[cfg(feature = "testing")]
impl ::smithay::backend::renderer::element::RenderElement<::smithay::backend::renderer::test::DummyRenderer>
for $($name_generic<::smithay::backend::renderer::test::DummyRenderer>)? $($name_no_generic)?
{
fn draw(
&self,
frame: &mut <::smithay::backend::renderer::test::DummyRenderer as ::smithay::backend::renderer::Renderer>::Frame<'_>,
src: ::smithay::utils::Rectangle<f64, ::smithay::utils::Buffer>,
dst: ::smithay::utils::Rectangle<i32, ::smithay::utils::Physical>,
damage: &[::smithay::utils::Rectangle<i32, ::smithay::utils::Physical>],
) -> ::std::result::Result<
(),
<::smithay::backend::renderer::test::DummyRenderer as ::smithay::backend::renderer::Renderer>::Error,
> {
match self {
$($name::$variant(elem) => {
::smithay::backend::renderer::element::RenderElement::<
::smithay::backend::renderer::test::DummyRenderer
>::draw(elem, frame, src, dst, damage)
})+
}
}
fn underlying_storage(
&self,
renderer: &mut ::smithay::backend::renderer::test::DummyRenderer,
) -> ::std::option::Option<::smithay::backend::renderer::element::UnderlyingStorage> {
match self {
$($name::$variant(elem) => elem.underlying_storage(renderer)),+
}
}
}
}
}

101
src/render/texture.rs Normal file
View file

@ -0,0 +1,101 @@
use smithay::{
backend::renderer::{
element::{self, texture::TextureRenderElement, Element, RenderElement},
gles::{GlesRenderer, GlesTexture},
utils::{CommitCounter, DamageSet, OpaqueRegions},
Renderer,
},
utils::{Buffer, Physical, Rectangle, Scale},
};
use crate::backend::udev::UdevRenderer;
/// TODO: docs
pub struct CommonTextureRenderElement(TextureRenderElement<GlesTexture>);
impl Element for CommonTextureRenderElement {
fn id(&self) -> &element::Id {
self.0.id()
}
fn current_commit(&self) -> CommitCounter {
self.0.current_commit()
}
fn src(&self) -> Rectangle<f64, Buffer> {
self.0.src()
}
fn geometry(&self, scale: Scale<f64>) -> Rectangle<i32, Physical> {
self.0.geometry(scale)
}
fn location(&self, scale: Scale<f64>) -> smithay::utils::Point<i32, Physical> {
self.0.location(scale)
}
fn transform(&self) -> smithay::utils::Transform {
self.0.transform()
}
fn damage_since(
&self,
scale: Scale<f64>,
commit: Option<CommitCounter>,
) -> DamageSet<i32, Physical> {
self.0.damage_since(scale, commit)
}
fn opaque_regions(&self, scale: Scale<f64>) -> OpaqueRegions<i32, Physical> {
self.0.opaque_regions(scale)
}
fn alpha(&self) -> f32 {
self.0.alpha()
}
fn kind(&self) -> element::Kind {
self.0.kind()
}
}
impl RenderElement<GlesRenderer> for CommonTextureRenderElement {
fn draw(
&self,
frame: &mut <GlesRenderer as Renderer>::Frame<'_>,
src: Rectangle<f64, Buffer>,
dst: Rectangle<i32, Physical>,
damage: &[Rectangle<i32, Physical>],
) -> Result<(), <GlesRenderer as Renderer>::Error> {
RenderElement::<GlesRenderer>::draw(&self.0, frame, src, dst, damage)
}
fn underlying_storage(
&self,
renderer: &mut GlesRenderer,
) -> Option<element::UnderlyingStorage<'_>> {
let _ = renderer;
None
}
}
impl<'a> RenderElement<UdevRenderer<'a>> for CommonTextureRenderElement {
fn draw(
&self,
frame: &mut <UdevRenderer<'a> as Renderer>::Frame<'_>,
src: Rectangle<f64, Buffer>,
dst: Rectangle<i32, Physical>,
damage: &[Rectangle<i32, Physical>],
) -> Result<(), <UdevRenderer<'a> as Renderer>::Error> {
RenderElement::<GlesRenderer>::draw(&self.0, frame.as_mut(), src, dst, damage)?;
Ok(())
}
fn underlying_storage(
&self,
renderer: &mut UdevRenderer<'a>,
) -> Option<element::UnderlyingStorage<'_>> {
let _ = renderer;
None
}
}