c++desktopduplicationdirect3d11

Direct3D Desktop Duplication: How to Recover From Changing Screen Resolution?


I'm developing a desktop application that uses the IDXGIOutputDuplication interface to take screen pictures several times per second. Whenever I call its AcquireNextFrame method, I check if the returned HRESULT is DXGI_ERROR_ACCESS_LOST to see if some event invalidates the duplication interface. I also have an IDXGIFactory1, and I use isCurrent() to see if anything in the graphics setup changed, like a new GPU was installed (for some reason), a new monitor was attached, or the desktop's resolution was changed.

My approach when isCurrent() returns false is to reconstruct ALL the IDXGI and ID3D11 interfaces using IDXGIFactory1. This means all adapters, all outputs, and all duplication interfaces. Based on cout logs, the interfaces for each monitor seem to be reconstructed properly.

My problem with this approach is that based on what I've observed, the monitor whose OutputDuplication interface returned a DXGI_ERROR_ACCESS_LOST code never recovers even when a new interface was constructed. So if Monitor A produces an error, and later on I capture from Monitor B, it gives me screen caps. But if I continue to capture from Monitor A, I can't get anything, maybe just DXGI_ERROR_ACCESS_LOST error codes.

I know this sounds a bit weird and possibly unclear in some parts, but so far this is the best way I can explain. I also tried searching online, but nothing has helped. Any ideas?

(Also, if it's any help, I'm using JNI so that the application's Java code can access C++'s Direct3D interfaces. It's a project I'm doing at work, and no one there knows the solution.)


Solution

  • Okay, so I was fiddling around some more, and I found the solution.

    After reconstructing all the ID3D11 interfaces, the desktop duplication interface (IDXGIOutputDuplication) is still invalid. Maybe because it was retrieved while the screen resolution was still updating.

    All I had to do was to call IDXGIOutput1's DuplicateOutput() method again when the next call to AcquireNextFrame() returns a DXGI_ERROR_ACCESS_LOST code.

    Putting this here in case anyone ever has the same problem.