Free graphics resources without item tree traversal

This commit is contained in:
Simon Hausmann 2020-11-17 22:52:38 +01:00
parent ba0ec058ab
commit 7a5113ece1
7 changed files with 54 additions and 40 deletions

View file

@ -96,11 +96,9 @@ public:
sixtyfps_component_window_set_scale_factor(&inner, value); sixtyfps_component_window_set_scale_factor(&inner, value);
} }
template<typename Component> void free_graphics_resources(const sixtyfps::Slice<ItemRef> &items) const
void free_graphics_resources(Component *c) const
{ {
cbindgen_private::sixtyfps_component_window_free_graphics_resources( cbindgen_private::sixtyfps_component_window_free_graphics_resources(&inner, &items);
&inner, vtable::VRef<ComponentVTable> { &Component::component_type, c });
} }
void set_focus_item(vtable::VRef<ComponentVTable> c, vtable::VRef<ItemVTable> item) void set_focus_item(vtable::VRef<ComponentVTable> c, vtable::VRef<ItemVTable> item)

View file

@ -894,6 +894,7 @@ fn generate_component(
let mut repeated_input_branch = vec![]; let mut repeated_input_branch = vec![];
let mut repeater_layout_code = vec![]; let mut repeater_layout_code = vec![];
let mut tree_array = vec![]; let mut tree_array = vec![];
let mut item_names_and_vt_symbols = vec![];
let mut repeater_count = 0; let mut repeater_count = 0;
super::build_array_helper(component, |item_rc, children_offset, is_flickable_rect| { super::build_array_helper(component, |item_rc, children_offset, is_flickable_rect| {
let item = item_rc.borrow(); let item = item_rc.borrow();
@ -944,6 +945,8 @@ fn generate_component(
children_offset, children_offset,
)); ));
handle_item(item_rc, &mut component_struct, &mut init); handle_item(item_rc, &mut component_struct, &mut init);
item_names_and_vt_symbols
.push((item.id.clone(), item.base_type.as_native().vtable_symbol.clone()));
} }
}); });
@ -979,7 +982,15 @@ fn generate_component(
if component.parent_element.upgrade().is_some() { if component.parent_element.upgrade().is_some() {
destructor.push("if (!parent) return;".to_owned()) destructor.push("if (!parent) return;".to_owned())
} }
destructor.push("self->window.free_graphics_resources(this);".into()); if !item_names_and_vt_symbols.is_empty() {
destructor.push("sixtyfps::private_api::ItemRef items[] = {".into());
destructor.push(item_names_and_vt_symbols.iter()
.map(|(item_name, vt_symbol)|
format!("{{ &sixtyfps::private_api::{vt}, const_cast<decltype(this->{id})*>(&this->{id}) }}", id = item_name, vt = vt_symbol)
).join(","));
destructor.push("};".into());
destructor.push("window.free_graphics_resources(sixtyfps::Slice<sixtyfps::private_api::ItemRef>{items, std::size(items)});".into());
}
component_struct.members.push(( component_struct.members.push((
Access::Public, Access::Public,

View file

@ -611,7 +611,10 @@ fn generate_component(
Some(quote!(impl sixtyfps::re_exports::PinnedDrop for #component_id { Some(quote!(impl sixtyfps::re_exports::PinnedDrop for #component_id {
fn drop(self: core::pin::Pin<&mut #component_id>) { fn drop(self: core::pin::Pin<&mut #component_id>) {
use sixtyfps::re_exports::*; use sixtyfps::re_exports::*;
self.window.free_graphics_resources(VRef::new_pin(self.as_ref())); let items = [
#(VRef::new_pin(Self::FIELD_OFFSETS.#item_names.apply_pin(self.as_ref())),)*
];
self.window.free_graphics_resources(&Slice::from_slice(&items));
} }
})), })),
quote!(#[pin_drop]), quote!(#[pin_drop]),

View file

@ -13,7 +13,11 @@ LICENSE END */
[GenericWindow] trait used by the generated code and the run-time to change [GenericWindow] trait used by the generated code and the run-time to change
aspects of windows on the screen. aspects of windows on the screen.
*/ */
use crate::component::{ComponentRc, ComponentVTable}; use crate::{
component::{ComponentRc, ComponentVTable},
items::ItemRef,
slice::Slice,
};
use std::cell::RefCell; use std::cell::RefCell;
use std::{ use std::{
convert::TryInto, convert::TryInto,
@ -91,10 +95,7 @@ pub trait GenericWindow {
/// This function is called by the generated code when a component and therefore its tree of items are destroyed. The /// This function is called by the generated code when a component and therefore its tree of items are destroyed. The
/// implementation typically uses this to free the underlying graphics resources cached via [`crate::graphics::RenderingCache`]. /// implementation typically uses this to free the underlying graphics resources cached via [`crate::graphics::RenderingCache`].
fn free_graphics_resources( fn free_graphics_resources<'a>(self: Rc<Self>, items: &Slice<'a, Pin<ItemRef<'a>>>);
self: Rc<Self>,
component: core::pin::Pin<crate::component::ComponentRef>,
);
/// Installs a binding on the specified property that's toggled whenever the text cursor is supposed to be visible or not. /// Installs a binding on the specified property that's toggled whenever the text cursor is supposed to be visible or not.
fn set_cursor_blink_binding(&self, prop: &crate::properties::Property<bool>); fn set_cursor_blink_binding(&self, prop: &crate::properties::Property<bool>);
@ -151,11 +152,8 @@ impl ComponentWindow {
/// This function is called by the generated code when a component and therefore its tree of items are destroyed. The /// This function is called by the generated code when a component and therefore its tree of items are destroyed. The
/// implementation typically uses this to free the underlying graphics resources cached via [RenderingCache][`crate::graphics::RenderingCache`]. /// implementation typically uses this to free the underlying graphics resources cached via [RenderingCache][`crate::graphics::RenderingCache`].
pub fn free_graphics_resources( pub fn free_graphics_resources<'a>(&self, items: &Slice<'a, Pin<ItemRef<'a>>>) {
&self, self.0.clone().free_graphics_resources(items);
component: core::pin::Pin<crate::component::ComponentRef>,
) {
self.0.clone().free_graphics_resources(component);
} }
/// Installs a binding on the specified property that's toggled whenever the text cursor is supposed to be visible or not. /// Installs a binding on the specified property that's toggled whenever the text cursor is supposed to be visible or not.
@ -599,12 +597,12 @@ pub mod ffi {
/// Sets the window scale factor, merely for testing purposes. /// Sets the window scale factor, merely for testing purposes.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sixtyfps_component_window_free_graphics_resources( pub unsafe extern "C" fn sixtyfps_component_window_free_graphics_resources<'a>(
handle: *const ComponentWindowOpaque, handle: *const ComponentWindowOpaque,
component: Pin<VRef<ComponentVTable>>, items: &Slice<'a, Pin<ItemRef<'a>>>,
) { ) {
let window = &*(handle as *const ComponentWindow); let window = &*(handle as *const ComponentWindow);
window.free_graphics_resources(component) window.free_graphics_resources(items)
} }
/// Sets the focus item. /// Sets the focus item.

View file

@ -20,7 +20,6 @@ LICENSE END */
created by the backend in a type-erased manner. created by the backend in a type-erased manner.
*/ */
extern crate alloc; extern crate alloc;
use crate::component::{ComponentRc, ComponentWeak};
use crate::input::{KeyEvent, KeyboardModifiers, MouseEvent, MouseEventType}; use crate::input::{KeyEvent, KeyboardModifiers, MouseEvent, MouseEventType};
use crate::items::ItemRef; use crate::items::ItemRef;
use crate::properties::{InterpolatedPropertyValue, Property, PropertyTracker}; use crate::properties::{InterpolatedPropertyValue, Property, PropertyTracker};
@ -29,6 +28,10 @@ use crate::rtti::{BuiltinItem, FieldInfo, PropertyInfo, ValueType};
use crate::SharedArray; use crate::SharedArray;
#[cfg(feature = "rtti")] #[cfg(feature = "rtti")]
use crate::Signal; use crate::Signal;
use crate::{
component::{ComponentRc, ComponentWeak},
slice::Slice,
};
use auto_enums::auto_enum; use auto_enums::auto_enum;
use cgmath::Matrix4; use cgmath::Matrix4;
@ -820,14 +823,11 @@ impl<Backend: GraphicsBackend> crate::eventloop::GenericWindow for GraphicsWindo
) )
} }
fn free_graphics_resources( fn free_graphics_resources<'a>(self: Rc<Self>, items: &Slice<'a, Pin<ItemRef<'a>>>) {
self: Rc<Self>,
component: core::pin::Pin<crate::component::ComponentRef>,
) {
match &*self.map_state.borrow() { match &*self.map_state.borrow() {
GraphicsWindowBackendState::Unmapped => {} GraphicsWindowBackendState::Unmapped => {}
GraphicsWindowBackendState::Mapped(window) => { GraphicsWindowBackendState::Mapped(window) => {
crate::item_rendering::free_item_rendering_data(component, &window.rendering_cache) crate::item_rendering::free_item_rendering_data(items, &window.rendering_cache)
} }
} }
} }

View file

@ -14,8 +14,8 @@ use super::graphics::{
Frame, GraphicsBackend, GraphicsWindow, RenderingCache, RenderingPrimitivesBuilder, Frame, GraphicsBackend, GraphicsWindow, RenderingCache, RenderingPrimitivesBuilder,
}; };
use super::items::ItemRef; use super::items::ItemRef;
use crate::eventloop::ComponentWindow;
use crate::item_tree::ItemVisitorResult; use crate::item_tree::ItemVisitorResult;
use crate::{eventloop::ComponentWindow, slice::Slice};
use cgmath::{Matrix4, SquareMatrix, Vector3}; use cgmath::{Matrix4, SquareMatrix, Vector3};
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
@ -123,18 +123,12 @@ pub(crate) fn render_component_items<Backend: GraphicsBackend>(
); );
} }
pub(crate) fn free_item_rendering_data<Backend: GraphicsBackend>( pub(crate) fn free_item_rendering_data<'a, Backend: GraphicsBackend>(
component: crate::component::ComponentRefPin, items: &Slice<'a, core::pin::Pin<ItemRef<'a>>>,
rendering_cache: &RefCell<RenderingCache<Backend>>, rendering_cache: &RefCell<RenderingCache<Backend>>,
) { ) {
crate::item_tree::visit_items( for item in items.iter() {
component,
crate::item_tree::TraversalOrder::FrontToBack,
|_, item, _| {
let cached_rendering_data = item.cached_rendering_data_offset(); let cached_rendering_data = item.cached_rendering_data_offset();
cached_rendering_data.release(rendering_cache); cached_rendering_data.release(rendering_cache);
ItemVisitorResult::Continue(()) }
},
(),
);
} }

View file

@ -77,9 +77,19 @@ impl<'id> ComponentBox<'id> {
impl<'id> Drop for ComponentBox<'id> { impl<'id> Drop for ComponentBox<'id> {
fn drop(&mut self) { fn drop(&mut self) {
match eval::window_ref(self.borrow_instance()) { let instance_ref = self.borrow_instance();
match eval::window_ref(instance_ref) {
Some(window) => { Some(window) => {
window.free_graphics_resources(self.borrow()); let items = self
.component_type
.items
.values()
.map(|item_within_component| unsafe {
item_within_component.item_from_component(instance_ref.as_ptr())
})
.collect::<Vec<_>>();
window.free_graphics_resources(&Slice::from_slice(items.as_slice()));
} }
None => {} None => {}
} }