User Tools

Site Tools


ohm_gl_fix:phase6_step0_chromium_wayland_routing_2026-05-01

ohm_gl_fix — Phase 6 Step 0: Chromium's Wayland video presentation path, 2026-05-01

Per Phase 4 §3 Step 0 (with the Q2 methodology fix applied): characterise statically whether Chromium's GPU process routes a hardware-decoded NativePixmap to the Wayland zwp_linux_dmabuf_v1 overlay path, or composes it via Skia GL onto the page's main surface. Output gate: file:line citation for the gating logic in the decision document.

Summary

Step 2 is confirmed needed. Under the current Chromium M138 design, overlay delegation on KWin Wayland is forced off by a gate condition that KWin's compositor capabilities trip. Phase 4 Step 2 (Chromium display-side patch) is no longer conditional; it is in scope.

The patch site is one specific predicate in WaylandConnection::ShouldUseOverlayDelegation().

Routing decision chain (top-down)

A NativePixmap (dmabuf-backed VA-API surface) flows from VaapiVideoDecoder to the GPU process to Viz compositor to Ozone Wayland. The routing decision happens in two stages:

  1. Stage 1 — system-wide enable. WaylandConnection::ShouldUseOverlayDelegation() returns a single bool that gates the entire overlay-subsurface path. If false, no buffer ever becomes an overlay regardless of its properties; everything goes through Skia GL composite onto the main page surface.
  2. Stage 2 — per-buffer candidate filtering. If overlay delegation is enabled, individual buffers are filtered by a Viz-side OverlayProcessor / IsOverlayCandidate() chain (in components/viz/service/display/overlay_processor*.cc). This stage checks format, modifier, size, damage region, and so on. The transport layer (WaylandBufferManagerHost) is buffer-agnostic at this point — it just shuttles whatever the candidate pipeline produced.

For Brave on KWin: Stage 1 fails, so Stage 2 is unreachable. The campaign's Step 2 patch lives at Stage 1.

The gating predicate

ui/ozone/platform/wayland/host/wayland_connection.cc lines 495-509:

bool WaylandConnection::ShouldUseOverlayDelegation() const {
  bool should_use_overlay_delegation =
      IsWaylandOverlayDelegationEnabled() && !fractional_scale_manager_v1();
  should_use_overlay_delegation &= !!single_pixel_buffer();
  return should_use_overlay_delegation;
}

Three conjuncts:

  • IsWaylandOverlayDelegationEnabled() — runtime feature flag. Likely off by default but settable via –enable-features= or chrome:flags. Sub-task open: confirm flag name in M138. * !fractional_scale_manager_v1() — the compositor must NOT advertise the wp_fractional_scale_manager_v1 Wayland protocol. * !!single_pixel_buffer() — the compositor MUST advertise the wp_single_pixel_buffer_manager_v1 Wayland protocol. KWin's compositor capabilities (verified empirically in mpv's verbose log captured during Phase 3): * Registered wp_fractional_scale_manager_v1 at version 1 → second conjunct is false → predicate returns false. * Registered wp_single_pixel_buffer_manager_v1 at version 1 → third conjunct passes (but moot given second). So on KWin Wayland, ShouldUseOverlayDelegation() returns false unconditionally regardless of feature flag. ===== Why the gate exists (per upstream comment) ===== Reading of the surrounding comment block (lines 497-502): fractional scaling requires viewport rescaling that, on non-exo compositors (i.e. anything that isn't ChromeOS/Crostini), conflicts with overlay support because subpixel viewport destinations and subsurface positions aren't widely available. The conservative gate disables overlay whenever fractional scaling is even *possible* (advertised), not just when it's actually active for the surface. This is over-conservative for Markus's use case: PineTab2 + KWin typically runs at integer (1.0) display scale; fractional scale is advertised but not enabled. The gate trips on capability advertisement, not on actual scale state. ===== Patch shape (Phase 4 Step 2 specification) ===== Three plausible patches, in order of least-to-most invasive: - Surface-state-gated relaxation. Replace !fractional_scale_manager_v1() with a check that returns true when the surface's currently-applied scale is integer (1.0, 2.0, etc.). The protocol is allowed to be advertised; we just require that the relevant surface isn't *using* fractional scale right now. Smallest behavioural change; preserves correctness when fractional scale is in fact active. - Per-surface negotiation. Drop the gate entirely and let the Viz OverlayCandidate validator (Stage 2) reject candidates that need viewport-subpixel destinations on this compositor. Bigger refactor; touches Viz's overlay validator code. - Compositor-capability allow-list. Add a feature flag (e.g. –enable-features=WaylandOverlayDelegationOnFractionalCompositor) that bypasses the second conjunct when set. Crudest; relies on the user to know the trade-off. Useful as a probe during Step 2 development but not a shippable answer. Patch (1) is the recommended Step 2 shape — minimal blast radius, restores correct behaviour for KWin's typical integer-scale usage without breaking fractional-scale users. ===== Step 0 sub-task status ===== * Source archaeologywayland_buffer_manager_host.cc, wayland_window.cc, wayland_connection.cc all read. The gating predicate is named with file:line. ✓ * Verify with feature-flag inventory. Confirm IsWaylandOverlayDelegationEnabled() accepts a known –enable-features= flag name (M138 source archaeology or chrome:flags enumeration). Open.
  • Optional stub libva driver test. Per Phase 4 §3 Step 0, only run if static analysis is inconclusive. Static analysis is conclusive enough — Step 2 is needed. Skipped.
  • Document Viz-side per-buffer filtering (Stage 2 above). If/when the Step 2 patch lifts the Stage-1 gate, Stage 2 becomes the next-level gate that needs to pass for actual Brave-decoded NativePixmap to land as an overlay. Not blocking Step 1 / Step 2 work, but should be characterised before Phase 7 verification so we can predict whether C3 (DRM_IOCTL/sec ≤ 100) will be met. Open.

Implications for Phase 4

Phase 4 §3 has been amended (in-place, 2026-05-01):

  • Step 2 is confirmed needed, no longer conditional.
  • Step 2 patch site: chromium/ui/ozone/platform/wayland/host/wayland_connection.cc WaylandConnection::ShouldUseOverlayDelegation() lines 495-509.
  • Step 2 patch shape: surface-state-gated relaxation of the !fractional_scale_manager_v1() predicate.
  • Step 2 build target: chromium-ohm-gl-fix or brave-ohm-gl-fix on marfrit-packages.

The R2 risk in Phase 4 §6 (“Chromium routes via Skia GL by default”) was correctly anticipated and the mitigation is now activated, not just spec'd.

Artefact references

ohm_gl_fix/phase6_step0_chromium_wayland_routing_2026-05-01.txt · Last modified: by markus_fritsche