#[cfg(target_os = "linux")]
fn main() {
demo::run();
}
#[cfg(not(target_os = "linux"))]
fn main() {
eprintln!(
"interop_cube is a Linux example: it renders into a shareable Vulkan image and exports it as \
a dma-buf for the window's renderer. Run it on Linux."
);
}
#[cfg(target_os = "linux")]
#[path = "common/cube.rs"]
mod cube;
#[cfg(target_os = "linux")]
mod demo {
use std::cell::RefCell;
use std::rc::Rc;
use gpui::{
AnyElement, App, Bounds, Context, IntoElement, Render, Window, WindowBounds, WindowOptions,
div, gpu_canvas, prelude::*, px, rgb, size,
};
use crate::cube::{Cube, OPAQUE};
const TILE: u32 = 320;
pub fn run() {
gpui::application().run(|cx: &mut App| {
let bounds = Bounds::centered(None, size(px(560.), px(520.)), cx);
cx.open_window(
WindowOptions {
window_bounds: Some(WindowBounds::Windowed(bounds)),
..Default::default()
},
|_, cx| cx.new(|_| Showcase::new()),
)
.expect("a window to composite into");
cx.activate(true);
});
}
struct Showcase {
cube: Rc<RefCell<Option<Cube>>>,
error: Rc<RefCell<Option<String>>>,
requested: u32,
}
impl Showcase {
fn new() -> Self {
Self {
cube: Rc::new(RefCell::new(None)),
error: Rc::new(RefCell::new(None)),
requested: 0,
}
}
}
impl Render for Showcase {
fn render(&mut self, window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
let built = self.cube.borrow().is_some();
if built || self.requested < 2 {
self.requested += 1;
window.request_animation_frame();
}
let line = match (self.cube.borrow().as_ref(), self.error.borrow().as_ref()) {
(Some(cube), _) => format!(
"{} · {} frames rendered, {} dropped",
cube.gpu(),
cube.rendered(),
cube.dropped()
),
(None, Some(error)) => error.clone(),
(None, None) => "negotiating with the window's renderer…".to_owned(),
};
div()
.size_full()
.bg(rgb(0x101014))
.flex()
.flex_col()
.items_center()
.justify_center()
.gap_6()
.p_8()
.child(
div()
.flex()
.flex_col()
.items_center()
.gap_1()
.child(
div()
.text_2xl()
.text_color(rgb(0xffffff))
.child("Foreign 3D viewport"),
)
.child(
div()
.text_sm()
.text_color(rgb(0x9a9aa2))
.text_center()
.max_w(px(460.))
.child(
"gpui_interop · Linux · a cube a producer renders with its own \
Vulkan pipeline, exported as a dma-buf and sampled by the window's \
renderer — no CPU copy",
),
)
.child(div().text_sm().text_color(rgb(0x6f8fbf)).child(line)),
)
.child(canvas(self.cube.clone(), self.error.clone()))
}
}
fn canvas(cube: Rc<RefCell<Option<Cube>>>, error: Rc<RefCell<Option<String>>>) -> AnyElement {
div()
.flex()
.flex_col()
.items_center()
.w(px(TILE as f32))
.child(
div().w(px(TILE as f32)).h(px(TILE as f32)).child(
gpu_canvas(move |gpu| {
let mut cube = cube.borrow_mut();
if cube.is_none() {
match Cube::build(gpu, TILE, OPAQUE) {
Ok(built) => *cube = Some(built),
Err(build) => {
log::error!("interop_cube: cannot build the cube: {build:#}");
*error.borrow_mut() = Some(format!("{build}"));
return;
}
}
}
let cube = cube.as_mut().expect("the cube was just built");
cube.turn(0.013, 0.013 * 0.6);
if let Some(handle) = cube.frame() {
gpu.paint_surface(handle);
}
})
.bg(rgb(0x23232c))
.size_full(),
),
)
.into_any_element()
}
}