cosmic-comp/src/backend/render/element.rs

469 lines
16 KiB
Rust
Raw Normal View History

use crate::{
backend::render::{GlMultiError, wayland::SurfaceRenderElement},
shell::{CosmicMappedRenderElement, WorkspaceRenderElement},
};
2022-11-17 20:32:54 +01:00
#[cfg(feature = "debug")]
use smithay::backend::renderer::element::texture::TextureRenderElement;
2022-11-17 20:32:54 +01:00
use smithay::{
backend::{
allocator::dmabuf::Dmabuf,
renderer::{
Bind, Blit, ExportMem, ImportAll, ImportMem, Offscreen, Renderer,
element::{
Element, Id, Kind, RenderElement, UnderlyingStorage,
memory::MemoryRenderBufferRenderElement,
utils::{CropRenderElement, Relocate, RelocateRenderElement, RescaleRenderElement},
},
gles::{GlesError, GlesRenderbuffer, GlesTexture, element::TextureShaderElement},
glow::{GlowFrame, GlowRenderer},
utils::{CommitCounter, DamageSet, OpaqueRegions},
},
2022-11-17 20:32:54 +01:00
},
2026-01-22 16:10:57 +01:00
utils::{
Buffer as BufferCoords, Logical, Physical, Point, Rectangle, Scale, user_data::UserDataMap,
},
2022-11-17 20:32:54 +01:00
};
2025-10-16 18:53:57 +02:00
use super::{GlMultiRenderer, cursor::CursorRenderElement};
2022-11-17 20:32:54 +01:00
pub enum CosmicElement<R>
where
R: AsGlowRenderer,
2025-03-11 19:14:49 +01:00
R::TextureId: 'static,
CosmicMappedRenderElement<R>: RenderElement<R>,
2022-11-17 20:32:54 +01:00
{
Workspace(
RelocateRenderElement<CropRenderElement<RescaleRenderElement<WorkspaceRenderElement<R>>>>,
),
Cursor(RescaleRenderElement<RelocateRenderElement<CursorRenderElement<R>>>),
Dnd(SurfaceRenderElement<R>),
MoveGrab(RescaleRenderElement<CosmicMappedRenderElement<R>>),
Postprocess(
CropRenderElement<RelocateRenderElement<RescaleRenderElement<TextureShaderElement>>>,
2024-04-24 17:25:33 +02:00
),
2025-02-13 21:09:13 +01:00
Zoom(MemoryRenderBufferRenderElement<R>),
2022-11-17 20:32:54 +01:00
#[cfg(feature = "debug")]
2023-05-03 19:47:48 +02:00
Egui(TextureRenderElement<GlesTexture>),
2022-11-17 20:32:54 +01:00
}
impl<R> Element for CosmicElement<R>
where
R: AsGlowRenderer,
2025-03-11 19:14:49 +01:00
R::TextureId: 'static,
CosmicMappedRenderElement<R>: RenderElement<R>,
2022-11-17 20:32:54 +01:00
{
2024-03-12 19:42:48 +01:00
fn id(&self) -> &Id {
2022-11-17 20:32:54 +01:00
match self {
CosmicElement::Workspace(elem) => elem.id(),
CosmicElement::Cursor(elem) => elem.id(),
2024-03-12 19:42:48 +01:00
CosmicElement::Dnd(elem) => elem.id(),
2022-11-17 20:32:54 +01:00
CosmicElement::MoveGrab(elem) => elem.id(),
CosmicElement::Postprocess(elem) => elem.id(),
2025-02-13 21:09:13 +01:00
CosmicElement::Zoom(elem) => elem.id(),
2022-11-17 20:32:54 +01:00
#[cfg(feature = "debug")]
CosmicElement::Egui(elem) => elem.id(),
}
}
2024-03-12 19:42:48 +01:00
fn current_commit(&self) -> CommitCounter {
2022-11-17 20:32:54 +01:00
match self {
CosmicElement::Workspace(elem) => elem.current_commit(),
CosmicElement::Cursor(elem) => elem.current_commit(),
2024-03-12 19:42:48 +01:00
CosmicElement::Dnd(elem) => elem.current_commit(),
2022-11-17 20:32:54 +01:00
CosmicElement::MoveGrab(elem) => elem.current_commit(),
CosmicElement::Postprocess(elem) => elem.current_commit(),
2025-02-13 21:09:13 +01:00
CosmicElement::Zoom(elem) => elem.current_commit(),
2022-11-17 20:32:54 +01:00
#[cfg(feature = "debug")]
CosmicElement::Egui(elem) => elem.current_commit(),
}
}
fn src(&self) -> Rectangle<f64, smithay::utils::Buffer> {
match self {
CosmicElement::Workspace(elem) => elem.src(),
CosmicElement::Cursor(elem) => elem.src(),
2024-03-12 19:42:48 +01:00
CosmicElement::Dnd(elem) => elem.src(),
2022-11-17 20:32:54 +01:00
CosmicElement::MoveGrab(elem) => elem.src(),
CosmicElement::Postprocess(elem) => elem.src(),
2025-02-13 21:09:13 +01:00
CosmicElement::Zoom(elem) => elem.src(),
2022-11-17 20:32:54 +01:00
#[cfg(feature = "debug")]
CosmicElement::Egui(elem) => elem.src(),
}
}
fn geometry(&self, scale: Scale<f64>) -> Rectangle<i32, Physical> {
match self {
CosmicElement::Workspace(elem) => elem.geometry(scale),
CosmicElement::Cursor(elem) => elem.geometry(scale),
2024-03-12 19:42:48 +01:00
CosmicElement::Dnd(elem) => elem.geometry(scale),
2022-11-17 20:32:54 +01:00
CosmicElement::MoveGrab(elem) => elem.geometry(scale),
CosmicElement::Postprocess(elem) => elem.geometry(scale),
2025-02-13 21:09:13 +01:00
CosmicElement::Zoom(elem) => elem.geometry(scale),
2022-11-17 20:32:54 +01:00
#[cfg(feature = "debug")]
CosmicElement::Egui(elem) => elem.geometry(scale),
}
}
fn location(&self, scale: Scale<f64>) -> Point<i32, Physical> {
match self {
CosmicElement::Workspace(elem) => elem.location(scale),
CosmicElement::Cursor(elem) => elem.location(scale),
2024-03-12 19:42:48 +01:00
CosmicElement::Dnd(elem) => elem.location(scale),
2022-11-17 20:32:54 +01:00
CosmicElement::MoveGrab(elem) => elem.location(scale),
CosmicElement::Postprocess(elem) => elem.location(scale),
2025-02-13 21:09:13 +01:00
CosmicElement::Zoom(elem) => elem.location(scale),
2022-11-17 20:32:54 +01:00
#[cfg(feature = "debug")]
CosmicElement::Egui(elem) => elem.location(scale),
}
}
fn transform(&self) -> smithay::utils::Transform {
match self {
CosmicElement::Workspace(elem) => elem.transform(),
CosmicElement::Cursor(elem) => elem.transform(),
2024-03-12 19:42:48 +01:00
CosmicElement::Dnd(elem) => elem.transform(),
2022-11-17 20:32:54 +01:00
CosmicElement::MoveGrab(elem) => elem.transform(),
CosmicElement::Postprocess(elem) => elem.transform(),
2025-02-13 21:09:13 +01:00
CosmicElement::Zoom(elem) => elem.transform(),
2022-11-17 20:32:54 +01:00
#[cfg(feature = "debug")]
CosmicElement::Egui(elem) => elem.transform(),
}
}
fn damage_since(
&self,
scale: Scale<f64>,
2024-03-12 19:42:48 +01:00
commit: Option<CommitCounter>,
2024-04-08 16:55:41 -07:00
) -> DamageSet<i32, Physical> {
2022-11-17 20:32:54 +01:00
match self {
CosmicElement::Workspace(elem) => elem.damage_since(scale, commit),
CosmicElement::Cursor(elem) => elem.damage_since(scale, commit),
2024-03-12 19:42:48 +01:00
CosmicElement::Dnd(elem) => elem.damage_since(scale, commit),
2022-11-17 20:32:54 +01:00
CosmicElement::MoveGrab(elem) => elem.damage_since(scale, commit),
CosmicElement::Postprocess(elem) => elem.damage_since(scale, commit),
2025-02-13 21:09:13 +01:00
CosmicElement::Zoom(elem) => elem.damage_since(scale, commit),
2022-11-17 20:32:54 +01:00
#[cfg(feature = "debug")]
CosmicElement::Egui(elem) => elem.damage_since(scale, commit),
}
}
fn opaque_regions(&self, scale: Scale<f64>) -> OpaqueRegions<i32, Physical> {
2022-11-17 20:32:54 +01:00
match self {
CosmicElement::Workspace(elem) => elem.opaque_regions(scale),
CosmicElement::Cursor(elem) => elem.opaque_regions(scale),
2024-03-12 19:42:48 +01:00
CosmicElement::Dnd(elem) => elem.opaque_regions(scale),
2022-11-17 20:32:54 +01:00
CosmicElement::MoveGrab(elem) => elem.opaque_regions(scale),
CosmicElement::Postprocess(elem) => elem.opaque_regions(scale),
2025-02-13 21:09:13 +01:00
CosmicElement::Zoom(elem) => elem.opaque_regions(scale),
2022-11-17 20:32:54 +01:00
#[cfg(feature = "debug")]
CosmicElement::Egui(elem) => elem.opaque_regions(scale),
}
}
2023-05-12 20:01:37 +02:00
fn alpha(&self) -> f32 {
match self {
CosmicElement::Workspace(elem) => elem.alpha(),
CosmicElement::Cursor(elem) => elem.alpha(),
2024-03-12 19:42:48 +01:00
CosmicElement::Dnd(elem) => elem.alpha(),
2023-05-12 20:01:37 +02:00
CosmicElement::MoveGrab(elem) => elem.alpha(),
CosmicElement::Postprocess(elem) => elem.alpha(),
2025-02-13 21:09:13 +01:00
CosmicElement::Zoom(elem) => elem.alpha(),
2023-05-12 20:01:37 +02:00
#[cfg(feature = "debug")]
CosmicElement::Egui(elem) => elem.alpha(),
}
}
fn kind(&self) -> Kind {
match self {
CosmicElement::Workspace(elem) => elem.kind(),
CosmicElement::Cursor(elem) => elem.kind(),
CosmicElement::Dnd(elem) => elem.kind(),
CosmicElement::MoveGrab(elem) => elem.kind(),
CosmicElement::Postprocess(elem) => elem.kind(),
2025-02-13 21:09:13 +01:00
CosmicElement::Zoom(elem) => elem.kind(),
#[cfg(feature = "debug")]
CosmicElement::Egui(elem) => elem.kind(),
}
}
2026-01-22 16:10:57 +01:00
fn is_framebuffer_effect(&self) -> bool {
match self {
CosmicElement::Workspace(elem) => elem.is_framebuffer_effect(),
CosmicElement::Cursor(elem) => elem.is_framebuffer_effect(),
CosmicElement::Dnd(elem) => elem.is_framebuffer_effect(),
CosmicElement::MoveGrab(elem) => elem.is_framebuffer_effect(),
CosmicElement::Postprocess(elem) => elem.is_framebuffer_effect(),
CosmicElement::Zoom(elem) => elem.is_framebuffer_effect(),
#[cfg(feature = "debug")]
CosmicElement::Egui(elem) => elem.is_framebuffer_effect(),
}
}
2022-11-17 20:32:54 +01:00
}
impl<R> RenderElement<R> for CosmicElement<R>
where
R: AsGlowRenderer,
2025-03-11 19:14:49 +01:00
R::TextureId: 'static,
CosmicMappedRenderElement<R>: RenderElement<R>,
{
2024-08-30 13:58:49 +01:00
fn draw(
2022-11-17 20:32:54 +01:00
&self,
2025-03-11 19:14:49 +01:00
frame: &mut R::Frame<'_, '_>,
2022-12-27 18:27:29 +01:00
src: Rectangle<f64, BufferCoords>,
dst: Rectangle<i32, Physical>,
2022-11-17 20:32:54 +01:00
damage: &[Rectangle<i32, Physical>],
2024-06-18 19:23:16 -07:00
opaque_regions: &[Rectangle<i32, Physical>],
2026-01-22 16:10:57 +01:00
cache: Option<&UserDataMap>,
) -> Result<(), R::Error> {
2022-11-17 20:32:54 +01:00
match self {
2026-01-22 16:10:57 +01:00
CosmicElement::Workspace(elem) => {
elem.draw(frame, src, dst, damage, opaque_regions, cache)
}
CosmicElement::Cursor(elem) => {
elem.draw(frame, src, dst, damage, opaque_regions, cache)
}
CosmicElement::Dnd(elem) => elem.draw(frame, src, dst, damage, opaque_regions, cache),
CosmicElement::MoveGrab(elem) => {
elem.draw(frame, src, dst, damage, opaque_regions, cache)
}
CosmicElement::Postprocess(elem) => {
let glow_frame = R::glow_frame_mut(frame);
RenderElement::<GlowRenderer>::draw(
elem,
glow_frame,
src,
dst,
damage,
opaque_regions,
2026-01-22 16:10:57 +01:00
cache,
)
.map_err(R::from_gles_error)
2024-04-24 17:25:33 +02:00
}
2026-01-22 16:10:57 +01:00
CosmicElement::Zoom(elem) => elem.draw(frame, src, dst, damage, opaque_regions, cache),
2022-11-17 20:32:54 +01:00
#[cfg(feature = "debug")]
CosmicElement::Egui(elem) => {
let glow_frame = R::glow_frame_mut(frame);
RenderElement::<GlowRenderer>::draw(
elem,
glow_frame,
src,
dst,
damage,
opaque_regions,
2026-01-22 16:10:57 +01:00
cache,
)
.map_err(R::from_gles_error)
2022-11-17 20:32:54 +01:00
}
}
}
fn underlying_storage(&self, renderer: &mut R) -> Option<UnderlyingStorage<'_>> {
2022-11-17 20:32:54 +01:00
match self {
CosmicElement::Workspace(elem) => elem.underlying_storage(renderer),
CosmicElement::Cursor(elem) => elem.underlying_storage(renderer),
2024-03-12 19:42:48 +01:00
CosmicElement::Dnd(elem) => elem.underlying_storage(renderer),
2022-11-17 20:32:54 +01:00
CosmicElement::MoveGrab(elem) => elem.underlying_storage(renderer),
CosmicElement::Postprocess(elem) => {
2024-04-24 17:25:33 +02:00
let glow_renderer = renderer.glow_renderer_mut();
elem.underlying_storage(glow_renderer)
2024-04-24 17:25:33 +02:00
}
2025-02-13 21:09:13 +01:00
CosmicElement::Zoom(elem) => elem.underlying_storage(renderer),
2022-11-17 20:32:54 +01:00
#[cfg(feature = "debug")]
CosmicElement::Egui(elem) => {
let glow_renderer = renderer.glow_renderer_mut();
elem.underlying_storage(glow_renderer)
2022-11-17 20:32:54 +01:00
}
}
}
2026-01-22 16:10:57 +01:00
fn capture_framebuffer(
&self,
frame: &mut <R>::Frame<'_, '_>,
src: Rectangle<f64, BufferCoords>,
dst: Rectangle<i32, Physical>,
cache: &UserDataMap,
) -> Result<(), <R>::Error> {
match self {
CosmicElement::Workspace(elem) => elem.capture_framebuffer(frame, src, dst, cache),
CosmicElement::Cursor(elem) => elem.capture_framebuffer(frame, src, dst, cache),
CosmicElement::Dnd(elem) => elem.capture_framebuffer(frame, src, dst, cache),
CosmicElement::MoveGrab(elem) => elem.capture_framebuffer(frame, src, dst, cache),
CosmicElement::Postprocess(elem) => {
let glow_frame = R::glow_frame_mut(frame);
RenderElement::<GlowRenderer>::capture_framebuffer(
elem, glow_frame, src, dst, cache,
)
.map_err(R::from_gles_error)
2026-01-22 16:10:57 +01:00
}
CosmicElement::Zoom(elem) => elem.capture_framebuffer(frame, src, dst, cache),
#[cfg(feature = "debug")]
CosmicElement::Egui(elem) => {
let glow_frame = R::glow_frame_mut(frame);
RenderElement::<GlowRenderer>::capture_framebuffer(
elem, glow_frame, src, dst, cache,
)
.map_err(R::from_gles_error)
2026-01-22 16:10:57 +01:00
}
}
}
2022-11-17 20:32:54 +01:00
}
impl<R> From<CropRenderElement<RescaleRenderElement<WorkspaceRenderElement<R>>>>
for CosmicElement<R>
2022-11-17 20:32:54 +01:00
where
R: AsGlowRenderer,
2025-03-11 19:14:49 +01:00
R::TextureId: 'static,
CosmicMappedRenderElement<R>: RenderElement<R>,
2022-11-17 20:32:54 +01:00
{
fn from(elem: CropRenderElement<RescaleRenderElement<WorkspaceRenderElement<R>>>) -> Self {
Self::Workspace(RelocateRenderElement::from_element(
elem,
(0, 0),
Relocate::Relative,
))
2022-11-17 20:32:54 +01:00
}
}
2025-02-13 21:09:13 +01:00
impl<R> From<MemoryRenderBufferRenderElement<R>> for CosmicElement<R>
where
R: AsGlowRenderer,
2025-03-11 19:14:49 +01:00
R::TextureId: 'static,
2025-02-13 21:09:13 +01:00
CosmicMappedRenderElement<R>: RenderElement<R>,
{
fn from(value: MemoryRenderBufferRenderElement<R>) -> Self {
Self::Zoom(value)
}
2022-11-17 20:32:54 +01:00
}
#[cfg(feature = "debug")]
2023-05-03 19:47:48 +02:00
impl<R> From<TextureRenderElement<GlesTexture>> for CosmicElement<R>
2022-11-17 20:32:54 +01:00
where
R: AsGlowRenderer,
2025-03-11 19:14:49 +01:00
R::TextureId: 'static,
CosmicMappedRenderElement<R>: RenderElement<R>,
2022-11-17 20:32:54 +01:00
{
2023-05-03 19:47:48 +02:00
fn from(elem: TextureRenderElement<GlesTexture>) -> Self {
2022-11-17 20:32:54 +01:00
Self::Egui(elem)
}
}
pub trait AsGlowRenderer:
Renderer
+ Offscreen<GlesTexture>
+ Offscreen<GlesRenderbuffer>
+ ImportAll
+ ImportMem
+ ExportMem
+ Bind<Dmabuf>
+ Blit
2022-11-17 20:32:54 +01:00
{
fn glow_renderer(&self) -> &GlowRenderer;
fn glow_renderer_mut(&mut self) -> &mut GlowRenderer;
2025-03-11 19:14:49 +01:00
fn glow_frame<'a, 'frame, 'buffer>(
frame: &'a Self::Frame<'frame, 'buffer>,
) -> &'a GlowFrame<'frame, 'buffer>;
fn glow_frame_mut<'a, 'frame, 'buffer>(
frame: &'a mut Self::Frame<'frame, 'buffer>,
) -> &'a mut GlowFrame<'frame, 'buffer>;
fn from_gles_error(err: GlesError) -> Self::Error;
2022-11-17 20:32:54 +01:00
}
impl AsGlowRenderer for GlowRenderer {
fn glow_renderer(&self) -> &GlowRenderer {
self
}
fn glow_renderer_mut(&mut self) -> &mut GlowRenderer {
self
}
2025-03-11 19:14:49 +01:00
fn glow_frame<'a, 'frame, 'buffer>(
frame: &'a Self::Frame<'frame, 'buffer>,
) -> &'a GlowFrame<'frame, 'buffer> {
frame
}
2025-03-11 19:14:49 +01:00
fn glow_frame_mut<'a, 'frame, 'buffer>(
frame: &'a mut Self::Frame<'frame, 'buffer>,
) -> &'a mut GlowFrame<'frame, 'buffer> {
frame
}
fn from_gles_error(err: GlesError) -> Self::Error {
err
}
2022-11-17 20:32:54 +01:00
}
2025-10-16 13:50:32 +02:00
impl AsGlowRenderer for GlMultiRenderer<'_> {
2022-11-17 20:32:54 +01:00
fn glow_renderer(&self) -> &GlowRenderer {
self.as_ref()
}
fn glow_renderer_mut(&mut self) -> &mut GlowRenderer {
self.as_mut()
}
2025-03-11 19:14:49 +01:00
fn glow_frame<'b, 'frame, 'buffer>(
frame: &'b Self::Frame<'frame, 'buffer>,
) -> &'b GlowFrame<'frame, 'buffer> {
frame.as_ref()
2022-11-17 20:32:54 +01:00
}
2025-03-11 19:14:49 +01:00
fn glow_frame_mut<'b, 'frame, 'buffer>(
frame: &'b mut Self::Frame<'frame, 'buffer>,
) -> &'b mut GlowFrame<'frame, 'buffer> {
frame.as_mut()
2022-11-17 20:32:54 +01:00
}
fn from_gles_error(err: GlesError) -> Self::Error {
GlMultiError::Render(err)
}
2022-11-17 20:32:54 +01:00
}
2024-03-12 19:42:48 +01:00
pub struct DamageElement {
id: Id,
geometry: Rectangle<i32, Logical>,
}
impl DamageElement {
pub fn new(geometry: Rectangle<i32, Logical>) -> DamageElement {
DamageElement {
id: Id::new(),
geometry,
}
}
}
impl Element for DamageElement {
fn id(&self) -> &Id {
&self.id
}
fn current_commit(&self) -> CommitCounter {
CommitCounter::default()
}
fn src(&self) -> Rectangle<f64, BufferCoords> {
Rectangle::from_size((1.0, 1.0).into())
2024-03-12 19:42:48 +01:00
}
fn geometry(&self, scale: Scale<f64>) -> Rectangle<i32, Physical> {
self.geometry.to_f64().to_physical(scale).to_i32_round()
}
fn damage_since(
&self,
scale: Scale<f64>,
_commit: Option<CommitCounter>,
2024-04-08 16:55:41 -07:00
) -> DamageSet<i32, Physical> {
2025-10-16 13:50:32 +02:00
DamageSet::from_slice(&[Rectangle::from_size(self.geometry(scale).size)])
2024-03-12 19:42:48 +01:00
}
}
impl<R: Renderer> RenderElement<R> for DamageElement {
fn draw(
&self,
2025-03-11 19:14:49 +01:00
_frame: &mut R::Frame<'_, '_>,
2024-03-12 19:42:48 +01:00
_src: Rectangle<f64, BufferCoords>,
_dst: Rectangle<i32, Physical>,
_damage: &[Rectangle<i32, Physical>],
2024-06-18 19:23:16 -07:00
_opaque_regions: &[Rectangle<i32, Physical>],
2026-01-22 16:10:57 +01:00
_cache: Option<&UserDataMap>,
2025-03-11 19:14:49 +01:00
) -> Result<(), R::Error> {
2024-03-12 19:42:48 +01:00
Ok(())
}
}