move platform and renderer backends out of Dear Imgui

Store the objects containing the callback methods for multi viewport
support in two globals that are managed by imgui-rs, instead of using
BackendPlatformUserdata and BackendRendererUserData

fixes #820
This commit is contained in:
Paulo Santana 2025-01-12 00:58:58 -03:00 committed by Jonathan Spira
parent 150ede3b4e
commit 184b86d355
2 changed files with 23 additions and 23 deletions

View File

@ -683,12 +683,11 @@ impl Context {
/// Installs a [`PlatformViewportBackend`](crate::PlatformViewportBackend) that is used to
/// create platform windows on demand if a window is dragged outside of the main viewport.
pub fn set_platform_backend<T: crate::PlatformViewportBackend>(&mut self, backend: T) {
let ctx = Box::new(UnsafeCell::new(crate::PlatformViewportContext {
let ctx = crate::PlatformViewportContext {
backend: Box::new(backend),
}));
};
let io = self.io_mut();
io.backend_platform_user_data = ctx.get() as *mut _;
*crate::PLATFORM_VIEWPORT_BACKEND.lock().unwrap() = Some(ctx);
let pio = self.platform_io_mut();
pio.platform_create_window = Some(docking_utils::platform_create_window);
@ -719,18 +718,15 @@ impl Context {
pio.platform_render_window = Some(docking_utils::platform_render_window);
pio.platform_swap_buffers = Some(docking_utils::platform_swap_buffers);
pio.platform_create_vk_surface = Some(docking_utils::platform_create_vk_surface);
self.platform_viewport_ctx = ctx;
}
/// Installs a [`RendererViewportBackend`](crate::RendererViewportBackend) that is used to
/// render extra viewports created by ImGui.
pub fn set_renderer_backend<T: crate::RendererViewportBackend>(&mut self, backend: T) {
let ctx = Box::new(UnsafeCell::new(crate::RendererViewportContext {
let ctx = crate::RendererViewportContext {
backend: Box::new(backend),
}));
};
let io = self.io_mut();
io.backend_renderer_user_data = ctx.get() as *mut _;
*crate::RENDERER_VIEWPORT_BACKEND.lock().unwrap() = Some(ctx);
let pio = self.platform_io_mut();
pio.renderer_create_window = Some(docking_utils::renderer_create_window);
@ -738,8 +734,6 @@ impl Context {
pio.renderer_set_window_size = Some(docking_utils::renderer_set_window_size);
pio.renderer_render_window = Some(docking_utils::renderer_render_window);
pio.renderer_swap_buffers = Some(docking_utils::renderer_swap_buffers);
self.renderer_viewport_ctx = ctx;
}
/// Updates the extra Viewports created by ImGui.
/// Has to be called every frame if Viewports are enabled.

View File

@ -1,9 +1,17 @@
use std::{
cell::UnsafeCell,
ffi::{c_void, CStr},
os::raw::{c_char, c_int},
sync::{Mutex, MutexGuard},
};
use crate::{Io, PlatformIo, Viewport};
use crate::{PlatformIo, Viewport};
pub(crate) static PLATFORM_VIEWPORT_BACKEND: Mutex<Option<crate::PlatformViewportContext>> =
Mutex::new(None);
pub(crate) static RENDERER_VIEWPORT_BACKEND: Mutex<Option<crate::RendererViewportContext>> =
Mutex::new(None);
/// Trait holding functions needed when the platform integration supports viewports.
///
@ -67,20 +75,14 @@ pub trait PlatformViewportBackend: 'static {
/// Used to get the current Contexts [`PlatformViewportContext`].
fn get_platform_ctx() -> &'static mut PlatformViewportContext {
unsafe {
// should be safe as it is impossible to call any imgui function on a non-active context.
&mut *((*(sys::igGetIO() as *const Io)).backend_platform_user_data
as *mut PlatformViewportContext)
}
let a = UnsafeCell::new(PLATFORM_VIEWPORT_BACKEND.lock().unwrap()).get();
unsafe { (*a).as_mut().unwrap() }
}
/// Used to get the current Contexts [`RendererViewportContext`].
fn get_renderer_ctx() -> &'static mut RendererViewportContext {
unsafe {
// should be safe as it is impossible to call any imgui function on a non-active context.
&mut *((*(sys::igGetIO() as *const Io)).backend_renderer_user_data
as *mut RendererViewportContext)
}
let a = UnsafeCell::new(RENDERER_VIEWPORT_BACKEND.lock().unwrap()).get();
unsafe { (*a).as_mut().unwrap() }
}
pub(crate) extern "C" fn platform_create_window(viewport: *mut Viewport) {
@ -259,6 +261,8 @@ impl PlatformViewportContext {
}
}
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.
@ -332,6 +336,8 @@ impl RendererViewportContext {
}
}
unsafe impl Send for RendererViewportContext {}
/// Describes a monitor that can be used by ImGui.
#[repr(C)]
pub struct PlatformMonitor {