diff --git a/src/state.rs b/src/state.rs index f6095892..cd47bd99 100644 --- a/src/state.rs +++ b/src/state.rs @@ -1,5 +1,6 @@ mod animations; mod connectors; +mod rendering; pub(crate) use animations::LayoutAnimationCandidate; pub use connectors::{ConnectorData, DrmDevData, OutputData}; @@ -19,11 +20,7 @@ use { backends::dummy::DummyBackend, cli::RunArgs, client::{Client, ClientId, Clients, NUM_CACHED_SERIAL_RANGES, SerialRange}, - clientmem::ClientMemOffset, - cmm::{ - cmm_description::ColorDescription, cmm_manager::ColorManager, - cmm_render_intent::RenderIntent, - }, + cmm::cmm_manager::ColorManager, compositor::LIBEI_SOCKET, config::ConfigProxy, copy_device::CopyDeviceRegistry, @@ -39,14 +36,8 @@ use { ei_client::{EiClient, EiClients}, }, eventfd_cache::EventfdCache, - fixed::Fixed, forker::ForkerProxy, - format::Format, - gfx_api::{ - AcquireSync, AlphaMode, BufferResv, FdSync, GfxApi, GfxBlendBuffer, GfxContext, - GfxError, GfxFramebuffer, GfxTexture, PendingShmTransfer, ReleaseSync, - STAGING_DOWNLOAD, SampleRect, - }, + gfx_api::{GfxApi, GfxContext, GfxError}, gfx_apis::create_gfx_context, globals::{Globals, GlobalsError, RemovableWaylandGlobal, WaylandGlobal}, icons::Icons, @@ -83,7 +74,6 @@ use { workspace_manager::WorkspaceManagerState, xdg_activation_token_v1::ActivationToken, zwlr_foreign_toplevel_manager_v1::ZwlrForeignToplevelManagerV1, - zwlr_screencopy_frame_v1::ZwlrScreencopyFrameV1, zwp_linux_dmabuf_feedback_v1::ZwpLinuxDmabufFeedbackV1, }, io_uring::IoUring, @@ -93,8 +83,7 @@ use { leaks::Tracker, logger::Logger, pr_caps::PrCapsThread, - rect::{Rect, Region}, - renderer::Renderer, + rect::Rect, scale::Scale, theme::{BarPosition, Color, Theme, ThemeColor, ThemeSized}, time::Time, @@ -102,7 +91,7 @@ use { ContainerNode, ContainerSplit, Direction, DisplayNode, FindTreeUsecase, FloatNode, FoundNode, LatchListener, Node, NodeIds, NodeVisitorBase, OutputNode, PlaceholderNode, TearingMode, TileState, ToplevelData, ToplevelIdentifier, - ToplevelNode, ToplevelNodeBase, Transform, VrrMode, WorkspaceDisplayOrder, + ToplevelNode, ToplevelNodeBase, VrrMode, WorkspaceDisplayOrder, WorkspaceNode, WorkspaceNodeId, WsMoveConfig, generic_node_visitor, move_ws_to_output, }, udmabuf::UdmabufHolder, @@ -145,7 +134,6 @@ use { sync::Arc, time::{Duration, SystemTime}, }, - thiserror::Error, uapi::{OwnedFd, c}, }; @@ -1102,180 +1090,6 @@ impl State { } } - pub fn present_output( - &self, - output: &OutputNode, - fb: &Rc, - cd: &Rc, - acquire_sync: AcquireSync, - release_sync: ReleaseSync, - tex: &Rc, - render_hw_cursor: bool, - blend_buffer: Option<&Rc>, - blend_cd: &Rc, - ) -> Result, GfxError> { - let sync = fb.render_output( - acquire_sync, - release_sync, - cd, - output, - self, - Some(output.global.pos.get()), - output.global.persistent.scale.get(), - render_hw_cursor, - true, - blend_buffer, - blend_cd, - )?; - output.latched(false); - output.perform_screencopies( - tex, - cd, - None, - &AcquireSync::Unnecessary, - ReleaseSync::None, - !render_hw_cursor, - 0, - 0, - None, - ); - Ok(sync) - } - - pub fn perform_screencopy( - &self, - src: &Rc, - resv: Option<&Rc>, - acquire_sync: &AcquireSync, - release_sync: ReleaseSync, - src_cd: &Rc, - target: &Rc, - target_acquire_sync: AcquireSync, - target_release_sync: ReleaseSync, - target_transform: Transform, - target_cd: &Rc, - position: Rect, - render_hardware_cursors: bool, - x_off: i32, - y_off: i32, - size: Option<(i32, i32)>, - transform: Transform, - scale: Scale, - ) -> Result, GfxError> { - let mut ops = vec![]; - let mut renderer = Renderer { - base: target.renderer_base(&mut ops, scale, target_transform), - state: self, - logical_extents: position.at_point(0, 0), - pixel_extents: { - let (width, height) = target.logical_size(target_transform); - Rect::new_sized_saturating(0, 0, width, height) - }, - stretch: None, - corner_radius: None, - }; - let mut sample_rect = SampleRect::identity(); - sample_rect.buffer_transform = transform; - renderer.base.render_texture( - src, - None, - x_off, - y_off, - Some(sample_rect), - size, - scale, - None, - resv.cloned(), - acquire_sync.clone(), - release_sync, - false, - src_cd, - RenderIntent::Perceptual, - AlphaMode::PremultipliedElectrical, - ); - if render_hardware_cursors - && let Some(cursor_user_group) = self.cursor_user_group_hardware_cursor.get() - && let Some(cursor_user) = cursor_user_group.active() - && let Some(cursor) = cursor_user.get() - { - let (mut x, mut y) = cursor_user.position(); - x = x + x_off - Fixed::from_int(position.x1()); - y = y + y_off - Fixed::from_int(position.y1()); - cursor.render(&mut renderer, x, y); - } - target.render( - target_acquire_sync, - target_release_sync, - target_cd, - &ops, - Some(&Color::SOLID_BLACK), - &target_cd.linear, - None, - target_cd, - ) - } - - pub fn perform_shm_screencopy( - &self, - src: &Rc, - src_cd: &Rc, - acquire_sync: &AcquireSync, - position: Rect, - x_off: i32, - y_off: i32, - size: Option<(i32, i32)>, - capture: &Rc, - mem: &Rc, - stride: i32, - format: &'static Format, - transform: Transform, - scale: Scale, - ) -> Result, ShmScreencopyError> { - let Some(ctx) = self.render_ctx.get() else { - return Err(ShmScreencopyError::NoRenderContext); - }; - let fb = ctx - .clone() - .create_internal_fb( - &self.cpu_worker, - capture.rect.width(), - capture.rect.height(), - stride, - format, - ) - .map_err(ShmScreencopyError::CreateTemporaryFb)?; - self.perform_screencopy( - src, - None, - acquire_sync, - ReleaseSync::None, - src_cd, - &(fb.clone() as Rc), - AcquireSync::Unnecessary, - ReleaseSync::None, - transform, - self.color_manager.srgb_gamma22(), - position, - true, - x_off - capture.rect.x1(), - y_off - capture.rect.y1(), - size, - transform, - scale, - ) - .map_err(ShmScreencopyError::CopyToTemporary)?; - let staging = ctx.create_staging_buffer(fb.staging_size(), STAGING_DOWNLOAD); - let pending = fb - .download( - &staging, - capture.clone(), - mem.clone(), - Region::new(capture.rect.at_point(0, 0)), - ) - .map_err(ShmScreencopyError::ReadPixels)?; - Ok(pending) - } - pub fn create_seat(self: &Rc, name: &str) -> Rc { let global_name = self.globals.name(); let seat = WlSeatGlobal::new(global_name, name, self); @@ -1881,15 +1695,3 @@ impl State { }) } } - -#[derive(Debug, Error)] -pub enum ShmScreencopyError { - #[error("There is no render context")] - NoRenderContext, - #[error("Could not create a bridge framebuffer")] - CreateTemporaryFb(#[source] GfxError), - #[error("Could not copy texture to bridge framebuffer")] - CopyToTemporary(#[source] GfxError), - #[error("Could not read pixels from texture")] - ReadPixels(#[source] GfxError), -} diff --git a/src/state/rendering.rs b/src/state/rendering.rs new file mode 100644 index 00000000..ca118d30 --- /dev/null +++ b/src/state/rendering.rs @@ -0,0 +1,212 @@ +use { + crate::{ + clientmem::ClientMemOffset, + cmm::{cmm_description::ColorDescription, cmm_render_intent::RenderIntent}, + fixed::Fixed, + format::Format, + gfx_api::{ + AcquireSync, AlphaMode, BufferResv, FdSync, GfxBlendBuffer, GfxError, + GfxFramebuffer, GfxTexture, PendingShmTransfer, ReleaseSync, STAGING_DOWNLOAD, + SampleRect, + }, + ifs::zwlr_screencopy_frame_v1::ZwlrScreencopyFrameV1, + rect::{Rect, Region}, + renderer::Renderer, + scale::Scale, + theme::Color, + tree::{OutputNode, Transform}, + }, + std::rc::Rc, + thiserror::Error, +}; + +use super::State; + +impl State { + pub fn present_output( + &self, + output: &OutputNode, + fb: &Rc, + cd: &Rc, + acquire_sync: AcquireSync, + release_sync: ReleaseSync, + tex: &Rc, + render_hw_cursor: bool, + blend_buffer: Option<&Rc>, + blend_cd: &Rc, + ) -> Result, GfxError> { + let sync = fb.render_output( + acquire_sync, + release_sync, + cd, + output, + self, + Some(output.global.pos.get()), + output.global.persistent.scale.get(), + render_hw_cursor, + true, + blend_buffer, + blend_cd, + )?; + output.latched(false); + output.perform_screencopies( + tex, + cd, + None, + &AcquireSync::Unnecessary, + ReleaseSync::None, + !render_hw_cursor, + 0, + 0, + None, + ); + Ok(sync) + } + + pub fn perform_screencopy( + &self, + src: &Rc, + resv: Option<&Rc>, + acquire_sync: &AcquireSync, + release_sync: ReleaseSync, + src_cd: &Rc, + target: &Rc, + target_acquire_sync: AcquireSync, + target_release_sync: ReleaseSync, + target_transform: Transform, + target_cd: &Rc, + position: Rect, + render_hardware_cursors: bool, + x_off: i32, + y_off: i32, + size: Option<(i32, i32)>, + transform: Transform, + scale: Scale, + ) -> Result, GfxError> { + let mut ops = vec![]; + let mut renderer = Renderer { + base: target.renderer_base(&mut ops, scale, target_transform), + state: self, + logical_extents: position.at_point(0, 0), + pixel_extents: { + let (width, height) = target.logical_size(target_transform); + Rect::new_sized_saturating(0, 0, width, height) + }, + stretch: None, + corner_radius: None, + }; + let mut sample_rect = SampleRect::identity(); + sample_rect.buffer_transform = transform; + renderer.base.render_texture( + src, + None, + x_off, + y_off, + Some(sample_rect), + size, + scale, + None, + resv.cloned(), + acquire_sync.clone(), + release_sync, + false, + src_cd, + RenderIntent::Perceptual, + AlphaMode::PremultipliedElectrical, + ); + if render_hardware_cursors + && let Some(cursor_user_group) = self.cursor_user_group_hardware_cursor.get() + && let Some(cursor_user) = cursor_user_group.active() + && let Some(cursor) = cursor_user.get() + { + let (mut x, mut y) = cursor_user.position(); + x = x + x_off - Fixed::from_int(position.x1()); + y = y + y_off - Fixed::from_int(position.y1()); + cursor.render(&mut renderer, x, y); + } + target.render( + target_acquire_sync, + target_release_sync, + target_cd, + &ops, + Some(&Color::SOLID_BLACK), + &target_cd.linear, + None, + target_cd, + ) + } + + pub fn perform_shm_screencopy( + &self, + src: &Rc, + src_cd: &Rc, + acquire_sync: &AcquireSync, + position: Rect, + x_off: i32, + y_off: i32, + size: Option<(i32, i32)>, + capture: &Rc, + mem: &Rc, + stride: i32, + format: &'static Format, + transform: Transform, + scale: Scale, + ) -> Result, ShmScreencopyError> { + let Some(ctx) = self.render_ctx.get() else { + return Err(ShmScreencopyError::NoRenderContext); + }; + let fb = ctx + .clone() + .create_internal_fb( + &self.cpu_worker, + capture.rect.width(), + capture.rect.height(), + stride, + format, + ) + .map_err(ShmScreencopyError::CreateTemporaryFb)?; + self.perform_screencopy( + src, + None, + acquire_sync, + ReleaseSync::None, + src_cd, + &(fb.clone() as Rc), + AcquireSync::Unnecessary, + ReleaseSync::None, + transform, + self.color_manager.srgb_gamma22(), + position, + true, + x_off - capture.rect.x1(), + y_off - capture.rect.y1(), + size, + transform, + scale, + ) + .map_err(ShmScreencopyError::CopyToTemporary)?; + let staging = ctx.create_staging_buffer(fb.staging_size(), STAGING_DOWNLOAD); + let pending = fb + .download( + &staging, + capture.clone(), + mem.clone(), + Region::new(capture.rect.at_point(0, 0)), + ) + .map_err(ShmScreencopyError::ReadPixels)?; + Ok(pending) + } + +} + +#[derive(Debug, Error)] +pub enum ShmScreencopyError { + #[error("There is no render context")] + NoRenderContext, + #[error("Could not create a bridge framebuffer")] + CreateTemporaryFb(#[source] GfxError), + #[error("Could not copy texture to bridge framebuffer")] + CopyToTemporary(#[source] GfxError), + #[error("Could not read pixels from texture")] + ReadPixels(#[source] GfxError), +}