Skip to main content

ferroui_base/rendering/composition/drawing/
composition_render_data.rs

1use super::render_data_drawing_context::RecordedResource;
2use super::{RenderDataStream, ServerCompositionRenderData};
3use crate::media::{Geometry, IntersectionResult};
4use crate::rendering::composition::server::ServerObjectId;
5use crate::rendering::composition::transport::BatchStreamWriter;
6use crate::rendering::composition::{Compositor, ICompositorSerializable};
7use crate::{Point, Ref};
8use std::cell::{Cell, RefCell};
9use std::rc::{Rc, Weak};
10
11/// What a visual drew, on the UI thread: the recorded stream (kept for hit
12/// testing) and the id of its server-side counterpart.
13pub struct CompositionRenderData {
14    compositor: Weak<Compositor>,
15    stream: RefCell<RenderDataStream>,
16    resources: RefCell<Vec<RecordedResource>>,
17    items_sent: Cell<bool>,
18    server: ServerObjectId,
19}
20
21impl CompositionRenderData {
22    pub(crate) fn new(
23        compositor: &Rc<Compositor>,
24        stream: RenderDataStream,
25        resources: Vec<RecordedResource>,
26    ) -> Rc<CompositionRenderData> {
27        let server = compositor.create_server_object(|server_compositor, _| ServerCompositionRenderData::new(server_compositor));
28        Rc::new(CompositionRenderData {
29            compositor: Rc::downgrade(compositor),
30            stream: RefCell::new(stream),
31            resources: RefCell::new(resources),
32            items_sent: Cell::new(false),
33            server,
34        })
35    }
36
37    /// The id of the server-side render data.
38    pub fn server(&self) -> ServerObjectId {
39        self.server
40    }
41
42    /// Releases the render data: the resource references it holds and its
43    /// server-side counterpart.
44    pub fn dispose(&self) {
45        let mut stream = self.stream.borrow_mut();
46        if !self.items_sent.get() {
47            stream.dispose_resources();
48        }
49        let compositor = self.compositor.upgrade();
50        for resource in self.resources.borrow_mut().drain(..) {
51            if let Some(compositor) = &compositor {
52                resource.with_resource(|r| r.release_on_compositor(compositor));
53            }
54        }
55        stream.dispose();
56        self.items_sent.set(false);
57        if let Some(compositor) = compositor {
58            compositor.dispose_on_next_batch(self.server);
59        }
60    }
61
62    /// Whether anything drawn is hit at a point.
63    pub fn hit_test(&self, pt: Point) -> bool {
64        self.stream.borrow().hit_test(pt)
65    }
66
67    /// How the drawn content intersects a geometry.
68    pub fn hit_test_geometry(&self, geometry: &Ref<Geometry>) -> IntersectionResult {
69        self.stream.borrow().hit_test_geometry(geometry)
70    }
71}
72
73impl ICompositorSerializable for CompositionRenderData {
74    fn try_get_server(&self, _c: &Compositor) -> Option<ServerObjectId> {
75        Some(self.server)
76    }
77
78    fn serialize_changes(&self, _c: &Compositor, writer: &mut BatchStreamWriter<'_>) {
79        self.stream.borrow().serialize_to(writer);
80        self.items_sent.set(true);
81    }
82}