use PROJECT_NAME::{Core, init_gpu_inner}; use glam::UVec2; use raw_window_handle::{RawDisplayHandle, RawWindowHandle}; use crate::core::ICoreImpl; pub use factory::ICoreFactoryImpl; mod core { use std::ops::{Deref, DerefMut}; use PROJECT_NAME::{Core, RedrawArgs}; use glam::uvec2; #[repr(C)] struct ICoreVTable { destroy: unsafe extern "C" fn(this: Box), configure: unsafe extern "C" fn(this: &mut ICoreImpl, width: u32, height: u32), redraw: unsafe extern "C" fn(this: &mut ICoreImpl, args: &RedrawArgs), } unsafe extern "C" fn destroy(this: Box) { drop(this); } unsafe extern "C" fn configure(this: &mut ICoreImpl, width: u32, height: u32) { this.core.configure(uvec2(width, height)); } unsafe extern "C" fn redraw(this: &mut ICoreImpl, args: &RedrawArgs) { this.core.redraw(args); } static VTABLE: ICoreVTable = ICoreVTable { destroy, configure, redraw, }; #[repr(C)] pub(crate) struct ICoreImpl { vtable: &'static ICoreVTable, core: Core, } impl ICoreImpl { pub(crate) fn new(core: Core) -> Box { Box::new(ICoreImpl { vtable: &VTABLE, core, }) } } impl DerefMut for ICoreImpl { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.core } } impl Deref for ICoreImpl { type Target = Core; fn deref(&self) -> &Self::Target { &self.core } } } mod factory { use std::{ffi::c_void, num::NonZero, ptr::NonNull}; use glam::uvec2; use raw_window_handle::{XcbDisplayHandle, XcbWindowHandle}; use crate::core::ICoreImpl; #[repr(C)] struct ICoreFactoryVTable { new_xcb: unsafe extern "C" fn( this: &mut ICoreFactoryImpl, connection: NonNull, window: NonZero, width: u32, height: u32, ) -> Box, } unsafe extern "C" fn new_xcb( _this: &mut ICoreFactoryImpl, connection: NonNull, window: NonZero, width: u32, height: u32, ) -> Box { let display = XcbDisplayHandle::new(Some(connection), 0); let window = XcbWindowHandle::new(window); unsafe { crate::create_viewport(display, window, uvec2(width, height)) } } static VTABLE: ICoreFactoryVTable = ICoreFactoryVTable { new_xcb }; #[repr(C)] pub struct ICoreFactoryImpl { vtable: &'static ICoreFactoryVTable, } impl ICoreFactoryImpl { pub fn new() -> Self { ICoreFactoryImpl { vtable: &VTABLE } } } } unsafe fn create_viewport( display: impl Into, window: impl Into, size: UVec2, ) -> Box { let target = wgpu::SurfaceTargetUnsafe::RawHandle { raw_display_handle: display.into(), raw_window_handle: window.into(), }; let gpu = pollster::block_on(init_gpu_inner(|instance| unsafe { instance.create_surface_unsafe(target) })) .unwrap(); ICoreImpl::new(Core::new(gpu, size)) }