state: split render context handling
This commit is contained in:
parent
c4655d4641
commit
16c402825f
2 changed files with 250 additions and 232 deletions
238
src/state.rs
238
src/state.rs
|
|
@ -2,6 +2,7 @@ mod animations;
|
||||||
mod connectors;
|
mod connectors;
|
||||||
mod idle;
|
mod idle;
|
||||||
mod rendering;
|
mod rendering;
|
||||||
|
mod render_context;
|
||||||
mod settings;
|
mod settings;
|
||||||
mod tree_ops;
|
mod tree_ops;
|
||||||
mod xwayland;
|
mod xwayland;
|
||||||
|
|
@ -43,8 +44,7 @@ use {
|
||||||
},
|
},
|
||||||
eventfd_cache::EventfdCache,
|
eventfd_cache::EventfdCache,
|
||||||
forker::ForkerProxy,
|
forker::ForkerProxy,
|
||||||
gfx_api::{GfxApi, GfxContext, GfxError},
|
gfx_api::{GfxApi, GfxContext},
|
||||||
gfx_apis::create_gfx_context,
|
|
||||||
globals::{Globals, GlobalsError, RemovableWaylandGlobal, WaylandGlobal},
|
globals::{Globals, GlobalsError, RemovableWaylandGlobal, WaylandGlobal},
|
||||||
icons::Icons,
|
icons::Icons,
|
||||||
ifs::{
|
ifs::{
|
||||||
|
|
@ -90,9 +90,9 @@ use {
|
||||||
theme::Theme,
|
theme::Theme,
|
||||||
time::Time,
|
time::Time,
|
||||||
tree::{
|
tree::{
|
||||||
ContainerNode, DisplayNode, FloatNode, FoundNode, LatchListener, Node, NodeIds,
|
ContainerNode, DisplayNode, FloatNode, FoundNode, LatchListener, NodeIds, OutputNode,
|
||||||
NodeVisitorBase, OutputNode, PlaceholderNode, TearingMode, ToplevelIdentifier,
|
PlaceholderNode, TearingMode, ToplevelIdentifier, ToplevelNode, VrrMode,
|
||||||
ToplevelNode, VrrMode, WorkspaceDisplayOrder, WorkspaceNode, WorkspaceNodeId,
|
WorkspaceDisplayOrder, WorkspaceNode, WorkspaceNodeId,
|
||||||
},
|
},
|
||||||
udmabuf::UdmabufHolder,
|
udmabuf::UdmabufHolder,
|
||||||
utils::{
|
utils::{
|
||||||
|
|
@ -110,10 +110,7 @@ use {
|
||||||
refcounted::RefCounted,
|
refcounted::RefCounted,
|
||||||
run_toplevel::RunToplevel,
|
run_toplevel::RunToplevel,
|
||||||
},
|
},
|
||||||
video::{
|
video::{dmabuf::DmaBufIds, drm::wait_for_syncobj::WaitForSyncobj},
|
||||||
dmabuf::DmaBufIds,
|
|
||||||
drm::{Drm, wait_for_syncobj::WaitForSyncobj},
|
|
||||||
},
|
|
||||||
virtual_output::VirtualOutputs,
|
virtual_output::VirtualOutputs,
|
||||||
wheel::Wheel,
|
wheel::Wheel,
|
||||||
wire::{
|
wire::{
|
||||||
|
|
@ -123,7 +120,6 @@ use {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ahash::AHashMap,
|
ahash::AHashMap,
|
||||||
bstr::ByteSlice,
|
|
||||||
std::{
|
std::{
|
||||||
cell::{Cell, RefCell},
|
cell::{Cell, RefCell},
|
||||||
fmt::{Debug, Formatter},
|
fmt::{Debug, Formatter},
|
||||||
|
|
@ -329,229 +325,7 @@ pub struct DeviceHandlerData {
|
||||||
pub mods_listener: EventListener<dyn LedsListener>,
|
pub mods_listener: EventListener<dyn LedsListener>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct UpdateTextTexturesVisitor;
|
|
||||||
impl NodeVisitorBase for UpdateTextTexturesVisitor {
|
|
||||||
fn visit_container(&mut self, node: &Rc<ContainerNode>) {
|
|
||||||
node.node_visit_children(self);
|
|
||||||
}
|
|
||||||
fn visit_output(&mut self, node: &Rc<OutputNode>) {
|
|
||||||
node.schedule_update_render_data();
|
|
||||||
node.node_visit_children(self);
|
|
||||||
}
|
|
||||||
fn visit_float(&mut self, node: &Rc<FloatNode>) {
|
|
||||||
node.node_visit_children(self);
|
|
||||||
}
|
|
||||||
fn visit_workspace(&mut self, node: &Rc<WorkspaceNode>) {
|
|
||||||
node.title_texture.take();
|
|
||||||
node.node_visit_children(self);
|
|
||||||
}
|
|
||||||
fn visit_placeholder(&mut self, node: &Rc<PlaceholderNode>) {
|
|
||||||
node.textures.borrow_mut().clear();
|
|
||||||
node.schedule_update_texture();
|
|
||||||
node.node_visit_children(self);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl State {
|
impl State {
|
||||||
pub fn create_gfx_context(
|
|
||||||
&self,
|
|
||||||
drm: &Drm,
|
|
||||||
api: Option<GfxApi>,
|
|
||||||
) -> Result<Rc<dyn GfxContext>, 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<Rc<dyn GfxContext>>) {
|
|
||||||
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<ContainerNode>) {
|
|
||||||
node.node_visit_children(self);
|
|
||||||
}
|
|
||||||
fn visit_workspace(&mut self, node: &Rc<WorkspaceNode>) {
|
|
||||||
node.title_texture.take();
|
|
||||||
node.node_visit_children(self);
|
|
||||||
}
|
|
||||||
fn visit_output(&mut self, node: &Rc<OutputNode>) {
|
|
||||||
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<FloatNode>) {
|
|
||||||
node.node_visit_children(self);
|
|
||||||
}
|
|
||||||
fn visit_placeholder(&mut self, node: &Rc<PlaceholderNode>) {
|
|
||||||
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<T: WaylandGlobal>(&self, global: &Rc<T>) {
|
pub fn add_global<T: WaylandGlobal>(&self, global: &Rc<T>) {
|
||||||
self.globals.add_global(self, global)
|
self.globals.add_global(self, global)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
244
src/state/render_context.rs
Normal file
244
src/state/render_context.rs
Normal file
|
|
@ -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<ContainerNode>) {
|
||||||
|
node.node_visit_children(self);
|
||||||
|
}
|
||||||
|
fn visit_output(&mut self, node: &Rc<OutputNode>) {
|
||||||
|
node.schedule_update_render_data();
|
||||||
|
node.node_visit_children(self);
|
||||||
|
}
|
||||||
|
fn visit_float(&mut self, node: &Rc<FloatNode>) {
|
||||||
|
node.node_visit_children(self);
|
||||||
|
}
|
||||||
|
fn visit_workspace(&mut self, node: &Rc<WorkspaceNode>) {
|
||||||
|
node.title_texture.take();
|
||||||
|
node.node_visit_children(self);
|
||||||
|
}
|
||||||
|
fn visit_placeholder(&mut self, node: &Rc<PlaceholderNode>) {
|
||||||
|
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<GfxApi>,
|
||||||
|
) -> Result<Rc<dyn GfxContext>, 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<Rc<dyn GfxContext>>) {
|
||||||
|
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<ContainerNode>) {
|
||||||
|
node.node_visit_children(self);
|
||||||
|
}
|
||||||
|
fn visit_workspace(&mut self, node: &Rc<WorkspaceNode>) {
|
||||||
|
node.title_texture.take();
|
||||||
|
node.node_visit_children(self);
|
||||||
|
}
|
||||||
|
fn visit_output(&mut self, node: &Rc<OutputNode>) {
|
||||||
|
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<FloatNode>) {
|
||||||
|
node.node_visit_children(self);
|
||||||
|
}
|
||||||
|
fn visit_placeholder(&mut self, node: &Rc<PlaceholderNode>) {
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue