fix(capture/win-display): a deactivated laptop panel is a named stall suspect, not a blind spot
audit / bun-audit (push) Successful in 14s
ci / web (push) Successful in 52s
windows-drivers / probe-and-proto (push) Successful in 44s
ci / docs-site (push) Successful in 1m7s
audit / cargo-audit (push) Successful in 2m18s
windows-drivers / driver-build (push) Successful in 2m21s
apple / swift (push) Successful in 4m54s
ci / bench (push) Successful in 6m41s
ci / rust-arm64 (push) Successful in 10m4s
decky / build-publish (push) Successful in 42s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 26s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 56s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 14s
deb / build-publish-host (push) Successful in 10m31s
docker / build-push (ci, ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 15s
ci / rust (push) Failing after 13m9s
deb / build-publish (push) Successful in 12m14s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 1m9s
android / android (push) Successful in 16m5s
arch / build-publish (push) Successful in 17m22s
deb / build-publish-client-arm64 (push) Successful in 9m46s
windows-host / package (push) Successful in 16m38s
windows-host / winget-source (push) Skipped
flatpak / build-publish (push) Successful in 7m11s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 3m24s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 4m30s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 17m10s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 16m38s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 4m42s
release / apple (push) Successful in 27m50s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 5m49s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 26m34s
docker / deploy-docs (push) Successful in 54s
docker / build-push-arm64cross (push) Successful in 9m53s
apple / screenshots (push) Successful in 23m52s
audit / bun-audit (push) Successful in 14s
ci / web (push) Successful in 52s
windows-drivers / probe-and-proto (push) Successful in 44s
ci / docs-site (push) Successful in 1m7s
audit / cargo-audit (push) Successful in 2m18s
windows-drivers / driver-build (push) Successful in 2m21s
apple / swift (push) Successful in 4m54s
ci / bench (push) Successful in 6m41s
ci / rust-arm64 (push) Successful in 10m4s
decky / build-publish (push) Successful in 42s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 26s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 56s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 14s
deb / build-publish-host (push) Successful in 10m31s
docker / build-push (ci, ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 15s
ci / rust (push) Failing after 13m9s
deb / build-publish (push) Successful in 12m14s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 1m9s
android / android (push) Successful in 16m5s
arch / build-publish (push) Successful in 17m22s
deb / build-publish-client-arm64 (push) Successful in 9m46s
windows-host / package (push) Successful in 16m38s
windows-host / winget-source (push) Skipped
flatpak / build-publish (push) Successful in 7m11s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 3m24s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 4m30s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 17m10s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 16m38s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 4m42s
release / apple (push) Successful in 27m50s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 5m49s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 26m34s
docker / deploy-docs (push) Successful in 54s
docker / build-push-arm64cross (push) Successful in 9m53s
apple / screenshots (push) Successful in 23m52s
Field A/B (reporter, Legion 5 Pro hybrid, 2026-07-27): the ~2 s capture-stall metronome IS the exclusive isolate's own doing — deactivating the laptop panel leaves a dark-but-connected eDP head whose driver-level servicing disturbs the capture path (~1.7-2.8 s period); `topology: primary` (panel stays active) stopped it outright (16.3 stalls/min → 0). Our own .221 logged the identical signature the day before. The detector then steered AWAY from the cause: connected_inactive filtered to EXTERNAL physicals only, so the one display that mattered — on a hybrid laptop, the default config — reported as `none`. - TargetInventory: new `internal_panel` class bit (eDP/LVDS/embedded). - connected_inactive_externals → connected_inactive_physicals: internal panels join the suspect list (virtual/indirect stay excluded); a nameless panel renders as "laptop panel". - The below-OS METRONOMIC warn names the dark-panel case and its actual cures (`topology: primary`, `pnp_disable_monitors`) — the old text's "unplug it" prescriptions are impossible for an internal panel. - ddc_power_off: a zero-ack sweep now says at INFO that the axis did nothing (internal panels have no DDC/CI) instead of silently no-op'ing. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -115,7 +115,7 @@ impl StallWatch {
|
||||
delivered no frame for the gap; the present path stalled below capture"
|
||||
);
|
||||
if let Some(period) = stall.metronomic {
|
||||
let suspects = pf_win_display::display_events::connected_inactive_externals();
|
||||
let suspects = pf_win_display::display_events::connected_inactive_physicals();
|
||||
let suspects = if suspects.is_empty() {
|
||||
"none".to_string()
|
||||
} else {
|
||||
@@ -151,10 +151,13 @@ impl StallWatch {
|
||||
display-poller software (the SteelSeries-GG/SignalRGB class — \
|
||||
correlate 'slow display-descriptor poll' lines), or the DWM present \
|
||||
clock (try a different refresh rate). If connected_inactive lists a \
|
||||
display, its standby probing is the prime suspect: unplug it at the \
|
||||
GPU, disable its OSD auto input scan (TVs: instant-on/quick-start + \
|
||||
CEC off), use an HPD-holding adapter/dummy, or keep it active while \
|
||||
streaming"
|
||||
display, its standby servicing is the prime suspect. For a LAPTOP \
|
||||
PANEL (the exclusive isolate deactivated it — the dark-but-connected \
|
||||
head is itself the disturbance on hybrid laptops): keep it active \
|
||||
with `topology: primary`, or try the `pnp_disable_monitors` axis. \
|
||||
For an external display: unplug it at the GPU, disable its OSD auto \
|
||||
input scan (TVs: instant-on/quick-start + CEC off), use an \
|
||||
HPD-holding adapter/dummy, or keep it active while streaming"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,9 +181,14 @@ pub fn panel_off_except(exclude_gdi: &str) -> u32 {
|
||||
acked += set_power(m.hmon, &m.device, POWER_OFF);
|
||||
}
|
||||
if acked == 0 {
|
||||
tracing::debug!(
|
||||
"DDC/CI: no physical panel accepted the DPMS-off command \
|
||||
(no DDC/CI-capable panel besides the virtual display)"
|
||||
// INFO, not debug: the user opted into this axis, so "it did nothing" is an answer they
|
||||
// asked for. The common case is a laptop — internal eDP/LVDS panels have NO DDC/CI at
|
||||
// all (their brightness/power runs over the driver's own channel), so `ddc_power_off`
|
||||
// is structurally a no-op for them (reporter feedback 2026-07-27).
|
||||
tracing::info!(
|
||||
"DDC/CI: no panel accepted the DPMS-off command — the ddc_power_off axis did \
|
||||
nothing on this display set (internal eDP/LVDS panels expose no DDC/CI; external \
|
||||
monitors may have it disabled in the OSD or dropped by a dock/KVM)"
|
||||
);
|
||||
}
|
||||
acked
|
||||
|
||||
@@ -156,15 +156,27 @@ pub fn summarize(events: &[DisplayEvent]) -> String {
|
||||
out.join(", ")
|
||||
}
|
||||
|
||||
/// The prime suspects for link-probe disturbances, from the cached inventory: external physical
|
||||
/// displays that are CONNECTED but not part of the desktop (standby TV / input-switched monitor).
|
||||
/// Rendered as `"<friendly> (<connector>)"`. Never blocks on the CCD lock.
|
||||
pub fn connected_inactive_externals() -> Vec<String> {
|
||||
/// The prime suspects for link-probe/dark-head disturbances, from the cached inventory: PHYSICAL
|
||||
/// displays — external connectors AND internal panels — that are CONNECTED but not part of the
|
||||
/// desktop. External = the classic standby TV / input-switched monitor; internal = the laptop
|
||||
/// panel the exclusive isolate deactivated, whose driver-level servicing produces the identical
|
||||
/// ~2 s metronome on hybrid laptops (field A/B 2026-07-27: reporter's Legion, exclusive
|
||||
/// 16.3 stalls/min vs primary 0 — the old external-only filter reported `none` there and steered
|
||||
/// the diagnosis AWAY from the real cause for hours). Virtual/indirect targets stay excluded
|
||||
/// (precision rule). Rendered as `"<friendly> (<connector>)"`. Never blocks on the CCD lock.
|
||||
pub fn connected_inactive_physicals() -> Vec<String> {
|
||||
let st = state().lock().unwrap();
|
||||
st.inventory
|
||||
.iter()
|
||||
.filter(|t| t.external_physical && !t.active)
|
||||
.map(|t| format!("{} ({})", t.friendly, t.tech))
|
||||
.filter(|t| (t.external_physical || t.internal_panel) && !t.active)
|
||||
.map(|t| {
|
||||
let name = if t.friendly.is_empty() && t.internal_panel {
|
||||
"laptop panel"
|
||||
} else {
|
||||
&t.friendly
|
||||
};
|
||||
format!("{} ({})", name, t.tech)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
|
||||
@@ -844,15 +844,21 @@ pub unsafe fn count_other_active(keep_target_ids: &[u32]) -> Option<u32> {
|
||||
}
|
||||
|
||||
/// One CONNECTED display target from a full (`QDC_ALL_PATHS`) CCD sweep — the disturbance-
|
||||
/// attribution inventory. `external_physical` is the load-bearing bit: a standby TV/monitor on a
|
||||
/// real connector is the prime suspect for the periodic link-probe stutter class, while internal
|
||||
/// panels and indirect/virtual targets (our own IDD included) are not.
|
||||
/// attribution inventory. `external_physical` and `internal_panel` are the load-bearing bits: a
|
||||
/// standby TV/monitor on a real connector is the classic suspect for the periodic link-probe
|
||||
/// stutter class, and a laptop panel the exclusive isolate DEACTIVATED is the hybrid-laptop
|
||||
/// variant of the same disturbance (field A/B 2026-07-27: dark-but-connected eDP head on the
|
||||
/// iGPU → ~2 s stall metronome; `topology: primary` → zero) — only indirect/virtual targets
|
||||
/// (our own IDD included) can never be suspects.
|
||||
pub struct TargetInventory {
|
||||
pub target_id: u32,
|
||||
/// Whether any active path drives this target (part of the desktop right now).
|
||||
pub active: bool,
|
||||
/// External physical connector (HDMI/DP/DVI/…): candidate for standby link-probe churn.
|
||||
pub external_physical: bool,
|
||||
/// Internal panel (eDP/LVDS/embedded): candidate for dark-head servicing churn when
|
||||
/// connected-but-inactive (the exclusive isolate on a laptop creates exactly that state).
|
||||
pub internal_panel: bool,
|
||||
/// Short connector label for logs (`"HDMI"`, `"DisplayPort"`, `"internal-panel"`, …).
|
||||
pub tech: &'static str,
|
||||
/// The monitor's friendly name (`"LG TV SSCR2"`); empty when the EDID carries none.
|
||||
@@ -953,6 +959,7 @@ pub unsafe fn target_inventory() -> Vec<TargetInventory> {
|
||||
target_id: t.id,
|
||||
active: active.contains(&key),
|
||||
external_physical,
|
||||
internal_panel: tech == "internal-panel",
|
||||
tech,
|
||||
friendly: utf16z_str(&req.monitorFriendlyDeviceName),
|
||||
monitor_device_path: utf16z_str(&req.monitorDevicePath),
|
||||
|
||||
Reference in New Issue
Block a user