diff --git a/helper_crates/vtable/macro/macro.rs b/helper_crates/vtable/macro/macro.rs index 4997dd17b..0a3cf92a6 100644 --- a/helper_crates/vtable/macro/macro.rs +++ b/helper_crates/vtable/macro/macro.rs @@ -390,6 +390,7 @@ pub fn vtable(_attr: TokenStream, item: TokenStream) -> TokenStream { let result = quote!( #[allow(non_snake_case)] + #[macro_use] /// This private module is generated by the `vtable` macro mod #module_name { #[allow(unused)] @@ -448,8 +449,13 @@ pub fn vtable(_attr: TokenStream, item: TokenStream) -> TokenStream { pub type #refmut_name<'a> = VRefMut<'a, #vtable_name>; pub type #box_name = VBox<#vtable_name>; - #[macro_export] - macro_rules! #static_vtable_macro_name { + } + #[doc(inline)] + #[macro_use] + #vis use #module_name::*; + + #[macro_export] + macro_rules! #static_vtable_macro_name { ($ty:ty) => { { type T = $ty; @@ -459,11 +465,8 @@ pub fn vtable(_attr: TokenStream, item: TokenStream) -> TokenStream { } } } - - } - #[doc(inline)] - #vis use #module_name::*; ); - //println!("{}", result); +// println!("{}", result); result.into() } + diff --git a/helper_crates/vtable/src/lib.rs b/helper_crates/vtable/src/lib.rs index 74fcd0e22..536d41845 100644 --- a/helper_crates/vtable/src/lib.rs +++ b/helper_crates/vtable/src/lib.rs @@ -1,7 +1,7 @@ use core::ops::{Deref, DerefMut, Drop}; use core::ptr::NonNull; use core::marker::PhantomData; -pub use vtable_macro::vtable; +pub use vtable_macro::*; pub unsafe trait VTableMeta { /// that's the rust trait. (e.g: `Hello`) @@ -189,6 +189,9 @@ impl<'a, T: ?Sized + VTableMeta> VRefMut<'a, T> { pub fn into_ref(self) -> VRef<'a, T> { unsafe { VRef::from_inner(VRefMut::inner(&self)) } } + pub unsafe fn from_raw(vtable: NonNull, ptr: NonNull) -> Self { + Self {inner : T::from_raw(vtable, ptr), _phantom: PhantomData } + } pub fn get_vtable(&self) -> &T::VTable { unsafe { T::get_vtable(&self.inner) } } diff --git a/sixtyfps_runtime/corelib/abi/datastructures.rs b/sixtyfps_runtime/corelib/abi/datastructures.rs index 71dfcd5bc..c5ac43f55 100644 --- a/sixtyfps_runtime/corelib/abi/datastructures.rs +++ b/sixtyfps_runtime/corelib/abi/datastructures.rs @@ -14,16 +14,6 @@ pub struct ComponentVTable { pub item_tree: extern "C" fn(VRef) -> *const ItemTreeNode, } -/// From the ItemTreeNode and a ComponentImpl, you can get a pointer to the instance data -/// ItemImpl via the offset field. -pub struct ItemImpl; -// Example memory representation: -// offset| type | value -// 0 | f32 | x -// 4 | f32 | y -// ... -// 64 | CachedRenderingData | struct - #[repr(C)] #[derive(Default)] pub struct CachedRenderingData { @@ -75,24 +65,25 @@ pub enum ItemTreeNode { /// It is supposed to be in static array unsafe impl Sync for ItemTreeNode {} +#[vtable] #[repr(C)] -#[derive(Default)] pub struct ItemVTable { /// Rectangle: x/y/width/height ==> (path -> vertices/indicies(triangle)) - pub geometry: Option ()>, // like kurbo::Rect + pub geometry: extern "C" fn(VRef<'_, ItemVTable>) -> (), // like kurbo::Rect /// offset in bytes fromthe *const ItemImpl. /// isize::MAX means None + #[allow(non_upper_case_globals)] pub cached_rendering_data_offset: isize, /// Return a rendering info - pub rendering_info: Option RenderingInfo>, + pub rendering_info: extern "C" fn(VRef<'_, ItemVTable>) -> RenderingInfo, /// We would need max/min/preferred size, and all layout info - pub layouting_info: Option LayoutInfo>, + pub layouting_info: extern "C" fn(VRef<'_, ItemVTable>) -> LayoutInfo, /// input event - pub input_event: Option, + pub input_event: extern "C" fn(VRef<'_, ItemVTable>, MouseEvent), } // given an ItemImpl & ItemVTable @@ -117,7 +108,7 @@ pub enum RenderingInfo { Text(String)*/ } -type MouseEvent = (); +pub type MouseEvent = (); /* -- Safe wrappers*/ @@ -128,36 +119,17 @@ type MouseEvent = (); fn rendering_info(&self) -> CachedRenderingData; }*/ -// To be used as &'x Item -pub struct Item { - vtable: NonNull, - inner: NonNull, +pub fn cached_rendering_data(item: VRef<'_, ItemVTable>) -> &CachedRenderingData { + unsafe { + &*(VRef::get_ptr(&item).as_ptr().offset(item.get_vtable().cached_rendering_data_offset) + as *const CachedRenderingData) + } } -impl Item { - /// One should create only one instance of item at the time to keep the &mut invariant - pub unsafe fn new(vtable: NonNull, inner: NonNull) -> Self { - Self { vtable, inner } - } - - pub fn cached_rendering_data(&self) -> &CachedRenderingData { - unsafe { - &*((self.inner.as_ptr() as *const u8) - .offset(self.vtable.as_ref().cached_rendering_data_offset) - as *const CachedRenderingData) - } - } - - pub fn cached_rendering_data_mut(&mut self) -> &mut CachedRenderingData { - unsafe { - &mut *((self.inner.as_ptr() as *mut u8) - .offset(self.vtable.as_ref().cached_rendering_data_offset) - as *mut CachedRenderingData) - } - } - - pub fn rendering_info(&self) -> Option { - unsafe { self.vtable.as_ref().rendering_info.map(|x| x(self.inner.as_ptr())) } +pub fn cached_rendering_data_mut(item: VRefMut<'_, ItemVTable>) -> &mut CachedRenderingData { + unsafe { + &mut *(VRefMut::get_ptr(&item).as_ptr().offset(item.get_vtable().cached_rendering_data_offset) + as *mut CachedRenderingData) } } @@ -166,7 +138,7 @@ impl Item { /// The state parametter returned by the visitor is passed to each children. pub fn visit_items( component: VRef<'_, ComponentVTable>, - mut visitor: impl FnMut(&Item, &State) -> State, + mut visitor: impl FnMut(ItemRef<'_>, &State) -> State, state: State, ) { visit_internal(component, &mut visitor, 0, &state) @@ -174,7 +146,7 @@ pub fn visit_items( fn visit_internal( component: VRef<'_, ComponentVTable>, - visitor: &mut impl FnMut(&Item, &State) -> State, + visitor: &mut impl FnMut(ItemRef<'_>, &State) -> State, index: isize, state: &State, ) { @@ -182,14 +154,14 @@ fn visit_internal( match unsafe { &*item_tree.offset(index) } { ItemTreeNode::Item { vtable, offset, children_index, chilren_count } => { let item = unsafe { - Item::new( + ItemRef::from_raw( NonNull::new_unchecked(*vtable as *mut _), NonNull::new_unchecked( - (VRef::get_ptr(&component).as_ptr()).offset(*offset) as *mut _, + (VRef::get_ptr(&component).as_ptr()).offset(*offset) as *mut _ ), ) }; - let state = visitor(&item, state); + let state = visitor(item, state); for c in *children_index..(*children_index + *chilren_count) { visit_internal(component, visitor, c as isize, &state) } @@ -200,7 +172,7 @@ fn visit_internal( pub fn visit_items_mut( component: VRefMut<'_, ComponentVTable>, - mut visitor: impl FnMut(&mut Item, &State) -> State, + mut visitor: impl FnMut(ItemRefMut<'_>, &State) -> State, state: State, ) { visit_internal_mut(component, &mut visitor, 0, &state) @@ -208,7 +180,7 @@ pub fn visit_items_mut( fn visit_internal_mut( mut component: VRefMut<'_, ComponentVTable>, - visitor: &mut impl FnMut(&mut Item, &State) -> State, + visitor: &mut impl FnMut(ItemRefMut<'_>, &State) -> State, index: isize, state: &State, ) { @@ -216,15 +188,15 @@ fn visit_internal_mut( match unsafe { &*item_tree.offset(index) } { ItemTreeNode::Item { vtable, offset, children_index, chilren_count } => { let mut item = unsafe { - Item::new( + ItemRefMut::from_raw( NonNull::new_unchecked(*vtable as *mut _), NonNull::new_unchecked( - (VRefMut::get_ptr(&component).as_ptr() as *mut u8).offset(*offset) as *mut _, + (VRefMut::get_ptr(&component).as_ptr() as *mut u8).offset(*offset) + as *mut _, ), - ) }; - let state = visitor(&mut item, state); + let state = visitor(item.borrow_mut(), state); for c in *children_index..(*children_index + *chilren_count) { visit_internal_mut(component.borrow_mut(), visitor, c as isize, &state) } @@ -323,3 +295,13 @@ pub static QT_BUTTON_VTABLE: ItemVTable = ItemVTable { rendering_info: render_qt_button, }; */ + + + +#[allow(non_upper_case_globals)] +#[no_mangle] +pub static RectangleVTable: ItemVTable = ItemVTable_static!(crate::abi::primitives::Rectangle); + +#[allow(non_upper_case_globals)] +#[no_mangle] +pub static ImageVTable: ItemVTable = ItemVTable_static!(crate::abi::primitives::Image); diff --git a/sixtyfps_runtime/corelib/abi/primitives.rs b/sixtyfps_runtime/corelib/abi/primitives.rs index 829b733a4..5a731c677 100644 --- a/sixtyfps_runtime/corelib/abi/primitives.rs +++ b/sixtyfps_runtime/corelib/abi/primitives.rs @@ -1,4 +1,6 @@ -use super::datastructures::{CachedRenderingData, ItemImpl, ItemVTable, RenderingInfo}; +#![allow(non_upper_case_globals)] + +use super::datastructures::{CachedRenderingData, Item, ItemConsts, LayoutInfo, RenderingInfo}; /// FIXME: more properties #[repr(C)] @@ -13,21 +15,23 @@ pub struct Rectangle { pub cached_rendering_data: CachedRenderingData, } -unsafe extern "C" fn render_rectangle(i: *const ItemImpl) -> RenderingInfo { - let r = &*(i as *const Rectangle); - RenderingInfo::Rectangle(r.x, r.y, r.width, r.height, r.color) +impl Item for Rectangle { + fn geometry(&self) {} + fn rendering_info(&self) -> RenderingInfo { + RenderingInfo::Rectangle(self.x, self.y, self.width, self.height, self.color) + } + + fn layouting_info(&self) -> LayoutInfo { + todo!() + } + + fn input_event(&self, _: super::datastructures::MouseEvent) {} } -#[allow(non_upper_case_globals)] -#[no_mangle] -pub static RectangleVTable: ItemVTable = ItemVTable { - geometry: None, - // offset_of!(Rectangle, render_node), is not const on stable rust - cached_rendering_data_offset: Rectangle::field_offsets().cached_rendering_data as isize, - rendering_info: Some(render_rectangle), - layouting_info: None, - input_event: None, -}; +impl ItemConsts for Rectangle { + const cached_rendering_data_offset: isize = + Rectangle::field_offsets().cached_rendering_data as isize; +} // FIXME: remove (or use the libc one) #[allow(non_camel_case_types)] @@ -58,19 +62,23 @@ impl Default for Image { } } -unsafe extern "C" fn render_image(i: *const ItemImpl) -> RenderingInfo { - let i = &*(i as *const Image); - RenderingInfo::Image(std::ffi::CStr::from_ptr(i.source).to_str().unwrap()) +impl Item for Image { + fn geometry(&self) {} + fn rendering_info(&self) -> RenderingInfo { + unsafe { RenderingInfo::Image(std::ffi::CStr::from_ptr(self.source).to_str().unwrap()) } + } + + fn layouting_info(&self) -> LayoutInfo { + todo!() + } + + fn input_event(&self, _: super::datastructures::MouseEvent) {} } -/// TODO -#[allow(non_upper_case_globals)] -#[no_mangle] -pub static ImageVTable: super::datastructures::ItemVTable = super::datastructures::ItemVTable { - geometry: None, - // offset_of!(Rectangle, render_node), is not const on stable rust - cached_rendering_data_offset: Image::field_offsets().cached_rendering_data as isize, - rendering_info: Some(render_image), - layouting_info: None, - input_event: None, -}; +impl ItemConsts for Image { + const cached_rendering_data_offset: isize = + Image::field_offsets().cached_rendering_data as isize; +} + + +pub use super::datastructures::{ImageVTable, RectangleVTable}; diff --git a/sixtyfps_runtime/corelib/item_rendering.rs b/sixtyfps_runtime/corelib/item_rendering.rs index 277714b45..2f49d15a8 100644 --- a/sixtyfps_runtime/corelib/item_rendering.rs +++ b/sixtyfps_runtime/corelib/item_rendering.rs @@ -1,23 +1,18 @@ -use super::abi::datastructures::{Item, RenderingInfo}; +use super::abi::datastructures::{ItemRefMut, RenderingInfo}; use super::graphics::{Color, Frame, GraphicsBackend, RenderingCache, RenderingPrimitivesBuilder}; use cgmath::{Matrix4, SquareMatrix, Vector3}; use lyon::math::{Point, Rect, Size}; pub(crate) fn update_item_rendering_data( - item: &mut Item, + mut item: ItemRefMut<'_>, rendering_cache: &mut RenderingCache, rendering_primitives_builder: &mut Backend::RenderingPrimitivesBuilder, ) { - let item_rendering_info = { - match item.rendering_info() { - Some(info) => info, - None => return, - } - }; + let item_rendering_info = item.rendering_info(); println!("Caching ... {:?}", item_rendering_info); - let rendering_data = item.cached_rendering_data_mut(); + let rendering_data = super::abi::datastructures::cached_rendering_data_mut(item.borrow_mut()); match item_rendering_info { RenderingInfo::Rectangle(_x, _y, width, height, color) => { @@ -81,12 +76,7 @@ pub(crate) fn render_component_items( component, |item, transform| { let mut transform = transform.clone(); - let item_rendering_info = { - match item.rendering_info() { - Some(info) => info, - None => return transform, - } - }; + let item_rendering_info = item.rendering_info(); match item_rendering_info { RenderingInfo::Rectangle(x, y, ..) => { @@ -95,14 +85,14 @@ pub(crate) fn render_component_items( _ => {} } - if item.cached_rendering_data().cache_ok { + let cached_rendering_data = super::abi::datastructures::cached_rendering_data(item); + if cached_rendering_data.cache_ok { println!( "Rendering... {:?} from cache {}", - item_rendering_info, - item.cached_rendering_data().cache_index + item_rendering_info, cached_rendering_data.cache_index ); - let primitive = rendering_cache.entry_at(item.cached_rendering_data().cache_index); + let primitive = rendering_cache.entry_at(cached_rendering_data.cache_index); frame.render_primitive(&primitive, &transform); } diff --git a/tools/viewer/main.rs b/tools/viewer/main.rs index b5bc9851c..05ecebc19 100644 --- a/tools/viewer/main.rs +++ b/tools/viewer/main.rs @@ -47,7 +47,7 @@ impl PropertyWriter for *const i8 { } } -unsafe fn construct(ptr: *mut corelib::abi::datastructures::ItemImpl) { +unsafe fn construct(ptr: *mut u8) { core::ptr::write(ptr as *mut T, T::default()); } @@ -72,12 +72,12 @@ struct MyComponentType { unsafe extern "C" fn item_tree( r: ComponentRef<'_>, ) -> *const corelib::abi::datastructures::ItemTreeNode { - (*(ComponentRef::get_vtable(&r).as_ptr() as *const MyComponentType)).it.as_ptr() + (*(ComponentRef::get_vtable(&r) as *const ComponentVTable as *const MyComponentType)).it.as_ptr() } struct RuntimeTypeInfo { vtable: *const corelib::abi::datastructures::ItemVTable, - construct: unsafe fn(*mut corelib::abi::datastructures::ItemImpl), + construct: unsafe fn(*mut u8), properties: HashMap<&'static str, (usize, unsafe fn(*mut u8, &Expression))>, size: usize, }