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);
}
template<typename Component>
void free_graphics_resources(Component *c) const
void free_graphics_resources(const sixtyfps::Slice<ItemRef> &items) const
{
cbindgen_private::sixtyfps_component_window_free_graphics_resources(
&inner, vtable::VRef<ComponentVTable> { &Component::component_type, c });
cbindgen_private::sixtyfps_component_window_free_graphics_resources(&inner, &items);
}
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 repeater_layout_code = vec![];
let mut tree_array = vec![];
let mut item_names_and_vt_symbols = vec![];
let mut repeater_count = 0;
super::build_array_helper(component, |item_rc, children_offset, is_flickable_rect| {
let item = item_rc.borrow();
@ -944,6 +945,8 @@ fn generate_component(
children_offset,
));
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() {
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((
Access::Public,

View file

@ -611,7 +611,10 @@ fn generate_component(
Some(quote!(impl sixtyfps::re_exports::PinnedDrop for #component_id {
fn drop(self: core::pin::Pin<&mut #component_id>) {
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]),

View file

@ -13,7 +13,11 @@ LICENSE END */
[GenericWindow] trait used by the generated code and the run-time to change
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::{
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
/// implementation typically uses this to free the underlying graphics resources cached via [`crate::graphics::RenderingCache`].
fn free_graphics_resources(
self: Rc<Self>,
component: core::pin::Pin<crate::component::ComponentRef>,
);
fn free_graphics_resources<'a>(self: Rc<Self>, items: &Slice<'a, Pin<ItemRef<'a>>>);
/// 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>);
@ -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
/// implementation typically uses this to free the underlying graphics resources cached via [RenderingCache][`crate::graphics::RenderingCache`].
pub fn free_graphics_resources(
&self,
component: core::pin::Pin<crate::component::ComponentRef>,
) {
self.0.clone().free_graphics_resources(component);
pub fn free_graphics_resources<'a>(&self, items: &Slice<'a, Pin<ItemRef<'a>>>) {
self.0.clone().free_graphics_resources(items);
}
/// 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.
#[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,
component: Pin<VRef<ComponentVTable>>,
items: &Slice<'a, Pin<ItemRef<'a>>>,
) {
let window = &*(handle as *const ComponentWindow);
window.free_graphics_resources(component)
window.free_graphics_resources(items)
}
/// Sets the focus item.

View file

@ -20,7 +20,6 @@ LICENSE END */
created by the backend in a type-erased manner.
*/
extern crate alloc;
use crate::component::{ComponentRc, ComponentWeak};
use crate::input::{KeyEvent, KeyboardModifiers, MouseEvent, MouseEventType};
use crate::items::ItemRef;
use crate::properties::{InterpolatedPropertyValue, Property, PropertyTracker};
@ -29,6 +28,10 @@ use crate::rtti::{BuiltinItem, FieldInfo, PropertyInfo, ValueType};
use crate::SharedArray;
#[cfg(feature = "rtti")]
use crate::Signal;
use crate::{
component::{ComponentRc, ComponentWeak},
slice::Slice,
};
use auto_enums::auto_enum;
use cgmath::Matrix4;
@ -820,14 +823,11 @@ impl<Backend: GraphicsBackend> crate::eventloop::GenericWindow for GraphicsWindo
)
}
fn free_graphics_resources(
self: Rc<Self>,
component: core::pin::Pin<crate::component::ComponentRef>,
) {
fn free_graphics_resources<'a>(self: Rc<Self>, items: &Slice<'a, Pin<ItemRef<'a>>>) {
match &*self.map_state.borrow() {
GraphicsWindowBackendState::Unmapped => {}
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,
};
use super::items::ItemRef;
use crate::eventloop::ComponentWindow;
use crate::item_tree::ItemVisitorResult;
use crate::{eventloop::ComponentWindow, slice::Slice};
use cgmath::{Matrix4, SquareMatrix, Vector3};
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>(
component: crate::component::ComponentRefPin,
pub(crate) fn free_item_rendering_data<'a, Backend: GraphicsBackend>(
items: &Slice<'a, core::pin::Pin<ItemRef<'a>>>,
rendering_cache: &RefCell<RenderingCache<Backend>>,
) {
crate::item_tree::visit_items(
component,
crate::item_tree::TraversalOrder::FrontToBack,
|_, item, _| {
for item in items.iter() {
let cached_rendering_data = item.cached_rendering_data_offset();
cached_rendering_data.release(rendering_cache);
ItemVisitorResult::Continue(())
},
(),
);
}
}

View file

@ -77,9 +77,19 @@ impl<'id> ComponentBox<'id> {
impl<'id> Drop for ComponentBox<'id> {
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) => {
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 => {}
}