perf(web-ui): use ResizeObserver for canvas sizing#621
Conversation
…me getBoundingClientRect desiredEnhancedCanvasSize() called getBoundingClientRect() every decoded frame to size the WebGL backing store, forcing a synchronous layout on the hot render path. Cache the size in device pixels via ResizeObserver instead, re-observing only when the target detaches or moves to a different document (Document Picture-in-Picture re-parents the player surface into a floating window).
Documentation previewThe documentation preview has been deployed for this pull request. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 79487937f2
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Pull request overview
This PR optimizes the Web UI video renderer’s canvas backing-store sizing by removing a per-frame synchronous layout dependency and replacing it with a cached, observer-driven size in device pixels (including support for Document Picture-in-Picture re-parenting).
Changes:
- Replaces per-frame ancestor
getBoundingClientRect()scanning with aResizeObserverattached to a stable sized ancestor, caching the latest device-pixel size. - Adds realm-aware observer management so the observer is recreated when the canvas is moved across documents (e.g., Document Picture-in-Picture).
- Seeds cached size synchronously to keep the first enhanced frame correctly sized before observer callbacks fire.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
The observed element and the canvas move into the Document Picture-in- Picture window together, so comparing their ownerDocuments could never detect the re-parent and the observer built in the original window went stale. Track the observer's own document instead and recreate it in the target's window when they diverge. Drop the CSS-content-box x DPR fallback: device-pixel-content-box is supported across all target browsers, so read device pixels directly.
Summary
desiredEnhancedCanvasSize()calledgetBoundingClientRect()on the canvas's ancestor chain every decoded frame to compute the WebGL backing-store size, forcing a synchronous layout on the hot render path (up to 60fps, across both double-buffered renderer slots).ResizeObserveron the stableaspect-videocontainer, caching the size in device pixels. The per-frame path now just reads the cache plus a cheapisConnected/ownerDocumentcheck — no layout, nogetBoundingClientRect.devicePixelContentBoxSizefor exact device pixels (auto-tracks DPR changes, e.g. moving windows across monitors), falling back to CSS content box × clamped DPR for engines that don't support it.[source, min(source×2, 1920×1088)]) is unchanged.Test plan
pnpm tsc --noEmitandpnpm biome checkpass