Skip to content

Commit 5b4d33d

Browse files
committed
Recreate DDupl adapters when DXGI_ERROR_MODE_CHANGE_IN_PROGRESS occurs
This happens under unclear circumstances when switching two screes beween extended and duplicated mode. Contrary to the error description, it goes away only once the user switched back.
1 parent b8728cb commit 5b4d33d

File tree

2 files changed

+39
-16
lines changed

2 files changed

+39
-16
lines changed

Software/grab/DDuplGrabber.cpp

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -128,23 +128,10 @@ bool DDuplGrabber::init()
128128
if (!m_createDXGIFactory1Func || !m_D3D11CreateDeviceFunc)
129129
return false;
130130

131-
IDXGIFactory1Ptr factory;
132-
HRESULT hr = ((CreateDXGIFactory1Func)m_createDXGIFactory1Func)(__uuidof(IDXGIFactory1), (void**)&factory);
133-
if (FAILED(hr))
134-
{
135-
qCritical(Q_FUNC_INFO " Failed to CreateDXGIFactory1: 0x%X", hr);
131+
if (!recreateAdapters()) {
136132
return false;
137133
}
138134

139-
IDXGIAdapter1Ptr adapter;
140-
for (int i = 0; factory->EnumAdapters1(i, &adapter) != DXGI_ERROR_NOT_FOUND; i++)
141-
{
142-
DXGI_ADAPTER_DESC1 desc;
143-
adapter->GetDesc1(&desc);
144-
DEBUG_LOW_LEVEL << Q_FUNC_INFO << "Found Adapter: " << QString::fromWCharArray(desc.Description);
145-
m_adapters.push_back(adapter);
146-
}
147-
148135
if (NULL == (m_threadEvent = CreateEventW(NULL, false, false, DDUPL_THREAD_EVENT_NAME))) {
149136
qCritical(Q_FUNC_INFO " unable to create threadEvent");
150137
return false;
@@ -164,6 +151,29 @@ bool DDuplGrabber::init()
164151
return true;
165152
}
166153

154+
bool DDuplGrabber::recreateAdapters() {
155+
m_adapters.clear();
156+
157+
IDXGIFactory1Ptr factory;
158+
HRESULT hr = ((CreateDXGIFactory1Func)m_createDXGIFactory1Func)(__uuidof(IDXGIFactory1), (void**)&factory);
159+
if (FAILED(hr))
160+
{
161+
qCritical(Q_FUNC_INFO " Failed to CreateDXGIFactory1: 0x%X", hr);
162+
return false;
163+
}
164+
165+
IDXGIAdapter1Ptr adapter;
166+
for (int i = 0; factory->EnumAdapters1(i, &adapter) != DXGI_ERROR_NOT_FOUND; i++)
167+
{
168+
DXGI_ADAPTER_DESC1 desc;
169+
adapter->GetDesc1(&desc);
170+
DEBUG_LOW_LEVEL << Q_FUNC_INFO << "Found Adapter: " << QString::fromWCharArray(desc.Description);
171+
m_adapters.push_back(adapter);
172+
}
173+
174+
return true;
175+
}
176+
167177
DWORD WINAPI DDuplGrabberThreadProc(LPVOID arg) {
168178
DDuplGrabber* _this = (DDuplGrabber*)arg;
169179
DWORD errorcode;
@@ -320,7 +330,7 @@ bool DDuplGrabber::reallocate(const QList< ScreenInfo > &grabScreens)
320330
}
321331

322332
// Must be called from DDuplGrabberThreadProc !
323-
bool DDuplGrabber::_reallocate(const QList< ScreenInfo > &grabScreens)
333+
bool DDuplGrabber::_reallocate(const QList< ScreenInfo > &grabScreens, bool noRecursion)
324334
{
325335
if (m_state == Uninitialized)
326336
{
@@ -397,6 +407,18 @@ bool DDuplGrabber::_reallocate(const QList< ScreenInfo > &grabScreens)
397407
qCritical(Q_FUNC_INFO " Desktop Duplication not available on this system / in this configuration (desktop 0x%X, 0x%X)", screenInfo.handle, hr);
398408
return false;
399409
}
410+
else if (hr == DXGI_ERROR_MODE_CHANGE_IN_PROGRESS) {
411+
if (!noRecursion) {
412+
qWarning(Q_FUNC_INFO " DXGI mode change in progress. Recreating adapters");
413+
if (!recreateAdapters()) {
414+
return false;
415+
}
416+
return _reallocate(grabScreens, true);
417+
} else {
418+
qCritical(Q_FUNC_INFO " Failed to reallocate: DXGI mode change in progress (after recreation)");
419+
return false;
420+
}
421+
}
400422
else if (FAILED(hr))
401423
{
402424
qCritical(Q_FUNC_INFO " Failed to duplicate output: 0x%X", hr);

Software/grab/include/DDuplGrabber.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,15 @@ public slots:
7474
protected slots:
7575
virtual GrabResult grabScreens();
7676
virtual bool reallocate(const QList< ScreenInfo > &grabScreens);
77-
virtual bool _reallocate(const QList< ScreenInfo > &grabScreens);
77+
virtual bool _reallocate(const QList< ScreenInfo > &grabScreens, bool noRecursion = false);
7878

7979
virtual QList< ScreenInfo > * screensWithWidgets(QList< ScreenInfo > * result, const QList<GrabWidget *> &grabWidgets);
8080

8181
virtual bool isReallocationNeeded(const QList< ScreenInfo > &grabScreens) const;
8282

8383
protected:
8484
bool init();
85+
bool recreateAdapters();
8586
void freeScreens();
8687
GrabResult returnBlackBuffer();
8788
bool runThreadCommand(DWORD timeout);

0 commit comments

Comments
 (0)