Skip to content

Commit 885ffe1

Browse files
committed
feat(webgl): run iOS WebGL contexts on the WebGL thread
iOS WebGL drew through a GLKView, whose display (the per-frame present) only runs on the main thread, which is the JS thread: a heavy scene held the UI to the GPU's pace. The GLKView is replaced by a view backed by a CAEAGLLayer. The context owns its drawing buffer: a framebuffer whose color buffer is stored in the layer (renderbufferStorage:fromDrawable:) and presented with presentRenderbuffer:, both of which run on any thread, plus a packed depth/stencil buffer from the context attributes. An offscreen context gets plain renderbuffers instead of an unshown GLKView. That lets an iOS context be threaded as on Android (the default; getContext(..., { threaded: false }) opts out): it is created, drawn, presented and dropped on the shared WebGL thread, and requestAnimationFrame is held back while a canvas is behind. - Resizing reallocates the drawing buffer, queued behind earlier calls; a GL-backed 2D context reallocates its own as it resizes. - Snapshots read the drawing buffer on the context's thread. - The texImage helpers and video frame uploads (NSCRender) run on the context's thread; NSCRender makes its GL objects on first use there. - Depth and stencil are discarded after each present unless preserveDrawingBuffer is set, as GLKView did.
1 parent 6dcb6dd commit 885ffe1

12 files changed

Lines changed: 678 additions & 539 deletions

File tree

‎crates/canvas-c/src/c2d/context.rs‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,13 @@ pub fn resize_gl(context: &mut CanvasRenderingContext2D, width: f32, height: f32
124124
context.clear_rect(0., 0., width, height);
125125
context.flush_and_render_to_surface();
126126

127+
// The view's layer changed size; its drawable follows, and is what the surface wraps.
128+
#[cfg(any(target_os = "ios", target_os = "visionos", target_os = "tvos"))]
129+
if let Some(gl) = context.gl_context.as_mut() {
130+
gl.resize_drawable(width as i32, height as i32);
131+
gl.bind_drawable();
132+
}
133+
127134
unsafe {
128135
gl_bindings::Viewport(0, 0, width as i32, height as i32);
129136
match context.window_framebuffer() {

0 commit comments

Comments
 (0)