From 9811e6ce8915bf0ded9d0f2d862308fdc14df404 Mon Sep 17 00:00:00 2001 From: Michael Fahrbach Date: Thu, 16 Jul 2020 01:10:42 +0200 Subject: [PATCH 1/2] Chnges to DesktopDuplication to conform to Guidelines ( https://docs.microsoft.com/en-us/windows/win32/api/dxgi1_2/nf-dxgi1_2-idxgioutputduplication-releaseframe ) --- Software/grab/DDuplGrabber.cpp | 71 +++++++++++++++----------- Software/grab/include/DDuplGrabber.hpp | 13 ++--- 2 files changed, 48 insertions(+), 36 deletions(-) diff --git a/Software/grab/DDuplGrabber.cpp b/Software/grab/DDuplGrabber.cpp index 4fe29dea0..6033a9699 100644 --- a/Software/grab/DDuplGrabber.cpp +++ b/Software/grab/DDuplGrabber.cpp @@ -43,8 +43,8 @@ _COM_SMARTPTR_TYPEDEF(ID3D11Texture2D, __uuidof(ID3D11Texture2D)); _COM_SMARTPTR_TYPEDEF(ID3D11ShaderResourceView, __uuidof(ID3D11ShaderResourceView)); -typedef HRESULT(WINAPI *CreateDXGIFactory1Func)(REFIID riid, _Out_ void **ppFactory); -typedef HRESULT(WINAPI *D3D11CreateDeviceFunc)( +typedef HRESULT(WINAPI* CreateDXGIFactory1Func)(REFIID riid, _Out_ void** ppFactory); +typedef HRESULT(WINAPI* D3D11CreateDeviceFunc)( _In_opt_ IDXGIAdapter* pAdapter, D3D_DRIVER_TYPE DriverType, HMODULE Software, @@ -79,16 +79,16 @@ struct DDuplScreenData : output(_output), duplication(_duplication), device(_device), context(_context) {} - IDXGIOutputPtr output{nullptr}; - IDXGIOutputDuplicationPtr duplication{nullptr}; - ID3D11DevicePtr device{nullptr}; - ID3D11DeviceContextPtr context{nullptr}; + IDXGIOutputPtr output{ nullptr }; + IDXGIOutputDuplicationPtr duplication{ nullptr }; + ID3D11DevicePtr device{ nullptr }; + ID3D11DeviceContextPtr context{ nullptr }; - ID3D11Texture2DPtr textureCopy{nullptr}; + ID3D11Texture2DPtr textureCopy{ nullptr }; DXGI_MAPPED_RECT surfaceMap; }; -DDuplGrabber::DDuplGrabber(QObject * parent, GrabberContext *context) +DDuplGrabber::DDuplGrabber(QObject* parent, GrabberContext* context) : GrabberBase(parent, context), m_state(Uninitialized), m_accessDeniedLastCheck(0), @@ -162,6 +162,7 @@ bool DDuplGrabber::init() } m_state = Ready; + m_releaseFrame = false; return true; } @@ -220,7 +221,7 @@ bool DDuplGrabber::runThreadCommand(DWORD timeout) { } } -bool anyWidgetOnThisMonitor(HMONITOR monitor, const QList &grabWidgets) +bool anyWidgetOnThisMonitor(HMONITOR monitor, const QList& grabWidgets) { for (GrabWidget* widget : grabWidgets) { @@ -234,12 +235,12 @@ bool anyWidgetOnThisMonitor(HMONITOR monitor, const QList &grabWid return false; } -QList< ScreenInfo > * DDuplGrabber::screensWithWidgets(QList< ScreenInfo > * result, const QList &grabWidgets) +QList< ScreenInfo >* DDuplGrabber::screensWithWidgets(QList< ScreenInfo >* result, const QList& grabWidgets) { return __screensWithWidgets(result, grabWidgets); } -QList< ScreenInfo > * DDuplGrabber::__screensWithWidgets(QList< ScreenInfo > * result, const QList &grabWidgets, bool noRecursion) +QList< ScreenInfo >* DDuplGrabber::__screensWithWidgets(QList< ScreenInfo >* result, const QList& grabWidgets, bool noRecursion) { result->clear(); @@ -261,7 +262,8 @@ QList< ScreenInfo > * DDuplGrabber::__screensWithWidgets(QList< ScreenInfo > * r qWarning() << Q_FUNC_INFO << "Found a monitor with NULL handle. Recreating adapters"; recreateAdapters(); return __screensWithWidgets(result, grabWidgets, true); - } else { + } + else { qWarning() << Q_FUNC_INFO << "Found a monitor with NULL handle (after recreation)"; continue; } @@ -296,7 +298,7 @@ void DDuplGrabber::onSessionChange(int change) } } -bool DDuplGrabber::isReallocationNeeded(const QList< ScreenInfo > &grabScreens) const +bool DDuplGrabber::isReallocationNeeded(const QList< ScreenInfo >& grabScreens) const { if (m_state != Allocated) { @@ -350,7 +352,7 @@ void DDuplGrabber::freeScreens() _screensWithWidgets.clear(); } -bool DDuplGrabber::reallocate(const QList< ScreenInfo > &grabScreens) +bool DDuplGrabber::reallocate(const QList< ScreenInfo >& grabScreens) { // Reallocate on the dedicated thread to be able to SetThreadDesktop to the currently active input desktop // once the duplication is created, it seems like it can be used from the normal thread. @@ -358,13 +360,14 @@ bool DDuplGrabber::reallocate(const QList< ScreenInfo > &grabScreens) m_threadReallocateArg = grabScreens; if (runThreadCommand(INFINITE)) { return m_threadReallocateResult; - } else { + } + else { return false; } } // Must be called from DDuplGrabberThreadProc ! -bool DDuplGrabber::_reallocate(const QList< ScreenInfo > &grabScreens, bool noRecursion) +bool DDuplGrabber::_reallocate(const QList< ScreenInfo >& grabScreens, bool noRecursion) { if (m_state == Uninitialized) { @@ -384,7 +387,8 @@ bool DDuplGrabber::_reallocate(const QList< ScreenInfo > &grabScreens, bool noRe m_accessDeniedLastCheck = GetTickCount(); qWarning(Q_FUNC_INFO " Access to input desktop denied, retry later"); return true; - } else { + } + else { qCritical(Q_FUNC_INFO " Failed to open input desktop: %x", GetLastError()); return true; } @@ -449,7 +453,8 @@ bool DDuplGrabber::_reallocate(const QList< ScreenInfo > &grabScreens, bool noRe return false; } return _reallocate(grabScreens, true); - } else { + } + else { qCritical(Q_FUNC_INFO " Failed to reallocate: DXGI mode change in progress (after recreation)"); return false; } @@ -461,7 +466,7 @@ bool DDuplGrabber::_reallocate(const QList< ScreenInfo > &grabScreens, bool noRe } GrabbedScreen grabScreen; - grabScreen.imgData = (unsigned char *)NULL; + grabScreen.imgData = (unsigned char*)NULL; grabScreen.imgFormat = BufferFormatArgb; grabScreen.screenInfo = screenInfo; grabScreen.scale = 1.0; @@ -513,15 +518,15 @@ BufferFormat mapDXGIFormatToBufferFormat(DXGI_FORMAT format) { switch (format) { - case DXGI_FORMAT_B8G8R8A8_UNORM: - case DXGI_FORMAT_B8G8R8A8_TYPELESS: - return BufferFormatArgb; - case DXGI_FORMAT_R8G8B8A8_UINT: - case DXGI_FORMAT_R8G8B8A8_UNORM: - case DXGI_FORMAT_R8G8B8A8_TYPELESS: - return BufferFormatAbgr; - default: - return BufferFormatUnknown; + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + return BufferFormatArgb; + case DXGI_FORMAT_R8G8B8A8_UINT: + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + return BufferFormatAbgr; + default: + return BufferFormatUnknown; } } @@ -604,6 +609,11 @@ GrabResult DDuplGrabber::grabScreens() DDuplScreenData* screenData = (DDuplScreenData*)screen.associatedData; DXGI_OUTDUPL_FRAME_INFO frameInfo; IDXGIResourcePtr resource; + if (m_releaseFrame) + { + screenData->duplication->ReleaseFrame(); + m_releaseFrame = false; + } HRESULT hr = screenData->duplication->AcquireNextFrame(ACQUIRE_TIMEOUT_INTERVAL, &frameInfo, &resource); if (hr == DXGI_ERROR_WAIT_TIMEOUT) { @@ -627,6 +637,7 @@ GrabResult DDuplGrabber::grabScreens() return GrabResultError; } anyUpdate = true; + m_releaseFrame = true; ID3D11Texture2DPtr texture; hr = resource->QueryInterface(IID_ID3D11Texture2D, (void**)&texture); @@ -668,7 +679,8 @@ GrabResult DDuplGrabber::grabScreens() // reset texture and data before getting new one if (screenData->textureCopy) { screenData->textureCopy = nullptr; - } else if (screen.imgData) { + } + else if (screen.imgData) { free((void*)screen.imgData); } @@ -741,7 +753,6 @@ GrabResult DDuplGrabber::grabScreens() screen.scale = 1.0 / (1 << DownscaleMipLevel); screen.bytesPerRow = screenData->surfaceMap.Pitch; - screenData->duplication->ReleaseFrame(); } if (!anyUpdate) diff --git a/Software/grab/include/DDuplGrabber.hpp b/Software/grab/include/DDuplGrabber.hpp index 117f559e2..07942a373 100644 --- a/Software/grab/include/DDuplGrabber.hpp +++ b/Software/grab/include/DDuplGrabber.hpp @@ -63,7 +63,7 @@ class DDuplGrabber : public GrabberBase { Q_OBJECT public: - DDuplGrabber(QObject * parent, GrabberContext *context); + DDuplGrabber(QObject* parent, GrabberContext* context); virtual ~DDuplGrabber(); DECLARE_GRABBER_NAME("DDuplGrabber") @@ -73,13 +73,13 @@ public slots: protected slots: virtual GrabResult grabScreens(); - virtual bool reallocate(const QList< ScreenInfo > &grabScreens); - bool _reallocate(const QList< ScreenInfo > &grabScreens, bool noRecursion = false); + virtual bool reallocate(const QList< ScreenInfo >& grabScreens); + bool _reallocate(const QList< ScreenInfo >& grabScreens, bool noRecursion = false); - virtual QList< ScreenInfo > * screensWithWidgets(QList< ScreenInfo > * result, const QList &grabWidgets); - QList< ScreenInfo > * __screensWithWidgets(QList< ScreenInfo > * result, const QList &grabWidgets, bool noRecursion = false); + virtual QList< ScreenInfo >* screensWithWidgets(QList< ScreenInfo >* result, const QList& grabWidgets); + QList< ScreenInfo >* __screensWithWidgets(QList< ScreenInfo >* result, const QList& grabWidgets, bool noRecursion = false); - virtual bool isReallocationNeeded(const QList< ScreenInfo > &grabScreens) const; + virtual bool isReallocationNeeded(const QList< ScreenInfo >& grabScreens) const; protected: bool init(); @@ -105,6 +105,7 @@ protected slots: QList m_threadReallocateArg; bool m_threadReallocateResult; bool m_isSessionLocked; + bool m_releaseFrame; }; From 979edbfa0088ca8ecd274fe3d50ee2da96f01337 Mon Sep 17 00:00:00 2001 From: Michael Fahrbach Date: Fri, 21 Aug 2020 23:47:21 +0200 Subject: [PATCH 2/2] Revert "Chnges to DesktopDuplication to conform to Guidelines ( https://docs.microsoft.com/en-us/windows/win32/api/dxgi1_2/nf-dxgi1_2-idxgioutputduplication-releaseframe )" This reverts commit 9811e6ce8915bf0ded9d0f2d862308fdc14df404. --- Software/grab/DDuplGrabber.cpp | 71 +++++++++++--------------- Software/grab/include/DDuplGrabber.hpp | 13 +++-- 2 files changed, 36 insertions(+), 48 deletions(-) diff --git a/Software/grab/DDuplGrabber.cpp b/Software/grab/DDuplGrabber.cpp index 6033a9699..4fe29dea0 100644 --- a/Software/grab/DDuplGrabber.cpp +++ b/Software/grab/DDuplGrabber.cpp @@ -43,8 +43,8 @@ _COM_SMARTPTR_TYPEDEF(ID3D11Texture2D, __uuidof(ID3D11Texture2D)); _COM_SMARTPTR_TYPEDEF(ID3D11ShaderResourceView, __uuidof(ID3D11ShaderResourceView)); -typedef HRESULT(WINAPI* CreateDXGIFactory1Func)(REFIID riid, _Out_ void** ppFactory); -typedef HRESULT(WINAPI* D3D11CreateDeviceFunc)( +typedef HRESULT(WINAPI *CreateDXGIFactory1Func)(REFIID riid, _Out_ void **ppFactory); +typedef HRESULT(WINAPI *D3D11CreateDeviceFunc)( _In_opt_ IDXGIAdapter* pAdapter, D3D_DRIVER_TYPE DriverType, HMODULE Software, @@ -79,16 +79,16 @@ struct DDuplScreenData : output(_output), duplication(_duplication), device(_device), context(_context) {} - IDXGIOutputPtr output{ nullptr }; - IDXGIOutputDuplicationPtr duplication{ nullptr }; - ID3D11DevicePtr device{ nullptr }; - ID3D11DeviceContextPtr context{ nullptr }; + IDXGIOutputPtr output{nullptr}; + IDXGIOutputDuplicationPtr duplication{nullptr}; + ID3D11DevicePtr device{nullptr}; + ID3D11DeviceContextPtr context{nullptr}; - ID3D11Texture2DPtr textureCopy{ nullptr }; + ID3D11Texture2DPtr textureCopy{nullptr}; DXGI_MAPPED_RECT surfaceMap; }; -DDuplGrabber::DDuplGrabber(QObject* parent, GrabberContext* context) +DDuplGrabber::DDuplGrabber(QObject * parent, GrabberContext *context) : GrabberBase(parent, context), m_state(Uninitialized), m_accessDeniedLastCheck(0), @@ -162,7 +162,6 @@ bool DDuplGrabber::init() } m_state = Ready; - m_releaseFrame = false; return true; } @@ -221,7 +220,7 @@ bool DDuplGrabber::runThreadCommand(DWORD timeout) { } } -bool anyWidgetOnThisMonitor(HMONITOR monitor, const QList& grabWidgets) +bool anyWidgetOnThisMonitor(HMONITOR monitor, const QList &grabWidgets) { for (GrabWidget* widget : grabWidgets) { @@ -235,12 +234,12 @@ bool anyWidgetOnThisMonitor(HMONITOR monitor, const QList& grabWidg return false; } -QList< ScreenInfo >* DDuplGrabber::screensWithWidgets(QList< ScreenInfo >* result, const QList& grabWidgets) +QList< ScreenInfo > * DDuplGrabber::screensWithWidgets(QList< ScreenInfo > * result, const QList &grabWidgets) { return __screensWithWidgets(result, grabWidgets); } -QList< ScreenInfo >* DDuplGrabber::__screensWithWidgets(QList< ScreenInfo >* result, const QList& grabWidgets, bool noRecursion) +QList< ScreenInfo > * DDuplGrabber::__screensWithWidgets(QList< ScreenInfo > * result, const QList &grabWidgets, bool noRecursion) { result->clear(); @@ -262,8 +261,7 @@ QList< ScreenInfo >* DDuplGrabber::__screensWithWidgets(QList< ScreenInfo >* res qWarning() << Q_FUNC_INFO << "Found a monitor with NULL handle. Recreating adapters"; recreateAdapters(); return __screensWithWidgets(result, grabWidgets, true); - } - else { + } else { qWarning() << Q_FUNC_INFO << "Found a monitor with NULL handle (after recreation)"; continue; } @@ -298,7 +296,7 @@ void DDuplGrabber::onSessionChange(int change) } } -bool DDuplGrabber::isReallocationNeeded(const QList< ScreenInfo >& grabScreens) const +bool DDuplGrabber::isReallocationNeeded(const QList< ScreenInfo > &grabScreens) const { if (m_state != Allocated) { @@ -352,7 +350,7 @@ void DDuplGrabber::freeScreens() _screensWithWidgets.clear(); } -bool DDuplGrabber::reallocate(const QList< ScreenInfo >& grabScreens) +bool DDuplGrabber::reallocate(const QList< ScreenInfo > &grabScreens) { // Reallocate on the dedicated thread to be able to SetThreadDesktop to the currently active input desktop // once the duplication is created, it seems like it can be used from the normal thread. @@ -360,14 +358,13 @@ bool DDuplGrabber::reallocate(const QList< ScreenInfo >& grabScreens) m_threadReallocateArg = grabScreens; if (runThreadCommand(INFINITE)) { return m_threadReallocateResult; - } - else { + } else { return false; } } // Must be called from DDuplGrabberThreadProc ! -bool DDuplGrabber::_reallocate(const QList< ScreenInfo >& grabScreens, bool noRecursion) +bool DDuplGrabber::_reallocate(const QList< ScreenInfo > &grabScreens, bool noRecursion) { if (m_state == Uninitialized) { @@ -387,8 +384,7 @@ bool DDuplGrabber::_reallocate(const QList< ScreenInfo >& grabScreens, bool noRe m_accessDeniedLastCheck = GetTickCount(); qWarning(Q_FUNC_INFO " Access to input desktop denied, retry later"); return true; - } - else { + } else { qCritical(Q_FUNC_INFO " Failed to open input desktop: %x", GetLastError()); return true; } @@ -453,8 +449,7 @@ bool DDuplGrabber::_reallocate(const QList< ScreenInfo >& grabScreens, bool noRe return false; } return _reallocate(grabScreens, true); - } - else { + } else { qCritical(Q_FUNC_INFO " Failed to reallocate: DXGI mode change in progress (after recreation)"); return false; } @@ -466,7 +461,7 @@ bool DDuplGrabber::_reallocate(const QList< ScreenInfo >& grabScreens, bool noRe } GrabbedScreen grabScreen; - grabScreen.imgData = (unsigned char*)NULL; + grabScreen.imgData = (unsigned char *)NULL; grabScreen.imgFormat = BufferFormatArgb; grabScreen.screenInfo = screenInfo; grabScreen.scale = 1.0; @@ -518,15 +513,15 @@ BufferFormat mapDXGIFormatToBufferFormat(DXGI_FORMAT format) { switch (format) { - case DXGI_FORMAT_B8G8R8A8_UNORM: - case DXGI_FORMAT_B8G8R8A8_TYPELESS: - return BufferFormatArgb; - case DXGI_FORMAT_R8G8B8A8_UINT: - case DXGI_FORMAT_R8G8B8A8_UNORM: - case DXGI_FORMAT_R8G8B8A8_TYPELESS: - return BufferFormatAbgr; - default: - return BufferFormatUnknown; + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + return BufferFormatArgb; + case DXGI_FORMAT_R8G8B8A8_UINT: + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + return BufferFormatAbgr; + default: + return BufferFormatUnknown; } } @@ -609,11 +604,6 @@ GrabResult DDuplGrabber::grabScreens() DDuplScreenData* screenData = (DDuplScreenData*)screen.associatedData; DXGI_OUTDUPL_FRAME_INFO frameInfo; IDXGIResourcePtr resource; - if (m_releaseFrame) - { - screenData->duplication->ReleaseFrame(); - m_releaseFrame = false; - } HRESULT hr = screenData->duplication->AcquireNextFrame(ACQUIRE_TIMEOUT_INTERVAL, &frameInfo, &resource); if (hr == DXGI_ERROR_WAIT_TIMEOUT) { @@ -637,7 +627,6 @@ GrabResult DDuplGrabber::grabScreens() return GrabResultError; } anyUpdate = true; - m_releaseFrame = true; ID3D11Texture2DPtr texture; hr = resource->QueryInterface(IID_ID3D11Texture2D, (void**)&texture); @@ -679,8 +668,7 @@ GrabResult DDuplGrabber::grabScreens() // reset texture and data before getting new one if (screenData->textureCopy) { screenData->textureCopy = nullptr; - } - else if (screen.imgData) { + } else if (screen.imgData) { free((void*)screen.imgData); } @@ -753,6 +741,7 @@ GrabResult DDuplGrabber::grabScreens() screen.scale = 1.0 / (1 << DownscaleMipLevel); screen.bytesPerRow = screenData->surfaceMap.Pitch; + screenData->duplication->ReleaseFrame(); } if (!anyUpdate) diff --git a/Software/grab/include/DDuplGrabber.hpp b/Software/grab/include/DDuplGrabber.hpp index 07942a373..117f559e2 100644 --- a/Software/grab/include/DDuplGrabber.hpp +++ b/Software/grab/include/DDuplGrabber.hpp @@ -63,7 +63,7 @@ class DDuplGrabber : public GrabberBase { Q_OBJECT public: - DDuplGrabber(QObject* parent, GrabberContext* context); + DDuplGrabber(QObject * parent, GrabberContext *context); virtual ~DDuplGrabber(); DECLARE_GRABBER_NAME("DDuplGrabber") @@ -73,13 +73,13 @@ public slots: protected slots: virtual GrabResult grabScreens(); - virtual bool reallocate(const QList< ScreenInfo >& grabScreens); - bool _reallocate(const QList< ScreenInfo >& grabScreens, bool noRecursion = false); + virtual bool reallocate(const QList< ScreenInfo > &grabScreens); + bool _reallocate(const QList< ScreenInfo > &grabScreens, bool noRecursion = false); - virtual QList< ScreenInfo >* screensWithWidgets(QList< ScreenInfo >* result, const QList& grabWidgets); - QList< ScreenInfo >* __screensWithWidgets(QList< ScreenInfo >* result, const QList& grabWidgets, bool noRecursion = false); + virtual QList< ScreenInfo > * screensWithWidgets(QList< ScreenInfo > * result, const QList &grabWidgets); + QList< ScreenInfo > * __screensWithWidgets(QList< ScreenInfo > * result, const QList &grabWidgets, bool noRecursion = false); - virtual bool isReallocationNeeded(const QList< ScreenInfo >& grabScreens) const; + virtual bool isReallocationNeeded(const QList< ScreenInfo > &grabScreens) const; protected: bool init(); @@ -105,7 +105,6 @@ protected slots: QList m_threadReallocateArg; bool m_threadReallocateResult; bool m_isSessionLocked; - bool m_releaseFrame; };