diff --git a/src/state.rs b/src/state.rs index 794a2721..f81ed745 100644 --- a/src/state.rs +++ b/src/state.rs @@ -2,6 +2,7 @@ mod animations; mod connectors; mod idle; mod rendering; +mod render_context; mod settings; mod tree_ops; mod xwayland; @@ -43,8 +44,7 @@ use { }, eventfd_cache::EventfdCache, forker::ForkerProxy, - gfx_api::{GfxApi, GfxContext, GfxError}, - gfx_apis::create_gfx_context, + gfx_api::{GfxApi, GfxContext}, globals::{Globals, GlobalsError, RemovableWaylandGlobal, WaylandGlobal}, icons::Icons, ifs::{ @@ -90,9 +90,9 @@ use { theme::Theme, time::Time, tree::{ - ContainerNode, DisplayNode, FloatNode, FoundNode, LatchListener, Node, NodeIds, - NodeVisitorBase, OutputNode, PlaceholderNode, TearingMode, ToplevelIdentifier, - ToplevelNode, VrrMode, WorkspaceDisplayOrder, WorkspaceNode, WorkspaceNodeId, + ContainerNode, DisplayNode, FloatNode, FoundNode, LatchListener, NodeIds, OutputNode, + PlaceholderNode, TearingMode, ToplevelIdentifier, ToplevelNode, VrrMode, + WorkspaceDisplayOrder, WorkspaceNode, WorkspaceNodeId, }, udmabuf::UdmabufHolder, utils::{ @@ -110,10 +110,7 @@ use { refcounted::RefCounted, run_toplevel::RunToplevel, }, - video::{ - dmabuf::DmaBufIds, - drm::{Drm, wait_for_syncobj::WaitForSyncobj}, - }, + video::{dmabuf::DmaBufIds, drm::wait_for_syncobj::WaitForSyncobj}, virtual_output::VirtualOutputs, wheel::Wheel, wire::{ @@ -123,7 +120,6 @@ use { }, }, ahash::AHashMap, - bstr::ByteSlice, std::{ cell::{Cell, RefCell}, fmt::{Debug, Formatter}, @@ -329,229 +325,7 @@ pub struct DeviceHandlerData { pub mods_listener: EventListener, } -struct UpdateTextTexturesVisitor; -impl NodeVisitorBase for UpdateTextTexturesVisitor { - fn visit_container(&mut self, node: &Rc) { - node.node_visit_children(self); - } - fn visit_output(&mut self, node: &Rc) { - node.schedule_update_render_data(); - node.node_visit_children(self); - } - fn visit_float(&mut self, node: &Rc) { - node.node_visit_children(self); - } - fn visit_workspace(&mut self, node: &Rc) { - node.title_texture.take(); - node.node_visit_children(self); - } - fn visit_placeholder(&mut self, node: &Rc) { - node.textures.borrow_mut().clear(); - node.schedule_update_texture(); - node.node_visit_children(self); - } -} - impl State { - pub fn create_gfx_context( - &self, - drm: &Drm, - api: Option, - ) -> Result, GfxError> { - create_gfx_context( - &self.eng, - &self.ring, - &self.eventfd_cache, - drm, - api.unwrap_or(self.default_gfx_api.get()), - self.caps_thread.as_ref(), - ) - } - - pub fn add_output_scale(&self, scale: Scale) { - if self.scales.add(scale) { - self.output_scales_changed(); - } - } - - pub fn remove_output_scale(&self, scale: Scale) { - if self.scales.remove(&scale) { - self.output_scales_changed(); - } - } - - pub fn add_cursor_size(&self, size: u32) { - if self.cursor_sizes.add(size) { - self.cursor_sizes_changed(); - } - } - - pub fn remove_cursor_size(&self, size: u32) { - if self.cursor_sizes.remove(&size) { - self.cursor_sizes_changed(); - } - } - - fn output_scales_changed(&self) { - UpdateTextTexturesVisitor.visit_display(&self.root); - self.reload_cursors(); - self.update_xwayland_wire_scale(); - self.icons.update_sizes(self); - } - - fn cursor_sizes_changed(&self) { - self.reload_cursors(); - } - - pub fn devices_enumerated(&self) { - if let Some(config) = self.config.get() { - config.devices_enumerated() - } - if self.render_ctx.is_none() { - for dev in self.drm_devs.lock().values() { - if let Ok(version) = dev.dev.version() - && version.name.contains_str("nvidia") - { - continue; - } - if dev.dev.gfx_fast_ram_access() { - continue; - } - dev.make_render_device(); - if self.render_ctx.is_some() { - break; - } - } - if self.render_ctx.is_none() - && let Some(dev) = self.drm_devs.lock().values().next() - { - dev.make_render_device(); - } - } - } - - pub fn set_render_ctx(&self, ctx: Option>) { - self.explicit_sync_supported.set(false); - self.render_ctx.set(ctx.clone()); - self.render_ctx_version.fetch_add(1); - self.cursors.set(None); - self.drm_feedback.set(None); - self.icons.clear(); - self.wait_for_syncobj - .set_ctx(ctx.as_ref().and_then(|c| c.syncobj_ctx().cloned())); - self.virtual_outputs.handle_render_ctx_change(self); - - 'handle_new_feedback: { - if let Some(ctx) = &ctx { - let feedback = match DrmFeedback::new(&self.drm_feedback_ids, &**ctx) { - Ok(fb) => fb, - Err(e) => { - log::error!("Could not create new DRM feedback: {}", ErrorFmt(e)); - break 'handle_new_feedback; - } - }; - for watcher in self.drm_feedback_consumers.lock().values() { - watcher.send_feedback(&feedback); - } - self.drm_feedback.set(Some(Rc::new(feedback))); - } - } - - { - struct Walker; - impl NodeVisitorBase for Walker { - fn visit_container(&mut self, node: &Rc) { - node.node_visit_children(self); - } - fn visit_workspace(&mut self, node: &Rc) { - node.title_texture.take(); - node.node_visit_children(self); - } - fn visit_output(&mut self, node: &Rc) { - node.render_data.borrow_mut().titles.clear(); - node.render_data.borrow_mut().status.take(); - node.set_hardware_cursor(None); - node.node_visit_children(self); - } - fn visit_float(&mut self, node: &Rc) { - node.node_visit_children(self); - } - fn visit_placeholder(&mut self, node: &Rc) { - node.textures.borrow_mut().clear(); - node.node_visit_children(self); - } - } - Walker.visit_display(&self.root); - let mut updated_buffers = AHashMap::new(); - for buffer in self.gfx_ctx_changed.iter() { - let had_buffer_texture = buffer.handle_gfx_context_change(); - updated_buffers.insert(Rc::as_ptr(&buffer), had_buffer_texture); - } - for client in self.clients.clients.borrow_mut().values() { - for surface in client.data.objects.surfaces.lock().values() { - let had_shm_texture = surface.reset_shm_textures(); - if let Some(buffer) = surface.buffer.get() { - let buf = &buffer.buffer.buf; - let had_buffer_texture = *updated_buffers.get(&Rc::as_ptr(buf)).unwrap(); - if had_shm_texture || had_buffer_texture { - buf.update_texture_or_log(surface, true); - } - } - } - } - } - - if ctx.is_some() { - self.reload_cursors(); - UpdateTextTexturesVisitor.visit_display(&self.root); - } - - for cursor_user_groups in self.cursor_user_groups.lock().values() { - cursor_user_groups.render_ctx_changed(); - } - - if let Some(ctx) = &ctx { - if let Some(ctx) = ctx.syncobj_ctx() - && ctx.supports_async_wait() - { - self.explicit_sync_supported.set(true); - } - if !self.render_ctx_ever_initialized.replace(true) - && let Some(config) = self.config.get() - { - config.graphics_initialized(); - } - } - - for watcher in self.render_ctx_watchers.lock().values() { - watcher.send_render_ctx(ctx.clone()); - } - - for client in self.clients.clients.borrow_mut().values() { - for sc in client.data.objects.ext_copy_sessions.lock().values() { - sc.stop(); - } - } - - self.expose_new_singletons(); - } - - fn reload_cursors(&self) { - if let Some(ctx) = self.render_ctx.get() { - let cursors = match ServerCursors::load(&ctx, self) { - Ok(c) => c.map(Rc::new), - Err(e) => { - log::error!("Could not load the cursors: {}", ErrorFmt(e)); - None - } - }; - self.cursors.set(cursors); - for cursor_user_group in self.cursor_user_groups.lock().values() { - cursor_user_group.reload_known_cursor(); - } - } - } - pub fn add_global(&self, global: &Rc) { self.globals.add_global(self, global) } diff --git a/src/state/render_context.rs b/src/state/render_context.rs new file mode 100644 index 00000000..043c9621 --- /dev/null +++ b/src/state/render_context.rs @@ -0,0 +1,244 @@ +use { + crate::{ + cursor::ServerCursors, + drm_feedback::DrmFeedback, + gfx_api::{GfxApi, GfxContext, GfxError}, + gfx_apis::create_gfx_context, + scale::Scale, + tree::{ + ContainerNode, FloatNode, Node, NodeVisitorBase, OutputNode, PlaceholderNode, + WorkspaceNode, + }, + utils::errorfmt::ErrorFmt, + video::drm::Drm, + }, + ahash::AHashMap, + bstr::ByteSlice, + std::rc::Rc, +}; + +use super::State; + +struct UpdateTextTexturesVisitor; +impl NodeVisitorBase for UpdateTextTexturesVisitor { + fn visit_container(&mut self, node: &Rc) { + node.node_visit_children(self); + } + fn visit_output(&mut self, node: &Rc) { + node.schedule_update_render_data(); + node.node_visit_children(self); + } + fn visit_float(&mut self, node: &Rc) { + node.node_visit_children(self); + } + fn visit_workspace(&mut self, node: &Rc) { + node.title_texture.take(); + node.node_visit_children(self); + } + fn visit_placeholder(&mut self, node: &Rc) { + node.textures.borrow_mut().clear(); + node.schedule_update_texture(); + node.node_visit_children(self); + } +} + +impl State { + pub fn create_gfx_context( + &self, + drm: &Drm, + api: Option, + ) -> Result, GfxError> { + create_gfx_context( + &self.eng, + &self.ring, + &self.eventfd_cache, + drm, + api.unwrap_or(self.default_gfx_api.get()), + self.caps_thread.as_ref(), + ) + } + + pub fn add_output_scale(&self, scale: Scale) { + if self.scales.add(scale) { + self.output_scales_changed(); + } + } + + pub fn remove_output_scale(&self, scale: Scale) { + if self.scales.remove(&scale) { + self.output_scales_changed(); + } + } + + pub fn add_cursor_size(&self, size: u32) { + if self.cursor_sizes.add(size) { + self.cursor_sizes_changed(); + } + } + + pub fn remove_cursor_size(&self, size: u32) { + if self.cursor_sizes.remove(&size) { + self.cursor_sizes_changed(); + } + } + + fn output_scales_changed(&self) { + UpdateTextTexturesVisitor.visit_display(&self.root); + self.reload_cursors(); + self.update_xwayland_wire_scale(); + self.icons.update_sizes(self); + } + + fn cursor_sizes_changed(&self) { + self.reload_cursors(); + } + + pub fn devices_enumerated(&self) { + if let Some(config) = self.config.get() { + config.devices_enumerated() + } + if self.render_ctx.is_none() { + for dev in self.drm_devs.lock().values() { + if let Ok(version) = dev.dev.version() + && version.name.contains_str("nvidia") + { + continue; + } + if dev.dev.gfx_fast_ram_access() { + continue; + } + dev.make_render_device(); + if self.render_ctx.is_some() { + break; + } + } + if self.render_ctx.is_none() + && let Some(dev) = self.drm_devs.lock().values().next() + { + dev.make_render_device(); + } + } + } + + pub fn set_render_ctx(&self, ctx: Option>) { + self.explicit_sync_supported.set(false); + self.render_ctx.set(ctx.clone()); + self.render_ctx_version.fetch_add(1); + self.cursors.set(None); + self.drm_feedback.set(None); + self.icons.clear(); + self.wait_for_syncobj + .set_ctx(ctx.as_ref().and_then(|c| c.syncobj_ctx().cloned())); + self.virtual_outputs.handle_render_ctx_change(self); + + 'handle_new_feedback: { + if let Some(ctx) = &ctx { + let feedback = match DrmFeedback::new(&self.drm_feedback_ids, &**ctx) { + Ok(fb) => fb, + Err(e) => { + log::error!("Could not create new DRM feedback: {}", ErrorFmt(e)); + break 'handle_new_feedback; + } + }; + for watcher in self.drm_feedback_consumers.lock().values() { + watcher.send_feedback(&feedback); + } + self.drm_feedback.set(Some(Rc::new(feedback))); + } + } + + { + struct Walker; + impl NodeVisitorBase for Walker { + fn visit_container(&mut self, node: &Rc) { + node.node_visit_children(self); + } + fn visit_workspace(&mut self, node: &Rc) { + node.title_texture.take(); + node.node_visit_children(self); + } + fn visit_output(&mut self, node: &Rc) { + node.render_data.borrow_mut().titles.clear(); + node.render_data.borrow_mut().status.take(); + node.set_hardware_cursor(None); + node.node_visit_children(self); + } + fn visit_float(&mut self, node: &Rc) { + node.node_visit_children(self); + } + fn visit_placeholder(&mut self, node: &Rc) { + node.textures.borrow_mut().clear(); + node.node_visit_children(self); + } + } + Walker.visit_display(&self.root); + let mut updated_buffers = AHashMap::new(); + for buffer in self.gfx_ctx_changed.iter() { + let had_buffer_texture = buffer.handle_gfx_context_change(); + updated_buffers.insert(Rc::as_ptr(&buffer), had_buffer_texture); + } + for client in self.clients.clients.borrow_mut().values() { + for surface in client.data.objects.surfaces.lock().values() { + let had_shm_texture = surface.reset_shm_textures(); + if let Some(buffer) = surface.buffer.get() { + let buf = &buffer.buffer.buf; + let had_buffer_texture = *updated_buffers.get(&Rc::as_ptr(buf)).unwrap(); + if had_shm_texture || had_buffer_texture { + buf.update_texture_or_log(surface, true); + } + } + } + } + } + + if ctx.is_some() { + self.reload_cursors(); + UpdateTextTexturesVisitor.visit_display(&self.root); + } + + for cursor_user_groups in self.cursor_user_groups.lock().values() { + cursor_user_groups.render_ctx_changed(); + } + + if let Some(ctx) = &ctx { + if let Some(ctx) = ctx.syncobj_ctx() + && ctx.supports_async_wait() + { + self.explicit_sync_supported.set(true); + } + if !self.render_ctx_ever_initialized.replace(true) + && let Some(config) = self.config.get() + { + config.graphics_initialized(); + } + } + + for watcher in self.render_ctx_watchers.lock().values() { + watcher.send_render_ctx(ctx.clone()); + } + + for client in self.clients.clients.borrow_mut().values() { + for sc in client.data.objects.ext_copy_sessions.lock().values() { + sc.stop(); + } + } + + self.expose_new_singletons(); + } + + fn reload_cursors(&self) { + if let Some(ctx) = self.render_ctx.get() { + let cursors = match ServerCursors::load(&ctx, self) { + Ok(c) => c.map(Rc::new), + Err(e) => { + log::error!("Could not load the cursors: {}", ErrorFmt(e)); + None + } + }; + self.cursors.set(cursors); + for cursor_user_group in self.cursor_user_groups.lock().values() { + cursor_user_group.reload_known_cursor(); + } + } + } +}