-
Notifications
You must be signed in to change notification settings - Fork 136
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add SDL2 & C-powered window handling compatibility. (#671)
This pull request adds `create_surface_unsafe()`, that allows you to add unsafe surface targets. This allows Vello to be used in SDL2, and it should also work in other libraries like GLFW, but that's not tested yet. Here's a screenshot of Vello running in SDL2, i'll push an example of it soon :D. ![image](https://github.com/user-attachments/assets/f968ea22-bbcd-4408-91d4-2e8c15b2df20) --------- Co-authored-by: Daniel McNab <[email protected]>
- Loading branch information
1 parent
3c8dc79
commit 5a7c34e
Showing
6 changed files
with
246 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
[package] | ||
name = "simple_sdl2" | ||
edition.workspace = true | ||
license.workspace = true | ||
repository.workspace = true | ||
publish = false | ||
|
||
[lints] | ||
workspace = true | ||
|
||
# The dependencies here are independent from the workspace versions | ||
[dependencies] | ||
# When using this example outside of the original Vello workspace, | ||
# remove the path property of the following Vello dependency requirement. | ||
vello = { version = "0.2.0", path = "../../vello" } | ||
pollster = "0.3.0" | ||
sdl2 = { version = "0.37.0", features = ["raw-window-handle", "bundled"] } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
// 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::util::{RenderContext, RenderSurface}; | ||
use vello::{AaConfig, DebugLayers, Renderer, RendererOptions, Scene}; | ||
|
||
use vello::wgpu; | ||
|
||
pub 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]; | ||
|
||
let surface_texture = surface | ||
.surface | ||
.get_current_texture() | ||
.expect("failed to get surface texture"); | ||
|
||
renderers[surface.dev_id] | ||
.as_mut() | ||
.unwrap() | ||
.render_to_surface( | ||
&device_handle.device, | ||
&device_handle.queue, | ||
&scene, | ||
&surface_texture, | ||
&vello::RenderParams { | ||
base_color: Color::BLACK, // Background color | ||
width, | ||
height, | ||
antialiasing_method: AaConfig::Msaa16, | ||
debug: DebugLayers::none(), | ||
}, | ||
) | ||
.expect("failed to render to surface"); | ||
|
||
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 { | ||
surface_format: Some(surface.format), | ||
use_cpu: false, | ||
antialiasing_support: vello::AaSupport::all(), | ||
num_init_threads: NonZeroUsize::new(1), | ||
}, | ||
) | ||
.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::rgb(0.9804, 0.702, 0.5294); | ||
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::rgb(0.9529, 0.5451, 0.6588); | ||
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::rgb(0.7961, 0.651, 0.9686); | ||
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::rgb(0.5373, 0.7059, 0.9804); | ||
scene.stroke(&stroke, Affine::IDENTITY, line_stroke_color, None, &line); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters