OffscreenCanvas in Workers - #179
Merged
Merged
Conversation
An OffscreenCanvas can move to a Worker, which then owns its context: OffscreenCanvas._toHandle(offscreen) on the sending thread (detaching it, as a transfer does) and OffscreenCanvas._fromHandle(handle) on the receiving one. A runtime transfer hook can later call the same three entry points (_toHandle, _fromHandle, _releaseHandle). - canvas-c offscreen: CanvasOffscreenSurface, a thread-safe surface made on the UI thread from a transferred canvas's view (or viewless), plus a take-once handle registry. The UI thread reaches the owner thread's context only through the render thread (new weak TargetHandle), the WebGL thread or wgpu's locks, and hears back through a sink (resize, context made). - Bindings: CanvasModule.OffscreenSurface (V8, N-API viewless only), NSCCanvas.transferToOffscreenSurface() on iOS and Android. - TS: OffscreenCanvas draws through surfaces and no longer imports Canvas; @nativescript/canvas/worker is the API without the view. - Viewless WebGL threaded on every platform; WebGPU offscreen contexts; Metal layers whose drawable the render thread sizes. - Per-thread canvases-behind count, so a Worker's canvases hold back only its own animation frames. Fixes found on the way: Android toDataURL on a threaded 2D canvas read whichever GL context was current; an Android pbuffer 2D context did not grow on resize; a new isolate could see a dead Worker's cached templates; iOS file callbacks from a Worker ran on main. Windows: transferred canvases still draw through their host and can't move to a Worker yet.
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
A transferred canvas can move to a Worker on Windows, as on Android and iOS, and moves with postMessage(..., [canvas]) where the runtime has transfer hooks (NativeScript/windows). - canvas-c offscreen/windows.rs: an OffscreenSurface over the view's SwapChainPanel. The context lives where the OffscreenCanvas is used (2D on the render thread, WebGL on the WebGL thread, WebGPU through wgpu); swapchains are bound on the UI thread through a message-only window (dxgi::UiThread), which wgpu's SetSwapChain from a Worker also goes through. Transparent canvases present into the view's SurfaceImageSource. The surface keeps the fit, scale and view size, and tracks what it shows itself rather than in the UI thread's 2D table. - NSCCanvas.transferToOffscreenSurface(listener), offscreenToDataURL and detachOffscreenSurface; napi-host's _createOffscreenSurface. The hidden host (OffscreenCanvas._legacyHost) is gone. - OffscreenCanvas registers as a transferable (__nsRegisterTransferable). - Viewless WebGL on Windows uses texture contexts, so resizing it works. - A transparent canvas whose fit overflows its view is placed with a margin and clipped to the panel: it was cut at the wrong place and drew over its neighbours. - A Worker's env no longer takes the native log console from the main thread. - Specs for postMessage transfers, and a canvas-offscreen-worker demo page.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
An OffscreenCanvas can now move to a Worker, which then owns its context. This covers 2d, bitmaprenderer, webgl, webgl2 and webgpu, for canvases sent from the main thread and canvases made in the Worker. On NativeScript Windows it moves with
worker.postMessage({ canvas }, [canvas]), with NativeScript/windows#23. The Android and iOS runtimes can't transfer it throughpostMessageyet, so there it goes as a handle:_toHandle/_fromHandle/_releaseHandle(take, adopt once, drop) are what a runtime transfer hook calls (OffscreenCanvas registers itself with__nsRegisterTransferablewhere the runtime has it), sopostMessage(…, [canvas])can work there later without app changes.How it works
crates/canvas-c/src/offscreen:CanvasOffscreenSurface, made on the UI thread from a transferred canvas's view, or viewless.TargetHandlesplit out ofRenderTarget), the WebGL thread, or wgpu's locks.CanvasModule.OffscreenSurface(OffscreenSurfaceImpl, andcrates/canvas-napi/src/offscreen.rs).NSCCanvas.transferToOffscreenSurface()in Swift and Kotlin, with the Android JNI inorg_nativescript_canvas_NSCCanvas_offscreen.rs.OffscreenCanvasdraws through surfaces and no longer importsCanvas;Canvas/common.tsimports it instead.@nativescript/canvas/workeris the API without the view.Canvasview by a brand instead ofinstanceof.requestAnimationFrame.Fixes found on the way
toDataURLof a threaded 2D canvas read whichever GL context was current on the render thread.Caches::Removeon install).NSOperationQueueWrappernow retains its run loop.GPUCanvasContext.__toDataURLwhen unconfigured, and iOSdrawAtlaswith an OffscreenCanvas source.Windows
A transferred canvas moves to a Worker as on Android and iOS; the hidden host (
OffscreenCanvas._legacyHost) is gone.offscreen/windows.rs: anOffscreenSurfaceover the view'sSwapChainPanel.dxgi::UiThread). wgpu'sSetSwapChainfrom a Worker goes through it too.SurfaceImageSource.SHOWNtable.NSCCanvas.transferToOffscreenSurface(listener)(plusoffscreenToDataURLanddetachOffscreenSurface) inhost/windows.rs, and_createOffscreenSurface()innapi-host.ts.canvas-offscreen-workershows a Worker drawing a transparent 2D and an opaque WebGL view.requestAnimationFrameand~/paths in Workers, transfer lists). 0.1.0-beta.5 can't run bundled Workers.On macOS
cargo check -p canvas-napihits two errors, both in Windows-only#[napi]methods outside this change (get_adapter_luid,draw_d3d_shared_frame); none of them is inoffscreen.rs.Tests
offscreen.worker.handle,offscreen.worker.transfer,offscreen.worker:offscreen.worker.postMessage: a canvas transferred to a Worker and back, a view's canvas transferred to a Worker, and what can't be transferred.crates/canvas-c/tests/offscreen_surface.rs.iOS simulator:
offscreenpasses 64/64 and2dpasses 180/180.webgpu,canvassource,scalingandlifecycleeach pass on their own.webgpu.videoafter 313 passes and no failures. That suite passes alone; I haven't checked whether master stalls the same way.Android emulator:
offscreen.workerpasses 27/27,2d180/180 andwebgl83/83, and the remaining groups pass.Windows (with NativeScript/windows#23):
offscreenpasses 69/69.webgpu.videoand fail the same way on 0.1.0-beta.5.The checked-in Windows
canvasnative.nodeis rebuilt for x64 and arm64. The checked-in xcframework and AAR are not rebuilt in this PR; the native libraries still need a full rebuild.