From 89d444b950d8244561397f96992410b2e64c8cfd Mon Sep 17 00:00:00 2001 From: 21pages Date: Wed, 2 Sep 2026 23:08:34 +0800 Subject: [PATCH] scrap: avoid null duplication after HDR fallback failure Signed-off-by: 21pages --- libs/scrap/src/dxgi/mod.rs | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/libs/scrap/src/dxgi/mod.rs b/libs/scrap/src/dxgi/mod.rs index 488f4c14f..449bd6b47 100644 --- a/libs/scrap/src/dxgi/mod.rs +++ b/libs/scrap/src/dxgi/mod.rs @@ -247,9 +247,8 @@ impl Capturer { } // Drops the tone-map and re-duplicates the output the legacy way, so DXGI - // hands over clipped BGRA8 (the pre-HDR behaviour) and the session stays on - // DXGI instead of being switched to GDI by the capture loop, which treats - // any other error that way. The caller sees WouldBlock and asks again. + // hands over clipped BGRA8 (the pre-HDR behaviour). If re-duplication fails, + // switch to GDI before returning. The caller sees WouldBlock and asks again. unsafe fn abandon_tonemap(&mut self, err: io::Error) -> io::Result { if hdr::is_permanent(&err) { hdr::UNAVAILABLE.store(true, std::sync::atomic::Ordering::Relaxed); @@ -259,9 +258,15 @@ impl Capturer { (*self.duplication.0).ReleaseFrame(); self.duplication = ComPtr(ptr::null_mut()); let mut duplication = ptr::null_mut(); - wrap_hresult( + let result = wrap_hresult( (*self.display.inner.0).DuplicateOutput(self.device.0 as *mut _, &mut duplication), - )?; + ); + if let Err(err) = result { + if self.set_gdi() { + return Err(io::ErrorKind::WouldBlock.into()); + } + return Err(err); + } self.duplication = ComPtr(duplication); let mut desc: DXGI_OUTDUPL_DESC = mem::zeroed(); (*duplication).GetDesc(&mut desc); @@ -422,6 +427,9 @@ impl Capturer { } unsafe fn load_frame(&mut self, timeout: UINT) -> io::Result<(*const u8, i32)> { + if self.duplication.0.is_null() { + return Err(io::ErrorKind::AddrNotAvailable.into()); + } let mut frame = ptr::null_mut(); #[allow(invalid_value)] let mut info = mem::MaybeUninit::uninit().assume_init(); @@ -681,6 +689,9 @@ impl Capturer { } fn unmap(&self) { + if self.duplication.0.is_null() { + return; + } unsafe { (*self.duplication.0).ReleaseFrame(); if self.fastlane {