Skip to content
Merged
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
70 changes: 70 additions & 0 deletions native/android/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,76 @@ pub extern "C" fn bloom_init_window(width: f64, height: f64, title_ptr: *const u
}
}

/// Attach the engine to a host-owned `ANativeWindow*` instead of pulling
/// it from the global set by `bloom_android_set_native_window`
/// (PerryTS/perry#5519). `handle` is the `ANativeWindow*` the host
/// (Perry UI's `BloomView`, backed by a `SurfaceView`/`TextureView`)
/// owns; `width`/`height` are the surface size in physical pixels.
/// Returns 1.0 on success, 0.0 on a null/invalid handle or surface
/// bring-up failure. Idempotent once attached.
#[no_mangle]
pub extern "C" fn bloom_attach_native(handle: i64, width: f64, height: f64) -> f64 {
if handle == 0 {
return 0.0;
}
if unsafe { ENGINE.get() }.is_some() {
return 1.0;
}
let window = handle as *mut libc::c_void;
let Some(win_nn) = std::ptr::NonNull::new(window) else {
return 0.0;
};
// Hold a reference for as long as the engine renders into it.
unsafe {
ANativeWindow_acquire(window);
NATIVE_WINDOW = window;
}
let target = {
let h = raw_window_handle::AndroidNdkWindowHandle::new(win_nn);
wgpu::SurfaceTargetUnsafe::RawHandle {
raw_display_handle: Some(raw_window_handle::RawDisplayHandle::Android(
raw_window_handle::AndroidDisplayHandle::new(),
)),
raw_window_handle: raw_window_handle::RawWindowHandle::AndroidNdk(h),
}
};
match unsafe {
bloom_shared::attach::attach_engine(
target,
bloom_shared::attach::AttachParams {
backends: wgpu::Backends::VULKAN | wgpu::Backends::GL,
logical_w: (width as u32).max(1),
logical_h: (height as u32).max(1),
physical_w: (width as u32).max(1),
physical_h: (height as u32).max(1),
format: bloom_shared::attach::FormatPreference::Srgb,
},
)
} {
Ok(es) => {
unsafe {
let _ = ENGINE.set(es);
}
1.0
}
Err(_) => 0.0,
}
}

/// Resize the engine's surface (#70 parity; used by host-driven
/// BloomViews on layout changes). `phys_*` physical px, `log_*` logical.
#[no_mangle]
pub extern "C" fn bloom_resize(phys_w: f64, phys_h: f64, log_w: f64, log_h: f64) {
if let Some(eng) = unsafe { ENGINE.get_mut() } {
eng.renderer.resize(phys_w as u32, phys_h as u32, log_w as u32, log_h as u32);
}
}

/// HWND host-embed (#70) — Windows only; a no-op here for FFI-manifest
/// parity. Non-Windows hosts attach via `bloom_attach_native`.
#[no_mangle]
pub extern "C" fn bloom_attach_hwnd(_hwnd_bits: f64, _width: f64, _height: f64) {}

#[no_mangle]
pub extern "C" fn bloom_close_window() {
unsafe {
Expand Down
64 changes: 64 additions & 0 deletions native/ios/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -733,6 +733,70 @@ pub extern "C" fn bloom_init_window(_width: f64, _height: f64, title_ptr: *const
}
}

/// Attach the engine to a host-owned `UIView*` instead of creating its
/// own UIWindow (PerryTS/perry#5519). `handle` is the raw `UIView*` the
/// host (Perry UI's `BloomView`) owns; `width`/`height` are its size in
/// points. Returns 1.0 on success, 0.0 on a null/invalid handle or if
/// surface bring-up failed. Idempotent once attached.
///
/// HiDPI: callers wanting full backing resolution should pass the pixel
/// size (points × `UIScreen.scale`); this path uses `width`/`height` as
/// the drawable size directly.
#[no_mangle]
pub extern "C" fn bloom_attach_native(handle: i64, width: f64, height: f64) -> f64 {
if handle == 0 {
return 0.0;
}
if unsafe { ENGINE.get() }.is_some() {
return 1.0;
}
let Some(view_nn) = std::ptr::NonNull::new(handle as *mut c_void) else {
return 0.0;
};
let target = {
let h = UiKitWindowHandle::new(view_nn);
wgpu::SurfaceTargetUnsafe::RawHandle {
raw_display_handle: Some(RawDisplayHandle::UiKit(UiKitDisplayHandle::new())),
raw_window_handle: RawWindowHandle::UiKit(h),
}
};
match unsafe {
bloom_shared::attach::attach_engine(
target,
bloom_shared::attach::AttachParams {
backends: wgpu::Backends::METAL,
logical_w: width as u32,
logical_h: height as u32,
physical_w: (width as u32).max(1),
physical_h: (height as u32).max(1),
format: bloom_shared::attach::FormatPreference::Srgb,
},
)
} {
Ok(es) => {
unsafe {
let _ = ENGINE.set(es);
}
1.0
}
Err(_) => 0.0,
}
}

/// Resize the engine's surface (#70 parity; used by host-driven
/// BloomViews on layout changes). `phys_*` physical px, `log_*` logical.
#[no_mangle]
pub extern "C" fn bloom_resize(phys_w: f64, phys_h: f64, log_w: f64, log_h: f64) {
if let Some(eng) = unsafe { ENGINE.get_mut() } {
eng.renderer.resize(phys_w as u32, phys_h as u32, log_w as u32, log_h as u32);
}
}

/// HWND host-embed (#70) — Windows only; a no-op here for FFI-manifest
/// parity. Non-Windows hosts attach via `bloom_attach_native`.
#[no_mangle]
pub extern "C" fn bloom_attach_hwnd(_hwnd_bits: f64, _width: f64, _height: f64) {}

#[no_mangle]
pub extern "C" fn bloom_close_window() {
unsafe { UI_VIEW = None; UI_WINDOW = None; }
Expand Down
31 changes: 31 additions & 0 deletions native/linux/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,37 @@ pub extern "C" fn bloom_init_window(width: f64, height: f64, title_ptr: *const u
panic!("bloom-linux can only run on Linux");
}

/// Attach the engine to a host-owned surface (PerryTS/perry#5519).
///
/// Not yet wired on Linux: Perry UI's GTK4 `BloomView` hands out a
/// `GtkWidget*`, and turning that into a wgpu surface needs the widget
/// realized/mapped and its `GdkSurface` bridged to an X11 `Window` (or a
/// Wayland `wl_surface`) — the GTK4 dmabuf/`GtkGLArea` path the issue
/// calls out as the larger follow-up. Until that lands this returns 0.0
/// (failure) so hosts fall back to the windowed `bloom_init_window`
/// path. The symbol exists so the FFI surface is uniform across
/// platforms (the shared bring-up is `bloom_shared::attach::attach_engine`,
/// already used by the Apple/Android/Windows attach paths).
#[no_mangle]
pub extern "C" fn bloom_attach_native(handle: i64, width: f64, height: f64) -> f64 {
let _ = (handle, width, height);
0.0
}

/// Resize the engine's surface (#70 parity; used by host-driven
/// BloomViews on layout changes). `phys_*` physical px, `log_*` logical.
#[no_mangle]
pub extern "C" fn bloom_resize(phys_w: f64, phys_h: f64, log_w: f64, log_h: f64) {
if let Some(eng) = unsafe { ENGINE.get_mut() } {
eng.renderer.resize(phys_w as u32, phys_h as u32, log_w as u32, log_h as u32);
}
}

/// HWND host-embed (#70) — Windows only; a no-op here for FFI-manifest
/// parity. Non-Windows hosts attach via `bloom_attach_native`.
#[no_mangle]
pub extern "C" fn bloom_attach_hwnd(_hwnd_bits: f64, _width: f64, _height: f64) {}

#[no_mangle]
pub extern "C" fn bloom_close_window() {}

Expand Down
Loading
Loading