mirror of
				https://github.com/gnif/LookingGlass.git
				synced 2025-10-31 20:52:09 +00:00 
			
		
		
		
	[idd] driver: relocate the HW cursor thread into CSwapChainProcessor
It is invalid to call `IddCxMonitorSetupHardwareCursor` before `IddCxSwapChainSetDevice`. This fixes this by moving the thread into CSwapChainProcessor and starting it after `IddCxSwapChainSetDevice` has succeeded.
This commit is contained in:
		| @@ -26,15 +26,11 @@ CIndirectMonitorContext::CIndirectMonitorContext(_In_ IDDCX_MONITOR monitor, CIn | ||||
|   m_monitor(monitor), | ||||
|   m_devContext(device) | ||||
| { | ||||
|   m_terminateEvent .Attach(CreateEvent(nullptr, FALSE, FALSE, nullptr)); | ||||
|   m_cursorDataEvent.Attach(CreateEvent(nullptr, FALSE, FALSE, nullptr)); | ||||
|   m_shapeBuffer = new BYTE[512 * 512 * 4]; | ||||
| } | ||||
|  | ||||
| CIndirectMonitorContext::~CIndirectMonitorContext() | ||||
| { | ||||
|   UnassignSwapChain(); | ||||
|   delete[] m_shapeBuffer; | ||||
| } | ||||
|  | ||||
| void CIndirectMonitorContext::AssignSwapChain(IDDCX_SWAPCHAIN swapChain, LUID renderAdapter, HANDLE newFrameEvent) | ||||
| @@ -73,96 +69,12 @@ reInit: | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   IDARG_IN_SETUP_HWCURSOR c = {}; | ||||
|   c.CursorInfo.Size                  = sizeof(c.CursorInfo); | ||||
|   c.CursorInfo.AlphaCursorSupport    = TRUE; | ||||
|   c.CursorInfo.ColorXorCursorSupport = IDDCX_XOR_CURSOR_SUPPORT_FULL; | ||||
|   c.CursorInfo.MaxX                  = 512; | ||||
|   c.CursorInfo.MaxY                  = 512; | ||||
|   c.hNewCursorDataAvailable          = m_cursorDataEvent.Get(); | ||||
|   NTSTATUS status = IddCxMonitorSetupHardwareCursor(m_monitor, &c); | ||||
|   if (!NT_SUCCESS(status)) | ||||
|   { | ||||
|     WdfObjectDelete(swapChain); | ||||
|     DEBUG_ERROR("IddCxMonitorSetupHardwareCursor Failed (0x%08x)", status); | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   m_swapChain.reset(new CSwapChainProcessor(m_devContext, swapChain, m_dx11Device, m_dx12Device, newFrameEvent)); | ||||
|  | ||||
|   m_lastShapeId = 0; | ||||
|   m_thread.Attach(CreateThread(nullptr, 0, _CursorThread, this, 0, nullptr)); | ||||
|   m_swapChain.reset(new CSwapChainProcessor(m_monitor, m_devContext, swapChain, m_dx11Device, m_dx12Device, newFrameEvent)); | ||||
| } | ||||
|  | ||||
| void CIndirectMonitorContext::UnassignSwapChain() | ||||
| { | ||||
|   SetEvent(m_terminateEvent.Get()); | ||||
|   if (m_thread.IsValid()) | ||||
|     WaitForSingleObject(m_thread.Get(), INFINITE); | ||||
|  | ||||
|   m_swapChain.reset();   | ||||
|   m_dx11Device.reset(); | ||||
|   m_dx12Device.reset(); | ||||
|  | ||||
|   ResetEvent(m_terminateEvent .Get()); | ||||
|   ResetEvent(m_cursorDataEvent.Get()); | ||||
| } | ||||
|  | ||||
| DWORD CALLBACK CIndirectMonitorContext::_CursorThread(LPVOID arg) | ||||
| { | ||||
|   reinterpret_cast<CIndirectMonitorContext*>(arg)->CursorThread(); | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| void CIndirectMonitorContext::CursorThread() | ||||
| { | ||||
|   HRESULT hr = 0; | ||||
|   bool running = true; | ||||
|  | ||||
|   while(running) | ||||
|   { | ||||
|     HANDLE waitHandles[] = | ||||
|     { | ||||
|       m_cursorDataEvent.Get(), | ||||
|       m_terminateEvent.Get() | ||||
|     }; | ||||
|  | ||||
|     DWORD waitResult = WaitForMultipleObjects( | ||||
|       ARRAYSIZE(waitHandles), waitHandles, FALSE, 100); | ||||
|  | ||||
|     switch (waitResult) | ||||
|     { | ||||
|       case WAIT_TIMEOUT: | ||||
|         continue; | ||||
|        | ||||
|       // cursorDataEvent | ||||
|       case WAIT_OBJECT_0: | ||||
|         break; | ||||
|        | ||||
|       // terminateEvent | ||||
|       case WAIT_OBJECT_0 + 1: | ||||
|         running = false; | ||||
|         continue; | ||||
|  | ||||
|       default: | ||||
|         hr = HRESULT_FROM_WIN32(waitResult); | ||||
|         DEBUG_ERROR_HR(hr, "WaitForMultipleObjects"); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     IDARG_IN_QUERY_HWCURSOR in  = {}; | ||||
|     in.LastShapeId            = m_lastShapeId; | ||||
|     in.pShapeBuffer           = m_shapeBuffer; | ||||
|     in.ShapeBufferSizeInBytes = 512 * 512 * 4; | ||||
|  | ||||
|     IDARG_OUT_QUERY_HWCURSOR out = {}; | ||||
|     NTSTATUS status = IddCxMonitorQueryHardwareCursor(m_monitor, &in, &out); | ||||
|     if (FAILED(status)) | ||||
|     { | ||||
|       DEBUG_ERROR("IddCxMonitorQueryHardwareCursor failed (0x%08x)", status); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     m_devContext->SendCursor(out, m_shapeBuffer); | ||||
|   } | ||||
| } | ||||
| @@ -41,16 +41,6 @@ private: | ||||
|   CIndirectDeviceContext * m_devContext; | ||||
|   std::unique_ptr<CSwapChainProcessor> m_swapChain; | ||||
|  | ||||
|   Wrappers::Event m_terminateEvent; | ||||
|   Wrappers::Event m_cursorDataEvent; | ||||
|   Wrappers::HandleT<Wrappers::HandleTraits::HANDLENullTraits> m_thread; | ||||
|   BYTE * m_shapeBuffer; | ||||
|  | ||||
|   DWORD m_lastShapeId = 0; | ||||
|  | ||||
|   static DWORD CALLBACK _CursorThread(LPVOID arg); | ||||
|   void CursorThread(); | ||||
|  | ||||
| public: | ||||
|   CIndirectMonitorContext(_In_ IDDCX_MONITOR monitor, CIndirectDeviceContext * device); | ||||
|  | ||||
|   | ||||
| @@ -23,8 +23,9 @@ | ||||
| #include <avrt.h> | ||||
| #include "CDebug.h" | ||||
|  | ||||
| CSwapChainProcessor::CSwapChainProcessor(CIndirectDeviceContext* devContext, IDDCX_SWAPCHAIN hSwapChain, | ||||
| CSwapChainProcessor::CSwapChainProcessor(IDDCX_MONITOR monitor, CIndirectDeviceContext* devContext, IDDCX_SWAPCHAIN hSwapChain, | ||||
|     std::shared_ptr<CD3D11Device> dx11Device, std::shared_ptr<CD3D12Device> dx12Device, HANDLE newFrameEvent) : | ||||
|   m_monitor(monitor), | ||||
|   m_devContext(devContext), | ||||
|   m_hSwapChain(hSwapChain), | ||||
|   m_dx11Device(dx11Device), | ||||
| @@ -36,6 +37,9 @@ CSwapChainProcessor::CSwapChainProcessor(CIndirectDeviceContext* devContext, IDD | ||||
|  | ||||
|   m_terminateEvent.Attach(CreateEvent(nullptr, FALSE, FALSE, nullptr)); | ||||
|   m_thread[0].Attach(CreateThread(nullptr, 0, _SwapChainThread, this, 0, nullptr)); | ||||
|  | ||||
|   m_cursorDataEvent.Attach(CreateEvent(nullptr, FALSE, FALSE, nullptr)); | ||||
|   m_shapeBuffer = new BYTE[512 * 512 * 4]; | ||||
| } | ||||
|  | ||||
| CSwapChainProcessor::~CSwapChainProcessor() | ||||
| @@ -48,6 +52,7 @@ CSwapChainProcessor::~CSwapChainProcessor() | ||||
|  | ||||
|   m_resPool.Reset(); | ||||
|   m_fbPool.Reset(); | ||||
|   delete[] m_shapeBuffer; | ||||
| } | ||||
|  | ||||
| DWORD CALLBACK CSwapChainProcessor::_SwapChainThread(LPVOID arg) | ||||
| @@ -105,6 +110,23 @@ void CSwapChainProcessor::SwapChainThreadCore() | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   IDARG_IN_SETUP_HWCURSOR c = {}; | ||||
|   c.CursorInfo.Size                  = sizeof(c.CursorInfo); | ||||
|   c.CursorInfo.AlphaCursorSupport    = TRUE; | ||||
|   c.CursorInfo.ColorXorCursorSupport = IDDCX_XOR_CURSOR_SUPPORT_FULL; | ||||
|   c.CursorInfo.MaxX                  = 512; | ||||
|   c.CursorInfo.MaxY                  = 512; | ||||
|   c.hNewCursorDataAvailable          = m_cursorDataEvent.Get(); | ||||
|   NTSTATUS status = IddCxMonitorSetupHardwareCursor(m_monitor, &c); | ||||
|   if (!NT_SUCCESS(status)) | ||||
|   { | ||||
|     DEBUG_ERROR("IddCxMonitorSetupHardwareCursor Failed (0x%08x)", status); | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   m_lastShapeId = 0; | ||||
|   m_thread[1].Attach(CreateThread(nullptr, 0, _CursorThread, this, 0, nullptr)); | ||||
|  | ||||
|   UINT lastFrameNumber = 0; | ||||
|   for (;;) | ||||
|   { | ||||
| @@ -259,3 +281,62 @@ bool CSwapChainProcessor::SwapChainNewFrame(ComPtr<IDXGIResource> acquiredBuffer | ||||
|  | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| DWORD CALLBACK CSwapChainProcessor::_CursorThread(LPVOID arg) | ||||
| { | ||||
|   reinterpret_cast<CSwapChainProcessor*>(arg)->CursorThread(); | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| void CSwapChainProcessor::CursorThread() | ||||
| { | ||||
|   HRESULT hr = 0; | ||||
|   bool running = true; | ||||
|  | ||||
|   while (running) | ||||
|   { | ||||
|     HANDLE waitHandles[] = | ||||
|     { | ||||
|       m_cursorDataEvent.Get(), | ||||
|       m_terminateEvent.Get() | ||||
|     }; | ||||
|  | ||||
|     DWORD waitResult = WaitForMultipleObjects( | ||||
|       ARRAYSIZE(waitHandles), waitHandles, FALSE, 100); | ||||
|  | ||||
|     switch (waitResult) | ||||
|     { | ||||
|     case WAIT_TIMEOUT: | ||||
|       continue; | ||||
|  | ||||
|       // cursorDataEvent | ||||
|     case WAIT_OBJECT_0: | ||||
|       break; | ||||
|  | ||||
|       // terminateEvent | ||||
|     case WAIT_OBJECT_0 + 1: | ||||
|       running = false; | ||||
|       continue; | ||||
|  | ||||
|     default: | ||||
|       hr = HRESULT_FROM_WIN32(waitResult); | ||||
|       DEBUG_ERROR_HR(hr, "WaitForMultipleObjects"); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     IDARG_IN_QUERY_HWCURSOR in = {}; | ||||
|     in.LastShapeId = m_lastShapeId; | ||||
|     in.pShapeBuffer = m_shapeBuffer; | ||||
|     in.ShapeBufferSizeInBytes = 512 * 512 * 4; | ||||
|  | ||||
|     IDARG_OUT_QUERY_HWCURSOR out = {}; | ||||
|     NTSTATUS status = IddCxMonitorQueryHardwareCursor(m_monitor, &in, &out); | ||||
|     if (FAILED(status)) | ||||
|     { | ||||
|       DEBUG_ERROR("IddCxMonitorQueryHardwareCursor failed (0x%08x)", status); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     m_devContext->SendCursor(out, m_shapeBuffer); | ||||
|   } | ||||
| } | ||||
| @@ -38,6 +38,7 @@ using namespace Microsoft::WRL; | ||||
| class CSwapChainProcessor | ||||
| { | ||||
| private: | ||||
|   IDDCX_MONITOR                   m_monitor; | ||||
|   CIndirectDeviceContext        * m_devContext; | ||||
|   IDDCX_SWAPCHAIN                 m_hSwapChain; | ||||
|   std::shared_ptr<CD3D11Device>   m_dx11Device; | ||||
| @@ -50,17 +51,23 @@ private: | ||||
|   Wrappers::HandleT<Wrappers::HandleTraits::HANDLENullTraits> m_thread[2]; | ||||
|   Wrappers::Event m_terminateEvent; | ||||
|  | ||||
|   static DWORD CALLBACK _SwapChainThread(LPVOID arg); | ||||
|   Wrappers::Event m_cursorDataEvent; | ||||
|   BYTE*           m_shapeBuffer; | ||||
|   DWORD           m_lastShapeId = 0; | ||||
|  | ||||
|   static DWORD CALLBACK _SwapChainThread(LPVOID arg); | ||||
|   void SwapChainThread(); | ||||
|   void SwapChainThreadCore(); | ||||
|  | ||||
|   static DWORD CALLBACK _CursorThread(LPVOID arg); | ||||
|   void CursorThread(); | ||||
|  | ||||
|   static void CompletionFunction( | ||||
|     CD3D12CommandQueue * queue, bool result, void * param1, void * param2); | ||||
|   bool SwapChainNewFrame(ComPtr<IDXGIResource> acquiredBuffer); | ||||
|  | ||||
| public: | ||||
|   CSwapChainProcessor(CIndirectDeviceContext * devContext, IDDCX_SWAPCHAIN hSwapChain, | ||||
|   CSwapChainProcessor(IDDCX_MONITOR monitor, CIndirectDeviceContext * devContext, IDDCX_SWAPCHAIN hSwapChain, | ||||
|     std::shared_ptr<CD3D11Device> dx11Device, std::shared_ptr<CD3D12Device> dx12Device, HANDLE newFrameEvent); | ||||
|   ~CSwapChainProcessor(); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Geoffrey McRae
					Geoffrey McRae