mirror of
https://github.com/slint-ui/slint.git
synced 2025-11-03 13:23:00 +00:00
Qt: use a HashMap for the cache
And not the cache dirrectly within the item, because it is already in use for the partial rendering
This commit is contained in:
parent
d2186593c0
commit
615c7635ee
13 changed files with 137 additions and 109 deletions
|
|
@ -295,7 +295,6 @@ fn gen_corelib(
|
|||
"slint_windowrc_hide",
|
||||
"slint_windowrc_get_scale_factor",
|
||||
"slint_windowrc_set_scale_factor",
|
||||
"slint_windowrc_free_graphics_resources",
|
||||
"slint_windowrc_set_focus_item",
|
||||
"slint_windowrc_set_component",
|
||||
"slint_windowrc_show_popup",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
# Changelog
|
||||
All notable changes to this crate will be documented in this file.
|
||||
|
||||
## [0.1.8] - Unreleased
|
||||
|
||||
- Changed the representation of the different types to use NonNull
|
||||
- Added `VRef::as_ptr`
|
||||
|
||||
## [0.1.7] - 2022-05-04
|
||||
|
||||
- Implement `Debug` for `VRc`
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
[package]
|
||||
name = "vtable"
|
||||
version = "0.1.7"
|
||||
version = "0.1.8"
|
||||
authors = ["Slint Developers <info@slint-ui.com>"]
|
||||
edition = "2021"
|
||||
license = "GPL-3.0-only OR LicenseRef-Slint-commercial"
|
||||
|
|
@ -14,7 +14,7 @@ homepage = "https://slint-ui.com"
|
|||
[lib]
|
||||
|
||||
[dependencies]
|
||||
vtable-macro = { version = "=0.1.7", path = "./macro" }
|
||||
vtable-macro = { version = "=0.1.8", path = "./macro" }
|
||||
const-field-offset = { version = "0.1", path = "../const-field-offset" }
|
||||
stable_deref_trait = { version = "1.2.0", default-features = false }
|
||||
atomic-polyfill = "0.1.5"
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
[package]
|
||||
name = "vtable-macro"
|
||||
version = "0.1.7"
|
||||
version = "0.1.8"
|
||||
authors = ["Slint Developers <info@slint-ui.com>"]
|
||||
edition = "2021"
|
||||
license = "GPL-3.0-only OR LicenseRef-Slint-commercial"
|
||||
|
|
|
|||
|
|
@ -303,6 +303,11 @@ impl<'a, T: ?Sized + VTableMeta> VRef<'a, T> {
|
|||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a pointer to the VRef's instance. This is primarily useful for comparisons.
|
||||
pub fn as_ptr(this: Self) -> NonNull<u8> {
|
||||
this.inner.ptr
|
||||
}
|
||||
}
|
||||
|
||||
/// `VRefMut<'a MyTraitVTable>` can be thought as a `&'a mut dyn MyTrait`
|
||||
|
|
|
|||
|
|
@ -299,7 +299,11 @@ impl PlatformWindow for GLWindow {
|
|||
}
|
||||
}
|
||||
|
||||
fn free_graphics_resources<'a>(&self, items: &mut dyn Iterator<Item = Pin<ItemRef<'a>>>) {
|
||||
fn free_graphics_resources<'a>(
|
||||
&self,
|
||||
_: corelib::component::ComponentRef,
|
||||
items: &mut dyn Iterator<Item = Pin<ItemRef<'a>>>,
|
||||
) {
|
||||
match &*self.map_state.borrow() {
|
||||
GraphicsWindowBackendState::Unmapped => {}
|
||||
GraphicsWindowBackendState::Mapped(_) => {
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ i-slint-core-macros = { version = "=0.2.5", path = "../../../internal/core-macro
|
|||
i-slint-core = { version = "=0.2.5", path = "../../../internal/core" }
|
||||
|
||||
const-field-offset = { version = "0.1", path = "../../../helper_crates/const-field-offset" }
|
||||
vtable = { version = "0.1.6", path = "../../../helper_crates/vtable" }
|
||||
vtable = { version = "0.1.8", path = "../../../helper_crates/vtable" }
|
||||
|
||||
cpp = "0.5.5"
|
||||
euclid = "0.22.1"
|
||||
|
|
|
|||
|
|
@ -5,25 +5,26 @@
|
|||
|
||||
use cpp::*;
|
||||
use euclid::approxeq::ApproxEq;
|
||||
use i_slint_core::component::{ComponentRc, ComponentRef};
|
||||
use i_slint_core::graphics::rendering_metrics_collector::{
|
||||
RenderingMetrics, RenderingMetricsCollector,
|
||||
};
|
||||
use i_slint_core::graphics::{
|
||||
Brush, Color, FontRequest, Image, Point, Rect, RenderingCache, SharedImageBuffer, Size,
|
||||
Brush, CachedGraphicsData, Color, FontRequest, Image, Point, Rect, SharedImageBuffer, Size,
|
||||
};
|
||||
use i_slint_core::input::{KeyEvent, KeyEventType, MouseEvent};
|
||||
use i_slint_core::item_rendering::{CachedRenderingData, ItemRenderer};
|
||||
use i_slint_core::item_rendering::ItemRenderer;
|
||||
use i_slint_core::items::{
|
||||
self, FillRule, ImageRendering, InputType, ItemRc, ItemRef, Layer, MouseCursor, Opacity,
|
||||
PointerEventButton, RenderingResult, TextOverflow, TextWrap,
|
||||
};
|
||||
use i_slint_core::layout::Orientation;
|
||||
use i_slint_core::window::{PlatformWindow, PopupWindow, PopupWindowLocation, WindowRc};
|
||||
use i_slint_core::{component::ComponentRc, SharedString};
|
||||
use i_slint_core::{ImageInner, PathData, Property};
|
||||
use i_slint_core::{ImageInner, PathData, Property, SharedString};
|
||||
use items::{ImageFit, TextHorizontalAlignment, TextVerticalAlignment};
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::pin::Pin;
|
||||
use std::ptr::NonNull;
|
||||
use std::rc::{Rc, Weak};
|
||||
|
|
@ -443,29 +444,63 @@ fn adjust_rect_and_border_for_inner_drawing(rect: &mut qttypes::QRectF, border_w
|
|||
rect.height -= *border_width as f64;
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
enum QtRenderingCacheItem {
|
||||
Pixmap(qttypes::QPixmap),
|
||||
Invalid,
|
||||
#[derive(Default)]
|
||||
struct ItemCache<T> {
|
||||
/// The pointer is a pointer to a component
|
||||
map: RefCell<HashMap<*const vtable::Dyn, HashMap<usize, CachedGraphicsData<T>>>>,
|
||||
}
|
||||
impl<T: Clone> ItemCache<T> {
|
||||
pub fn get_or_update_cache_entry(&self, item_rc: &ItemRc, update_fn: impl FnOnce() -> T) -> T {
|
||||
let component = &(*item_rc.component()) as *const _;
|
||||
let mut borrowed = self.map.borrow_mut();
|
||||
match borrowed.entry(component).or_default().entry(item_rc.index()) {
|
||||
std::collections::hash_map::Entry::Occupied(mut entry) => {
|
||||
let mut tracker = entry.get_mut().dependency_tracker.take();
|
||||
drop(borrowed);
|
||||
let maybe_new_data = tracker
|
||||
.get_or_insert_with(|| Box::pin(Default::default()))
|
||||
.as_ref()
|
||||
.evaluate_if_dirty(update_fn);
|
||||
let mut borrowed = self.map.borrow_mut();
|
||||
let e = borrowed.get_mut(&component).unwrap().get_mut(&item_rc.index()).unwrap();
|
||||
if let Some(new_data) = maybe_new_data {
|
||||
e.data = new_data.clone();
|
||||
new_data
|
||||
} else {
|
||||
e.data.clone()
|
||||
}
|
||||
}
|
||||
std::collections::hash_map::Entry::Vacant(entry) => {
|
||||
entry.insert(CachedGraphicsData::new(update_fn)).data.clone()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for QtRenderingCacheItem {
|
||||
fn default() -> Self {
|
||||
Self::Invalid
|
||||
pub fn clear_all(&self) {
|
||||
self.map.borrow_mut().clear();
|
||||
}
|
||||
pub fn component_destroyed(&self, component: ComponentRef) {
|
||||
let component_ptr: *const _ = ComponentRef::as_ptr(component).cast().as_ptr();
|
||||
self.map.borrow_mut().remove(&component_ptr);
|
||||
}
|
||||
|
||||
pub fn release(&self, item_rc: &ItemRc) {
|
||||
let component = &(*item_rc.component()) as *const _;
|
||||
if let Some(sub) = self.map.borrow_mut().get_mut(&component) {
|
||||
sub.remove(&item_rc.index());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type QtRenderingCache = Rc<RefCell<RenderingCache<QtRenderingCacheItem>>>;
|
||||
|
||||
struct QtItemRenderer {
|
||||
struct QtItemRenderer<'a> {
|
||||
painter: QPainterPtr,
|
||||
cache: QtRenderingCache,
|
||||
cache: &'a ItemCache<qttypes::QPixmap>,
|
||||
default_font_properties: FontRequest,
|
||||
window: WindowRc,
|
||||
metrics: RenderingMetrics,
|
||||
}
|
||||
|
||||
impl ItemRenderer for QtItemRenderer {
|
||||
impl ItemRenderer for QtItemRenderer<'_> {
|
||||
fn draw_rectangle(&mut self, rect_: Pin<&items::Rectangle>, _: &ItemRc) {
|
||||
let rect: qttypes::QRectF = get_geometry!(items::Rectangle, rect_);
|
||||
let brush: qttypes::QBrush = into_qbrush(rect_.background(), rect.width, rect.height);
|
||||
|
|
@ -486,10 +521,10 @@ impl ItemRenderer for QtItemRenderer {
|
|||
);
|
||||
}
|
||||
|
||||
fn draw_image(&mut self, image: Pin<&items::ImageItem>, _: &ItemRc) {
|
||||
fn draw_image(&mut self, image: Pin<&items::ImageItem>, item_rc: &ItemRc) {
|
||||
let dest_rect: qttypes::QRectF = get_geometry!(items::ImageItem, image);
|
||||
self.draw_image_impl(
|
||||
&image.cached_rendering_data,
|
||||
item_rc,
|
||||
items::ImageItem::FIELD_OFFSETS.source.apply_pin(image),
|
||||
dest_rect,
|
||||
None,
|
||||
|
|
@ -501,7 +536,7 @@ impl ItemRenderer for QtItemRenderer {
|
|||
);
|
||||
}
|
||||
|
||||
fn draw_clipped_image(&mut self, image: Pin<&items::ClippedImage>, _: &ItemRc) {
|
||||
fn draw_clipped_image(&mut self, image: Pin<&items::ClippedImage>, item_rc: &ItemRc) {
|
||||
let dest_rect: qttypes::QRectF = get_geometry!(items::ClippedImage, image);
|
||||
let source_rect = qttypes::QRectF {
|
||||
x: image.source_clip_x() as _,
|
||||
|
|
@ -510,7 +545,7 @@ impl ItemRenderer for QtItemRenderer {
|
|||
height: image.source_clip_height() as _,
|
||||
};
|
||||
self.draw_image_impl(
|
||||
&image.cached_rendering_data,
|
||||
item_rc,
|
||||
items::ClippedImage::FIELD_OFFSETS.source.apply_pin(image),
|
||||
dest_rect,
|
||||
Some(source_rect),
|
||||
|
|
@ -758,10 +793,8 @@ impl ItemRenderer for QtItemRenderer {
|
|||
}}
|
||||
}
|
||||
|
||||
fn draw_box_shadow(&mut self, box_shadow: Pin<&items::BoxShadow>, _: &ItemRc) {
|
||||
let cached_shadow_pixmap = box_shadow
|
||||
.cached_rendering_data
|
||||
.get_or_update(&self.cache, || {
|
||||
fn draw_box_shadow(&mut self, box_shadow: Pin<&items::BoxShadow>, item_rc: &ItemRc) {
|
||||
let pixmap : qttypes::QPixmap = self.cache.get_or_update_cache_entry( item_rc, || {
|
||||
let shadow_rect = get_geometry!(items::BoxShadow, box_shadow);
|
||||
|
||||
let source_size = qttypes::QSize {
|
||||
|
|
@ -791,7 +824,7 @@ impl ItemRenderer for QtItemRenderer {
|
|||
|
||||
let blur_radius = box_shadow.blur();
|
||||
|
||||
let shadow_pixmap = if blur_radius > 0. {
|
||||
if blur_radius > 0. {
|
||||
cpp! {
|
||||
unsafe[img as "QImage*", blur_radius as "float"] -> qttypes::QPixmap as "QPixmap" {
|
||||
class PublicGraphicsBlurEffect : public QGraphicsBlurEffect {
|
||||
|
|
@ -827,15 +860,9 @@ impl ItemRenderer for QtItemRenderer {
|
|||
cpp! { unsafe[img as "QImage*"] -> qttypes::QPixmap as "QPixmap" {
|
||||
return QPixmap::fromImage(*img);
|
||||
}}
|
||||
};
|
||||
QtRenderingCacheItem::Pixmap(shadow_pixmap)
|
||||
}
|
||||
});
|
||||
|
||||
let pixmap: &qttypes::QPixmap = match &cached_shadow_pixmap {
|
||||
QtRenderingCacheItem::Pixmap(pixmap) => pixmap,
|
||||
_ => return,
|
||||
};
|
||||
|
||||
let blur_radius = box_shadow.blur();
|
||||
|
||||
let shadow_offset = qttypes::QPointF {
|
||||
|
|
@ -847,26 +874,26 @@ impl ItemRenderer for QtItemRenderer {
|
|||
cpp! { unsafe [
|
||||
painter as "QPainterPtr*",
|
||||
shadow_offset as "QPointF",
|
||||
pixmap as "QPixmap*"
|
||||
pixmap as "QPixmap"
|
||||
] {
|
||||
(*painter)->drawPixmap(shadow_offset, *pixmap);
|
||||
(*painter)->drawPixmap(shadow_offset, pixmap);
|
||||
}}
|
||||
}
|
||||
|
||||
fn visit_opacity(&mut self, opacity_item: Pin<&Opacity>, self_rc: &ItemRc) -> RenderingResult {
|
||||
fn visit_opacity(&mut self, opacity_item: Pin<&Opacity>, item_rc: &ItemRc) -> RenderingResult {
|
||||
let opacity = opacity_item.opacity();
|
||||
if Opacity::need_layer(self_rc, opacity) {
|
||||
self.render_and_blend_layer(&opacity_item.cached_rendering_data, opacity, self_rc)
|
||||
if Opacity::need_layer(item_rc, opacity) {
|
||||
self.render_and_blend_layer(opacity, item_rc)
|
||||
} else {
|
||||
self.apply_opacity(opacity);
|
||||
opacity_item.cached_rendering_data.release(&mut self.cache.borrow_mut());
|
||||
self.cache.release(item_rc);
|
||||
RenderingResult::ContinueRenderingChildren
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_layer(&mut self, layer_item: Pin<&Layer>, self_rc: &ItemRc) -> RenderingResult {
|
||||
if layer_item.cache_rendering_hint() {
|
||||
self.render_and_blend_layer(&layer_item.cached_rendering_data, 1.0, self_rc)
|
||||
self.render_and_blend_layer(1.0, self_rc)
|
||||
} else {
|
||||
RenderingResult::ContinueRenderingChildren
|
||||
}
|
||||
|
|
@ -1115,10 +1142,10 @@ fn is_svg(resource: &ImageInner) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
impl QtItemRenderer {
|
||||
impl QtItemRenderer<'_> {
|
||||
fn draw_image_impl(
|
||||
&mut self,
|
||||
item_cache: &CachedRenderingData,
|
||||
item_rc: &ItemRc,
|
||||
source_property: Pin<&Property<Image>>,
|
||||
dest_rect: qttypes::QRectF,
|
||||
source_rect: Option<qttypes::QRectF>,
|
||||
|
|
@ -1132,7 +1159,7 @@ impl QtItemRenderer {
|
|||
debug_assert!(target_width.get() > 0.);
|
||||
debug_assert!(target_height.get() > 0.);
|
||||
|
||||
let cached = item_cache.get_or_update(&self.cache, || {
|
||||
let pixmap: qttypes::QPixmap = self.cache.get_or_update_cache_entry(item_rc, || {
|
||||
// Query target_width/height here again to ensure that changes will invalidate the item rendering cache.
|
||||
let target_width = target_width.get() as f64;
|
||||
let target_height = target_height.get() as f64;
|
||||
|
|
@ -1152,7 +1179,7 @@ impl QtItemRenderer {
|
|||
};
|
||||
|
||||
load_image_from_resource((&source_property.get()).into(), source_size, image_fit)
|
||||
.map_or(QtRenderingCacheItem::Invalid, |mut pixmap: qttypes::QPixmap| {
|
||||
.map_or_else(Default::default, |mut pixmap: qttypes::QPixmap| {
|
||||
let colorize = colorize_property.map_or(Brush::default(), |c| c.get());
|
||||
if !colorize.is_transparent() {
|
||||
let brush: qttypes::QBrush =
|
||||
|
|
@ -1163,13 +1190,10 @@ impl QtItemRenderer {
|
|||
p.fillRect(QRect(QPoint(), pixmap.size()), brush);
|
||||
});
|
||||
}
|
||||
QtRenderingCacheItem::Pixmap(pixmap)
|
||||
pixmap
|
||||
})
|
||||
});
|
||||
let pixmap: &qttypes::QPixmap = match &cached {
|
||||
QtRenderingCacheItem::Pixmap(pixmap) => pixmap,
|
||||
_ => return,
|
||||
};
|
||||
|
||||
let image_size = pixmap.size();
|
||||
let mut source_rect = source_rect.filter(|r| r.is_valid()).unwrap_or(qttypes::QRectF {
|
||||
x: 0.,
|
||||
|
|
@ -1183,13 +1207,13 @@ impl QtItemRenderer {
|
|||
let smooth: bool = rendering == ImageRendering::smooth;
|
||||
cpp! { unsafe [
|
||||
painter as "QPainterPtr*",
|
||||
pixmap as "QPixmap*",
|
||||
pixmap as "QPixmap",
|
||||
source_rect as "QRectF",
|
||||
dest_rect as "QRectF",
|
||||
smooth as "bool"] {
|
||||
(*painter)->save();
|
||||
(*painter)->setRenderHint(QPainter::SmoothPixmapTransform, smooth);
|
||||
(*painter)->drawPixmap(dest_rect, *pixmap, source_rect);
|
||||
(*painter)->drawPixmap(dest_rect, pixmap, source_rect);
|
||||
(*painter)->restore();
|
||||
}};
|
||||
}
|
||||
|
|
@ -1218,11 +1242,10 @@ impl QtItemRenderer {
|
|||
|
||||
fn render_layer(
|
||||
&mut self,
|
||||
item_cache: &CachedRenderingData,
|
||||
item_rc: &ItemRc,
|
||||
layer_size_fn: &dyn Fn() -> qttypes::QSize,
|
||||
) -> Option<qttypes::QPixmap> {
|
||||
let cache_entry = item_cache.get_or_update(&self.cache.clone(), || {
|
||||
) -> qttypes::QPixmap {
|
||||
self.cache.get_or_update_cache_entry(item_rc, || {
|
||||
let layer_size: qttypes::QSize = layer_size_fn();
|
||||
let mut layer_image = qttypes::QImage::new(layer_size, qttypes::ImageFormat::ARGB32_Premultiplied);
|
||||
layer_image.fill(qttypes::QColor::from_rgba_f(0., 0., 0., 0.));
|
||||
|
|
@ -1247,22 +1270,13 @@ impl QtItemRenderer {
|
|||
std::mem::swap(&mut self.painter, &mut layer_painter);
|
||||
drop(layer_painter);
|
||||
|
||||
QtRenderingCacheItem::Pixmap(qttypes::QPixmap::from(layer_image))
|
||||
});
|
||||
match &cache_entry {
|
||||
QtRenderingCacheItem::Pixmap(pixmap) => Some(pixmap.clone()),
|
||||
_ => None,
|
||||
}
|
||||
qttypes::QPixmap::from(layer_image)
|
||||
})
|
||||
}
|
||||
|
||||
fn render_and_blend_layer(
|
||||
&mut self,
|
||||
item_cache: &CachedRenderingData,
|
||||
alpha_tint: f32,
|
||||
self_rc: &ItemRc,
|
||||
) -> RenderingResult {
|
||||
fn render_and_blend_layer(&mut self, alpha_tint: f32, self_rc: &ItemRc) -> RenderingResult {
|
||||
let current_clip = self.get_current_clip();
|
||||
if let Some(mut layer_image) = self.render_layer(item_cache, self_rc, &|| {
|
||||
let mut layer_image = self.render_layer(self_rc, &|| {
|
||||
// We don't need to include the size of the opacity item itself, since it has no content.
|
||||
let children_rect = i_slint_core::properties::evaluate_no_tracking(|| {
|
||||
let self_ref = self_rc.borrow();
|
||||
|
|
@ -1278,21 +1292,20 @@ impl QtItemRenderer {
|
|||
width: children_rect.size.width as _,
|
||||
height: children_rect.size.height as _,
|
||||
}
|
||||
}) {
|
||||
self.save_state();
|
||||
self.apply_opacity(alpha_tint);
|
||||
{
|
||||
let painter: &mut QPainterPtr = &mut self.painter;
|
||||
let layer_image_ref: &mut qttypes::QPixmap = &mut layer_image;
|
||||
cpp! { unsafe [
|
||||
painter as "QPainterPtr*",
|
||||
layer_image_ref as "QPixmap*"
|
||||
] {
|
||||
(*painter)->drawPixmap(0, 0, *layer_image_ref);
|
||||
}}
|
||||
}
|
||||
self.restore_state();
|
||||
});
|
||||
self.save_state();
|
||||
self.apply_opacity(alpha_tint);
|
||||
{
|
||||
let painter: &mut QPainterPtr = &mut self.painter;
|
||||
let layer_image_ref: &mut qttypes::QPixmap = &mut layer_image;
|
||||
cpp! { unsafe [
|
||||
painter as "QPainterPtr*",
|
||||
layer_image_ref as "QPixmap*"
|
||||
] {
|
||||
(*painter)->drawPixmap(0, 0, *layer_image_ref);
|
||||
}}
|
||||
}
|
||||
self.restore_state();
|
||||
RenderingResult::ContinueRenderingWithoutChildren
|
||||
}
|
||||
}
|
||||
|
|
@ -1305,7 +1318,7 @@ pub struct QtWindow {
|
|||
|
||||
rendering_metrics_collector: Option<Rc<RenderingMetricsCollector>>,
|
||||
|
||||
cache: QtRenderingCache,
|
||||
cache: ItemCache<qttypes::QPixmap>,
|
||||
}
|
||||
|
||||
impl QtWindow {
|
||||
|
|
@ -1339,10 +1352,9 @@ impl QtWindow {
|
|||
let runtime_window = self.self_weak.upgrade().unwrap();
|
||||
runtime_window.clone().draw_contents(|components| {
|
||||
i_slint_core::animations::update_animations();
|
||||
let cache = self.cache.clone();
|
||||
let mut renderer = QtItemRenderer {
|
||||
painter,
|
||||
cache,
|
||||
cache: &self.cache,
|
||||
default_font_properties: self.default_font_properties(),
|
||||
window: runtime_window,
|
||||
metrics: RenderingMetrics { layers_created: Some(0) },
|
||||
|
|
@ -1552,11 +1564,12 @@ impl PlatformWindow for QtWindow {
|
|||
}};
|
||||
}
|
||||
|
||||
fn free_graphics_resources<'a>(&self, items: &mut dyn Iterator<Item = Pin<ItemRef<'a>>>) {
|
||||
for item in items {
|
||||
let cached_rendering_data = item.cached_rendering_data_offset();
|
||||
cached_rendering_data.release(&mut self.cache.borrow_mut());
|
||||
}
|
||||
fn free_graphics_resources<'a>(
|
||||
&self,
|
||||
component: ComponentRef,
|
||||
_: &mut dyn Iterator<Item = Pin<ItemRef<'a>>>,
|
||||
) {
|
||||
self.cache.component_destroyed(component);
|
||||
}
|
||||
|
||||
fn show_popup(&self, popup: &i_slint_core::component::ComponentRc, position: Point) {
|
||||
|
|
|
|||
|
|
@ -95,6 +95,7 @@ impl PlatformWindow for TestingWindow {
|
|||
|
||||
fn free_graphics_resources<'a>(
|
||||
&self,
|
||||
_: i_slint_core::component::ComponentRef,
|
||||
_items: &mut dyn Iterator<Item = Pin<i_slint_core::items::ItemRef<'a>>>,
|
||||
) {
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1122,7 +1122,9 @@ fn generate_item_tree(
|
|||
|
||||
impl slint::re_exports::PinnedDrop for #inner_component_id {
|
||||
fn drop(self: core::pin::Pin<&mut #inner_component_id>) {
|
||||
slint::re_exports::free_component_item_graphics_resources(self.as_ref(), Self::item_array(), self.window.get().unwrap().window_handle());
|
||||
use slint::re_exports::*;
|
||||
new_vref!(let vref : VRef<ComponentVTable> for Component = self.as_ref().get_ref());
|
||||
slint::re_exports::free_component_item_graphics_resources(self.as_ref(), vref, Self::item_array(), self.window.get().unwrap().window_handle());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -108,10 +108,14 @@ pub fn init_component_items<Base>(
|
|||
/// Free the backend graphics resources allocated by the component's items.
|
||||
pub fn free_component_item_graphics_resources<Base>(
|
||||
base: core::pin::Pin<&Base>,
|
||||
component: ComponentRef,
|
||||
item_array: &[vtable::VOffset<Base, ItemVTable, vtable::AllowPin>],
|
||||
window: &WindowRc,
|
||||
) {
|
||||
window.free_graphics_resources(&mut item_array.iter().map(|item| item.apply_pin(base)));
|
||||
window.free_graphics_resources(
|
||||
component,
|
||||
&mut item_array.iter().map(|item| item.apply_pin(base)),
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(feature = "ffi")]
|
||||
|
|
@ -145,6 +149,7 @@ pub(crate) mod ffi {
|
|||
let window = &*(window_handle as *const WindowRc);
|
||||
super::free_component_item_graphics_resources(
|
||||
core::pin::Pin::new_unchecked(&*(component.as_ptr() as *const u8)),
|
||||
core::pin::Pin::into_inner(component),
|
||||
item_array.as_slice(),
|
||||
window,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
//! Exposed Window API
|
||||
|
||||
use crate::api::CloseRequestResponse;
|
||||
use crate::component::{ComponentRc, ComponentWeak};
|
||||
use crate::component::{ComponentRc, ComponentRef, ComponentWeak};
|
||||
use crate::graphics::{Point, Rect, Size};
|
||||
use crate::input::{key_codes, KeyEvent, MouseEvent, MouseInputState, TextCursorBlinker};
|
||||
use crate::item_tree::ItemRc;
|
||||
|
|
@ -41,7 +41,11 @@ pub trait PlatformWindow {
|
|||
|
||||
/// 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<'a>(&self, items: &mut dyn Iterator<Item = Pin<ItemRef<'a>>>);
|
||||
fn free_graphics_resources<'a>(
|
||||
&self,
|
||||
component: ComponentRef,
|
||||
items: &mut dyn Iterator<Item = Pin<ItemRef<'a>>>,
|
||||
);
|
||||
|
||||
/// This function is called through the public API to register a callback that the backend needs to invoke during
|
||||
/// different phases of rendering.
|
||||
|
|
@ -697,7 +701,6 @@ pub mod ffi {
|
|||
|
||||
use super::*;
|
||||
use crate::api::{RenderingNotifier, RenderingState, SetRenderingNotifierError};
|
||||
use crate::slice::Slice;
|
||||
|
||||
/// This enum describes a low-level access to specific graphics APIs used
|
||||
/// by the renderer.
|
||||
|
|
@ -764,16 +767,6 @@ pub mod ffi {
|
|||
window.set_scale_factor(value)
|
||||
}
|
||||
|
||||
/// Sets the window scale factor, merely for testing purposes.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_windowrc_free_graphics_resources<'a>(
|
||||
handle: *const WindowRcOpaque,
|
||||
items: &Slice<'a, Pin<ItemRef<'a>>>,
|
||||
) {
|
||||
let window = &*(handle as *const WindowRc);
|
||||
window.free_graphics_resources(&mut items.iter().cloned())
|
||||
}
|
||||
|
||||
/// Sets the focus item.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_windowrc_set_focus_item(
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ impl<'id> Drop for ComponentBox<'id> {
|
|||
if let Some(window) = eval::window_ref(instance_ref) {
|
||||
i_slint_core::component::free_component_item_graphics_resources(
|
||||
instance_ref.instance,
|
||||
Pin::into_inner(instance_ref.borrow()),
|
||||
instance_ref.component_type.item_array.as_slice(),
|
||||
window,
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue