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:
2026-05-15 16:41:40 -04:00
parent f4c650c4d8
commit 90c029eddb
29 changed files with 2113 additions and 496 deletions
+17 -4
View File
@@ -1,6 +1,6 @@
use crate::{
App, Bounds, Element, ElementId, GlobalElementId, InspectorElementId, IntoElement, LayoutId,
ObjectFit, Pixels, Style, StyleRefinement, Styled, Window,
App, Bounds, Corners, Element, ElementId, GlobalElementId, InspectorElementId, IntoElement,
LayoutId, ObjectFit, Pixels, Style, StyleRefinement, Styled, Window,
};
#[cfg(target_os = "macos")]
use core_video::pixel_buffer::CVPixelBuffer;
@@ -25,6 +25,7 @@ impl From<CVPixelBuffer> for SurfaceSource {
pub struct Surface {
source: SurfaceSource,
object_fit: ObjectFit,
corner_radii: Option<Corners<Pixels>>,
style: StyleRefinement,
}
@@ -33,6 +34,7 @@ pub fn surface(source: impl Into<SurfaceSource>) -> Surface {
Surface {
source: source.into(),
object_fit: ObjectFit::Contain,
corner_radii: None,
style: Default::default(),
}
}
@@ -43,6 +45,12 @@ impl Surface {
self.object_fit = object_fit;
self
}
/// Set rounded clipping for the rendered surface.
pub fn corner_radii(mut self, corner_radii: impl Into<Corners<Pixels>>) -> Self {
self.corner_radii = Some(corner_radii.into());
self
}
}
impl Element for Surface {
@@ -96,8 +104,13 @@ impl Element for Surface {
SurfaceSource::Surface(surface) => {
let size = crate::size(surface.get_width().into(), surface.get_height().into());
let new_bounds = self.object_fit.get_bounds(bounds, size);
// TODO: Add support for corner_radii
window.paint_surface(new_bounds, surface.clone());
let mut style = Style::default();
style.refine(&self.style);
let corner_radii = self
.corner_radii
.unwrap_or_else(|| style.corner_radii.to_pixels(window.rem_size()))
.clamp_radii_for_quad_size(new_bounds.size);
window.paint_surface(new_bounds, corner_radii, surface.clone());
}
#[allow(unreachable_patterns)]
_ => {}