turn global contexts into thread locals

This commit is contained in:
Paulo Santana 2025-01-18 15:00:20 -03:00 committed by Jonathan Spira
parent 5cfd7fe182
commit ec123482c0
2 changed files with 88 additions and 75 deletions

View File

@ -664,7 +664,7 @@ impl Context {
backend: Box::new(backend),
};
*crate::PLATFORM_VIEWPORT_BACKEND.lock().unwrap() = Some(ctx);
crate::PLATFORM_VIEWPORT_CONTEXT.with_borrow_mut(|c| *c = Some(ctx));
let pio = self.platform_io_mut();
pio.platform_create_window = Some(docking_utils::platform_create_window);
@ -703,7 +703,7 @@ impl Context {
backend: Box::new(backend),
};
*crate::RENDERER_VIEWPORT_BACKEND.lock().unwrap() = Some(ctx);
crate::RENDERER_VIEWPORT_CONTEXT.with_borrow_mut(|c| *c = Some(ctx));
let pio = self.platform_io_mut();
pio.renderer_create_window = Some(docking_utils::renderer_create_window);

View File

@ -1,17 +1,16 @@
use std::{
cell::UnsafeCell,
cell::RefCell,
ffi::{c_void, CStr},
os::raw::{c_char, c_int},
sync::Mutex,
};
use crate::{PlatformIo, Viewport};
pub(crate) static PLATFORM_VIEWPORT_BACKEND: Mutex<Option<crate::PlatformViewportContext>> =
Mutex::new(None);
thread_local!(
pub(crate) static PLATFORM_VIEWPORT_CONTEXT: RefCell<Option<crate::PlatformViewportContext>> = const { RefCell::new(None) });
pub(crate) static RENDERER_VIEWPORT_BACKEND: Mutex<Option<crate::RendererViewportContext>> =
Mutex::new(None);
thread_local!(
pub(crate) static RENDERER_VIEWPORT_CONTEXT: RefCell<Option<crate::RendererViewportContext>> = const { RefCell::new(None) });
/// Trait holding functions needed when the platform integration supports viewports.
///
@ -73,94 +72,108 @@ pub trait PlatformViewportBackend: 'static {
) -> i32;
}
/// Used to get the current Contexts [`PlatformViewportContext`].
fn get_platform_ctx() -> &'static mut PlatformViewportContext {
let a = UnsafeCell::new(PLATFORM_VIEWPORT_BACKEND.lock().unwrap()).get();
unsafe { (*a).as_mut().unwrap() }
#[inline]
fn get_platform(
ctx: &mut Option<PlatformViewportContext>,
) -> &mut Box<dyn PlatformViewportBackend> {
&mut ctx.as_mut().unwrap().backend
}
/// Used to get the current Contexts [`RendererViewportContext`].
fn get_renderer_ctx() -> &'static mut RendererViewportContext {
let a = UnsafeCell::new(RENDERER_VIEWPORT_BACKEND.lock().unwrap()).get();
unsafe { (*a).as_mut().unwrap() }
#[inline]
fn get_renderer(
ctx: &mut Option<RendererViewportContext>,
) -> &mut Box<dyn RendererViewportBackend> {
&mut ctx.as_mut().unwrap().backend
}
pub(crate) extern "C" fn platform_create_window(viewport: *mut Viewport) {
let ctx = get_platform_ctx();
ctx.backend.create_window(unsafe { &mut *viewport });
PLATFORM_VIEWPORT_CONTEXT.with_borrow_mut(|ctx: &mut Option<crate::PlatformViewportContext>| {
get_platform(ctx).create_window(unsafe { &mut *viewport });
})
}
pub(crate) extern "C" fn platform_destroy_window(viewport: *mut Viewport) {
let ctx = get_platform_ctx();
ctx.backend.destroy_window(unsafe { &mut *viewport });
PLATFORM_VIEWPORT_CONTEXT.with_borrow_mut(|ctx| {
get_platform(ctx).destroy_window(unsafe { &mut *viewport });
})
}
pub(crate) extern "C" fn platform_show_window(viewport: *mut Viewport) {
let ctx = get_platform_ctx();
ctx.backend.show_window(unsafe { &mut *viewport });
PLATFORM_VIEWPORT_CONTEXT.with_borrow_mut(|ctx| {
get_platform(ctx).show_window(unsafe { &mut *viewport });
})
}
pub(crate) extern "C" fn platform_set_window_pos(viewport: *mut Viewport, pos: sys::ImVec2) {
let ctx = get_platform_ctx();
ctx.backend
.set_window_pos(unsafe { &mut *viewport }, [pos.x, pos.y]);
PLATFORM_VIEWPORT_CONTEXT.with_borrow_mut(|ctx| {
get_platform(ctx).set_window_pos(unsafe { &mut *viewport }, [pos.x, pos.y]);
})
}
pub(crate) extern "C" fn platform_get_window_pos(
viewport: *mut Viewport,
out_pos: *mut sys::ImVec2,
) {
let ctx = get_platform_ctx();
let pos = ctx.backend.get_window_pos(unsafe { &mut *viewport });
unsafe {
*out_pos = sys::ImVec2::new(pos[0], pos[1]);
}
PLATFORM_VIEWPORT_CONTEXT.with_borrow_mut(|ctx| {
let pos = get_platform(ctx).get_window_pos(unsafe { &mut *viewport });
unsafe {
*out_pos = sys::ImVec2::new(pos[0], pos[1]);
}
})
}
pub(crate) extern "C" fn platform_set_window_size(viewport: *mut Viewport, size: sys::ImVec2) {
let ctx = get_platform_ctx();
ctx.backend
.set_window_size(unsafe { &mut *viewport }, [size.x, size.y]);
PLATFORM_VIEWPORT_CONTEXT.with_borrow_mut(|ctx| {
get_platform(ctx).set_window_size(unsafe { &mut *viewport }, [size.x, size.y]);
})
}
pub(crate) extern "C" fn platform_get_window_size(
viewport: *mut Viewport,
out_size: *mut sys::ImVec2,
) {
let ctx = get_platform_ctx();
let size = ctx.backend.get_window_size(unsafe { &mut *viewport });
unsafe {
*out_size = sys::ImVec2::new(size[0], size[1]);
}
PLATFORM_VIEWPORT_CONTEXT.with_borrow_mut(|ctx: &mut Option<crate::PlatformViewportContext>| {
let size = get_platform(ctx).get_window_size(unsafe { &mut *viewport });
unsafe {
*out_size = sys::ImVec2::new(size[0], size[1]);
}
})
}
pub(crate) extern "C" fn platform_set_window_focus(viewport: *mut Viewport) {
let ctx = get_platform_ctx();
ctx.backend.set_window_focus(unsafe { &mut *viewport });
PLATFORM_VIEWPORT_CONTEXT.with_borrow_mut(|ctx: &mut Option<crate::PlatformViewportContext>| {
get_platform(ctx).set_window_focus(unsafe { &mut *viewport });
})
}
pub(crate) extern "C" fn platform_get_window_focus(viewport: *mut Viewport) -> bool {
let ctx = get_platform_ctx();
ctx.backend.get_window_focus(unsafe { &mut *viewport })
PLATFORM_VIEWPORT_CONTEXT.with_borrow_mut(|ctx: &mut Option<crate::PlatformViewportContext>| {
get_platform(ctx).get_window_focus(unsafe { &mut *viewport })
})
}
pub(crate) extern "C" fn platform_get_window_minimized(viewport: *mut Viewport) -> bool {
let ctx = get_platform_ctx();
ctx.backend.get_window_minimized(unsafe { &mut *viewport })
PLATFORM_VIEWPORT_CONTEXT.with_borrow_mut(|ctx: &mut Option<crate::PlatformViewportContext>| {
get_platform(ctx).get_window_minimized(unsafe { &mut *viewport })
})
}
pub(crate) extern "C" fn platform_set_window_title(viewport: *mut Viewport, title: *const c_char) {
let ctx = get_platform_ctx();
let title = unsafe { CStr::from_ptr(title).to_str().unwrap() };
ctx.backend
.set_window_title(unsafe { &mut *viewport }, title);
PLATFORM_VIEWPORT_CONTEXT.with_borrow_mut(|ctx| {
let title = unsafe { CStr::from_ptr(title).to_str().unwrap() };
get_platform(ctx).set_window_title(unsafe { &mut *viewport }, title);
})
}
pub(crate) extern "C" fn platform_set_window_alpha(viewport: *mut Viewport, alpha: f32) {
let ctx = get_platform_ctx();
ctx.backend
.set_window_alpha(unsafe { &mut *viewport }, alpha);
PLATFORM_VIEWPORT_CONTEXT.with_borrow_mut(|ctx| {
get_platform(ctx).set_window_alpha(unsafe { &mut *viewport }, alpha);
})
}
pub(crate) extern "C" fn platform_update_window(viewport: *mut Viewport) {
let ctx = get_platform_ctx();
ctx.backend.update_window(unsafe { &mut *viewport });
PLATFORM_VIEWPORT_CONTEXT.with_borrow_mut(|ctx| {
get_platform(ctx).update_window(unsafe { &mut *viewport });
})
}
pub(crate) extern "C" fn platform_render_window(viewport: *mut Viewport, _arg: *mut c_void) {
let ctx = get_platform_ctx();
ctx.backend.render_window(unsafe { &mut *viewport });
PLATFORM_VIEWPORT_CONTEXT.with_borrow_mut(|ctx| {
get_platform(ctx).render_window(unsafe { &mut *viewport });
})
}
pub(crate) extern "C" fn platform_swap_buffers(viewport: *mut Viewport, _arg: *mut c_void) {
let ctx = get_platform_ctx();
ctx.backend.swap_buffers(unsafe { &mut *viewport });
PLATFORM_VIEWPORT_CONTEXT.with_borrow_mut(|ctx| {
get_platform(ctx).swap_buffers(unsafe { &mut *viewport });
})
}
pub(crate) extern "C" fn platform_create_vk_surface(
viewport: *mut Viewport,
@ -168,11 +181,11 @@ pub(crate) extern "C" fn platform_create_vk_surface(
_arg: *const c_void,
out_surface: *mut u64,
) -> c_int {
let ctx = get_platform_ctx();
ctx.backend
.create_vk_surface(unsafe { &mut *viewport }, instance, unsafe {
PLATFORM_VIEWPORT_CONTEXT.with_borrow_mut(|ctx| {
get_platform(ctx).create_vk_surface(unsafe { &mut *viewport }, instance, unsafe {
&mut *out_surface
})
})
}
/// Just holds a [`PlatformViewportBackend`].
@ -180,8 +193,6 @@ pub(crate) struct PlatformViewportContext {
pub(crate) backend: Box<dyn PlatformViewportBackend>,
}
unsafe impl Send for PlatformViewportContext {}
/// Trait that holds optional functions for a rendering backend to support multiple viewports.
///
/// It is completely fine to not use this Backend at all, as all functions are optional.
@ -197,25 +208,29 @@ pub trait RendererViewportBackend: 'static {
}
pub(crate) extern "C" fn renderer_create_window(viewport: *mut Viewport) {
let ctx = get_renderer_ctx();
ctx.backend.create_window(unsafe { &mut *viewport });
RENDERER_VIEWPORT_CONTEXT.with_borrow_mut(|ctx| {
get_renderer(ctx).create_window(unsafe { &mut *viewport });
})
}
pub(crate) extern "C" fn renderer_destroy_window(viewport: *mut Viewport) {
let ctx = get_renderer_ctx();
ctx.backend.destroy_window(unsafe { &mut *viewport });
RENDERER_VIEWPORT_CONTEXT.with_borrow_mut(|ctx| {
get_renderer(ctx).destroy_window(unsafe { &mut *viewport });
})
}
pub(crate) extern "C" fn renderer_set_window_size(viewport: *mut Viewport, size: sys::ImVec2) {
let ctx = get_renderer_ctx();
ctx.backend
.set_window_size(unsafe { &mut *viewport }, [size.x, size.y]);
RENDERER_VIEWPORT_CONTEXT.with_borrow_mut(|ctx| {
get_renderer(ctx).set_window_size(unsafe { &mut *viewport }, [size.x, size.y]);
})
}
pub(crate) extern "C" fn renderer_render_window(viewport: *mut Viewport, _arg: *mut c_void) {
let ctx = get_renderer_ctx();
ctx.backend.render_window(unsafe { &mut *viewport });
RENDERER_VIEWPORT_CONTEXT.with_borrow_mut(|ctx| {
get_renderer(ctx).render_window(unsafe { &mut *viewport });
})
}
pub(crate) extern "C" fn renderer_swap_buffers(viewport: *mut Viewport, _arg: *mut c_void) {
let ctx = get_renderer_ctx();
ctx.backend.swap_buffers(unsafe { &mut *viewport });
RENDERER_VIEWPORT_CONTEXT.with_borrow_mut(|ctx| {
get_renderer(ctx).swap_buffers(unsafe { &mut *viewport });
})
}
/// Just holds a [`RendererViewportBackend`].
@ -223,8 +238,6 @@ pub(crate) struct RendererViewportContext {
pub(crate) backend: Box<dyn RendererViewportBackend>,
}
unsafe impl Send for RendererViewportContext {}
/// Describes a monitor that can be used by ImGui.
#[repr(C)]
pub struct PlatformMonitor {