blob: 5155b740aa994cb40c6354db41f4b5bc8739f682 [file] [log] [blame] [edit]
// Copyright 2024 the Vello Authors
// SPDX-License-Identifier: Apache-2.0 OR MIT
//! Vello can also be used with non-Winit crates which provide a `RawWindowHandle`.
//! This example uses it with [`sdl2`].
//!
//! Vello however is primarily designed for Xilem, which uses Winit, and so support for non-Winit crates
//! is on a tier-2 basis, i.e. it is checked in CI, but is not rarely manually validated.
extern crate sdl2;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use std::num::NonZeroUsize;
use vello::kurbo::{Affine, Circle, Ellipse, Line, RoundedRect, Stroke};
use vello::peniko::Color;
use vello::peniko::color::palette;
use vello::util::{RenderContext, RenderSurface};
use vello::{AaConfig, Renderer, RendererOptions, Scene};
use vello::wgpu;
fn main() {
let sdl_context = sdl2::init().unwrap();
let video_subsystem = sdl_context.video().unwrap();
let width: u32 = 800;
let height: u32 = 600;
let window = video_subsystem
.window("Vello SDL2 Demo", width, height)
.position_centered()
.metal_view()
.build()
.unwrap();
let mut context = RenderContext::new();
let surface_future = unsafe {
context.create_render_surface(
context
.instance
.create_surface_unsafe(wgpu::SurfaceTargetUnsafe::from_window(&window).unwrap())
.unwrap(),
width,
height,
wgpu::PresentMode::AutoVsync,
)
};
let surface = pollster::block_on(surface_future).expect("Error creating surface.");
let mut renderers: Vec<Option<Renderer>> = vec![];
renderers.resize_with(context.devices.len(), || None);
let _ = renderers[surface.dev_id].insert(create_vello_renderer(&context, &surface));
let mut scene = Scene::new();
let mut event_pump = sdl_context.event_pump().unwrap();
'running: loop {
scene.reset();
add_shapes_to_scene(&mut scene);
let device_handle = &context.devices[surface.dev_id];
renderers[surface.dev_id]
.as_mut()
.unwrap()
.render_to_texture(
&device_handle.device,
&device_handle.queue,
&scene,
&surface.target_view,
&vello::RenderParams {
base_color: palette::css::BLACK, // Background color
width,
height,
antialiasing_method: AaConfig::Msaa16,
},
)
.expect("failed to render to surface");
let surface_texture = surface
.surface
.get_current_texture()
.expect("failed to get surface texture");
let mut encoder =
device_handle
.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor {
label: Some("Surface Blit"),
});
surface.blitter.copy(
&device_handle.device,
&mut encoder,
&surface.target_view,
&surface_texture
.texture
.create_view(&wgpu::TextureViewDescriptor::default()),
);
device_handle.queue.submit([encoder.finish()]);
for event in event_pump.poll_iter() {
match event {
Event::Quit { .. }
| Event::KeyDown {
keycode: Some(Keycode::Escape),
..
} => break 'running,
_ => {}
}
}
surface_texture.present();
}
}
fn create_vello_renderer(render_cx: &RenderContext, surface: &RenderSurface<'_>) -> Renderer {
Renderer::new(
&render_cx.devices[surface.dev_id].device,
RendererOptions {
use_cpu: false,
antialiasing_support: vello::AaSupport::all(),
num_init_threads: NonZeroUsize::new(1),
pipeline_cache: None,
},
)
.expect("Couldn't create renderer")
}
fn add_shapes_to_scene(scene: &mut Scene) {
// Draw an outlined rectangle
let stroke = Stroke::new(6.0);
let rect = RoundedRect::new(10.0, 10.0, 240.0, 240.0, 20.0);
let rect_stroke_color = Color::new([0.9804, 0.702, 0.5294, 1.]);
scene.stroke(&stroke, Affine::IDENTITY, rect_stroke_color, None, &rect);
// Draw a filled circle
let circle = Circle::new((420.0, 200.0), 120.0);
let circle_fill_color = Color::new([0.9529, 0.5451, 0.6588, 1.]);
scene.fill(
vello::peniko::Fill::NonZero,
Affine::IDENTITY,
circle_fill_color,
None,
&circle,
);
// Draw a filled ellipse
let ellipse = Ellipse::new((250.0, 420.0), (100.0, 160.0), -90.0);
let ellipse_fill_color = Color::new([0.7961, 0.651, 0.9686, 1.]);
scene.fill(
vello::peniko::Fill::NonZero,
Affine::IDENTITY,
ellipse_fill_color,
None,
&ellipse,
);
// Draw a straight line
let line = Line::new((260.0, 20.0), (620.0, 100.0));
let line_stroke_color = Color::new([0.5373, 0.7059, 0.9804, 1.]);
scene.stroke(&stroke, Affine::IDENTITY, line_stroke_color, None, &line);
}