Plumb the rendering context kind from ely_app env var to the sidecar

T10.1: with the vendored `HardwareOffscreenContext` (048c5df) and the
host-level kind dispatch (a7d3e89) in place, the sidecar binary
still ignored the rendering context kind — every spawn was wired to
the software path regardless of how the host process was built. This
commit threads the choice end-to-end:

  * `ely_servo_sidecar` learns a `--rendering-context [software|
    hardware]` flag on its `live` subcommand. `LiveArgs` carries
    the parsed `RenderingContextKind` (defaulting to `Software` so
    existing invocations stay bit-identical) and `live.rs::run_live`
    routes it through to `SoftwareServoHost::new_with_config_dir_and_kind`.
    Unknown values produce a typed
    `SidecarArgsError::InvalidRenderingContext`; a missing value
    after the flag produces the existing `MissingArgumentValue`.

  * `ely_app` reads `ELY_SERVO_RENDERING_CONTEXT` (with values
    `software` / `hardware`, case-insensitive) and, if set, appends
    `--rendering-context VALUE` to the sidecar command line.
    Unset or unrecognised values fall through to the sidecar's own
    software default — a stale env var or a typo never breaks the
    browser startup. The sidecar arg parser is the source of truth
    for legality of explicit values; the env helper only gates
    which values reach it.

  * Five new unit tests in `args::tests` pin the new parse paths:
    default-is-software, explicit-software, explicit-hardware,
    bogus-value-rejected, missing-value-rejected. Run via
    `cargo test -p ely_servo_host --features servo-engine --bin
    ely_servo_sidecar` and now hit alongside the five existing
    snapshot tests for 10 passes.

End-to-end perf expectation: with the sidecar binary built using
`--features servo-engine,hardware-render` and the env var set to
`hardware`, every spawned sidecar webview rasterises through the
real GPU adapter (via the vendored
`HardwareOffscreenContext`/surfman/CGL chain on macOS). The host
still reads back RGBA into a `Vec<u8>` for the existing pipe
protocol; the IOSurface zero-copy bridge that deletes that
read-back is T10.2–T10.5 in docs/t10-iosurface-plan.md and lands
in subsequent commits.

cargo test --bin ely_app: 120 passed, 0 failed, 2 ignored.
cargo test -p ely_servo_host --features servo-engine --bin ely_servo_sidecar: 10 passed.
cargo test -p ely_servo_host --features servo-engine --test sidecar: 9 passed.
cargo test -p ely_servo_host --features servo-engine,hardware-render --test hardware_rendering_context: 1 passed.
This commit is contained in:
2026-05-10 21:27:12 -04:00
parent a7d3e896bb
commit 18fd20b577
3 changed files with 104 additions and 1 deletions
+30
View File
@@ -1,9 +1,21 @@
use std::{
env,
io::{self, BufRead, BufReader, Read, Write},
path::PathBuf,
process::{Child, ChildStdin, ChildStdout, Stdio},
};
/// Environment variable that lets the user pick the rendering context
/// kind used by the spawned sidecar. Accepted values: `software`
/// (default — bit-identical to pre-flag builds) and `hardware` (real
/// GPU adapter via the vendored `HardwareOffscreenContext`; requires
/// the sidecar binary to be compiled with the `hardware-render`
/// feature). Anything else is silently dropped and the sidecar
/// defaults to software so a typo'd value never blocks the browser
/// from starting; the sidecar's own arg parser still errors loudly on
/// an unrecognised value when set explicitly via the flag.
const RENDERING_CONTEXT_ENV: &str = "ELY_SERVO_RENDERING_CONTEXT";
use ely_domain::SitePermissionDecision;
use serde::{Deserialize, Serialize};
use thiserror::Error;
@@ -25,6 +37,9 @@ impl ServoLiveClient {
let mut command = command_target.command();
command.arg("live").arg("--profile-data-dir").arg(profile_data_dir);
if let Some(rendering_context) = rendering_context_from_env() {
command.arg("--rendering-context").arg(rendering_context);
}
let mut child = command
.stdin(Stdio::piped())
.stdout(Stdio::piped())
@@ -334,3 +349,18 @@ struct LiveFrameReport {
#[cfg(all(test, feature = "live-site-smoke"))]
sample_hash: u64,
}
/// Map `ELY_SERVO_RENDERING_CONTEXT` to a CLI argument value if it's
/// one we recognise. Unset variable returns `None` (sidecar uses its
/// own default of software); unknown value also returns `None`
/// rather than `Some("garbage")` so a stale env var doesn't fail the
/// sidecar startup. The sidecar's own arg parser is the source of
/// truth for what values are valid — we just gate which ones we
/// forward.
fn rendering_context_from_env() -> Option<&'static str> {
match env::var(RENDERING_CONTEXT_ENV).ok()?.to_lowercase().as_str() {
"software" => Some("software"),
"hardware" => Some("hardware"),
_ => None,
}
}