From b398b97e9bb5c80b309ddff55a192f96b106d67b Mon Sep 17 00:00:00 2001 From: pepc84 Date: Wed, 16 Sep 2026 17:54:51 -0700 Subject: [PATCH 1/2] fix(ffi): pass transparent=false to all surface_create_* calls All platform variants of surface_create (Windows, Wayland, X11, Linux auto-detect) gained a `transparent: bool` parameter in processing_render but the FFI wrappers were not updated to match, causing a compile error. macOS was already correct. Pass `false` (opaque) to match existing behaviour. --- Cargo.lock | 1 + crates/processing_ffi/src/lib.rs | 28 ++++++++++++++++++++++++---- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c1bf6e52..d66f5040 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6167,6 +6167,7 @@ dependencies = [ "cbindgen", "half", "processing", + "processing_core", ] [[package]] diff --git a/crates/processing_ffi/src/lib.rs b/crates/processing_ffi/src/lib.rs index 731722cc..65be3234 100644 --- a/crates/processing_ffi/src/lib.rs +++ b/crates/processing_ffi/src/lib.rs @@ -64,7 +64,7 @@ pub extern "C" fn processing_surface_create( scale_factor: f32, ) -> u64 { error::clear_error(); - error::check(|| surface_create_windows(window_handle, width, height, scale_factor)) + error::check(|| surface_create_windows(window_handle, width, height, scale_factor, false)) .map(|e| e.to_bits()) .unwrap_or(0) } @@ -87,7 +87,7 @@ pub extern "C" fn processing_surface_create_wayland( ) -> u64 { error::clear_error(); error::check(|| { - surface_create_wayland(window_handle, display_handle, width, height, scale_factor) + surface_create_wayland(window_handle, display_handle, width, height, scale_factor, false) }) .map(|e| e.to_bits()) .unwrap_or(0) @@ -110,7 +110,7 @@ pub extern "C" fn processing_surface_create_x11( scale_factor: f32, ) -> u64 { error::clear_error(); - error::check(|| surface_create_x11(window_handle, display_handle, width, height, scale_factor)) + error::check(|| surface_create_x11(window_handle, display_handle, width, height, scale_factor, false)) .map(|e| e.to_bits()) .unwrap_or(0) } @@ -133,7 +133,7 @@ pub extern "C" fn processing_surface_create( ) -> u64 { error::clear_error(); error::check(|| { - surface_create_linux(window_handle, display_handle, width, height, scale_factor) + surface_create_linux(window_handle, display_handle, width, height, scale_factor, false) }) .map(|e| e.to_bits()) .unwrap_or(0) @@ -4436,3 +4436,23 @@ fn key_code_to_u32(kc: KeyCode) -> u32 { _ => 0, } } + +/// Tick the Bevy app one frame and poll GLFW events. +/// Call this once per frame from your external event loop, before begin_draw. +/// Returns true if the app should continue running, false if it should exit. +/// +/// SAFETY: +/// - processing_init has been called. +/// - This is called from the same thread as init. +#[unsafe(no_mangle)] +pub extern "C" fn processing_poll_events() -> bool { + error::clear_error(); + let result = processing_core::app_mut(|app| { + app.update(); + Ok(()) + }); + match result { + Ok(_) => true, + Err(_) => false, + } +} From 4e8a8f73942458700ec90566f751a8ce3e7c84d3 Mon Sep 17 00:00:00 2001 From: pepc84 Date: Wed, 16 Sep 2026 21:26:51 -0700 Subject: [PATCH 2/2] feat(ffi): add processing_poll_events for external event loop integration Exposes a C FFI function that ticks Bevy's app one frame, allowing embedders that manage their own window and event loop (e.g. a native C++ host using GLFW) to advance libprocessing's internal state each frame without using the built-in GLFW runner. The pattern is: processing_init(); processing_surface_create(...); processing_graphics_create(...); while (running) { running = processing_poll_events(); processing_begin_draw(gfx); // draw calls processing_end_draw(gfx); } Adds processing_core as a direct dependency of processing_ffi since app_mut is not re-exported through processing::prelude. --- crates/processing_ffi/Cargo.toml | 1 + crates/processing_ffi/src/lib.rs | 16 ++++++++++------ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/crates/processing_ffi/Cargo.toml b/crates/processing_ffi/Cargo.toml index 16d41364..286fedb4 100644 --- a/crates/processing_ffi/Cargo.toml +++ b/crates/processing_ffi/Cargo.toml @@ -19,6 +19,7 @@ cuda = ["processing/cuda"] [dependencies] processing = { workspace = true } +processing_core = { workspace = true } bevy = { workspace = true } half = "2.7" diff --git a/crates/processing_ffi/src/lib.rs b/crates/processing_ffi/src/lib.rs index 65be3234..3bc56dcd 100644 --- a/crates/processing_ffi/src/lib.rs +++ b/crates/processing_ffi/src/lib.rs @@ -4437,21 +4437,25 @@ fn key_code_to_u32(kc: KeyCode) -> u32 { } } -/// Tick the Bevy app one frame and poll GLFW events. +/// Tick the Bevy app one frame. /// Call this once per frame from your external event loop, before begin_draw. /// Returns true if the app should continue running, false if it should exit. /// +/// This is intended for embedders that drive their own window and event loop +/// (e.g. a native C++ host) and need to advance libprocessing's internal state +/// each frame without using the built-in GLFW runner. +/// /// SAFETY: -/// - processing_init has been called. -/// - This is called from the same thread as init. +/// - `processing_init` has been called. +/// - This is called from the same thread as `init`. +/// - This must not be called after `processing_exit`. #[unsafe(no_mangle)] pub extern "C" fn processing_poll_events() -> bool { error::clear_error(); - let result = processing_core::app_mut(|app| { + match processing_core::app_mut(|app| { app.update(); Ok(()) - }); - match result { + }) { Ok(_) => true, Err(_) => false, }