scrap: replace the DXGI factory and output together when re-reading HDR state

Review follow-up: when the fresh factory did not find the output by name,
the refresh kept the new, current factory next to the old output, and
because IsCurrent then reported TRUE it never enumerated again, so the
stale output could stay forever. enumerate_output6 now returns both or
neither, and the refresh only replaces the pair together; a null factory
forces another enumeration on the next refresh while the old output is
still read in the meantime. The constructor gets the same guarantee for
free, since a failed lookup leaves the factory null there too.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RLb1dNdhFqUQExJPANjo1F
This commit is contained in:
rustdesk
2026-09-02 16:00:47 +08:00
parent 6e502cde2e
commit 2f3a6789de

View File

@@ -158,6 +158,8 @@ impl HdrToSdr {
)?;
let ps = ComPtr(ps);
// Not found leaves the factory null, so the first refresh enumerates
// again instead of trusting the capturer's possibly stale output.
let (factory, mut output6) = enumerate_output6(device_name);
if output6.is_null() {
output6 = query_output6(output as *mut IUnknown);
@@ -332,9 +334,12 @@ impl HdrToSdr {
self.queried_at = Instant::now();
if self.factory.is_null() || (*self.factory.0).IsCurrent() == FALSE {
let (factory, output6) = enumerate_output6(&self.device_name);
self.factory = factory;
if !output6.is_null() {
self.factory = factory;
self.output6 = output6;
} else {
// Keep reading the old output, but enumerate again next time.
self.factory = ComPtr(ptr::null_mut());
}
}
let is_hdr = output_is_hdr(self.output6.0).unwrap_or(self.is_hdr);
@@ -410,6 +415,8 @@ unsafe fn query_output6(object: *mut IUnknown) -> ComPtr<IDXGIOutput6> {
// A fresh factory sees the current display configuration; the output is found
// by its GDI name because the outputs of a stale factory keep stale descriptions.
// Returns both or neither: a non-null factory guarantees the output came from
// its topology, so a caller that sees a null factory knows to enumerate again.
unsafe fn enumerate_output6(
device_name: &[WCHAR; 32],
) -> (ComPtr<IDXGIFactory1>, ComPtr<IDXGIOutput6>) {
@@ -441,7 +448,7 @@ unsafe fn enumerate_output6(
}
}
}
(factory, ComPtr(ptr::null_mut()))
(ComPtr(ptr::null_mut()), ComPtr(ptr::null_mut()))
}
fn other(msg: impl Into<String>) -> io::Error {