summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/web/src/preview/components/index.tsx9
-rw-r--r--apps/web/src/services/renderer/compositor/wasm-compositor.ts8
-rw-r--r--apps/web/src/services/renderer/gpu-renderer.ts27
-rw-r--r--rust/crates/gpu/src/context.rs9
-rw-r--r--rust/wasm/src/compositor.rs12
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(())
})
})