Skip to content

Commit faa8ce4

Browse files
committed
[vello_hybrid]: add example for image destruction
1 parent 805986f commit faa8ce4

File tree

14 files changed

+297
-102
lines changed

14 files changed

+297
-102
lines changed

sparse_strips/vello_hybrid/examples/native_webgl/src/lib.rs

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,11 @@
1111

1212
use std::cell::RefCell;
1313
use std::rc::Rc;
14-
use vello_common::kurbo::{Affine, Vec2};
15-
use vello_hybrid_scenes::AnyScene;
14+
use vello_common::{
15+
kurbo::{Affine, Vec2},
16+
paint::ImageId,
17+
};
18+
use vello_hybrid_scenes::{AnyScene, SceneResources};
1619
use wasm_bindgen::prelude::*;
1720
use web_sys::{Event, HtmlCanvasElement, KeyboardEvent, MouseEvent, WheelEvent};
1821

@@ -41,6 +44,8 @@ struct AppState {
4144
renderer_wrapper: RendererWrapper,
4245
need_render: bool,
4346
canvas: HtmlCanvasElement,
47+
scene_resources: SceneResources,
48+
uploaded_images: Vec<ImageId>,
4449
}
4550

4651
impl AppState {
@@ -62,6 +67,8 @@ impl AppState {
6267
renderer_wrapper,
6368
need_render: true,
6469
canvas,
70+
scene_resources: SceneResources::new(),
71+
uploaded_images: Vec::new(),
6572
};
6673

6774
app_state.upload_images_to_atlas();
@@ -77,7 +84,11 @@ impl AppState {
7784
self.scene.reset();
7885

7986
// Render the current scene with transform
80-
self.scenes[self.current_scene].render(&mut self.scene, self.transform);
87+
self.scenes[self.current_scene].render(
88+
&mut self.scene,
89+
self.transform,
90+
&self.scene_resources,
91+
);
8192

8293
let render_size = vello_hybrid::RenderSize {
8394
width: self.width,
@@ -118,8 +129,9 @@ impl AppState {
118129
self.need_render = true;
119130
}
120131

121-
fn reset_transform(&mut self) {
132+
fn reset_scene(&mut self) {
122133
self.transform = Affine::IDENTITY;
134+
self.upload_images_to_atlas();
123135
self.need_render = true;
124136
}
125137

@@ -180,14 +192,27 @@ impl AppState {
180192
fn upload_images_to_atlas(&mut self) {
181193
use vello_hybrid_scenes::image::ImageScene;
182194

195+
self.scene_resources.images.clear();
196+
self.uploaded_images.clear();
197+
183198
// 1st example — uploading pixmap directly to WebGL atlas
184199
let pixmap1 = ImageScene::read_flower_image();
185-
self.renderer_wrapper.renderer.upload_image(&pixmap1);
200+
let image_id1 = self.renderer_wrapper.renderer.upload_image(&pixmap1);
186201

187202
// 2nd example — uploading from a WebGL texture
188203
let pixmap2 = ImageScene::read_cowboy_image();
189204
let texture2 = self.pixmap_to_webgl_texture(&pixmap2);
190-
self.renderer_wrapper.renderer.upload_image(&texture2);
205+
let image_id2 = self.renderer_wrapper.renderer.upload_image(&texture2);
206+
207+
self.scene_resources.images = vec![image_id1, image_id2];
208+
self.uploaded_images = vec![image_id2, image_id1];
209+
}
210+
211+
fn handle_destroy_image(&mut self) {
212+
if let Some(image_id) = self.uploaded_images.pop() {
213+
self.renderer_wrapper.renderer.destroy_image(image_id);
214+
}
215+
self.need_render = true;
191216
}
192217

193218
/// Convert a pixmap to WebGL texture
@@ -382,7 +407,8 @@ pub async fn run_interactive(canvas_width: u16, canvas_height: u16) {
382407
Box::new(move |event: KeyboardEvent| match event.key().as_str() {
383408
"ArrowRight" => app_state.borrow_mut().next_scene(),
384409
"ArrowLeft" => app_state.borrow_mut().prev_scene(),
385-
" " => app_state.borrow_mut().reset_transform(),
410+
"d" => app_state.borrow_mut().handle_destroy_image(),
411+
" " => app_state.borrow_mut().reset_scene(),
386412
_ => {}
387413
}) as Box<dyn FnMut(_)>,
388414
);
@@ -396,7 +422,7 @@ pub async fn run_interactive(canvas_width: u16, canvas_height: u16) {
396422
let document = web_sys::window().unwrap().document().unwrap();
397423
let instructions = document.create_element("div").unwrap();
398424
instructions.set_inner_html(
399-
"Left/Right Arrow: Change scene | Space: Reset view | Mouse Drag: Pan | Mouse Wheel: Zoom",
425+
"Left/Right Arrow: Change scene | Space: Reset scene | D: Destroy image | Mouse Drag: Pan | Mouse Wheel: Zoom",
400426
);
401427
let style = instructions
402428
.dyn_ref::<web_sys::HtmlElement>()

sparse_strips/vello_hybrid/examples/scenes/src/clip.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use vello_hybrid::Scene;
2222
pub struct ClipScene {}
2323

2424
impl ExampleScene for ClipScene {
25-
fn render(&mut self, ctx: &mut Scene, root_transform: Affine) {
25+
fn render(&mut self, ctx: &mut Scene, root_transform: Affine, _resources: &crate::SceneResources) {
2626
render(ctx, root_transform);
2727
}
2828
}

sparse_strips/vello_hybrid/examples/scenes/src/image.rs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,28 @@ use vello_common::peniko::ImageFormat;
1010
use vello_common::pixmap::Pixmap;
1111
use vello_common::{
1212
kurbo::{Affine, Rect},
13-
paint::{Image, ImageId, ImageSource},
13+
paint::{Image, ImageSource},
1414
peniko::{Extend, ImageQuality},
1515
};
1616
use vello_hybrid::Scene;
1717

18-
use crate::ExampleScene;
18+
use crate::{ExampleScene, SceneResources};
1919

20-
/// Image scene state
21-
#[derive(Debug)]
22-
pub struct ImageScene {}
20+
/// Image scene shows how to use images in the scene.
21+
#[derive(Debug, Default)]
22+
pub struct ImageScene;
23+
24+
impl ImageScene {
25+
/// Create a new image scene
26+
pub fn new() -> Self {
27+
Self
28+
}
29+
}
2330

2431
impl ExampleScene for ImageScene {
25-
fn render(&mut self, scene: &mut Scene, root_transform: Affine) {
26-
let splash_flower_id = ImageId::new(0);
27-
let cowboy_id = ImageId::new(1);
32+
fn render(&mut self, scene: &mut Scene, root_transform: Affine, resources: &SceneResources) {
33+
let splash_flower_id = resources.images.first().copied().unwrap();
34+
let cowboy_id = resources.images.get(1).copied().unwrap();
2835

2936
scene.set_transform(
3037
root_transform
@@ -73,7 +80,7 @@ impl ExampleScene for ImageScene {
7380
);
7481
scene.set_paint_transform(Affine::scale(0.25));
7582
scene.set_paint(Image {
76-
source: ImageSource::OpaqueId(ImageId::new(0)),
83+
source: ImageSource::OpaqueId(splash_flower_id),
7784
x_extend: Extend::Repeat,
7885
y_extend: Extend::Repeat,
7986
quality: ImageQuality::Low,

sparse_strips/vello_hybrid/examples/scenes/src/lib.rs

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,30 @@ pub mod svg;
1010
pub mod text;
1111

1212
use vello_common::kurbo::Affine;
13+
use vello_common::paint::ImageId;
1314
use vello_hybrid::Scene;
1415

15-
/// Example scene that can maintain state between renders
16+
/// Resources that scenes may need each frame.
17+
#[derive(Debug, Clone, Default)]
18+
pub struct SceneResources {
19+
/// Image ids that have been uploaded to the GPU.
20+
pub images: Vec<ImageId>,
21+
}
22+
23+
impl SceneResources {
24+
/// Create a new instance
25+
pub fn new() -> Self {
26+
Self { images: Vec::new() }
27+
}
28+
}
29+
30+
/// Example scene that can maintain state between renders.
31+
///
32+
/// The `resources` parameter contains data such a uploaded image ids.
33+
/// Scenes that do not require external resources can ignore this parameter.
1634
pub trait ExampleScene {
17-
/// Render the scene using the current state
18-
fn render(&mut self, scene: &mut Scene, root_transform: Affine);
35+
/// Render the scene using the current state.
36+
fn render(&mut self, scene: &mut Scene, root_transform: Affine, resources: &SceneResources);
1937
}
2038

2139
/// A type-erased example scene
@@ -25,7 +43,7 @@ pub struct AnyScene {
2543
}
2644

2745
/// A type-erased render function
28-
type RenderFn = Box<dyn FnMut(&mut Scene, Affine)>;
46+
type RenderFn = Box<dyn FnMut(&mut Scene, Affine, &SceneResources)>;
2947

3048
impl std::fmt::Debug for AnyScene {
3149
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
@@ -37,13 +55,18 @@ impl AnyScene {
3755
/// Create a new `AnyScene` from any type that implements `ExampleScene`
3856
pub fn new<T: ExampleScene + 'static>(mut scene: T) -> Self {
3957
Self {
40-
render_fn: Box::new(move |s, transform| scene.render(s, transform)),
58+
render_fn: Box::new(move |s, transform, res| scene.render(s, transform, res)),
4159
}
4260
}
4361

4462
/// Render the scene
45-
pub fn render(&mut self, scene: &mut Scene, root_transform: Affine) {
46-
(self.render_fn)(scene, root_transform);
63+
pub fn render(
64+
&mut self,
65+
scene: &mut Scene,
66+
root_transform: Affine,
67+
resources: &SceneResources,
68+
) {
69+
(self.render_fn)(scene, root_transform, resources);
4770
}
4871
}
4972

@@ -67,7 +90,7 @@ pub fn get_example_scenes(svg_paths: Option<Vec<&str>>) -> Box<[AnyScene]> {
6790
scenes.push(AnyScene::new(text::TextScene::new("Hello, Vello!")));
6891
scenes.push(AnyScene::new(simple::SimpleScene::new()));
6992
scenes.push(AnyScene::new(clip::ClipScene::new()));
70-
scenes.push(AnyScene::new(image::ImageScene {}));
93+
scenes.push(AnyScene::new(image::ImageScene::new()));
7194

7295
scenes.into_boxed_slice()
7396
}
@@ -80,7 +103,7 @@ pub fn get_example_scenes() -> Box<[AnyScene]> {
80103
AnyScene::new(text::TextScene::new("Hello, Vello!")),
81104
AnyScene::new(simple::SimpleScene::new()),
82105
AnyScene::new(clip::ClipScene::new()),
83-
AnyScene::new(image::ImageScene {}),
106+
AnyScene::new(image::ImageScene::new()),
84107
]
85108
.into_boxed_slice()
86109
}

sparse_strips/vello_hybrid/examples/scenes/src/simple.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use crate::ExampleScene;
1414
pub struct SimpleScene {}
1515

1616
impl ExampleScene for SimpleScene {
17-
fn render(&mut self, ctx: &mut Scene, root_transform: Affine) {
17+
fn render(&mut self, ctx: &mut Scene, root_transform: Affine, _resources: &crate::SceneResources) {
1818
render(ctx, root_transform);
1919
}
2020
}

sparse_strips/vello_hybrid/examples/scenes/src/svg.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ impl fmt::Debug for SvgScene {
2626
}
2727

2828
impl ExampleScene for SvgScene {
29-
fn render(&mut self, scene: &mut Scene, root_transform: Affine) {
29+
fn render(&mut self, scene: &mut Scene, root_transform: Affine, _resources: &crate::SceneResources) {
3030
render_svg(scene, &self.svg.items, root_transform * self.transform);
3131
}
3232
}

sparse_strips/vello_hybrid/examples/scenes/src/text.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ impl fmt::Debug for TextScene {
4545
}
4646

4747
impl ExampleScene for TextScene {
48-
fn render(&mut self, scene: &mut Scene, root_transform: Affine) {
48+
fn render(&mut self, scene: &mut Scene, root_transform: Affine, _resources: &crate::SceneResources) {
4949
scene.set_transform(root_transform);
5050
render_text(self, scene);
5151
}

0 commit comments

Comments
 (0)