Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
847 changes: 19 additions & 828 deletions Cargo.lock

Large diffs are not rendered by default.

11 changes: 10 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ autoexamples = false
[lints]
workspace = true

[features]
default = ["wayland"]
wayland = ["processing_render/wayland"]
x11 = ["processing_render/x11"]

[workspace]
resolver = "3"
members = ["crates/*"]
Expand All @@ -16,9 +21,13 @@ type_complexity = "allow"
too_many_arguments = "allow"

[workspace.dependencies]
bevy = { git = "https://github.com/bevyengine/bevy", branch = "main", no-default-features = true, features = [
bevy = { git = "https://github.com/bevyengine/bevy", branch = "main", default-features = false, features = [
"bevy_render",
"bevy_color",
"bevy_pbr",
"bevy_log",
"bevy_window",
"bevy_winit",
] }
processing = { path = "." }
processing_pyo3 = { path = "crates/processing_pyo3" }
Expand Down
5 changes: 5 additions & 0 deletions crates/processing_ffi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ workspace = true
name = "processing"
crate-type = ["cdylib"]

[features]
default = []
wayland = ["processing/wayland"]
x11 = ["processing/x11"]

[dependencies]
processing = { workspace = true }
bevy = { workspace = true }
Expand Down
76 changes: 71 additions & 5 deletions crates/processing_ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,90 @@ pub extern "C" fn processing_init() {
error::check(init);
}

/// Create a WebGPU surface from a native window handle.
/// Returns a window ID (entity ID) that should be used for subsequent operations.
/// Returns 0 on failure.
/// Create a WebGPU surface from a macOS NSWindow handle.
///
/// SAFETY:
/// - Init has been called.
/// - window_handle is a valid GLFW window pointer.
/// - window_handle is a valid NSWindow pointer.
/// - This is called from the same thread as init.
#[cfg(target_os = "macos")]
#[unsafe(no_mangle)]
pub extern "C" fn processing_surface_create(
window_handle: u64,
_display_handle: u64,
width: u32,
height: u32,
scale_factor: f32,
) -> u64 {
error::clear_error();
error::check(|| surface_create_macos(window_handle, width, height, scale_factor))
.map(|e| e.to_bits())
.unwrap_or(0)
}

/// Create a WebGPU surface from a Windows HWND handle.
///
/// SAFETY:
/// - Init has been called.
/// - window_handle is a valid HWND.
/// - This is called from the same thread as init.
#[cfg(target_os = "windows")]
#[unsafe(no_mangle)]
pub extern "C" fn processing_surface_create(
window_handle: u64,
_display_handle: u64,
width: u32,
height: u32,
scale_factor: f32,
) -> u64 {
error::clear_error();
error::check(|| surface_create_windows(window_handle, width, height, scale_factor))
.map(|e| e.to_bits())
.unwrap_or(0)
}

/// Create a WebGPU surface from a Wayland window and display handle.
///
/// SAFETY:
/// - Init has been called.
/// - window_handle is a valid wl_surface pointer.
/// - display_handle is a valid wl_display pointer.
/// - This is called from the same thread as init.
#[cfg(all(target_os = "linux", feature = "wayland"))]
#[unsafe(no_mangle)]
pub extern "C" fn processing_surface_create_wayland(
window_handle: u64,
display_handle: u64,
width: u32,
height: u32,
scale_factor: f32,
) -> u64 {
error::clear_error();
error::check(|| {
surface_create_wayland(window_handle, display_handle, width, height, scale_factor)
})
.map(|e| e.to_bits())
.unwrap_or(0)
}

/// Create a WebGPU surface from an X11 window and display handle.
///
/// SAFETY:
/// - Init has been called.
/// - window_handle is a valid X11 Window ID.
/// - display_handle is a valid X11 Display pointer.
/// - This is called from the same thread as init.
#[cfg(all(target_os = "linux", feature = "x11"))]
#[unsafe(no_mangle)]
pub extern "C" fn processing_surface_create_x11(
window_handle: u64,
display_handle: u64,
width: u32,
height: u32,
scale_factor: f32,
) -> u64 {
error::clear_error();
error::check(|| surface_create(window_handle, display_handle, width, height, scale_factor))
error::check(|| surface_create_x11(window_handle, display_handle, width, height, scale_factor))
.map(|e| e.to_bits())
.unwrap_or(0)
}
Expand Down
8 changes: 5 additions & 3 deletions crates/processing_pyo3/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ workspace = true
name = "processing"
crate-type = ["cdylib"]

[features]
default = ["wayland"]
wayland = ["processing/wayland", "glfw/wayland"]
x11 = ["processing/x11"]

[dependencies]
pyo3 = "0.27.0"
processing = { workspace = true }
Expand All @@ -18,6 +23,3 @@ glfw = { version = "0.60.0"}

[target.'cfg(target_os = "macos")'.dependencies]
glfw = { version = "0.60.0", features = ["static-link"] }

[target.'cfg(target_os = "linux")'.dependencies]
glfw = { version = "0.60.0", features = ["wayland"] }
52 changes: 37 additions & 15 deletions crates/processing_pyo3/src/glfw.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use bevy::prelude::Entity;
/// Minimal GLFW helper for Processing examples
use glfw::{Glfw, GlfwReceiver, PWindow, WindowEvent, WindowMode};
use processing::prelude::error::Result;
Expand Down Expand Up @@ -30,28 +31,49 @@ impl GlfwContext {
}

#[cfg(target_os = "macos")]
pub fn get_window(&self) -> u64 {
self.window.get_cocoa_window() as u64
pub fn create_surface(&self, width: u32, height: u32, scale_factor: f32) -> Result<Entity> {
use processing::prelude::surface_create_macos;
surface_create_macos(
self.window.get_cocoa_window() as u64,
width,
height,
scale_factor,
)
}

#[cfg(target_os = "windows")]
pub fn get_window(&self) -> u64 {
self.window.get_win32_window() as u64
pub fn create_surface(&self, width: u32, height: u32, scale_factor: f32) -> Result<Entity> {
use processing::prelude::surface_create_windows;
surface_create_windows(
self.window.get_win32_window() as u64,
width,
height,
scale_factor,
)
}

#[cfg(target_os = "linux")]
pub fn get_window(&self) -> u64 {
self.window.get_wayland_window() as u64
#[cfg(all(target_os = "linux", feature = "wayland"))]
pub fn create_surface(&self, width: u32, height: u32, scale_factor: f32) -> Result<Entity> {
use processing::prelude::surface_create_wayland;
surface_create_wayland(
self.window.get_wayland_window() as u64,
self.glfw.get_wayland_display() as u64,
width,
height,
scale_factor,
)
}

#[cfg(not(target_os = "linux"))]
pub fn get_display(&self) -> u64 {
0
}

#[cfg(target_os = "linux")]
pub fn get_display(&self) -> u64 {
self.glfw.get_wayland_display() as u64
#[cfg(all(target_os = "linux", feature = "x11"))]
pub fn create_surface(&self, width: u32, height: u32, scale_factor: f32) -> Result<Entity> {
use processing::prelude::surface_create_x11;
surface_create_x11(
self.window.get_x11_window() as u64,
self.glfw.get_x11_display() as u64,
width,
height,
scale_factor,
)
}

pub fn poll_events(&mut self) -> bool {
Expand Down
5 changes: 2 additions & 3 deletions crates/processing_pyo3/src/graphics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,8 @@ impl Graphics {

init().map_err(|e| PyRuntimeError::new_err(format!("{e}")))?;

let window_handle = glfw_ctx.get_window();
let display_handle = glfw_ctx.get_display();
let surface = surface_create(window_handle, display_handle, width, height, 1.0)
let surface = glfw_ctx
.create_surface(width, height, 1.0)
.map_err(|e| PyRuntimeError::new_err(format!("{e}")))?;

let surface = Surface {
Expand Down
5 changes: 5 additions & 0 deletions crates/processing_render/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ edition = "2024"
[lints]
workspace = true

[features]
default = []
wayland = ["bevy/wayland"]
x11 = ["bevy/x11"]

[dependencies]
bevy = { workspace = true }
lyon = "1.0"
Expand Down
79 changes: 67 additions & 12 deletions crates/processing_render/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,20 +42,43 @@ fn app_mut<T>(cb: impl FnOnce(&mut App) -> error::Result<T>) -> error::Result<T>
Ok(res)
}

/// Create a WebGPU surface from a native window handle.
///
/// Currently, this just creates a bevy window with the given parameters and
/// stores the raw window handle for later use by the renderer, which will
/// actually create the surface.
pub fn surface_create(
/// Create a WebGPU surface from a macOS NSWindow handle.
#[cfg(target_os = "macos")]
pub fn surface_create_macos(
window_handle: u64,
width: u32,
height: u32,
scale_factor: f32,
) -> error::Result<Entity> {
app_mut(|app| {
surface::create_surface_macos(app.world_mut(), window_handle, width, height, scale_factor)
})
}

/// Create a WebGPU surface from a Windows HWND handle.
#[cfg(target_os = "windows")]
pub fn surface_create_windows(
window_handle: u64,
width: u32,
height: u32,
scale_factor: f32,
) -> error::Result<Entity> {
app_mut(|app| {
surface::create_surface_windows(app.world_mut(), window_handle, width, height, scale_factor)
})
}

/// Create a WebGPU surface from a Wayland window and display handle.
#[cfg(all(target_os = "linux", feature = "wayland"))]
pub fn surface_create_wayland(
window_handle: u64,
display_handle: u64,
width: u32,
height: u32,
scale_factor: f32,
) -> error::Result<Entity> {
app_mut(|app| {
surface::create(
surface::create_surface_wayland(
app.world_mut(),
window_handle,
display_handle,
Expand All @@ -66,6 +89,40 @@ pub fn surface_create(
})
}

/// Create a WebGPU surface from an X11 window and display handle.
#[cfg(all(target_os = "linux", feature = "x11"))]
pub fn surface_create_x11(
window_handle: u64,
display_handle: u64,
width: u32,
height: u32,
scale_factor: f32,
) -> error::Result<Entity> {
app_mut(|app| {
surface::create_surface_x11(
app.world_mut(),
window_handle,
display_handle,
width,
height,
scale_factor,
)
})
}

/// Create a WebGPU surface from a web canvas element pointer.
#[cfg(target_arch = "wasm32")]
pub fn surface_create_web(
window_handle: u64,
width: u32,
height: u32,
scale_factor: f32,
) -> error::Result<Entity> {
app_mut(|app| {
surface::create_surface_web(app.world_mut(), window_handle, width, height, scale_factor)
})
}

pub fn surface_create_offscreen(
width: u32,
height: u32,
Expand Down Expand Up @@ -106,7 +163,7 @@ pub fn surface_create_from_canvas(
// TODO: not sure if this is right to force here
let scale_factor = 1.0;

surface_create(canvas_ptr, 0, width, height, scale_factor)
surface_create_web(canvas_ptr, width, height, scale_factor)
}

pub fn surface_destroy(graphics_entity: Entity) -> error::Result<()> {
Expand All @@ -124,9 +181,8 @@ fn create_app() -> App {
#[cfg(not(target_arch = "wasm32"))]
let plugins = DefaultPlugins
.build()
.disable::<bevy::log::LogPlugin>()
.disable::<bevy::winit::WinitPlugin>()
.disable::<bevy::render::pipelined_rendering::PipelinedRenderingPlugin>()
.disable::<bevy::log::LogPlugin>()
.set(WindowPlugin {
primary_window: None,
exit_condition: bevy::window::ExitCondition::DontExit,
Expand All @@ -136,9 +192,8 @@ fn create_app() -> App {
#[cfg(target_arch = "wasm32")]
let plugins = DefaultPlugins
.build()
.disable::<bevy::log::LogPlugin>()
.disable::<bevy::winit::WinitPlugin>()
.disable::<bevy::audio::AudioPlugin>()
.disable::<bevy::log::LogPlugin>()
.set(WindowPlugin {
primary_window: None,
exit_condition: bevy::window::ExitCondition::DontExit,
Expand Down
Loading