fix: WebGL frame rendering and opencut-wasm 0.2.8

This commit is contained in:
Maze Winther
2026-04-19 07:42:52 +02:00
parent 9da365bc01
commit 729d10592f
14 changed files with 338 additions and 127 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "opencut-wasm"
version = "0.2.5"
version = "0.2.8"
edition = "2024"
description = "Shared video editor logic compiled to WebAssembly"
repository = "https://github.com/opencut/opencut"
+34 -16
View File
@@ -131,22 +131,41 @@ pub fn render_frame(options: JsValue) -> Result<(), JsValue> {
));
};
let surface = gpu_runtime
.context
.instance()
.create_surface(wgpu::SurfaceTarget::Canvas(runtime.canvas.clone()))
.map_err(|error| JsValue::from_str(&error.to_string()))?;
if gpu_runtime.context.supports_surface_rendering() {
let surface = gpu_runtime
.context
.instance()
.create_surface(wgpu::SurfaceTarget::Canvas(runtime.canvas.clone()))
.map_err(|error| JsValue::from_str(&error.to_string()))?;
runtime
.compositor
.render_frame(
&gpu_runtime.context,
RenderFrameOptions {
frame: &frame,
surface: &surface,
},
)
.map_err(|error| JsValue::from_str(&error.to_string()))
runtime
.compositor
.render_frame(
&gpu_runtime.context,
RenderFrameOptions {
frame: &frame,
surface: &surface,
},
)
.map_err(|error| JsValue::from_str(&error.to_string()))
} else {
// WebGL cannot surface-render to an arbitrary canvas element.
// Composite to a texture, then blit to the canvas via the 2D context.
let texture = runtime
.compositor
.render_frame_to_texture(&gpu_runtime.context, &frame)
.map_err(|error| JsValue::from_str(&error.to_string()))?;
gpu_runtime
.context
.render_texture_via_gl_canvas(
&texture,
&runtime.canvas,
frame.width,
frame.height,
)
.map_err(|error| JsValue::from_str(&error.to_string()))
}
})
})
}
@@ -171,4 +190,3 @@ fn parse_upload_texture_options(value: JsValue) -> Result<UploadTextureOptions,
height: read_u32_property(&object, "height")?,
})
}
+19 -1
View File
@@ -19,9 +19,27 @@ thread_local! {
static GPU_RUNTIME: RefCell<Option<GpuRuntime>> = const { RefCell::new(None) };
}
fn set_panic_hook() {
static SET_HOOK: std::sync::Once = std::sync::Once::new();
SET_HOOK.call_once(|| {
std::panic::set_hook(Box::new(|info| {
// Store the full panic message in window.__wasmPanic so the JS catch block
// can surface it instead of the opaque "Unreachable" WASM trap message.
if let Some(window) = web_sys::window() {
let _ = Reflect::set(
&window,
&JsValue::from_str("__wasmPanic"),
&JsValue::from_str(&info.to_string()),
);
}
console_error_panic_hook::hook(info);
}));
});
}
#[wasm_bindgen(js_name = initializeGpu)]
pub async fn initialize_gpu() -> Result<(), JsValue> {
console_error_panic_hook::set_once();
set_panic_hook();
if GPU_RUNTIME.with(|runtime| runtime.borrow().is_some()) {
return Ok(());