diff options
| -rw-r--r-- | apps/web/src/preview/components/index.tsx | 9 | ||||
| -rw-r--r-- | apps/web/src/services/renderer/compositor/wasm-compositor.ts | 8 | ||||
| -rw-r--r-- | apps/web/src/services/renderer/gpu-renderer.ts | 27 | ||||
| -rw-r--r-- | rust/crates/gpu/src/context.rs | 9 | ||||
| -rw-r--r-- | rust/wasm/src/compositor.rs | 12 |
5 files changed, 56 insertions, 9 deletions
diff --git a/apps/web/src/preview/components/index.tsx b/apps/web/src/preview/components/index.tsx index 894eec78..643eb002 100644 --- a/apps/web/src/preview/components/index.tsx +++ b/apps/web/src/preview/components/index.tsx @@ -7,6 +7,7 @@ import { useRafLoop } from "@/hooks/use-raf-loop"; import { useContainerSize } from "@/hooks/use-container-size"; import { useFullscreen } from "@/hooks/use-fullscreen"; import { CanvasRenderer } from "@/services/renderer/canvas-renderer"; +import { onGpuCanvasRepaired } from "@/services/renderer/gpu-renderer"; import { TICKS_PER_SECOND } from "@/wasm"; import type { RootNode } from "@/services/renderer/nodes/root-node"; import { buildScene } from "@/services/renderer/scene-builder"; @@ -214,6 +215,14 @@ function PreviewCanvas({ useRafLoop(render); useEffect(() => { + return onGpuCanvasRepaired({ + callback: () => { + lastFrameRef.current = -1; + }, + }); + }, []); + + useEffect(() => { const container = viewportRef.current; if (!container) return; diff --git a/apps/web/src/services/renderer/compositor/wasm-compositor.ts b/apps/web/src/services/renderer/compositor/wasm-compositor.ts index 10684f11..5d2ddc3f 100644 --- a/apps/web/src/services/renderer/compositor/wasm-compositor.ts +++ b/apps/web/src/services/renderer/compositor/wasm-compositor.ts @@ -96,6 +96,14 @@ class WasmCompositor { } } + repairSharedCanvas() { + if (!this.canvas || !this.initializedSize) return; + const { width, height } = this.initializedSize; + if (this.canvas.width === width && this.canvas.height === height) return; + resizeCompositor(width + 1, height); + resizeCompositor(width, height); + } + private syncExternalTexture(texture: ExternalTextureDescriptor) { const previous = this.cache.get(texture.id); if ( diff --git a/apps/web/src/services/renderer/gpu-renderer.ts b/apps/web/src/services/renderer/gpu-renderer.ts index c1be3f1a..8ad11083 100644 --- a/apps/web/src/services/renderer/gpu-renderer.ts +++ b/apps/web/src/services/renderer/gpu-renderer.ts @@ -4,6 +4,25 @@ import { initializeGpu, } from "opencut-wasm"; import type { EffectPass, EffectUniformValue } from "@/effects/types"; +import { wasmCompositor } from "./compositor/wasm-compositor"; + +const canvasRepairListeners = new Set<() => void>(); + +export function onGpuCanvasRepaired({ + callback, +}: { + callback: () => void; +}): () => void { + canvasRepairListeners.add(callback); + return () => canvasRepairListeners.delete(callback); +} + +function repairSharedCompositorCanvas(): void { + wasmCompositor.repairSharedCanvas(); + for (const listener of canvasRepairListeners) { + listener(); + } +} let gpuAvailable = false; let initPromise: Promise<void> | null = null; @@ -43,12 +62,14 @@ export const gpuRenderer = { return source; } - return applyEffectPasses({ + const result = applyEffectPasses({ source, width, height, passes: serializeEffectPasses(passes), }); + repairSharedCompositorCanvas(); + return result; }, applyMaskFeather({ @@ -66,12 +87,14 @@ export const gpuRenderer = { return maskCanvas; } - return applyMaskFeatherWasm({ + const result = applyMaskFeatherWasm({ mask: maskCanvas, width, height, feather, }); + repairSharedCompositorCanvas(); + return result; }, }; diff --git a/rust/crates/gpu/src/context.rs b/rust/crates/gpu/src/context.rs index da835280..353d54da 100644 --- a/rust/crates/gpu/src/context.rs +++ b/rust/crates/gpu/src/context.rs @@ -604,6 +604,10 @@ impl GpuContext { width: u32, height: u32, ) -> Result<(), GpuError> { + let previous_size = self + .gl_canvas + .as_ref() + .map(|gl_canvas| (gl_canvas.width(), gl_canvas.height())); let gl_canvas = self.render_texture_to_gl_canvas_surface(texture, width, height)?; let ctx: web_sys::OffscreenCanvasRenderingContext2d = canvas @@ -616,6 +620,11 @@ impl GpuContext { ctx.draw_image_with_html_canvas_element(gl_canvas, 0.0, 0.0) .map_err(|_| GpuError::AdapterUnavailable)?; + if let Some((previous_width, previous_height)) = previous_size { + gl_canvas.set_width(previous_width); + gl_canvas.set_height(previous_height); + } + Ok(()) } diff --git a/rust/wasm/src/compositor.rs b/rust/wasm/src/compositor.rs index 7652b3f3..4d73e9ad 100644 --- a/rust/wasm/src/compositor.rs +++ b/rust/wasm/src/compositor.rs @@ -81,13 +81,11 @@ pub fn resize_compositor(width: u32, height: u32) -> Result<(), JsValue> { }; runtime.canvas.set_width(width); runtime.canvas.set_height(height); - if runtime.surface_size != (width, height) { - gpu_runtime - .context - .configure_surface(&runtime.surface, width, height) - .map_err(|error| JsValue::from_str(&error.to_string()))?; - runtime.surface_size = (width, height); - } + gpu_runtime + .context + .configure_surface(&runtime.surface, width, height) + .map_err(|error| JsValue::from_str(&error.to_string()))?; + runtime.surface_size = (width, height); Ok(()) }) }) |
