Move Servo IPC off UI thread
Root cause of the post-tab lag: the GPUI 16 ms timer was calling `WebSurfaceRuntime::ensure_tab` and `tick` on the UI thread, and each call did a synchronous `serde_json` write plus `read_line` against the Servo sidecar over stdin/stdout. With even one visible tab, every frame stalled on cross-process IPC. Introduce `web_surface_worker.rs` — a per-profile worker thread that owns the `ServoLiveClient`, drains a coalescing request queue (latest Ensure/Poll per tab wins, no unbounded growth), and ships results back through a `std::sync::mpsc` channel. `WebSurfaceRuntime` now submits work non-blockingly and drains responses in `tick`; the UI thread never blocks on the sidecar. Adjacent in-flight cleanup riding along: hardware IOSurface rendering-context completion (sidecar `live_protocol`, `hardware_rendering_context`, GPUI BGRA surface shader), CSS viewport size + device pixel ratio plumbing into `ServoLiveFrame`, and the Send opt-ins for `CVPixelBuffer`-bearing types so frames can cross the thread boundary.
This commit is contained in:
@@ -108,8 +108,8 @@ impl SoftwareServoHost {
|
||||
|
||||
/// Paint and present the webview's current surface while leaving
|
||||
/// framebuffer readback to callers that explicitly need RGBA
|
||||
/// bytes. The live hardware path uses this before publishing the
|
||||
/// IOSurface handle to the renderer process.
|
||||
/// bytes. The live hardware path exports the just-presented
|
||||
/// IOSurface from the rendering context.
|
||||
pub fn paint_without_readback(&mut self, webview_id: &WebViewId) -> Result<(), ServoHostError> {
|
||||
self.paint_webview(webview_id, false).map(|_| ())
|
||||
}
|
||||
@@ -204,9 +204,13 @@ impl ServoHost for SoftwareServoHost {
|
||||
|
||||
webview.delegate.set_state(WebViewState::Loading);
|
||||
if should_create_initial_document {
|
||||
let hidpi_scale_factor = webview.webview.hidpi_scale_factor();
|
||||
webview.webview = WebViewBuilder::new(&servo, webview.rendering_context.clone())
|
||||
.delegate(webview.delegate.clone())
|
||||
.url(url)
|
||||
// The live path pushes DPR before first navigation. Preserve that scale when
|
||||
// replacing the about:blank WebView so CSS viewport = physical surface / DPR.
|
||||
.hidpi_scale_factor(hidpi_scale_factor)
|
||||
.build();
|
||||
// Cosmetic: makes the freshly built WebView paint its
|
||||
// first frame. The input-accepting invariant lives in
|
||||
@@ -444,10 +448,7 @@ impl SoftwareServoHost {
|
||||
let Some(hardware) = webview.hardware_context.as_ref() else {
|
||||
return Ok(None);
|
||||
};
|
||||
hardware
|
||||
.peek_iosurface_identity()
|
||||
.map(Some)
|
||||
.map_err(|_| ServoHostError::RenderingContextUnavailable)
|
||||
hardware.peek_iosurface_identity().map_err(|_| ServoHostError::RenderingContextUnavailable)
|
||||
}
|
||||
|
||||
/// Mint a fresh mach port for the IOSurface bound to this
|
||||
|
||||
Reference in New Issue
Block a user