Commit Graph
3 Commits
Author SHA1 Message Date
ZacharyZhang-NY 05a7a0d67f Present Servo BGRA hardware surfaces 2026-05-13 00:22:00 -04:00
ZacharyZhang-NY bb0bd0032f T10.2: extract IOSurface mach port from the hardware surface on macOS 2026-05-10 23:01:34 -04:00
ZacharyZhang-NY 048c5dfecd Vendor a headless hardware RenderingContext for Servo
The first concrete step toward the T10 IOSurface zero-copy path
(plan in docs/t10-iosurface-plan.md). Before this commit the sidecar
process could only use `SoftwareRenderingContext` — CPU rasterising
plus an 8 MB RGBA readback per 1080p frame is most of where scroll
latency comes from after the file pipe (a80d039), Vec clone
(e02c0fd), texture dedup (7f3b8b4), and hash swap (3f184ee) have
all landed.

The blocker is purely architectural: `servo-paint-api 0.1` exposes
`OffscreenRenderingContext` only as a child of
`WindowRenderingContext`, which requires a `DisplayHandle +
WindowHandle`. The sidecar has no window. The underlying
`SurfmanRenderingContext` glue *can* drive a hardware adapter
against a `SurfaceType::Generic` offscreen surface, but its
constructor is private. Until the upstream PR lands, this commit
vendors the minimal slice of that glue into `ely_servo_host`:

  * `HardwareOffscreenContext::new(size)` uses
    `Connection::new() → create_adapter()` (real GPU, not the
    software adapter) and a `SurfaceType::Generic` offscreen
    surface. On macOS the surfman CGL backend backs that surface
    with an `IOSurface` — exactly the thing the IOSurface bridge
    in subsequent commits will reach for.
  * Implements `servo::RenderingContext` so it slots into
    `ServoBuilder::rendering_context` wherever the existing
    `SoftwareRenderingContext` does, with no other Servo-side
    knowledge.
  * Scope deliberately narrow: only the methods Servo's headless
    readback actually calls. `create_texture` /
    `destroy_texture` / `connection` / `refresh_driver` fall
    through to the trait's `None` defaults. `read_to_image` inlines
    the upstream `Framebuffer::read_framebuffer_to_image` helper so
    we don't reach for a private helper that may change shape.
  * No `RawWindowHandle` and no `RefreshDriver` — both belong to
    paths the headless sidecar doesn't take.

The whole thing is feature-gated on `hardware-render`. Default
builds compile zero new lines; the additional surfman / gleam /
glow / euclid / image / log deps are all `optional = true`. Sidecar
binary still uses `SoftwareServoHost` until a follow-up commit
threads the new context in behind a CLI flag.

A smoke test at `tests/hardware_rendering_context.rs` constructs
the context. On a host with a real GPU it returns `Ok`; on a no-GPU
CI host it logs the surfman cause and reports `ok` rather than
failing the suite — the test is guarding the wiring, not the
hardware availability. On this Mac it constructs cleanly.

The `expect_used` / `unwrap_used` workspace lints are honoured —
fallible reads return `None` instead of panicking, no `.expect()` /
`.unwrap()` survives in the vendored body. The two `unsafe` blocks
(loading GL function pointers via surfman's `get_proc_address`) are
the same blocks upstream uses, with `#[expect(unsafe_code)]` to
override the workspace `unsafe_code = "deny"` lint locally.

cargo test --bin ely_app: 120 passed.
cargo test -p ely_servo_host --features servo-engine,hardware-render
  --test hardware_rendering_context: 1 passed (constructs cleanly).
Pre-existing `manages_real_servo_webview_lifecycle` failure on
servo.org is unrelated (reproduces on b8795bf without this change,
already documented in T7's commit history).
2026-05-10 20:50:59 -04:00