diff options
author | Mamadou DIOP <bossiel@yahoo.fr> | 2016-02-23 22:00:35 +0100 |
---|---|---|
committer | Mamadou DIOP <bossiel@yahoo.fr> | 2016-02-23 22:00:35 +0100 |
commit | 50dfb4359619563012997bc3ddafb7667741066c (patch) | |
tree | db234c1edc3240a653363b5735fc4077af4b8720 /plugins/pluginWinDD | |
parent | 94b2219209038e05dd26395f6fb700be4d1062c0 (diff) | |
download | doubango-50dfb4359619563012997bc3ddafb7667741066c.zip doubango-50dfb4359619563012997bc3ddafb7667741066c.tar.gz |
Add new QoS implementation
Code formatting
Diffstat (limited to 'plugins/pluginWinDD')
-rwxr-xr-x | plugins/pluginWinDD/dllmain_dd.cxx | 98 | ||||
-rwxr-xr-x | plugins/pluginWinDD/internals/CommonTypes.h | 22 | ||||
-rwxr-xr-x | plugins/pluginWinDD/internals/DisplayManager.cxx | 315 | ||||
-rwxr-xr-x | plugins/pluginWinDD/internals/DisplayManager.h | 44 | ||||
-rwxr-xr-x | plugins/pluginWinDD/internals/DuplicationManager.cxx | 393 | ||||
-rwxr-xr-x | plugins/pluginWinDD/internals/DuplicationManager.h | 40 | ||||
-rwxr-xr-x | plugins/pluginWinDD/internals/OutputManager.cxx | 503 | ||||
-rwxr-xr-x | plugins/pluginWinDD/internals/OutputManager.h | 66 | ||||
-rwxr-xr-x | plugins/pluginWinDD/internals/ThreadManager.cxx | 95 | ||||
-rwxr-xr-x | plugins/pluginWinDD/internals/ThreadManager.h | 28 | ||||
-rwxr-xr-x | plugins/pluginWinDD/plugin_win_dd_config.h | 4 | ||||
-rwxr-xr-x | plugins/pluginWinDD/plugin_win_dd_producer.cxx | 1600 |
12 files changed, 1437 insertions, 1771 deletions
diff --git a/plugins/pluginWinDD/dllmain_dd.cxx b/plugins/pluginWinDD/dllmain_dd.cxx index b390c90..e8df126 100755 --- a/plugins/pluginWinDD/dllmain_dd.cxx +++ b/plugins/pluginWinDD/dllmain_dd.cxx @@ -35,80 +35,72 @@ PLUGIN_WIN_DDP_API tsk_plugin_def_ptr_const_t __plugin_get_def_at(int index); PLUGIN_WIN_DD_END_DECLS /* END */ BOOL APIENTRY DllMain(HMODULE hModule, -DWORD ul_reason_for_call, -LPVOID lpReserved -) + DWORD ul_reason_for_call, + LPVOID lpReserved + ) { - switch (ul_reason_for_call) - { - case DLL_PROCESS_ATTACH: - break; - case DLL_THREAD_ATTACH: - break; - case DLL_THREAD_DETACH: - break; - case DLL_PROCESS_DETACH: - break; - } - return TRUE; + switch (ul_reason_for_call) { + case DLL_PROCESS_ATTACH: + break; + case DLL_THREAD_ATTACH: + break; + case DLL_THREAD_DETACH: + break; + case DLL_PROCESS_DETACH: + break; + } + return TRUE; } -typedef enum PLUGIN_INDEX_E -{ - PLUGIN_INDEX_PRODUCER, +typedef enum PLUGIN_INDEX_E { + PLUGIN_INDEX_PRODUCER, - PLUGIN_INDEX_COUNT + PLUGIN_INDEX_COUNT } PLUGIN_INDEX_T; int __plugin_get_def_count() { - return PLUGIN_INDEX_COUNT; + return PLUGIN_INDEX_COUNT; } tsk_plugin_def_type_t __plugin_get_def_type_at(int index) { - switch (index){ - case PLUGIN_INDEX_PRODUCER: - { - return tsk_plugin_def_type_producer; - } - default: - { - TSK_DEBUG_ERROR("No plugin at index %d", index); - return tsk_plugin_def_type_none; - } - } + switch (index) { + case PLUGIN_INDEX_PRODUCER: { + return tsk_plugin_def_type_producer; + } + default: { + TSK_DEBUG_ERROR("No plugin at index %d", index); + return tsk_plugin_def_type_none; + } + } } tsk_plugin_def_media_type_t __plugin_get_def_media_type_at(int index) { - switch (index){ - case PLUGIN_INDEX_PRODUCER: - { - return tsk_plugin_def_media_type_screencast; - } - default: - { - TSK_DEBUG_ERROR("No plugin at index %d", index); - return tsk_plugin_def_media_type_none; - } - } + switch (index) { + case PLUGIN_INDEX_PRODUCER: { + return tsk_plugin_def_media_type_screencast; + } + default: { + TSK_DEBUG_ERROR("No plugin at index %d", index); + return tsk_plugin_def_media_type_none; + } + } } tsk_plugin_def_ptr_const_t __plugin_get_def_at(int index) { - switch (index){ - case PLUGIN_INDEX_PRODUCER: - { - return plugin_win_dd_producer_plugin_def_t; - } - default: - { - TSK_DEBUG_ERROR("No plugin at index %d", index); - return tsk_null; - } - } + switch (index) { + case PLUGIN_INDEX_PRODUCER: { + return plugin_win_dd_producer_plugin_def_t; + } + default: { + TSK_DEBUG_ERROR("No plugin at index %d", index); + return tsk_null; + } + } } diff --git a/plugins/pluginWinDD/internals/CommonTypes.h b/plugins/pluginWinDD/internals/CommonTypes.h index 7b9c2d4..3870e96 100755 --- a/plugins/pluginWinDD/internals/CommonTypes.h +++ b/plugins/pluginWinDD/internals/CommonTypes.h @@ -32,12 +32,11 @@ extern HRESULT AcquireFrameExpectedError[]; extern HRESULT EnumOutputsExpectedErrors[]; -typedef _Return_type_success_(return == DUPL_RETURN_SUCCESS) enum -{ +typedef _Return_type_success_(return == DUPL_RETURN_SUCCESS) enum { DUPL_RETURN_SUCCESS = 0, DUPL_RETURN_ERROR_EXPECTED = 1, DUPL_RETURN_ERROR_UNEXPECTED = 2 -}DUPL_RETURN; +} DUPL_RETURN; _Post_satisfies_(return != DUPL_RETURN_SUCCESS) DUPL_RETURN ProcessFailure(_In_opt_ ID3D11Device* Device, _In_ LPCWSTR Str, _In_ LPCWSTR Title, HRESULT hr, _In_opt_z_ HRESULT* ExpectedErrors = nullptr); @@ -47,8 +46,7 @@ void DisplayMsg(_In_ LPCWSTR Str, _In_ LPCWSTR Title, HRESULT hr); // // Holds info about the pointer/cursor // -typedef struct _PTR_INFO -{ +typedef struct _PTR_INFO { _Field_size_bytes_(BufferSize) BYTE* PtrShapeBuffer; DXGI_OUTDUPL_POINTER_SHAPE_INFO ShapeInfo; POINT Position; @@ -61,8 +59,7 @@ typedef struct _PTR_INFO // // Structure that holds D3D resources not directly tied to any one thread // -typedef struct _DX_RESOURCES -{ +typedef struct _DX_RESOURCES { ID3D11Device* Device; ID3D11DeviceContext* Context; ID3D11VertexShader* VertexShader; @@ -74,8 +71,7 @@ typedef struct _DX_RESOURCES // // Structure to pass to a new thread // -typedef struct _THREAD_DATA -{ +typedef struct _THREAD_DATA { // Used to indicate abnormal error condition HANDLE UnexpectedErrorEvent; @@ -92,14 +88,13 @@ typedef struct _THREAD_DATA PTR_INFO* PtrInfo; DX_RESOURCES DxRes; - const struct tmedia_producer_s* Producer; + const struct tmedia_producer_s* Producer; } THREAD_DATA; // // FRAME_DATA holds information about an acquired frame // -typedef struct _FRAME_DATA -{ +typedef struct _FRAME_DATA { ID3D11Texture2D* Frame; DXGI_OUTDUPL_FRAME_INFO FrameInfo; _Field_size_bytes_((MoveCount * sizeof(DXGI_OUTDUPL_MOVE_RECT)) + (DirtyCount * sizeof(RECT))) BYTE* MetaData; @@ -110,8 +105,7 @@ typedef struct _FRAME_DATA // // A vertex with a position and texture coordinate // -typedef struct _VERTEX -{ +typedef struct _VERTEX { DirectX::XMFLOAT3 Pos; DirectX::XMFLOAT2 TexCoord; } VERTEX; diff --git a/plugins/pluginWinDD/internals/DisplayManager.cxx b/plugins/pluginWinDD/internals/DisplayManager.cxx index 98209a0..e60ab64 100755 --- a/plugins/pluginWinDD/internals/DisplayManager.cxx +++ b/plugins/pluginWinDD/internals/DisplayManager.cxx @@ -12,15 +12,15 @@ using namespace DirectX; // Constructor NULLs out vars // DISPLAYMANAGER::DISPLAYMANAGER() : m_Device(nullptr), - m_DeviceContext(nullptr), - m_MoveSurf(nullptr), - m_VertexShader(nullptr), - m_PixelShader(nullptr), - m_InputLayout(nullptr), - m_RTV(nullptr), - m_SamplerLinear(nullptr), - m_DirtyVertexBufferAlloc(nullptr), - m_DirtyVertexBufferAllocSize(0) + m_DeviceContext(nullptr), + m_MoveSurf(nullptr), + m_VertexShader(nullptr), + m_PixelShader(nullptr), + m_InputLayout(nullptr), + m_RTV(nullptr), + m_SamplerLinear(nullptr), + m_DirtyVertexBufferAlloc(nullptr), + m_DirtyVertexBufferAllocSize(0) { } @@ -31,8 +31,7 @@ DISPLAYMANAGER::~DISPLAYMANAGER() { CleanRefs(); - if (m_DirtyVertexBufferAlloc) - { + if (m_DirtyVertexBufferAlloc) { delete [] m_DirtyVertexBufferAlloc; m_DirtyVertexBufferAlloc = nullptr; } @@ -66,22 +65,18 @@ DUPL_RETURN DISPLAYMANAGER::ProcessFrame(_In_ FRAME_DATA* Data, _Inout_ ID3D11Te DUPL_RETURN Ret = DUPL_RETURN_SUCCESS; // Process dirties and moves - if (Data->FrameInfo.TotalMetadataBufferSize) - { + if (Data->FrameInfo.TotalMetadataBufferSize) { D3D11_TEXTURE2D_DESC Desc; Data->Frame->GetDesc(&Desc); - if (Data->MoveCount) - { + if (Data->MoveCount) { Ret = CopyMove(SharedSurf, reinterpret_cast<DXGI_OUTDUPL_MOVE_RECT*>(Data->MetaData), Data->MoveCount, OffsetX, OffsetY, DeskDesc, Desc.Width, Desc.Height); - if (Ret != DUPL_RETURN_SUCCESS) - { + if (Ret != DUPL_RETURN_SUCCESS) { return Ret; } } - if (Data->DirtyCount) - { + if (Data->DirtyCount) { Ret = CopyDirty(Data->Frame, SharedSurf, reinterpret_cast<RECT*>(Data->MetaData + (Data->MoveCount * sizeof(DXGI_OUTDUPL_MOVE_RECT))), Data->DirtyCount, OffsetX, OffsetY, DeskDesc); } } @@ -102,64 +97,58 @@ ID3D11Device* DISPLAYMANAGER::GetDevice() // void DISPLAYMANAGER::SetMoveRect(_Out_ RECT* SrcRect, _Out_ RECT* DestRect, _In_ DXGI_OUTPUT_DESC* DeskDesc, _In_ DXGI_OUTDUPL_MOVE_RECT* MoveRect, INT TexWidth, INT TexHeight) { - switch (DeskDesc->Rotation) - { - case DXGI_MODE_ROTATION_UNSPECIFIED: - case DXGI_MODE_ROTATION_IDENTITY: - { - SrcRect->left = MoveRect->SourcePoint.x; - SrcRect->top = MoveRect->SourcePoint.y; - SrcRect->right = MoveRect->SourcePoint.x + MoveRect->DestinationRect.right - MoveRect->DestinationRect.left; - SrcRect->bottom = MoveRect->SourcePoint.y + MoveRect->DestinationRect.bottom - MoveRect->DestinationRect.top; - - *DestRect = MoveRect->DestinationRect; - break; - } - case DXGI_MODE_ROTATION_ROTATE90: - { - SrcRect->left = TexHeight - (MoveRect->SourcePoint.y + MoveRect->DestinationRect.bottom - MoveRect->DestinationRect.top); - SrcRect->top = MoveRect->SourcePoint.x; - SrcRect->right = TexHeight - MoveRect->SourcePoint.y; - SrcRect->bottom = MoveRect->SourcePoint.x + MoveRect->DestinationRect.right - MoveRect->DestinationRect.left; - - DestRect->left = TexHeight - MoveRect->DestinationRect.bottom; - DestRect->top = MoveRect->DestinationRect.left; - DestRect->right = TexHeight - MoveRect->DestinationRect.top; - DestRect->bottom = MoveRect->DestinationRect.right; - break; - } - case DXGI_MODE_ROTATION_ROTATE180: - { - SrcRect->left = TexWidth - (MoveRect->SourcePoint.x + MoveRect->DestinationRect.right - MoveRect->DestinationRect.left); - SrcRect->top = TexHeight - (MoveRect->SourcePoint.y + MoveRect->DestinationRect.bottom - MoveRect->DestinationRect.top); - SrcRect->right = TexWidth - MoveRect->SourcePoint.x; - SrcRect->bottom = TexHeight - MoveRect->SourcePoint.y; - - DestRect->left = TexWidth - MoveRect->DestinationRect.right; - DestRect->top = TexHeight - MoveRect->DestinationRect.bottom; - DestRect->right = TexWidth - MoveRect->DestinationRect.left; - DestRect->bottom = TexHeight - MoveRect->DestinationRect.top; - break; - } - case DXGI_MODE_ROTATION_ROTATE270: - { - SrcRect->left = MoveRect->SourcePoint.x; - SrcRect->top = TexWidth - (MoveRect->SourcePoint.x + MoveRect->DestinationRect.right - MoveRect->DestinationRect.left); - SrcRect->right = MoveRect->SourcePoint.y + MoveRect->DestinationRect.bottom - MoveRect->DestinationRect.top; - SrcRect->bottom = TexWidth - MoveRect->SourcePoint.x; - - DestRect->left = MoveRect->DestinationRect.top; - DestRect->top = TexWidth - MoveRect->DestinationRect.right; - DestRect->right = MoveRect->DestinationRect.bottom; - DestRect->bottom = TexWidth - MoveRect->DestinationRect.left; - break; - } - default: - { - RtlZeroMemory(DestRect, sizeof(RECT)); - RtlZeroMemory(SrcRect, sizeof(RECT)); - break; - } + switch (DeskDesc->Rotation) { + case DXGI_MODE_ROTATION_UNSPECIFIED: + case DXGI_MODE_ROTATION_IDENTITY: { + SrcRect->left = MoveRect->SourcePoint.x; + SrcRect->top = MoveRect->SourcePoint.y; + SrcRect->right = MoveRect->SourcePoint.x + MoveRect->DestinationRect.right - MoveRect->DestinationRect.left; + SrcRect->bottom = MoveRect->SourcePoint.y + MoveRect->DestinationRect.bottom - MoveRect->DestinationRect.top; + + *DestRect = MoveRect->DestinationRect; + break; + } + case DXGI_MODE_ROTATION_ROTATE90: { + SrcRect->left = TexHeight - (MoveRect->SourcePoint.y + MoveRect->DestinationRect.bottom - MoveRect->DestinationRect.top); + SrcRect->top = MoveRect->SourcePoint.x; + SrcRect->right = TexHeight - MoveRect->SourcePoint.y; + SrcRect->bottom = MoveRect->SourcePoint.x + MoveRect->DestinationRect.right - MoveRect->DestinationRect.left; + + DestRect->left = TexHeight - MoveRect->DestinationRect.bottom; + DestRect->top = MoveRect->DestinationRect.left; + DestRect->right = TexHeight - MoveRect->DestinationRect.top; + DestRect->bottom = MoveRect->DestinationRect.right; + break; + } + case DXGI_MODE_ROTATION_ROTATE180: { + SrcRect->left = TexWidth - (MoveRect->SourcePoint.x + MoveRect->DestinationRect.right - MoveRect->DestinationRect.left); + SrcRect->top = TexHeight - (MoveRect->SourcePoint.y + MoveRect->DestinationRect.bottom - MoveRect->DestinationRect.top); + SrcRect->right = TexWidth - MoveRect->SourcePoint.x; + SrcRect->bottom = TexHeight - MoveRect->SourcePoint.y; + + DestRect->left = TexWidth - MoveRect->DestinationRect.right; + DestRect->top = TexHeight - MoveRect->DestinationRect.bottom; + DestRect->right = TexWidth - MoveRect->DestinationRect.left; + DestRect->bottom = TexHeight - MoveRect->DestinationRect.top; + break; + } + case DXGI_MODE_ROTATION_ROTATE270: { + SrcRect->left = MoveRect->SourcePoint.x; + SrcRect->top = TexWidth - (MoveRect->SourcePoint.x + MoveRect->DestinationRect.right - MoveRect->DestinationRect.left); + SrcRect->right = MoveRect->SourcePoint.y + MoveRect->DestinationRect.bottom - MoveRect->DestinationRect.top; + SrcRect->bottom = TexWidth - MoveRect->SourcePoint.x; + + DestRect->left = MoveRect->DestinationRect.top; + DestRect->top = TexWidth - MoveRect->DestinationRect.right; + DestRect->right = MoveRect->DestinationRect.bottom; + DestRect->bottom = TexWidth - MoveRect->DestinationRect.left; + break; + } + default: { + RtlZeroMemory(DestRect, sizeof(RECT)); + RtlZeroMemory(SrcRect, sizeof(RECT)); + break; + } } } @@ -172,8 +161,7 @@ DUPL_RETURN DISPLAYMANAGER::CopyMove(_Inout_ ID3D11Texture2D* SharedSurf, _In_re SharedSurf->GetDesc(&FullDesc); // Make new intermediate surface to copy into for moving - if (!m_MoveSurf) - { + if (!m_MoveSurf) { D3D11_TEXTURE2D_DESC MoveDesc; MoveDesc = FullDesc; MoveDesc.Width = DeskDesc->DesktopCoordinates.right - DeskDesc->DesktopCoordinates.left; @@ -181,14 +169,12 @@ DUPL_RETURN DISPLAYMANAGER::CopyMove(_Inout_ ID3D11Texture2D* SharedSurf, _In_re MoveDesc.BindFlags = D3D11_BIND_RENDER_TARGET; MoveDesc.MiscFlags = 0; HRESULT hr = m_Device->CreateTexture2D(&MoveDesc, nullptr, &m_MoveSurf); - if (FAILED(hr)) - { + if (FAILED(hr)) { return ProcessFailure(m_Device, L"Failed to create staging texture for move rects", L"Error", hr, SystemTransitionsExpectedErrors); } } - for (UINT i = 0; i < MoveCount; ++i) - { + for (UINT i = 0; i < MoveCount; ++i) { RECT SrcRect; RECT DestRect; @@ -235,75 +221,70 @@ void DISPLAYMANAGER::SetDirtyVert(_Out_writes_(NUMVERTICES) VERTEX* Vertices, _I RECT DestDirty = *Dirty; // Set appropriate coordinates compensated for rotation - switch (DeskDesc->Rotation) - { - case DXGI_MODE_ROTATION_ROTATE90: - { - DestDirty.left = Width - Dirty->bottom; - DestDirty.top = Dirty->left; - DestDirty.right = Width - Dirty->top; - DestDirty.bottom = Dirty->right; - - Vertices[0].TexCoord = XMFLOAT2(Dirty->right / static_cast<FLOAT>(ThisDesc->Width), Dirty->bottom / static_cast<FLOAT>(ThisDesc->Height)); - Vertices[1].TexCoord = XMFLOAT2(Dirty->left / static_cast<FLOAT>(ThisDesc->Width), Dirty->bottom / static_cast<FLOAT>(ThisDesc->Height)); - Vertices[2].TexCoord = XMFLOAT2(Dirty->right / static_cast<FLOAT>(ThisDesc->Width), Dirty->top / static_cast<FLOAT>(ThisDesc->Height)); - Vertices[5].TexCoord = XMFLOAT2(Dirty->left / static_cast<FLOAT>(ThisDesc->Width), Dirty->top / static_cast<FLOAT>(ThisDesc->Height)); - break; - } - case DXGI_MODE_ROTATION_ROTATE180: - { - DestDirty.left = Width - Dirty->right; - DestDirty.top = Height - Dirty->bottom; - DestDirty.right = Width - Dirty->left; - DestDirty.bottom = Height - Dirty->top; - - Vertices[0].TexCoord = XMFLOAT2(Dirty->right / static_cast<FLOAT>(ThisDesc->Width), Dirty->top / static_cast<FLOAT>(ThisDesc->Height)); - Vertices[1].TexCoord = XMFLOAT2(Dirty->right / static_cast<FLOAT>(ThisDesc->Width), Dirty->bottom / static_cast<FLOAT>(ThisDesc->Height)); - Vertices[2].TexCoord = XMFLOAT2(Dirty->left / static_cast<FLOAT>(ThisDesc->Width), Dirty->top / static_cast<FLOAT>(ThisDesc->Height)); - Vertices[5].TexCoord = XMFLOAT2(Dirty->left / static_cast<FLOAT>(ThisDesc->Width), Dirty->bottom / static_cast<FLOAT>(ThisDesc->Height)); - break; - } - case DXGI_MODE_ROTATION_ROTATE270: - { - DestDirty.left = Dirty->top; - DestDirty.top = Height - Dirty->right; - DestDirty.right = Dirty->bottom; - DestDirty.bottom = Height - Dirty->left; - - Vertices[0].TexCoord = XMFLOAT2(Dirty->left / static_cast<FLOAT>(ThisDesc->Width), Dirty->top / static_cast<FLOAT>(ThisDesc->Height)); - Vertices[1].TexCoord = XMFLOAT2(Dirty->right / static_cast<FLOAT>(ThisDesc->Width), Dirty->top / static_cast<FLOAT>(ThisDesc->Height)); - Vertices[2].TexCoord = XMFLOAT2(Dirty->left / static_cast<FLOAT>(ThisDesc->Width), Dirty->bottom / static_cast<FLOAT>(ThisDesc->Height)); - Vertices[5].TexCoord = XMFLOAT2(Dirty->right / static_cast<FLOAT>(ThisDesc->Width), Dirty->bottom / static_cast<FLOAT>(ThisDesc->Height)); - break; - } - default: - assert(false); // drop through - case DXGI_MODE_ROTATION_UNSPECIFIED: - case DXGI_MODE_ROTATION_IDENTITY: - { - Vertices[0].TexCoord = XMFLOAT2(Dirty->left / static_cast<FLOAT>(ThisDesc->Width), Dirty->bottom / static_cast<FLOAT>(ThisDesc->Height)); - Vertices[1].TexCoord = XMFLOAT2(Dirty->left / static_cast<FLOAT>(ThisDesc->Width), Dirty->top / static_cast<FLOAT>(ThisDesc->Height)); - Vertices[2].TexCoord = XMFLOAT2(Dirty->right / static_cast<FLOAT>(ThisDesc->Width), Dirty->bottom / static_cast<FLOAT>(ThisDesc->Height)); - Vertices[5].TexCoord = XMFLOAT2(Dirty->right / static_cast<FLOAT>(ThisDesc->Width), Dirty->top / static_cast<FLOAT>(ThisDesc->Height)); - break; - } + switch (DeskDesc->Rotation) { + case DXGI_MODE_ROTATION_ROTATE90: { + DestDirty.left = Width - Dirty->bottom; + DestDirty.top = Dirty->left; + DestDirty.right = Width - Dirty->top; + DestDirty.bottom = Dirty->right; + + Vertices[0].TexCoord = XMFLOAT2(Dirty->right / static_cast<FLOAT>(ThisDesc->Width), Dirty->bottom / static_cast<FLOAT>(ThisDesc->Height)); + Vertices[1].TexCoord = XMFLOAT2(Dirty->left / static_cast<FLOAT>(ThisDesc->Width), Dirty->bottom / static_cast<FLOAT>(ThisDesc->Height)); + Vertices[2].TexCoord = XMFLOAT2(Dirty->right / static_cast<FLOAT>(ThisDesc->Width), Dirty->top / static_cast<FLOAT>(ThisDesc->Height)); + Vertices[5].TexCoord = XMFLOAT2(Dirty->left / static_cast<FLOAT>(ThisDesc->Width), Dirty->top / static_cast<FLOAT>(ThisDesc->Height)); + break; + } + case DXGI_MODE_ROTATION_ROTATE180: { + DestDirty.left = Width - Dirty->right; + DestDirty.top = Height - Dirty->bottom; + DestDirty.right = Width - Dirty->left; + DestDirty.bottom = Height - Dirty->top; + + Vertices[0].TexCoord = XMFLOAT2(Dirty->right / static_cast<FLOAT>(ThisDesc->Width), Dirty->top / static_cast<FLOAT>(ThisDesc->Height)); + Vertices[1].TexCoord = XMFLOAT2(Dirty->right / static_cast<FLOAT>(ThisDesc->Width), Dirty->bottom / static_cast<FLOAT>(ThisDesc->Height)); + Vertices[2].TexCoord = XMFLOAT2(Dirty->left / static_cast<FLOAT>(ThisDesc->Width), Dirty->top / static_cast<FLOAT>(ThisDesc->Height)); + Vertices[5].TexCoord = XMFLOAT2(Dirty->left / static_cast<FLOAT>(ThisDesc->Width), Dirty->bottom / static_cast<FLOAT>(ThisDesc->Height)); + break; + } + case DXGI_MODE_ROTATION_ROTATE270: { + DestDirty.left = Dirty->top; + DestDirty.top = Height - Dirty->right; + DestDirty.right = Dirty->bottom; + DestDirty.bottom = Height - Dirty->left; + + Vertices[0].TexCoord = XMFLOAT2(Dirty->left / static_cast<FLOAT>(ThisDesc->Width), Dirty->top / static_cast<FLOAT>(ThisDesc->Height)); + Vertices[1].TexCoord = XMFLOAT2(Dirty->right / static_cast<FLOAT>(ThisDesc->Width), Dirty->top / static_cast<FLOAT>(ThisDesc->Height)); + Vertices[2].TexCoord = XMFLOAT2(Dirty->left / static_cast<FLOAT>(ThisDesc->Width), Dirty->bottom / static_cast<FLOAT>(ThisDesc->Height)); + Vertices[5].TexCoord = XMFLOAT2(Dirty->right / static_cast<FLOAT>(ThisDesc->Width), Dirty->bottom / static_cast<FLOAT>(ThisDesc->Height)); + break; + } + default: + assert(false); // drop through + case DXGI_MODE_ROTATION_UNSPECIFIED: + case DXGI_MODE_ROTATION_IDENTITY: { + Vertices[0].TexCoord = XMFLOAT2(Dirty->left / static_cast<FLOAT>(ThisDesc->Width), Dirty->bottom / static_cast<FLOAT>(ThisDesc->Height)); + Vertices[1].TexCoord = XMFLOAT2(Dirty->left / static_cast<FLOAT>(ThisDesc->Width), Dirty->top / static_cast<FLOAT>(ThisDesc->Height)); + Vertices[2].TexCoord = XMFLOAT2(Dirty->right / static_cast<FLOAT>(ThisDesc->Width), Dirty->bottom / static_cast<FLOAT>(ThisDesc->Height)); + Vertices[5].TexCoord = XMFLOAT2(Dirty->right / static_cast<FLOAT>(ThisDesc->Width), Dirty->top / static_cast<FLOAT>(ThisDesc->Height)); + break; + } } // Set positions Vertices[0].Pos = XMFLOAT3((DestDirty.left + DeskDesc->DesktopCoordinates.left - OffsetX - CenterX) / static_cast<FLOAT>(CenterX), - -1 * (DestDirty.bottom + DeskDesc->DesktopCoordinates.top - OffsetY - CenterY) / static_cast<FLOAT>(CenterY), - 0.0f); + -1 * (DestDirty.bottom + DeskDesc->DesktopCoordinates.top - OffsetY - CenterY) / static_cast<FLOAT>(CenterY), + 0.0f); Vertices[1].Pos = XMFLOAT3((DestDirty.left + DeskDesc->DesktopCoordinates.left - OffsetX - CenterX) / static_cast<FLOAT>(CenterX), - -1 * (DestDirty.top + DeskDesc->DesktopCoordinates.top - OffsetY - CenterY) / static_cast<FLOAT>(CenterY), - 0.0f); + -1 * (DestDirty.top + DeskDesc->DesktopCoordinates.top - OffsetY - CenterY) / static_cast<FLOAT>(CenterY), + 0.0f); Vertices[2].Pos = XMFLOAT3((DestDirty.right + DeskDesc->DesktopCoordinates.left - OffsetX - CenterX) / static_cast<FLOAT>(CenterX), - -1 * (DestDirty.bottom + DeskDesc->DesktopCoordinates.top - OffsetY - CenterY) / static_cast<FLOAT>(CenterY), - 0.0f); + -1 * (DestDirty.bottom + DeskDesc->DesktopCoordinates.top - OffsetY - CenterY) / static_cast<FLOAT>(CenterY), + 0.0f); Vertices[3].Pos = Vertices[2].Pos; Vertices[4].Pos = Vertices[1].Pos; Vertices[5].Pos = XMFLOAT3((DestDirty.right + DeskDesc->DesktopCoordinates.left - OffsetX - CenterX) / static_cast<FLOAT>(CenterX), - -1 * (DestDirty.top + DeskDesc->DesktopCoordinates.top - OffsetY - CenterY) / static_cast<FLOAT>(CenterY), - 0.0f); + -1 * (DestDirty.top + DeskDesc->DesktopCoordinates.top - OffsetY - CenterY) / static_cast<FLOAT>(CenterY), + 0.0f); Vertices[3].TexCoord = Vertices[2].TexCoord; Vertices[4].TexCoord = Vertices[1].TexCoord; @@ -324,11 +305,9 @@ DUPL_RETURN DISPLAYMANAGER::CopyDirty(_In_ ID3D11Texture2D* SrcSurface, _Inout_ D3D11_TEXTURE2D_DESC ThisDesc; SrcSurface->GetDesc(&ThisDesc); - if (!m_RTV) - { + if (!m_RTV) { hr = m_Device->CreateRenderTargetView(SharedSurf, nullptr, &m_RTV); - if (FAILED(hr)) - { + if (FAILED(hr)) { return ProcessFailure(m_Device, L"Failed to create render target view for dirty rects", L"Error", hr, SystemTransitionsExpectedErrors); } } @@ -342,8 +321,7 @@ DUPL_RETURN DISPLAYMANAGER::CopyDirty(_In_ ID3D11Texture2D* SrcSurface, _Inout_ // Create new shader resource view ID3D11ShaderResourceView* ShaderResource = nullptr; hr = m_Device->CreateShaderResourceView(SrcSurface, &ShaderDesc, &ShaderResource); - if (FAILED(hr)) - { + if (FAILED(hr)) { return ProcessFailure(m_Device, L"Failed to create shader resource view for dirty rects", L"Error", hr, SystemTransitionsExpectedErrors); } @@ -358,16 +336,13 @@ DUPL_RETURN DISPLAYMANAGER::CopyDirty(_In_ ID3D11Texture2D* SrcSurface, _Inout_ // Create space for vertices for the dirty rects if the current space isn't large enough UINT BytesNeeded = sizeof(VERTEX) * NUMVERTICES * DirtyCount; - if (BytesNeeded > m_DirtyVertexBufferAllocSize) - { - if (m_DirtyVertexBufferAlloc) - { + if (BytesNeeded > m_DirtyVertexBufferAllocSize) { + if (m_DirtyVertexBufferAlloc) { delete [] m_DirtyVertexBufferAlloc; } m_DirtyVertexBufferAlloc = new (std::nothrow) BYTE[BytesNeeded]; - if (!m_DirtyVertexBufferAlloc) - { + if (!m_DirtyVertexBufferAlloc) { m_DirtyVertexBufferAllocSize = 0; return ProcessFailure(nullptr, L"Failed to allocate memory for dirty vertex buffer.", L"Error", E_OUTOFMEMORY); } @@ -377,8 +352,7 @@ DUPL_RETURN DISPLAYMANAGER::CopyDirty(_In_ ID3D11Texture2D* SrcSurface, _Inout_ // Fill them in VERTEX* DirtyVertex = reinterpret_cast<VERTEX*>(m_DirtyVertexBufferAlloc); - for (UINT i = 0; i < DirtyCount; ++i, DirtyVertex += NUMVERTICES) - { + for (UINT i = 0; i < DirtyCount; ++i, DirtyVertex += NUMVERTICES) { SetDirtyVert(DirtyVertex, &(DirtyBuffer[i]), OffsetX, OffsetY, DeskDesc, &FullDesc, &ThisDesc); } @@ -395,8 +369,7 @@ DUPL_RETURN DISPLAYMANAGER::CopyDirty(_In_ ID3D11Texture2D* SrcSurface, _Inout_ ID3D11Buffer* VertBuf = nullptr; hr = m_Device->CreateBuffer(&BufferDesc, &InitData, &VertBuf); - if (FAILED(hr)) - { + if (FAILED(hr)) { return ProcessFailure(m_Device, L"Failed to create vertex buffer in dirty rect processing", L"Error", hr, SystemTransitionsExpectedErrors); } UINT Stride = sizeof(VERTEX); @@ -428,50 +401,42 @@ DUPL_RETURN DISPLAYMANAGER::CopyDirty(_In_ ID3D11Texture2D* SrcSurface, _Inout_ // void DISPLAYMANAGER::CleanRefs() { - if (m_DeviceContext) - { + if (m_DeviceContext) { m_DeviceContext->Release(); m_DeviceContext = nullptr; } - if (m_Device) - { + if (m_Device) { m_Device->Release(); m_Device = nullptr; } - if (m_MoveSurf) - { + if (m_MoveSurf) { m_MoveSurf->Release(); m_MoveSurf = nullptr; } - if (m_VertexShader) - { + if (m_VertexShader) { m_VertexShader->Release(); m_VertexShader = nullptr; } - if (m_PixelShader) - { + if (m_PixelShader) { m_PixelShader->Release(); m_PixelShader = nullptr; } - if (m_InputLayout) - { + if (m_InputLayout) { m_InputLayout->Release(); m_InputLayout = nullptr; } - if (m_SamplerLinear) - { + if (m_SamplerLinear) { m_SamplerLinear->Release(); m_SamplerLinear = nullptr; } - if (m_RTV) - { + if (m_RTV) { m_RTV->Release(); m_RTV = nullptr; } diff --git a/plugins/pluginWinDD/internals/DisplayManager.h b/plugins/pluginWinDD/internals/DisplayManager.h index f9bf69c..3308ecb 100755 --- a/plugins/pluginWinDD/internals/DisplayManager.h +++ b/plugins/pluginWinDD/internals/DisplayManager.h @@ -15,32 +15,32 @@ // class DISPLAYMANAGER { - public: - DISPLAYMANAGER(); - ~DISPLAYMANAGER(); - void InitD3D(DX_RESOURCES* Data); - ID3D11Device* GetDevice(); - DUPL_RETURN ProcessFrame(_In_ FRAME_DATA* Data, _Inout_ ID3D11Texture2D* SharedSurf, INT OffsetX, INT OffsetY, _In_ DXGI_OUTPUT_DESC* DeskDesc); - void CleanRefs(); +public: + DISPLAYMANAGER(); + ~DISPLAYMANAGER(); + void InitD3D(DX_RESOURCES* Data); + ID3D11Device* GetDevice(); + DUPL_RETURN ProcessFrame(_In_ FRAME_DATA* Data, _Inout_ ID3D11Texture2D* SharedSurf, INT OffsetX, INT OffsetY, _In_ DXGI_OUTPUT_DESC* DeskDesc); + void CleanRefs(); - private: +private: // methods - DUPL_RETURN CopyDirty(_In_ ID3D11Texture2D* SrcSurface, _Inout_ ID3D11Texture2D* SharedSurf, _In_reads_(DirtyCount) RECT* DirtyBuffer, UINT DirtyCount, INT OffsetX, INT OffsetY, _In_ DXGI_OUTPUT_DESC* DeskDesc); - DUPL_RETURN CopyMove(_Inout_ ID3D11Texture2D* SharedSurf, _In_reads_(MoveCount) DXGI_OUTDUPL_MOVE_RECT* MoveBuffer, UINT MoveCount, INT OffsetX, INT OffsetY, _In_ DXGI_OUTPUT_DESC* DeskDesc, INT TexWidth, INT TexHeight); - void SetDirtyVert(_Out_writes_(NUMVERTICES) VERTEX* Vertices, _In_ RECT* Dirty, INT OffsetX, INT OffsetY, _In_ DXGI_OUTPUT_DESC* DeskDesc, _In_ D3D11_TEXTURE2D_DESC* FullDesc, _In_ D3D11_TEXTURE2D_DESC* ThisDesc); - void SetMoveRect(_Out_ RECT* SrcRect, _Out_ RECT* DestRect, _In_ DXGI_OUTPUT_DESC* DeskDesc, _In_ DXGI_OUTDUPL_MOVE_RECT* MoveRect, INT TexWidth, INT TexHeight); + DUPL_RETURN CopyDirty(_In_ ID3D11Texture2D* SrcSurface, _Inout_ ID3D11Texture2D* SharedSurf, _In_reads_(DirtyCount) RECT* DirtyBuffer, UINT DirtyCount, INT OffsetX, INT OffsetY, _In_ DXGI_OUTPUT_DESC* DeskDesc); + DUPL_RETURN CopyMove(_Inout_ ID3D11Texture2D* SharedSurf, _In_reads_(MoveCount) DXGI_OUTDUPL_MOVE_RECT* MoveBuffer, UINT MoveCount, INT OffsetX, INT OffsetY, _In_ DXGI_OUTPUT_DESC* DeskDesc, INT TexWidth, INT TexHeight); + void SetDirtyVert(_Out_writes_(NUMVERTICES) VERTEX* Vertices, _In_ RECT* Dirty, INT OffsetX, INT OffsetY, _In_ DXGI_OUTPUT_DESC* DeskDesc, _In_ D3D11_TEXTURE2D_DESC* FullDesc, _In_ D3D11_TEXTURE2D_DESC* ThisDesc); + void SetMoveRect(_Out_ RECT* SrcRect, _Out_ RECT* DestRect, _In_ DXGI_OUTPUT_DESC* DeskDesc, _In_ DXGI_OUTDUPL_MOVE_RECT* MoveRect, INT TexWidth, INT TexHeight); // variables - ID3D11Device* m_Device; - ID3D11DeviceContext* m_DeviceContext; - ID3D11Texture2D* m_MoveSurf; - ID3D11VertexShader* m_VertexShader; - ID3D11PixelShader* m_PixelShader; - ID3D11InputLayout* m_InputLayout; - ID3D11RenderTargetView* m_RTV; - ID3D11SamplerState* m_SamplerLinear; - BYTE* m_DirtyVertexBufferAlloc; - UINT m_DirtyVertexBufferAllocSize; + ID3D11Device* m_Device; + ID3D11DeviceContext* m_DeviceContext; + ID3D11Texture2D* m_MoveSurf; + ID3D11VertexShader* m_VertexShader; + ID3D11PixelShader* m_PixelShader; + ID3D11InputLayout* m_InputLayout; + ID3D11RenderTargetView* m_RTV; + ID3D11SamplerState* m_SamplerLinear; + BYTE* m_DirtyVertexBufferAlloc; + UINT m_DirtyVertexBufferAllocSize; }; #endif diff --git a/plugins/pluginWinDD/internals/DuplicationManager.cxx b/plugins/pluginWinDD/internals/DuplicationManager.cxx index 995c8ec..34ec896 100755 --- a/plugins/pluginWinDD/internals/DuplicationManager.cxx +++ b/plugins/pluginWinDD/internals/DuplicationManager.cxx @@ -12,24 +12,24 @@ #include <Mfapi.h> static inline HRESULT CopyRGBb32DownTop( - BYTE* pDst, - const BYTE* pSrc, - INT dwWidthDstPixels, - INT dwWidthSrcPixels, - INT dwHeightPixels - ); + BYTE* pDst, + const BYTE* pSrc, + INT dwWidthDstPixels, + INT dwWidthSrcPixels, + INT dwHeightPixels +); // // Constructor sets up references / variables // DUPLICATIONMANAGER::DUPLICATIONMANAGER() : m_DeskDupl(nullptr), - m_AcquiredDesktopImage(nullptr), - m_MetaDataBuffer(nullptr), - m_MetaDataSize(0), - m_OutputNumber(0), - m_Device(nullptr), - m_DeviceContext(nullptr), - m_BufferPtr(nullptr), - m_BufferSize(0) + m_AcquiredDesktopImage(nullptr), + m_MetaDataBuffer(nullptr), + m_MetaDataSize(0), + m_OutputNumber(0), + m_Device(nullptr), + m_DeviceContext(nullptr), + m_BufferPtr(nullptr), + m_BufferSize(0) { RtlZeroMemory(&m_OutputDesc, sizeof(m_OutputDesc)); } @@ -39,41 +39,35 @@ DUPLICATIONMANAGER::DUPLICATIONMANAGER() : m_DeskDupl(nullptr), // DUPLICATIONMANAGER::~DUPLICATIONMANAGER() { - if (m_DeskDupl) - { + if (m_DeskDupl) { m_DeskDupl->Release(); m_DeskDupl = nullptr; } - if (m_AcquiredDesktopImage) - { + if (m_AcquiredDesktopImage) { m_AcquiredDesktopImage->Release(); m_AcquiredDesktopImage = nullptr; } - if (m_MetaDataBuffer) - { + if (m_MetaDataBuffer) { delete [] m_MetaDataBuffer; m_MetaDataBuffer = nullptr; } - if (m_DeviceContext) - { - m_DeviceContext->Release(); - m_DeviceContext = nullptr; - } + if (m_DeviceContext) { + m_DeviceContext->Release(); + m_DeviceContext = nullptr; + } - if (m_Device) - { + if (m_Device) { m_Device->Release(); m_Device = nullptr; } - if (m_BufferPtr) - { - VirtualFree(m_BufferPtr, 0, MEM_RELEASE); - m_BufferPtr = nullptr; - } + if (m_BufferPtr) { + VirtualFree(m_BufferPtr, 0, MEM_RELEASE); + m_BufferPtr = nullptr; + } } // @@ -87,14 +81,13 @@ DUPL_RETURN DUPLICATIONMANAGER::InitDupl(_In_ ID3D11Device* Device, ID3D11Device m_Device = Device; m_Device->AddRef(); - m_DeviceContext = DeviceContext; - m_DeviceContext->AddRef(); + m_DeviceContext = DeviceContext; + m_DeviceContext->AddRef(); // Get DXGI device IDXGIDevice* DxgiDevice = nullptr; HRESULT hr = m_Device->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&DxgiDevice)); - if (FAILED(hr)) - { + if (FAILED(hr)) { return ProcessFailure(nullptr, L"Failed to QI for DXGI Device", L"Error", hr); } @@ -103,8 +96,7 @@ DUPL_RETURN DUPLICATIONMANAGER::InitDupl(_In_ ID3D11Device* Device, ID3D11Device hr = DxgiDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void**>(&DxgiAdapter)); DxgiDevice->Release(); DxgiDevice = nullptr; - if (FAILED(hr)) - { + if (FAILED(hr)) { return ProcessFailure(m_Device, L"Failed to get parent DXGI Adapter", L"Error", hr, SystemTransitionsExpectedErrors); } @@ -113,8 +105,7 @@ DUPL_RETURN DUPLICATIONMANAGER::InitDupl(_In_ ID3D11Device* Device, ID3D11Device hr = DxgiAdapter->EnumOutputs(Output, &DxgiOutput); DxgiAdapter->Release(); DxgiAdapter = nullptr; - if (FAILED(hr)) - { + if (FAILED(hr)) { return ProcessFailure(m_Device, L"Failed to get specified output in DUPLICATIONMANAGER", L"Error", hr, EnumOutputsExpectedErrors); } @@ -125,8 +116,7 @@ DUPL_RETURN DUPLICATIONMANAGER::InitDupl(_In_ ID3D11Device* Device, ID3D11Device hr = DxgiOutput->QueryInterface(__uuidof(DxgiOutput1), reinterpret_cast<void**>(&DxgiOutput1)); DxgiOutput->Release(); DxgiOutput = nullptr; - if (FAILED(hr)) - { + if (FAILED(hr)) { return ProcessFailure(nullptr, L"Failed to QI for DxgiOutput1 in DUPLICATIONMANAGER", L"Error", hr); } @@ -134,10 +124,8 @@ DUPL_RETURN DUPLICATIONMANAGER::InitDupl(_In_ ID3D11Device* Device, ID3D11Device hr = DxgiOutput1->DuplicateOutput(m_Device, &m_DeskDupl); DxgiOutput1->Release(); DxgiOutput1 = nullptr; - if (FAILED(hr)) - { - if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE) - { + if (FAILED(hr)) { + if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE) { MessageBoxW(nullptr, L"There is already the maximum number of applications using the Desktop Duplication API running, please close one of those applications and then try again.", L"Error", MB_OK); return DUPL_RETURN_ERROR_UNEXPECTED; } @@ -153,8 +141,7 @@ DUPL_RETURN DUPLICATIONMANAGER::InitDupl(_In_ ID3D11Device* Device, ID3D11Device DUPL_RETURN DUPLICATIONMANAGER::GetMouse(_Inout_ PTR_INFO* PtrInfo, _In_ DXGI_OUTDUPL_FRAME_INFO* FrameInfo, INT OffsetX, INT OffsetY) { // A non-zero mouse update timestamp indicates that there is a mouse position update and optionally a shape change - if (FrameInfo->LastMouseUpdateTime.QuadPart == 0) - { + if (FrameInfo->LastMouseUpdateTime.QuadPart == 0) { return DUPL_RETURN_SUCCESS; } @@ -163,20 +150,17 @@ DUPL_RETURN DUPLICATIONMANAGER::GetMouse(_Inout_ PTR_INFO* PtrInfo, _In_ DXGI_OU // Make sure we don't update pointer position wrongly // If pointer is invisible, make sure we did not get an update from another output that the last time that said pointer // was visible, if so, don't set it to invisible or update. - if (!FrameInfo->PointerPosition.Visible && (PtrInfo->WhoUpdatedPositionLast != m_OutputNumber)) - { + if (!FrameInfo->PointerPosition.Visible && (PtrInfo->WhoUpdatedPositionLast != m_OutputNumber)) { UpdatePosition = false; } // If two outputs both say they have a visible, only update if new update has newer timestamp - if (FrameInfo->PointerPosition.Visible && PtrInfo->Visible && (PtrInfo->WhoUpdatedPositionLast != m_OutputNumber) && (PtrInfo->LastTimeStamp.QuadPart > FrameInfo->LastMouseUpdateTime.QuadPart)) - { + if (FrameInfo->PointerPosition.Visible && PtrInfo->Visible && (PtrInfo->WhoUpdatedPositionLast != m_OutputNumber) && (PtrInfo->LastTimeStamp.QuadPart > FrameInfo->LastMouseUpdateTime.QuadPart)) { UpdatePosition = false; } // Update position - if (UpdatePosition) - { + if (UpdatePosition) { PtrInfo->Position.x = FrameInfo->PointerPosition.Position.x + m_OutputDesc.DesktopCoordinates.left - OffsetX; PtrInfo->Position.y = FrameInfo->PointerPosition.Position.y + m_OutputDesc.DesktopCoordinates.top - OffsetY; PtrInfo->WhoUpdatedPositionLast = m_OutputNumber; @@ -185,22 +169,18 @@ DUPL_RETURN DUPLICATIONMANAGER::GetMouse(_Inout_ PTR_INFO* PtrInfo, _In_ DXGI_OU } // No new shape - if (FrameInfo->PointerShapeBufferSize == 0) - { + if (FrameInfo->PointerShapeBufferSize == 0) { return DUPL_RETURN_SUCCESS; } // Old buffer too small - if (FrameInfo->PointerShapeBufferSize > PtrInfo->BufferSize) - { - if (PtrInfo->PtrShapeBuffer) - { + if (FrameInfo->PointerShapeBufferSize > PtrInfo->BufferSize) { + if (PtrInfo->PtrShapeBuffer) { delete [] PtrInfo->PtrShapeBuffer; PtrInfo->PtrShapeBuffer = nullptr; } PtrInfo->PtrShapeBuffer = new (std::nothrow) BYTE[FrameInfo->PointerShapeBufferSize]; - if (!PtrInfo->PtrShapeBuffer) - { + if (!PtrInfo->PtrShapeBuffer) { PtrInfo->BufferSize = 0; return ProcessFailure(nullptr, L"Failed to allocate memory for pointer shape in DUPLICATIONMANAGER", L"Error", E_OUTOFMEMORY); } @@ -212,8 +192,7 @@ DUPL_RETURN DUPLICATIONMANAGER::GetMouse(_Inout_ PTR_INFO* PtrInfo, _In_ DXGI_OU // Get shape UINT BufferSizeRequired; HRESULT hr = m_DeskDupl->GetFramePointerShape(FrameInfo->PointerShapeBufferSize, reinterpret_cast<VOID*>(PtrInfo->PtrShapeBuffer), &BufferSizeRequired, &(PtrInfo->ShapeInfo)); - if (FAILED(hr)) - { + if (FAILED(hr)) { delete [] PtrInfo->PtrShapeBuffer; PtrInfo->PtrShapeBuffer = nullptr; PtrInfo->BufferSize = 0; @@ -235,21 +214,18 @@ DUPL_RETURN DUPLICATIONMANAGER::GetFrame(_Out_ FRAME_DATA* Data, _Out_ bool* Tim // Get new frame HRESULT hr = m_DeskDupl->AcquireNextFrame(500, &FrameInfo, &DesktopResource); - if (hr == DXGI_ERROR_WAIT_TIMEOUT) - { + if (hr == DXGI_ERROR_WAIT_TIMEOUT) { *Timeout = true; return DUPL_RETURN_SUCCESS; } *Timeout = false; - if (FAILED(hr)) - { + if (FAILED(hr)) { return ProcessFailure(m_Device, L"Failed to acquire next frame in DUPLICATIONMANAGER", L"Error", hr, FrameInfoExpectedErrors); } // If still holding old frame, destroy it - if (m_AcquiredDesktopImage) - { + if (m_AcquiredDesktopImage) { m_AcquiredDesktopImage->Release(); m_AcquiredDesktopImage = nullptr; } @@ -258,25 +234,20 @@ DUPL_RETURN DUPLICATIONMANAGER::GetFrame(_Out_ FRAME_DATA* Data, _Out_ bool* Tim hr = DesktopResource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void **>(&m_AcquiredDesktopImage)); DesktopResource->Release(); DesktopResource = nullptr; - if (FAILED(hr)) - { + if (FAILED(hr)) { return ProcessFailure(nullptr, L"Failed to QI for ID3D11Texture2D from acquired IDXGIResource in DUPLICATIONMANAGER", L"Error", hr); } // Get metadata - if (FrameInfo.TotalMetadataBufferSize) - { + if (FrameInfo.TotalMetadataBufferSize) { // Old buffer too small - if (FrameInfo.TotalMetadataBufferSize > m_MetaDataSize) - { - if (m_MetaDataBuffer) - { + if (FrameInfo.TotalMetadataBufferSize > m_MetaDataSize) { + if (m_MetaDataBuffer) { delete [] m_MetaDataBuffer; m_MetaDataBuffer = nullptr; } m_MetaDataBuffer = new (std::nothrow) BYTE[FrameInfo.TotalMetadataBufferSize]; - if (!m_MetaDataBuffer) - { + if (!m_MetaDataBuffer) { m_MetaDataSize = 0; Data->MoveCount = 0; Data->DirtyCount = 0; @@ -289,8 +260,7 @@ DUPL_RETURN DUPLICATIONMANAGER::GetFrame(_Out_ FRAME_DATA* Data, _Out_ bool* Tim // Get move rectangles hr = m_DeskDupl->GetFrameMoveRects(BufSize, reinterpret_cast<DXGI_OUTDUPL_MOVE_RECT*>(m_MetaDataBuffer), &BufSize); - if (FAILED(hr)) - { + if (FAILED(hr)) { Data->MoveCount = 0; Data->DirtyCount = 0; return ProcessFailure(nullptr, L"Failed to get frame move rects in DUPLICATIONMANAGER", L"Error", hr, FrameInfoExpectedErrors); @@ -302,8 +272,7 @@ DUPL_RETURN DUPLICATIONMANAGER::GetFrame(_Out_ FRAME_DATA* Data, _Out_ bool* Tim // Get dirty rectangles hr = m_DeskDupl->GetFrameDirtyRects(BufSize, reinterpret_cast<RECT*>(DirtyRects), &BufSize); - if (FAILED(hr)) - { + if (FAILED(hr)) { Data->MoveCount = 0; Data->DirtyCount = 0; return ProcessFailure(nullptr, L"Failed to get frame dirty rects in DUPLICATIONMANAGER", L"Error", hr, FrameInfoExpectedErrors); @@ -325,13 +294,11 @@ DUPL_RETURN DUPLICATIONMANAGER::GetFrame(_Out_ FRAME_DATA* Data, _Out_ bool* Tim DUPL_RETURN DUPLICATIONMANAGER::DoneWithFrame() { HRESULT hr = m_DeskDupl->ReleaseFrame(); - if (FAILED(hr)) - { + if (FAILED(hr)) { return ProcessFailure(m_Device, L"Failed to release frame in DUPLICATIONMANAGER", L"Error", hr, FrameInfoExpectedErrors); } - if (m_AcquiredDesktopImage) - { + if (m_AcquiredDesktopImage) { m_AcquiredDesktopImage->Release(); m_AcquiredDesktopImage = nullptr; } @@ -350,150 +317,138 @@ void DUPLICATIONMANAGER::GetOutputDesc(_Out_ DXGI_OUTPUT_DESC* DescPtr) HRESULT DUPLICATIONMANAGER::SendData(struct tmedia_producer_s* pProducer, FRAME_DATA* FrameData) { - HRESULT hr = E_FAIL; - D3D11_TEXTURE2D_DESC CopyBufferDesc = {0}; - D3D11_TEXTURE2D_DESC FullDesc; - DXGI_MAPPED_RECT MappedSurface; - D3D11_BOX Box; - UINT BuffSize; - - ID3D11Texture2D* CopyBuffer = nullptr; - IDXGISurface* CopySurface = nullptr; - ID3D11Device* Device = nullptr; - - FrameData->Frame->GetDesc(&FullDesc); - - CopyBufferDesc.Width = FullDesc.Width; - CopyBufferDesc.Height = FullDesc.Height; - CopyBufferDesc.MipLevels = 1; - CopyBufferDesc.ArraySize = 1; - CopyBufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; - CopyBufferDesc.SampleDesc.Count = 1; - CopyBufferDesc.SampleDesc.Quality = 0; - CopyBufferDesc.Usage = D3D11_USAGE_STAGING; - CopyBufferDesc.BindFlags = 0; - CopyBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; - CopyBufferDesc.MiscFlags = 0; - - FrameData->Frame->GetDevice(&Device); - if (!Device) - { - hr = E_POINTER; - ProcessFailure(m_Device, L"Failed to get device", L"Error", hr, SystemTransitionsExpectedErrors); - goto bail; - } - - hr = Device->CreateTexture2D(&CopyBufferDesc, nullptr, &CopyBuffer); - if (FAILED(hr)) - { - ProcessFailure(m_Device, L"Failed creating staging texture for pointer", L"Error", hr, SystemTransitionsExpectedErrors); - goto bail; - } - - Box.left = 0; - Box.top = 0; - Box.right = CopyBufferDesc.Width; - Box.bottom = CopyBufferDesc.Height; - Box.front = 0; - Box.back = 1; - m_DeviceContext->CopySubresourceRegion(CopyBuffer, 0, 0, 0, 0, FrameData->Frame, 0, &Box); - - hr = CopyBuffer->QueryInterface(__uuidof(IDXGISurface), (void **)&CopySurface); - if (FAILED(hr)) - { - ProcessFailure(nullptr, L"Failed to QI staging texture into IDXGISurface for pointer", L"Error", hr, SystemTransitionsExpectedErrors); - goto bail; - } - - BuffSize = CopyBufferDesc.Width * CopyBufferDesc.Height * 4; - if (m_BufferSize < BuffSize) - { - if (m_BufferPtr) - { - VirtualFree(m_BufferPtr, 0, MEM_RELEASE); - m_BufferSize = 0; - } - if (!(m_BufferPtr = (BYTE*)VirtualAlloc(NULL, BuffSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE))) - { - ProcessFailure(Device, L"Failed to allocate memory", L"Error", hr, SystemTransitionsExpectedErrors); - goto bail; - } - m_BufferSize = BuffSize; - } - - hr = CopySurface->Map(&MappedSurface, DXGI_MAP_READ); // *** MAP *** // - if (FAILED(hr)) - { - ProcessFailure(Device, L"Failed to map surface for pointer", L"Error", hr, SystemTransitionsExpectedErrors); - goto bail; - } - - pProducer->video.width = CopyBufferDesc.Width; - pProducer->video.height = CopyBufferDesc.Height; + HRESULT hr = E_FAIL; + D3D11_TEXTURE2D_DESC CopyBufferDesc = {0}; + D3D11_TEXTURE2D_DESC FullDesc; + DXGI_MAPPED_RECT MappedSurface; + D3D11_BOX Box; + UINT BuffSize; + + ID3D11Texture2D* CopyBuffer = nullptr; + IDXGISurface* CopySurface = nullptr; + ID3D11Device* Device = nullptr; + + FrameData->Frame->GetDesc(&FullDesc); + + CopyBufferDesc.Width = FullDesc.Width; + CopyBufferDesc.Height = FullDesc.Height; + CopyBufferDesc.MipLevels = 1; + CopyBufferDesc.ArraySize = 1; + CopyBufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + CopyBufferDesc.SampleDesc.Count = 1; + CopyBufferDesc.SampleDesc.Quality = 0; + CopyBufferDesc.Usage = D3D11_USAGE_STAGING; + CopyBufferDesc.BindFlags = 0; + CopyBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + CopyBufferDesc.MiscFlags = 0; + + FrameData->Frame->GetDevice(&Device); + if (!Device) { + hr = E_POINTER; + ProcessFailure(m_Device, L"Failed to get device", L"Error", hr, SystemTransitionsExpectedErrors); + goto bail; + } + + hr = Device->CreateTexture2D(&CopyBufferDesc, nullptr, &CopyBuffer); + if (FAILED(hr)) { + ProcessFailure(m_Device, L"Failed creating staging texture for pointer", L"Error", hr, SystemTransitionsExpectedErrors); + goto bail; + } + + Box.left = 0; + Box.top = 0; + Box.right = CopyBufferDesc.Width; + Box.bottom = CopyBufferDesc.Height; + Box.front = 0; + Box.back = 1; + m_DeviceContext->CopySubresourceRegion(CopyBuffer, 0, 0, 0, 0, FrameData->Frame, 0, &Box); + + hr = CopyBuffer->QueryInterface(__uuidof(IDXGISurface), (void **)&CopySurface); + if (FAILED(hr)) { + ProcessFailure(nullptr, L"Failed to QI staging texture into IDXGISurface for pointer", L"Error", hr, SystemTransitionsExpectedErrors); + goto bail; + } + + BuffSize = CopyBufferDesc.Width * CopyBufferDesc.Height * 4; + if (m_BufferSize < BuffSize) { + if (m_BufferPtr) { + VirtualFree(m_BufferPtr, 0, MEM_RELEASE); + m_BufferSize = 0; + } + if (!(m_BufferPtr = (BYTE*)VirtualAlloc(NULL, BuffSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE))) { + ProcessFailure(Device, L"Failed to allocate memory", L"Error", hr, SystemTransitionsExpectedErrors); + goto bail; + } + m_BufferSize = BuffSize; + } + + hr = CopySurface->Map(&MappedSurface, DXGI_MAP_READ); // *** MAP *** // + if (FAILED(hr)) { + ProcessFailure(Device, L"Failed to map surface for pointer", L"Error", hr, SystemTransitionsExpectedErrors); + goto bail; + } + + pProducer->video.width = CopyBufferDesc.Width; + pProducer->video.height = CopyBufferDesc.Height; #if 0 - hr = MFCopyImage( - m_BufferPtr, - (LONG)(CopyBufferDesc.Width << 2), - (BYTE*)MappedSurface.pBits, - (LONG)MappedSurface.Pitch, - (DWORD)(CopyBufferDesc.Width << 2), - (DWORD)CopyBufferDesc.Height - ); + hr = MFCopyImage( + m_BufferPtr, + (LONG)(CopyBufferDesc.Width << 2), + (BYTE*)MappedSurface.pBits, + (LONG)MappedSurface.Pitch, + (DWORD)(CopyBufferDesc.Width << 2), + (DWORD)CopyBufferDesc.Height + ); #else; - hr = CopyRGBb32DownTop( - m_BufferPtr, - MappedSurface.pBits, - CopyBufferDesc.Width, - (MappedSurface.Pitch >> 2), // Bytes -> Pixels - CopyBufferDesc.Height); + hr = CopyRGBb32DownTop( + m_BufferPtr, + MappedSurface.pBits, + CopyBufferDesc.Width, + (MappedSurface.Pitch >> 2), // Bytes -> Pixels + CopyBufferDesc.Height); #endif - pProducer->enc_cb.callback(pProducer->enc_cb.callback_data, m_BufferPtr, BuffSize); + pProducer->enc_cb.callback(pProducer->enc_cb.callback_data, m_BufferPtr, BuffSize); - CopySurface->Unmap(); // *** UNMAP *** // + CopySurface->Unmap(); // *** UNMAP *** // bail: - if (CopyBuffer) - { - CopyBuffer->Release(); - } - if (CopySurface) - { - CopySurface->Release(); - } - if (Device) - { - Device->Release(); - } - return hr; + if (CopyBuffer) { + CopyBuffer->Release(); + } + if (CopySurface) { + CopySurface->Release(); + } + if (Device) { + Device->Release(); + } + return hr; } // For RGB32: // Direct3D -> Top-Down // Video Processor -> Down-Top static inline HRESULT CopyRGBb32DownTop( - BYTE* pDst, - const BYTE* pSrc, - INT dwWidthDstPixels, - INT dwWidthSrcPixels, - INT dwHeightPixels - ) + BYTE* pDst, + const BYTE* pSrc, + INT dwWidthDstPixels, + INT dwWidthSrcPixels, + INT dwHeightPixels +) { - RGBQUAD *pSrcPixel = &((RGBQUAD*)pSrc)[(dwWidthSrcPixels * dwHeightPixels) - dwWidthSrcPixels]; - RGBQUAD *pDestPixel = &((RGBQUAD*)pDst)[0]; - - register INT x; - register INT y; - - for (y = dwHeightPixels; y > 0; --y) - { - for (x = 0; x < dwWidthDstPixels; ++x) - { - pDestPixel[x] = pSrcPixel[x]; - } - pDestPixel += dwWidthDstPixels; - pSrcPixel -= dwWidthSrcPixels; - } - return S_OK; + RGBQUAD *pSrcPixel = &((RGBQUAD*)pSrc)[(dwWidthSrcPixels * dwHeightPixels) - dwWidthSrcPixels]; + RGBQUAD *pDestPixel = &((RGBQUAD*)pDst)[0]; + + register INT x; + register INT y; + + for (y = dwHeightPixels; y > 0; --y) { + for (x = 0; x < dwWidthDstPixels; ++x) { + pDestPixel[x] = pSrcPixel[x]; + } + pDestPixel += dwWidthDstPixels; + pSrcPixel -= dwWidthSrcPixels; + } + return S_OK; }
\ No newline at end of file diff --git a/plugins/pluginWinDD/internals/DuplicationManager.h b/plugins/pluginWinDD/internals/DuplicationManager.h index 2c44b57..8f98145 100755 --- a/plugins/pluginWinDD/internals/DuplicationManager.h +++ b/plugins/pluginWinDD/internals/DuplicationManager.h @@ -15,29 +15,29 @@ // class DUPLICATIONMANAGER { - public: - DUPLICATIONMANAGER(); - ~DUPLICATIONMANAGER(); - _Success_(*Timeout == false && return == DUPL_RETURN_SUCCESS) DUPL_RETURN GetFrame(_Out_ FRAME_DATA* Data, _Out_ bool* Timeout); - DUPL_RETURN DoneWithFrame(); - DUPL_RETURN InitDupl(_In_ ID3D11Device* Device, ID3D11DeviceContext* DeviceContext, UINT Output); - DUPL_RETURN GetMouse(_Inout_ PTR_INFO* PtrInfo, _In_ DXGI_OUTDUPL_FRAME_INFO* FrameInfo, INT OffsetX, INT OffsetY); - void GetOutputDesc(_Out_ DXGI_OUTPUT_DESC* DescPtr); - HRESULT SendData(struct tmedia_producer_s* pProducer, FRAME_DATA* FrameData); +public: + DUPLICATIONMANAGER(); + ~DUPLICATIONMANAGER(); + _Success_(*Timeout == false && return == DUPL_RETURN_SUCCESS) DUPL_RETURN GetFrame(_Out_ FRAME_DATA* Data, _Out_ bool* Timeout); + DUPL_RETURN DoneWithFrame(); + DUPL_RETURN InitDupl(_In_ ID3D11Device* Device, ID3D11DeviceContext* DeviceContext, UINT Output); + DUPL_RETURN GetMouse(_Inout_ PTR_INFO* PtrInfo, _In_ DXGI_OUTDUPL_FRAME_INFO* FrameInfo, INT OffsetX, INT OffsetY); + void GetOutputDesc(_Out_ DXGI_OUTPUT_DESC* DescPtr); + HRESULT SendData(struct tmedia_producer_s* pProducer, FRAME_DATA* FrameData); - private: +private: // vars - IDXGIOutputDuplication* m_DeskDupl; - ID3D11Texture2D* m_AcquiredDesktopImage; - _Field_size_bytes_(m_MetaDataSize) BYTE* m_MetaDataBuffer; - UINT m_MetaDataSize; - UINT m_OutputNumber; - DXGI_OUTPUT_DESC m_OutputDesc; - ID3D11Device* m_Device; - ID3D11DeviceContext* m_DeviceContext; - BYTE* m_BufferPtr; - UINT m_BufferSize; + IDXGIOutputDuplication* m_DeskDupl; + ID3D11Texture2D* m_AcquiredDesktopImage; + _Field_size_bytes_(m_MetaDataSize) BYTE* m_MetaDataBuffer; + UINT m_MetaDataSize; + UINT m_OutputNumber; + DXGI_OUTPUT_DESC m_OutputDesc; + ID3D11Device* m_Device; + ID3D11DeviceContext* m_DeviceContext; + BYTE* m_BufferPtr; + UINT m_BufferSize; }; #endif diff --git a/plugins/pluginWinDD/internals/OutputManager.cxx b/plugins/pluginWinDD/internals/OutputManager.cxx index 7468cf2..a82f84c 100755 --- a/plugins/pluginWinDD/internals/OutputManager.cxx +++ b/plugins/pluginWinDD/internals/OutputManager.cxx @@ -12,20 +12,20 @@ using namespace DirectX; // Constructor NULLs out all pointers & sets appropriate var vals // OUTPUTMANAGER::OUTPUTMANAGER() : m_SwapChain(nullptr), - m_Device(nullptr), - m_Factory(nullptr), - m_DeviceContext(nullptr), - m_RTV(nullptr), - m_SamplerLinear(nullptr), - m_BlendState(nullptr), - m_VertexShader(nullptr), - m_PixelShader(nullptr), - m_InputLayout(nullptr), - m_SharedSurf(nullptr), - m_KeyMutex(nullptr), - m_WindowHandle(nullptr), - m_NeedsResize(false), - m_OcclusionCookie(0) + m_Device(nullptr), + m_Factory(nullptr), + m_DeviceContext(nullptr), + m_RTV(nullptr), + m_SamplerLinear(nullptr), + m_BlendState(nullptr), + m_VertexShader(nullptr), + m_PixelShader(nullptr), + m_InputLayout(nullptr), + m_SharedSurf(nullptr), + m_KeyMutex(nullptr), + m_WindowHandle(nullptr), + m_NeedsResize(false), + m_OcclusionCookie(0) { } @@ -56,8 +56,7 @@ DUPL_RETURN OUTPUTMANAGER::InitOutput(HWND Window, INT SingleOutput, _Out_ UINT* m_WindowHandle = Window; // Driver types supported - D3D_DRIVER_TYPE DriverTypes[] = - { + D3D_DRIVER_TYPE DriverTypes[] = { D3D_DRIVER_TYPE_HARDWARE, D3D_DRIVER_TYPE_WARP, D3D_DRIVER_TYPE_REFERENCE, @@ -65,8 +64,7 @@ DUPL_RETURN OUTPUTMANAGER::InitOutput(HWND Window, INT SingleOutput, _Out_ UINT* UINT NumDriverTypes = ARRAYSIZE(DriverTypes); // Feature levels supported - D3D_FEATURE_LEVEL FeatureLevels[] = - { + D3D_FEATURE_LEVEL FeatureLevels[] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, @@ -76,26 +74,22 @@ DUPL_RETURN OUTPUTMANAGER::InitOutput(HWND Window, INT SingleOutput, _Out_ UINT* D3D_FEATURE_LEVEL FeatureLevel; // Create device - for (UINT DriverTypeIndex = 0; DriverTypeIndex < NumDriverTypes; ++DriverTypeIndex) - { + for (UINT DriverTypeIndex = 0; DriverTypeIndex < NumDriverTypes; ++DriverTypeIndex) { hr = D3D11CreateDevice(nullptr, DriverTypes[DriverTypeIndex], nullptr, 0, FeatureLevels, NumFeatureLevels, - D3D11_SDK_VERSION, &m_Device, &FeatureLevel, &m_DeviceContext); - if (SUCCEEDED(hr)) - { + D3D11_SDK_VERSION, &m_Device, &FeatureLevel, &m_DeviceContext); + if (SUCCEEDED(hr)) { // Device creation succeeded, no need to loop anymore break; } } - if (FAILED(hr)) - { + if (FAILED(hr)) { return ProcessFailure(m_Device, L"Device creation in OUTPUTMANAGER failed", L"Error", hr, SystemTransitionsExpectedErrors); } // Get DXGI factory IDXGIDevice* DxgiDevice = nullptr; hr = m_Device->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&DxgiDevice)); - if (FAILED(hr)) - { + if (FAILED(hr)) { return ProcessFailure(nullptr, L"Failed to QI for DXGI Device", L"Error", hr, nullptr); } @@ -103,79 +97,69 @@ DUPL_RETURN OUTPUTMANAGER::InitOutput(HWND Window, INT SingleOutput, _Out_ UINT* hr = DxgiDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void**>(&DxgiAdapter)); DxgiDevice->Release(); DxgiDevice = nullptr; - if (FAILED(hr)) - { + if (FAILED(hr)) { return ProcessFailure(m_Device, L"Failed to get parent DXGI Adapter", L"Error", hr, SystemTransitionsExpectedErrors); } hr = DxgiAdapter->GetParent(__uuidof(IDXGIFactory2), reinterpret_cast<void**>(&m_Factory)); DxgiAdapter->Release(); DxgiAdapter = nullptr; - if (FAILED(hr)) - { + if (FAILED(hr)) { return ProcessFailure(m_Device, L"Failed to get parent DXGI Factory", L"Error", hr, SystemTransitionsExpectedErrors); } // Register for occlusion status windows message - if (m_WindowHandle) - { - hr = m_Factory->RegisterOcclusionStatusWindow(Window, OCCLUSION_STATUS_MSG, &m_OcclusionCookie); - if (FAILED(hr)) - { - return ProcessFailure(m_Device, L"Failed to register for occlusion message", L"Error", hr, SystemTransitionsExpectedErrors); - } - } + if (m_WindowHandle) { + hr = m_Factory->RegisterOcclusionStatusWindow(Window, OCCLUSION_STATUS_MSG, &m_OcclusionCookie); + if (FAILED(hr)) { + return ProcessFailure(m_Device, L"Failed to register for occlusion message", L"Error", hr, SystemTransitionsExpectedErrors); + } + } // Get window size RECT WindowRect; - GetClientRect(m_WindowHandle ? m_WindowHandle : GetDesktopWindow(), &WindowRect); + GetClientRect(m_WindowHandle ? m_WindowHandle : GetDesktopWindow(), &WindowRect); UINT Width = WindowRect.right - WindowRect.left; UINT Height = WindowRect.bottom - WindowRect.top; - if (m_WindowHandle) - { - // Create swapchain for window - DXGI_SWAP_CHAIN_DESC1 SwapChainDesc; - RtlZeroMemory(&SwapChainDesc, sizeof(SwapChainDesc)); - - SwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; - SwapChainDesc.BufferCount = 2; - SwapChainDesc.Width = Width; - SwapChainDesc.Height = Height; - SwapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; - SwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - SwapChainDesc.SampleDesc.Count = 1; - SwapChainDesc.SampleDesc.Quality = 0; - hr = m_Factory->CreateSwapChainForHwnd(m_Device, Window, &SwapChainDesc, nullptr, nullptr, &m_SwapChain); - if (FAILED(hr)) - { - return ProcessFailure(m_Device, L"Failed to create window swapchain", L"Error", hr, SystemTransitionsExpectedErrors); - } - - // Disable the ALT-ENTER shortcut for entering full-screen mode - hr = m_Factory->MakeWindowAssociation(Window, DXGI_MWA_NO_ALT_ENTER); - if (FAILED(hr)) - { - return ProcessFailure(m_Device, L"Failed to make window association", L"Error", hr, SystemTransitionsExpectedErrors); - } - } + if (m_WindowHandle) { + // Create swapchain for window + DXGI_SWAP_CHAIN_DESC1 SwapChainDesc; + RtlZeroMemory(&SwapChainDesc, sizeof(SwapChainDesc)); + + SwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + SwapChainDesc.BufferCount = 2; + SwapChainDesc.Width = Width; + SwapChainDesc.Height = Height; + SwapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + SwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + SwapChainDesc.SampleDesc.Count = 1; + SwapChainDesc.SampleDesc.Quality = 0; + hr = m_Factory->CreateSwapChainForHwnd(m_Device, Window, &SwapChainDesc, nullptr, nullptr, &m_SwapChain); + if (FAILED(hr)) { + return ProcessFailure(m_Device, L"Failed to create window swapchain", L"Error", hr, SystemTransitionsExpectedErrors); + } + + // Disable the ALT-ENTER shortcut for entering full-screen mode + hr = m_Factory->MakeWindowAssociation(Window, DXGI_MWA_NO_ALT_ENTER); + if (FAILED(hr)) { + return ProcessFailure(m_Device, L"Failed to make window association", L"Error", hr, SystemTransitionsExpectedErrors); + } + } // Create shared texture DUPL_RETURN Return = CreateSharedSurf(SingleOutput, OutCount, DeskBounds); - if (Return != DUPL_RETURN_SUCCESS) - { + if (Return != DUPL_RETURN_SUCCESS) { return Return; } // Make new render target view - if (m_WindowHandle) - { - Return = MakeRTV(); - if (Return != DUPL_RETURN_SUCCESS) - { - return Return; - } - } + if (m_WindowHandle) { + Return = MakeRTV(); + if (Return != DUPL_RETURN_SUCCESS) { + return Return; + } + } // Set view port SetViewPort(Width, Height); @@ -191,41 +175,37 @@ DUPL_RETURN OUTPUTMANAGER::InitOutput(HWND Window, INT SingleOutput, _Out_ UINT* SampDesc.MinLOD = 0; SampDesc.MaxLOD = D3D11_FLOAT32_MAX; hr = m_Device->CreateSamplerState(&SampDesc, &m_SamplerLinear); - if (FAILED(hr)) - { + if (FAILED(hr)) { return ProcessFailure(m_Device, L"Failed to create sampler state in OUTPUTMANAGER", L"Error", hr, SystemTransitionsExpectedErrors); } - if (m_WindowHandle) - { - // Create the blend state - D3D11_BLEND_DESC BlendStateDesc; - BlendStateDesc.AlphaToCoverageEnable = FALSE; - BlendStateDesc.IndependentBlendEnable = FALSE; - BlendStateDesc.RenderTarget[0].BlendEnable = TRUE; - BlendStateDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; - BlendStateDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; - BlendStateDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; - BlendStateDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; - BlendStateDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; - BlendStateDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; - BlendStateDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; - hr = m_Device->CreateBlendState(&BlendStateDesc, &m_BlendState); - if (FAILED(hr)) - { - return ProcessFailure(m_Device, L"Failed to create blend state in OUTPUTMANAGER", L"Error", hr, SystemTransitionsExpectedErrors); - } - - // Initialize shaders - Return = InitShaders(); - if (Return != DUPL_RETURN_SUCCESS) - { - return Return; - } - - GetWindowRect(m_WindowHandle, &WindowRect); - MoveWindow(m_WindowHandle, WindowRect.left, WindowRect.top, (DeskBounds->right - DeskBounds->left) / 2, (DeskBounds->bottom - DeskBounds->top) / 2, TRUE); - } + if (m_WindowHandle) { + // Create the blend state + D3D11_BLEND_DESC BlendStateDesc; + BlendStateDesc.AlphaToCoverageEnable = FALSE; + BlendStateDesc.IndependentBlendEnable = FALSE; + BlendStateDesc.RenderTarget[0].BlendEnable = TRUE; + BlendStateDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; + BlendStateDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; + BlendStateDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; + BlendStateDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; + BlendStateDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; + BlendStateDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; + BlendStateDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; + hr = m_Device->CreateBlendState(&BlendStateDesc, &m_BlendState); + if (FAILED(hr)) { + return ProcessFailure(m_Device, L"Failed to create blend state in OUTPUTMANAGER", L"Error", hr, SystemTransitionsExpectedErrors); + } + + // Initialize shaders + Return = InitShaders(); + if (Return != DUPL_RETURN_SUCCESS) { + return Return; + } + + GetWindowRect(m_WindowHandle, &WindowRect); + MoveWindow(m_WindowHandle, WindowRect.left, WindowRect.top, (DeskBounds->right - DeskBounds->left) / 2, (DeskBounds->bottom - DeskBounds->top) / 2, TRUE); + } return Return; } @@ -240,8 +220,7 @@ DUPL_RETURN OUTPUTMANAGER::CreateSharedSurf(INT SingleOutput, _Out_ UINT* OutCou // Get DXGI resources IDXGIDevice* DxgiDevice = nullptr; hr = m_Device->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&DxgiDevice)); - if (FAILED(hr)) - { + if (FAILED(hr)) { return ProcessFailure(nullptr, L"Failed to QI for DXGI Device", L"Error", hr); } @@ -249,8 +228,7 @@ DUPL_RETURN OUTPUTMANAGER::CreateSharedSurf(INT SingleOutput, _Out_ UINT* OutCou hr = DxgiDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void**>(&DxgiAdapter)); DxgiDevice->Release(); DxgiDevice = nullptr; - if (FAILED(hr)) - { + if (FAILED(hr)) { return ProcessFailure(m_Device, L"Failed to get parent DXGI Adapter", L"Error", hr, SystemTransitionsExpectedErrors); } @@ -264,19 +242,15 @@ DUPL_RETURN OUTPUTMANAGER::CreateSharedSurf(INT SingleOutput, _Out_ UINT* OutCou // Figure out right dimensions for full size desktop texture and # of outputs to duplicate UINT OutputCount; - if (SingleOutput < 0) - { + if (SingleOutput < 0) { hr = S_OK; - for (OutputCount = 0; SUCCEEDED(hr); ++OutputCount) - { - if (DxgiOutput) - { + for (OutputCount = 0; SUCCEEDED(hr); ++OutputCount) { + if (DxgiOutput) { DxgiOutput->Release(); DxgiOutput = nullptr; } hr = DxgiAdapter->EnumOutputs(OutputCount, &DxgiOutput); - if (DxgiOutput && (hr != DXGI_ERROR_NOT_FOUND)) - { + if (DxgiOutput && (hr != DXGI_ERROR_NOT_FOUND)) { DXGI_OUTPUT_DESC DesktopDesc; DxgiOutput->GetDesc(&DesktopDesc); @@ -289,11 +263,9 @@ DUPL_RETURN OUTPUTMANAGER::CreateSharedSurf(INT SingleOutput, _Out_ UINT* OutCou --OutputCount; } - else - { + else { hr = DxgiAdapter->EnumOutputs(SingleOutput, &DxgiOutput); - if (FAILED(hr)) - { + if (FAILED(hr)) { DxgiAdapter->Release(); DxgiAdapter = nullptr; return ProcessFailure(m_Device, L"Output specified to be duplicated does not exist", L"Error", hr); @@ -314,8 +286,7 @@ DUPL_RETURN OUTPUTMANAGER::CreateSharedSurf(INT SingleOutput, _Out_ UINT* OutCou // Set passed in output count variable *OutCount = OutputCount; - if (OutputCount == 0) - { + if (OutputCount == 0) { // We could not find any outputs, the system must be in a transition so return expected error // so we will attempt to recreate return DUPL_RETURN_ERROR_EXPECTED; @@ -336,10 +307,8 @@ DUPL_RETURN OUTPUTMANAGER::CreateSharedSurf(INT SingleOutput, _Out_ UINT* OutCou DeskTexD.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX; hr = m_Device->CreateTexture2D(&DeskTexD, nullptr, &m_SharedSurf); - if (FAILED(hr)) - { - if (OutputCount != 1) - { + if (FAILED(hr)) { + if (OutputCount != 1) { // If we are duplicating the complete desktop we try to create a single texture to hold the // complete desktop image and blit updates from the per output DDA interface. The GPU can // always support a texture size of the maximum resolution of any single output but there is no @@ -348,16 +317,14 @@ DUPL_RETURN OUTPUTMANAGER::CreateSharedSurf(INT SingleOutput, _Out_ UINT* OutCou // we could revert back to using GDI to update the window in this failure case. return ProcessFailure(m_Device, L"Failed to create DirectX shared texture - we are attempting to create a texture the size of the complete desktop and this may be larger than the maximum texture size of your GPU. Please try again using the -output command line parameter to duplicate only 1 monitor or configure your computer to a single monitor configuration", L"Error", hr, SystemTransitionsExpectedErrors); } - else - { + else { return ProcessFailure(m_Device, L"Failed to create shared texture", L"Error", hr, SystemTransitionsExpectedErrors); } } // Get keyed mutex hr = m_SharedSurf->QueryInterface(__uuidof(IDXGIKeyedMutex), reinterpret_cast<void**>(&m_KeyMutex)); - if (FAILED(hr)) - { + if (FAILED(hr)) { return ProcessFailure(m_Device, L"Failed to query for keyed mutex in OUTPUTMANAGER", L"Error", hr); } @@ -376,23 +343,19 @@ DUPL_RETURN OUTPUTMANAGER::UpdateApplicationWindow(_In_ PTR_INFO* PointerInfo, _ // Try and acquire sync on common display buffer HRESULT hr = m_KeyMutex->AcquireSync(1, 100); - if (hr == static_cast<HRESULT>(WAIT_TIMEOUT)) - { + if (hr == static_cast<HRESULT>(WAIT_TIMEOUT)) { // Another thread has the keyed mutex so try again later return DUPL_RETURN_SUCCESS; } - else if (FAILED(hr)) - { + else if (FAILED(hr)) { return ProcessFailure(m_Device, L"Failed to acquire Keyed mutex in OUTPUTMANAGER", L"Error", hr, SystemTransitionsExpectedErrors); } // Got mutex, so draw DUPL_RETURN Ret = DrawFrame(); - if (Ret == DUPL_RETURN_SUCCESS) - { + if (Ret == DUPL_RETURN_SUCCESS) { // We have keyed mutex so we can access the mouse info - if (PointerInfo->Visible) - { + if (PointerInfo->Visible) { // Draw mouse into texture Ret = DrawMouse(PointerInfo); } @@ -400,27 +363,22 @@ DUPL_RETURN OUTPUTMANAGER::UpdateApplicationWindow(_In_ PTR_INFO* PointerInfo, _ // Release keyed mutex hr = m_KeyMutex->ReleaseSync(0); - if (FAILED(hr)) - { + if (FAILED(hr)) { return ProcessFailure(m_Device, L"Failed to Release Keyed mutex in OUTPUTMANAGER", L"Error", hr, SystemTransitionsExpectedErrors); } // Present to window if all worked - if (Ret == DUPL_RETURN_SUCCESS) - { + if (Ret == DUPL_RETURN_SUCCESS) { // Present to window - if (m_SwapChain) - { - hr = m_SwapChain->Present(1, 0); - if (FAILED(hr)) - { - return ProcessFailure(m_Device, L"Failed to present", L"Error", hr, SystemTransitionsExpectedErrors); - } - else if (hr == DXGI_STATUS_OCCLUDED) - { - *Occluded = true; - } - } + if (m_SwapChain) { + hr = m_SwapChain->Present(1, 0); + if (FAILED(hr)) { + return ProcessFailure(m_Device, L"Failed to present", L"Error", hr, SystemTransitionsExpectedErrors); + } + else if (hr == DXGI_STATUS_OCCLUDED) { + *Occluded = true; + } + } } return Ret; @@ -436,8 +394,7 @@ HANDLE OUTPUTMANAGER::GetSharedHandle() // QI IDXGIResource interface to synchronized shared surface. IDXGIResource* DXGIResource = nullptr; HRESULT hr = m_SharedSurf->QueryInterface(__uuidof(IDXGIResource), reinterpret_cast<void**>(&DXGIResource)); - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { // Obtain handle to IDXGIResource object. DXGIResource->GetSharedHandle(&Hnd); DXGIResource->Release(); @@ -455,19 +412,16 @@ DUPL_RETURN OUTPUTMANAGER::DrawFrame() HRESULT hr; // If window was resized, resize swapchain - if (m_NeedsResize) - { + if (m_NeedsResize) { DUPL_RETURN Ret = ResizeSwapChain(); - if (Ret != DUPL_RETURN_SUCCESS) - { + if (Ret != DUPL_RETURN_SUCCESS) { return Ret; } m_NeedsResize = false; } // Vertices for drawing whole texture - VERTEX Vertices[NUMVERTICES] = - { + VERTEX Vertices[NUMVERTICES] = { {XMFLOAT3(-1.0f, -1.0f, 0), XMFLOAT2(0.0f, 1.0f)}, {XMFLOAT3(-1.0f, 1.0f, 0), XMFLOAT2(0.0f, 0.0f)}, {XMFLOAT3(1.0f, -1.0f, 0), XMFLOAT2(1.0f, 1.0f)}, @@ -488,8 +442,7 @@ DUPL_RETURN OUTPUTMANAGER::DrawFrame() // Create new shader resource view ID3D11ShaderResourceView* ShaderResource = nullptr; hr = m_Device->CreateShaderResourceView(m_SharedSurf, &ShaderDesc, &ShaderResource); - if (FAILED(hr)) - { + if (FAILED(hr)) { return ProcessFailure(m_Device, L"Failed to create shader resource when drawing a frame", L"Error", hr, SystemTransitionsExpectedErrors); } @@ -519,8 +472,7 @@ DUPL_RETURN OUTPUTMANAGER::DrawFrame() // Create vertex buffer hr = m_Device->CreateBuffer(&BufferDesc, &InitData, &VertexBuffer); - if (FAILED(hr)) - { + if (FAILED(hr)) { ShaderResource->Release(); ShaderResource = nullptr; return ProcessFailure(m_Device, L"Failed to create vertex buffer when drawing a frame", L"Error", hr, SystemTransitionsExpectedErrors); @@ -543,7 +495,7 @@ DUPL_RETURN OUTPUTMANAGER::DrawFrame() // // Process both masked and monochrome pointers // -DUPL_RETURN OUTPUTMANAGER::ProcessMonoMask(bool IsMono, _Inout_ PTR_INFO* PtrInfo, _Out_ INT* PtrWidth, _Out_ INT* PtrHeight, _Out_ INT* PtrLeft, _Out_ INT* PtrTop, _Outptr_result_bytebuffer_(*PtrHeight * *PtrWidth * BPP) BYTE** InitBuffer, _Out_ D3D11_BOX* Box) +DUPL_RETURN OUTPUTMANAGER::ProcessMonoMask(bool IsMono, _Inout_ PTR_INFO* PtrInfo, _Out_ INT* PtrWidth, _Out_ INT* PtrHeight, _Out_ INT* PtrLeft, _Out_ INT* PtrTop, _Outptr_result_bytebuffer_(*PtrHeight **PtrWidth * BPP) BYTE** InitBuffer, _Out_ D3D11_BOX* Box) { // Desktop dimensions D3D11_TEXTURE2D_DESC FullDesc; @@ -556,39 +508,31 @@ DUPL_RETURN OUTPUTMANAGER::ProcessMonoMask(bool IsMono, _Inout_ PTR_INFO* PtrInf INT GivenTop = PtrInfo->Position.y; // Figure out if any adjustment is needed for out of bound positions - if (GivenLeft < 0) - { + if (GivenLeft < 0) { *PtrWidth = GivenLeft + static_cast<INT>(PtrInfo->ShapeInfo.Width); } - else if ((GivenLeft + static_cast<INT>(PtrInfo->ShapeInfo.Width)) > DesktopWidth) - { + else if ((GivenLeft + static_cast<INT>(PtrInfo->ShapeInfo.Width)) > DesktopWidth) { *PtrWidth = DesktopWidth - GivenLeft; } - else - { + else { *PtrWidth = static_cast<INT>(PtrInfo->ShapeInfo.Width); } - if (IsMono) - { + if (IsMono) { PtrInfo->ShapeInfo.Height = PtrInfo->ShapeInfo.Height / 2; } - if (GivenTop < 0) - { + if (GivenTop < 0) { *PtrHeight = GivenTop + static_cast<INT>(PtrInfo->ShapeInfo.Height); } - else if ((GivenTop + static_cast<INT>(PtrInfo->ShapeInfo.Height)) > DesktopHeight) - { + else if ((GivenTop + static_cast<INT>(PtrInfo->ShapeInfo.Height)) > DesktopHeight) { *PtrHeight = DesktopHeight - GivenTop; } - else - { + else { *PtrHeight = static_cast<INT>(PtrInfo->ShapeInfo.Height); } - if (IsMono) - { + if (IsMono) { PtrInfo->ShapeInfo.Height = PtrInfo->ShapeInfo.Height * 2; } @@ -611,8 +555,7 @@ DUPL_RETURN OUTPUTMANAGER::ProcessMonoMask(bool IsMono, _Inout_ PTR_INFO* PtrInf ID3D11Texture2D* CopyBuffer = nullptr; HRESULT hr = m_Device->CreateTexture2D(&CopyBufferDesc, nullptr, &CopyBuffer); - if (FAILED(hr)) - { + if (FAILED(hr)) { return ProcessFailure(m_Device, L"Failed creating staging texture for pointer", L"Error", hr, SystemTransitionsExpectedErrors); } @@ -628,25 +571,22 @@ DUPL_RETURN OUTPUTMANAGER::ProcessMonoMask(bool IsMono, _Inout_ PTR_INFO* PtrInf hr = CopyBuffer->QueryInterface(__uuidof(IDXGISurface), (void **)&CopySurface); CopyBuffer->Release(); CopyBuffer = nullptr; - if (FAILED(hr)) - { + if (FAILED(hr)) { return ProcessFailure(nullptr, L"Failed to QI staging texture into IDXGISurface for pointer", L"Error", hr, SystemTransitionsExpectedErrors); } // Map pixels DXGI_MAPPED_RECT MappedSurface; hr = CopySurface->Map(&MappedSurface, DXGI_MAP_READ); - if (FAILED(hr)) - { + if (FAILED(hr)) { CopySurface->Release(); CopySurface = nullptr; return ProcessFailure(m_Device, L"Failed to map surface for pointer", L"Error", hr, SystemTransitionsExpectedErrors); } // New mouseshape buffer - *InitBuffer = new (std::nothrow) BYTE[*PtrWidth * *PtrHeight * BPP]; - if (!(*InitBuffer)) - { + *InitBuffer = new (std::nothrow) BYTE[*PtrWidth **PtrHeight * BPP]; + if (!(*InitBuffer)) { return ProcessFailure(nullptr, L"Failed to allocate memory for new mouse shape buffer.", L"Error", E_OUTOFMEMORY); } @@ -658,15 +598,12 @@ DUPL_RETURN OUTPUTMANAGER::ProcessMonoMask(bool IsMono, _Inout_ PTR_INFO* PtrInf UINT SkipX = (GivenLeft < 0) ? (-1 * GivenLeft) : (0); UINT SkipY = (GivenTop < 0) ? (-1 * GivenTop) : (0); - if (IsMono) - { - for (INT Row = 0; Row < *PtrHeight; ++Row) - { + if (IsMono) { + for (INT Row = 0; Row < *PtrHeight; ++Row) { // Set mask BYTE Mask = 0x80; Mask = Mask >> (SkipX % 8); - for (INT Col = 0; Col < *PtrWidth; ++Col) - { + for (INT Col = 0; Col < *PtrWidth; ++Col) { // Get masks using appropriate offsets BYTE AndMask = PtrInfo->PtrShapeBuffer[((Col + SkipX) / 8) + ((Row + SkipY) * (PtrInfo->ShapeInfo.Pitch))] & Mask; BYTE XorMask = PtrInfo->PtrShapeBuffer[((Col + SkipX) / 8) + ((Row + SkipY + (PtrInfo->ShapeInfo.Height / 2)) * (PtrInfo->ShapeInfo.Pitch))] & Mask; @@ -674,40 +611,33 @@ DUPL_RETURN OUTPUTMANAGER::ProcessMonoMask(bool IsMono, _Inout_ PTR_INFO* PtrInf UINT XorMask32 = (XorMask) ? 0x00FFFFFF : 0x00000000; // Set new pixel - InitBuffer32[(Row * *PtrWidth) + Col] = (Desktop32[(Row * DesktopPitchInPixels) + Col] & AndMask32) ^ XorMask32; + InitBuffer32[(Row **PtrWidth) + Col] = (Desktop32[(Row * DesktopPitchInPixels) + Col] & AndMask32) ^ XorMask32; // Adjust mask - if (Mask == 0x01) - { + if (Mask == 0x01) { Mask = 0x80; } - else - { + else { Mask = Mask >> 1; } } } } - else - { + else { UINT* Buffer32 = reinterpret_cast<UINT*>(PtrInfo->PtrShapeBuffer); // Iterate through pixels - for (INT Row = 0; Row < *PtrHeight; ++Row) - { - for (INT Col = 0; Col < *PtrWidth; ++Col) - { + for (INT Row = 0; Row < *PtrHeight; ++Row) { + for (INT Col = 0; Col < *PtrWidth; ++Col) { // Set up mask UINT MaskVal = 0xFF000000 & Buffer32[(Col + SkipX) + ((Row + SkipY) * (PtrInfo->ShapeInfo.Pitch / sizeof(UINT)))]; - if (MaskVal) - { + if (MaskVal) { // Mask was 0xFF - InitBuffer32[(Row * *PtrWidth) + Col] = (Desktop32[(Row * DesktopPitchInPixels) + Col] ^ Buffer32[(Col + SkipX) + ((Row + SkipY) * (PtrInfo->ShapeInfo.Pitch / sizeof(UINT)))]) | 0xFF000000; + InitBuffer32[(Row **PtrWidth) + Col] = (Desktop32[(Row * DesktopPitchInPixels) + Col] ^ Buffer32[(Col + SkipX) + ((Row + SkipY) * (PtrInfo->ShapeInfo.Pitch / sizeof(UINT)))]) | 0xFF000000; } - else - { + else { // Mask was 0x00 - InitBuffer32[(Row * *PtrWidth) + Col] = Buffer32[(Col + SkipX) + ((Row + SkipY) * (PtrInfo->ShapeInfo.Pitch / sizeof(UINT)))] | 0xFF000000; + InitBuffer32[(Row **PtrWidth) + Col] = Buffer32[(Col + SkipX) + ((Row + SkipY) * (PtrInfo->ShapeInfo.Pitch / sizeof(UINT)))] | 0xFF000000; } } } @@ -717,8 +647,7 @@ DUPL_RETURN OUTPUTMANAGER::ProcessMonoMask(bool IsMono, _Inout_ PTR_INFO* PtrInf hr = CopySurface->Unmap(); CopySurface->Release(); CopySurface = nullptr; - if (FAILED(hr)) - { + if (FAILED(hr)) { return ProcessFailure(m_Device, L"Failed to unmap surface for pointer", L"Error", hr, SystemTransitionsExpectedErrors); } @@ -739,8 +668,7 @@ DUPL_RETURN OUTPUTMANAGER::DrawMouse(_In_ PTR_INFO* PtrInfo) D3D11_SHADER_RESOURCE_VIEW_DESC SDesc; // Position will be changed based on mouse position - VERTEX Vertices[NUMVERTICES] = - { + VERTEX Vertices[NUMVERTICES] = { {XMFLOAT3(-1.0f, -1.0f, 0), XMFLOAT2(0.0f, 1.0f)}, {XMFLOAT3(-1.0f, 1.0f, 0), XMFLOAT2(0.0f, 0.0f)}, {XMFLOAT3(1.0f, -1.0f, 0), XMFLOAT2(1.0f, 1.0f)}, @@ -788,33 +716,29 @@ DUPL_RETURN OUTPUTMANAGER::DrawMouse(_In_ PTR_INFO* PtrInfo) SDesc.Texture2D.MostDetailedMip = Desc.MipLevels - 1; SDesc.Texture2D.MipLevels = Desc.MipLevels; - switch (PtrInfo->ShapeInfo.Type) - { - case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_COLOR: - { - PtrLeft = PtrInfo->Position.x; - PtrTop = PtrInfo->Position.y; + switch (PtrInfo->ShapeInfo.Type) { + case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_COLOR: { + PtrLeft = PtrInfo->Position.x; + PtrTop = PtrInfo->Position.y; - PtrWidth = static_cast<INT>(PtrInfo->ShapeInfo.Width); - PtrHeight = static_cast<INT>(PtrInfo->ShapeInfo.Height); + PtrWidth = static_cast<INT>(PtrInfo->ShapeInfo.Width); + PtrHeight = static_cast<INT>(PtrInfo->ShapeInfo.Height); - break; - } + break; + } - case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MONOCHROME: - { - ProcessMonoMask(true, PtrInfo, &PtrWidth, &PtrHeight, &PtrLeft, &PtrTop, &InitBuffer, &Box); - break; - } + case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MONOCHROME: { + ProcessMonoMask(true, PtrInfo, &PtrWidth, &PtrHeight, &PtrLeft, &PtrTop, &InitBuffer, &Box); + break; + } - case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MASKED_COLOR: - { - ProcessMonoMask(false, PtrInfo, &PtrWidth, &PtrHeight, &PtrLeft, &PtrTop, &InitBuffer, &Box); - break; - } + case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MASKED_COLOR: { + ProcessMonoMask(false, PtrInfo, &PtrWidth, &PtrHeight, &PtrLeft, &PtrTop, &InitBuffer, &Box); + break; + } - default: - break; + default: + break; } // VERTEX creation @@ -842,15 +766,13 @@ DUPL_RETURN OUTPUTMANAGER::DrawMouse(_In_ PTR_INFO* PtrInfo) // Create mouseshape as texture HRESULT hr = m_Device->CreateTexture2D(&Desc, &InitData, &MouseTex); - if (FAILED(hr)) - { + if (FAILED(hr)) { return ProcessFailure(m_Device, L"Failed to create mouse pointer texture", L"Error", hr, SystemTransitionsExpectedErrors); } // Create shader resource from texture hr = m_Device->CreateShaderResourceView(MouseTex, &SDesc, &ShaderRes); - if (FAILED(hr)) - { + if (FAILED(hr)) { MouseTex->Release(); MouseTex = nullptr; return ProcessFailure(m_Device, L"Failed to create shader resource from mouse pointer texture", L"Error", hr, SystemTransitionsExpectedErrors); @@ -868,8 +790,7 @@ DUPL_RETURN OUTPUTMANAGER::DrawMouse(_In_ PTR_INFO* PtrInfo) // Create vertex buffer hr = m_Device->CreateBuffer(&BDesc, &InitData, &VertexBufferMouse); - if (FAILED(hr)) - { + if (FAILED(hr)) { ShaderRes->Release(); ShaderRes = nullptr; MouseTex->Release(); @@ -893,23 +814,19 @@ DUPL_RETURN OUTPUTMANAGER::DrawMouse(_In_ PTR_INFO* PtrInfo) m_DeviceContext->Draw(NUMVERTICES, 0); // Clean - if (VertexBufferMouse) - { + if (VertexBufferMouse) { VertexBufferMouse->Release(); VertexBufferMouse = nullptr; } - if (ShaderRes) - { + if (ShaderRes) { ShaderRes->Release(); ShaderRes = nullptr; } - if (MouseTex) - { + if (MouseTex) { MouseTex->Release(); MouseTex = nullptr; } - if (InitBuffer) - { + if (InitBuffer) { delete [] InitBuffer; InitBuffer = nullptr; } @@ -926,28 +843,24 @@ DUPL_RETURN OUTPUTMANAGER::InitShaders() UINT Size = ARRAYSIZE(g_VS); hr = m_Device->CreateVertexShader(g_VS, Size, nullptr, &m_VertexShader); - if (FAILED(hr)) - { + if (FAILED(hr)) { return ProcessFailure(m_Device, L"Failed to create vertex shader in OUTPUTMANAGER", L"Error", hr, SystemTransitionsExpectedErrors); } - D3D11_INPUT_ELEMENT_DESC Layout[] = - { + D3D11_INPUT_ELEMENT_DESC Layout[] = { {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0} }; UINT NumElements = ARRAYSIZE(Layout); hr = m_Device->CreateInputLayout(Layout, NumElements, g_VS, Size, &m_InputLayout); - if (FAILED(hr)) - { + if (FAILED(hr)) { return ProcessFailure(m_Device, L"Failed to create input layout in OUTPUTMANAGER", L"Error", hr, SystemTransitionsExpectedErrors); } m_DeviceContext->IASetInputLayout(m_InputLayout); Size = ARRAYSIZE(g_PS); hr = m_Device->CreatePixelShader(g_PS, Size, nullptr, &m_PixelShader); - if (FAILED(hr)) - { + if (FAILED(hr)) { return ProcessFailure(m_Device, L"Failed to create pixel shader in OUTPUTMANAGER", L"Error", hr, SystemTransitionsExpectedErrors); } @@ -962,16 +875,14 @@ DUPL_RETURN OUTPUTMANAGER::MakeRTV() // Get backbuffer ID3D11Texture2D* BackBuffer = nullptr; HRESULT hr = m_SwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&BackBuffer)); - if (FAILED(hr)) - { + if (FAILED(hr)) { return ProcessFailure(m_Device, L"Failed to get backbuffer for making render target view in OUTPUTMANAGER", L"Error", hr, SystemTransitionsExpectedErrors); } // Create a render target view hr = m_Device->CreateRenderTargetView(BackBuffer, nullptr, &m_RTV); BackBuffer->Release(); - if (FAILED(hr)) - { + if (FAILED(hr)) { return ProcessFailure(m_Device, L"Failed to create render target view in OUTPUTMANAGER", L"Error", hr, SystemTransitionsExpectedErrors); } @@ -1001,8 +912,7 @@ void OUTPUTMANAGER::SetViewPort(UINT Width, UINT Height) // DUPL_RETURN OUTPUTMANAGER::ResizeSwapChain() { - if (m_RTV) - { + if (m_RTV) { m_RTV->Release(); m_RTV = nullptr; } @@ -1016,15 +926,13 @@ DUPL_RETURN OUTPUTMANAGER::ResizeSwapChain() DXGI_SWAP_CHAIN_DESC SwapChainDesc; m_SwapChain->GetDesc(&SwapChainDesc); HRESULT hr = m_SwapChain->ResizeBuffers(SwapChainDesc.BufferCount, Width, Height, SwapChainDesc.BufferDesc.Format, SwapChainDesc.Flags); - if (FAILED(hr)) - { + if (FAILED(hr)) { return ProcessFailure(m_Device, L"Failed to resize swapchain buffers in OUTPUTMANAGER", L"Error", hr, SystemTransitionsExpectedErrors); } // Make new render target view DUPL_RETURN Ret = MakeRTV(); - if (Ret != DUPL_RETURN_SUCCESS) - { + if (Ret != DUPL_RETURN_SUCCESS) { return Ret; } @@ -1039,76 +947,63 @@ DUPL_RETURN OUTPUTMANAGER::ResizeSwapChain() // void OUTPUTMANAGER::CleanRefs() { - if (m_VertexShader) - { + if (m_VertexShader) { m_VertexShader->Release(); m_VertexShader = nullptr; } - if (m_PixelShader) - { + if (m_PixelShader) { m_PixelShader->Release(); m_PixelShader = nullptr; } - if (m_InputLayout) - { + if (m_InputLayout) { m_InputLayout->Release(); m_InputLayout = nullptr; } - if (m_RTV) - { + if (m_RTV) { m_RTV->Release(); m_RTV = nullptr; } - if (m_SamplerLinear) - { + if (m_SamplerLinear) { m_SamplerLinear->Release(); m_SamplerLinear = nullptr; } - if (m_BlendState) - { + if (m_BlendState) { m_BlendState->Release(); m_BlendState = nullptr; } - if (m_DeviceContext) - { + if (m_DeviceContext) { m_DeviceContext->Release(); m_DeviceContext = nullptr; } - if (m_Device) - { + if (m_Device) { m_Device->Release(); m_Device = nullptr; } - if (m_SwapChain) - { + if (m_SwapChain) { m_SwapChain->Release(); m_SwapChain = nullptr; } - if (m_SharedSurf) - { + if (m_SharedSurf) { m_SharedSurf->Release(); m_SharedSurf = nullptr; } - if (m_KeyMutex) - { + if (m_KeyMutex) { m_KeyMutex->Release(); m_KeyMutex = nullptr; } - if (m_Factory) - { - if (m_OcclusionCookie) - { + if (m_Factory) { + if (m_OcclusionCookie) { m_Factory->UnregisterOcclusionStatus(m_OcclusionCookie); m_OcclusionCookie = 0; } diff --git a/plugins/pluginWinDD/internals/OutputManager.h b/plugins/pluginWinDD/internals/OutputManager.h index cd16e5f..fa1902a 100755 --- a/plugins/pluginWinDD/internals/OutputManager.h +++ b/plugins/pluginWinDD/internals/OutputManager.h @@ -19,43 +19,43 @@ // class OUTPUTMANAGER { - public: - OUTPUTMANAGER(); - ~OUTPUTMANAGER(); - DUPL_RETURN InitOutput(HWND Window, INT SingleOutput, _Out_ UINT* OutCount, _Out_ RECT* DeskBounds); - DUPL_RETURN UpdateApplicationWindow(_In_ PTR_INFO* PointerInfo, _Inout_ bool* Occluded); - void CleanRefs(); - HANDLE GetSharedHandle(); - void WindowResize(); +public: + OUTPUTMANAGER(); + ~OUTPUTMANAGER(); + DUPL_RETURN InitOutput(HWND Window, INT SingleOutput, _Out_ UINT* OutCount, _Out_ RECT* DeskBounds); + DUPL_RETURN UpdateApplicationWindow(_In_ PTR_INFO* PointerInfo, _Inout_ bool* Occluded); + void CleanRefs(); + HANDLE GetSharedHandle(); + void WindowResize(); - private: +private: // Methods - DUPL_RETURN ProcessMonoMask(bool IsMono, _Inout_ PTR_INFO* PtrInfo, _Out_ INT* PtrWidth, _Out_ INT* PtrHeight, _Out_ INT* PtrLeft, _Out_ INT* PtrTop, _Outptr_result_bytebuffer_(*PtrHeight * *PtrWidth * BPP) BYTE** InitBuffer, _Out_ D3D11_BOX* Box); - DUPL_RETURN MakeRTV(); - void SetViewPort(UINT Width, UINT Height); - DUPL_RETURN InitShaders(); - DUPL_RETURN InitGeometry(); - DUPL_RETURN CreateSharedSurf(INT SingleOutput, _Out_ UINT* OutCount, _Out_ RECT* DeskBounds); - DUPL_RETURN DrawFrame(); - DUPL_RETURN DrawMouse(_In_ PTR_INFO* PtrInfo); - DUPL_RETURN ResizeSwapChain(); + DUPL_RETURN ProcessMonoMask(bool IsMono, _Inout_ PTR_INFO* PtrInfo, _Out_ INT* PtrWidth, _Out_ INT* PtrHeight, _Out_ INT* PtrLeft, _Out_ INT* PtrTop, _Outptr_result_bytebuffer_(*PtrHeight **PtrWidth * BPP) BYTE** InitBuffer, _Out_ D3D11_BOX* Box); + DUPL_RETURN MakeRTV(); + void SetViewPort(UINT Width, UINT Height); + DUPL_RETURN InitShaders(); + DUPL_RETURN InitGeometry(); + DUPL_RETURN CreateSharedSurf(INT SingleOutput, _Out_ UINT* OutCount, _Out_ RECT* DeskBounds); + DUPL_RETURN DrawFrame(); + DUPL_RETURN DrawMouse(_In_ PTR_INFO* PtrInfo); + DUPL_RETURN ResizeSwapChain(); // Vars - IDXGISwapChain1* m_SwapChain; - ID3D11Device* m_Device; - IDXGIFactory2* m_Factory; - ID3D11DeviceContext* m_DeviceContext; - ID3D11RenderTargetView* m_RTV; - ID3D11SamplerState* m_SamplerLinear; - ID3D11BlendState* m_BlendState; - ID3D11VertexShader* m_VertexShader; - ID3D11PixelShader* m_PixelShader; - ID3D11InputLayout* m_InputLayout; - ID3D11Texture2D* m_SharedSurf; - IDXGIKeyedMutex* m_KeyMutex; - HWND m_WindowHandle; - bool m_NeedsResize; - DWORD m_OcclusionCookie; + IDXGISwapChain1* m_SwapChain; + ID3D11Device* m_Device; + IDXGIFactory2* m_Factory; + ID3D11DeviceContext* m_DeviceContext; + ID3D11RenderTargetView* m_RTV; + ID3D11SamplerState* m_SamplerLinear; + ID3D11BlendState* m_BlendState; + ID3D11VertexShader* m_VertexShader; + ID3D11PixelShader* m_PixelShader; + ID3D11InputLayout* m_InputLayout; + ID3D11Texture2D* m_SharedSurf; + IDXGIKeyedMutex* m_KeyMutex; + HWND m_WindowHandle; + bool m_NeedsResize; + DWORD m_OcclusionCookie; }; #endif diff --git a/plugins/pluginWinDD/internals/ThreadManager.cxx b/plugins/pluginWinDD/internals/ThreadManager.cxx index 68fe757..fcae447 100755 --- a/plugins/pluginWinDD/internals/ThreadManager.cxx +++ b/plugins/pluginWinDD/internals/ThreadManager.cxx @@ -10,8 +10,8 @@ DWORD WINAPI DDProc(_In_ void* Param); THREADMANAGER::THREADMANAGER() : m_ThreadCount(0), - m_ThreadHandles(nullptr), - m_ThreadData(nullptr) + m_ThreadHandles(nullptr), + m_ThreadData(nullptr) { RtlZeroMemory(&m_PtrInfo, sizeof(m_PtrInfo)); } @@ -26,19 +26,15 @@ THREADMANAGER::~THREADMANAGER() // void THREADMANAGER::Clean() { - if (m_PtrInfo.PtrShapeBuffer) - { + if (m_PtrInfo.PtrShapeBuffer) { delete [] m_PtrInfo.PtrShapeBuffer; m_PtrInfo.PtrShapeBuffer = nullptr; } RtlZeroMemory(&m_PtrInfo, sizeof(m_PtrInfo)); - if (m_ThreadHandles) - { - for (UINT i = 0; i < m_ThreadCount; ++i) - { - if (m_ThreadHandles[i]) - { + if (m_ThreadHandles) { + for (UINT i = 0; i < m_ThreadCount; ++i) { + if (m_ThreadHandles[i]) { CloseHandle(m_ThreadHandles[i]); } } @@ -46,10 +42,8 @@ void THREADMANAGER::Clean() m_ThreadHandles = nullptr; } - if (m_ThreadData) - { - for (UINT i = 0; i < m_ThreadCount; ++i) - { + if (m_ThreadData) { + for (UINT i = 0; i < m_ThreadCount; ++i) { CleanDx(&m_ThreadData[i].DxRes); } delete [] m_ThreadData; @@ -64,38 +58,32 @@ void THREADMANAGER::Clean() // void THREADMANAGER::CleanDx(_Inout_ DX_RESOURCES* Data) { - if (Data->Device) - { + if (Data->Device) { Data->Device->Release(); Data->Device = nullptr; } - if (Data->Context) - { + if (Data->Context) { Data->Context->Release(); Data->Context = nullptr; } - if (Data->VertexShader) - { + if (Data->VertexShader) { Data->VertexShader->Release(); Data->VertexShader = nullptr; } - if (Data->PixelShader) - { + if (Data->PixelShader) { Data->PixelShader->Release(); Data->PixelShader = nullptr; } - if (Data->InputLayout) - { + if (Data->InputLayout) { Data->InputLayout->Release(); Data->InputLayout = nullptr; } - if (Data->SamplerLinear) - { + if (Data->SamplerLinear) { Data->SamplerLinear->Release(); Data->SamplerLinear = nullptr; } @@ -109,15 +97,13 @@ DUPL_RETURN THREADMANAGER::Initialize(INT SingleOutput, UINT OutputCount, HANDLE m_ThreadCount = OutputCount; m_ThreadHandles = new (std::nothrow) HANDLE[m_ThreadCount]; m_ThreadData = new (std::nothrow) THREAD_DATA[m_ThreadCount]; - if (!m_ThreadHandles || !m_ThreadData) - { + if (!m_ThreadHandles || !m_ThreadData) { return ProcessFailure(nullptr, L"Failed to allocate array for threads", L"Error", E_OUTOFMEMORY); } // Create appropriate # of threads for duplication DUPL_RETURN Ret = DUPL_RETURN_SUCCESS; - for (UINT i = 0; i < m_ThreadCount; ++i) - { + for (UINT i = 0; i < m_ThreadCount; ++i) { m_ThreadData[i].UnexpectedErrorEvent = UnexpectedErrorEvent; m_ThreadData[i].ExpectedErrorEvent = ExpectedErrorEvent; m_ThreadData[i].TerminateThreadsEvent = TerminateThreadsEvent; @@ -126,19 +112,17 @@ DUPL_RETURN THREADMANAGER::Initialize(INT SingleOutput, UINT OutputCount, HANDLE m_ThreadData[i].OffsetX = DesktopDim->left; m_ThreadData[i].OffsetY = DesktopDim->top; m_ThreadData[i].PtrInfo = &m_PtrInfo; - m_ThreadData[i].Producer = Producer; + m_ThreadData[i].Producer = Producer; RtlZeroMemory(&m_ThreadData[i].DxRes, sizeof(DX_RESOURCES)); Ret = InitializeDx(&m_ThreadData[i].DxRes); - if (Ret != DUPL_RETURN_SUCCESS) - { + if (Ret != DUPL_RETURN_SUCCESS) { return Ret; } DWORD ThreadId; m_ThreadHandles[i] = CreateThread(nullptr, 0, DDProc, &m_ThreadData[i], 0, &ThreadId); - if (m_ThreadHandles[i] == nullptr) - { + if (m_ThreadHandles[i] == nullptr) { return ProcessFailure(nullptr, L"Failed to create thread", L"Error", E_FAIL); } } @@ -154,8 +138,7 @@ DUPL_RETURN THREADMANAGER::InitializeDx(_Out_ DX_RESOURCES* Data) HRESULT hr = S_OK; // Driver types supported - D3D_DRIVER_TYPE DriverTypes[] = - { + D3D_DRIVER_TYPE DriverTypes[] = { D3D_DRIVER_TYPE_HARDWARE, D3D_DRIVER_TYPE_WARP, D3D_DRIVER_TYPE_REFERENCE, @@ -163,8 +146,7 @@ DUPL_RETURN THREADMANAGER::InitializeDx(_Out_ DX_RESOURCES* Data) UINT NumDriverTypes = ARRAYSIZE(DriverTypes); // Feature levels supported - D3D_FEATURE_LEVEL FeatureLevels[] = - { + D3D_FEATURE_LEVEL FeatureLevels[] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, @@ -175,39 +157,33 @@ DUPL_RETURN THREADMANAGER::InitializeDx(_Out_ DX_RESOURCES* Data) D3D_FEATURE_LEVEL FeatureLevel; // Create device - for (UINT DriverTypeIndex = 0; DriverTypeIndex < NumDriverTypes; ++DriverTypeIndex) - { + for (UINT DriverTypeIndex = 0; DriverTypeIndex < NumDriverTypes; ++DriverTypeIndex) { hr = D3D11CreateDevice(nullptr, DriverTypes[DriverTypeIndex], nullptr, 0, FeatureLevels, NumFeatureLevels, - D3D11_SDK_VERSION, &Data->Device, &FeatureLevel, &Data->Context); - if (SUCCEEDED(hr)) - { + D3D11_SDK_VERSION, &Data->Device, &FeatureLevel, &Data->Context); + if (SUCCEEDED(hr)) { // Device creation success, no need to loop anymore break; } } - if (FAILED(hr)) - { + if (FAILED(hr)) { return ProcessFailure(nullptr, L"Failed to create device in InitializeDx", L"Error", hr); } // VERTEX shader UINT Size = ARRAYSIZE(g_VS); hr = Data->Device->CreateVertexShader(g_VS, Size, nullptr, &Data->VertexShader); - if (FAILED(hr)) - { + if (FAILED(hr)) { return ProcessFailure(Data->Device, L"Failed to create vertex shader in InitializeDx", L"Error", hr, SystemTransitionsExpectedErrors); } // Input layout - D3D11_INPUT_ELEMENT_DESC Layout[] = - { + D3D11_INPUT_ELEMENT_DESC Layout[] = { {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0} }; UINT NumElements = ARRAYSIZE(Layout); hr = Data->Device->CreateInputLayout(Layout, NumElements, g_VS, Size, &Data->InputLayout); - if (FAILED(hr)) - { + if (FAILED(hr)) { return ProcessFailure(Data->Device, L"Failed to create input layout in InitializeDx", L"Error", hr, SystemTransitionsExpectedErrors); } Data->Context->IASetInputLayout(Data->InputLayout); @@ -215,8 +191,7 @@ DUPL_RETURN THREADMANAGER::InitializeDx(_Out_ DX_RESOURCES* Data) // Pixel shader Size = ARRAYSIZE(g_PS); hr = Data->Device->CreatePixelShader(g_PS, Size, nullptr, &Data->PixelShader); - if (FAILED(hr)) - { + if (FAILED(hr)) { return ProcessFailure(Data->Device, L"Failed to create pixel shader in InitializeDx", L"Error", hr, SystemTransitionsExpectedErrors); } @@ -231,8 +206,7 @@ DUPL_RETURN THREADMANAGER::InitializeDx(_Out_ DX_RESOURCES* Data) SampDesc.MinLOD = 0; SampDesc.MaxLOD = D3D11_FLOAT32_MAX; hr = Data->Device->CreateSamplerState(&SampDesc, &Data->SamplerLinear); - if (FAILED(hr)) - { + if (FAILED(hr)) { return ProcessFailure(Data->Device, L"Failed to create sampler state in InitializeDx", L"Error", hr, SystemTransitionsExpectedErrors); } @@ -252,10 +226,9 @@ PTR_INFO* THREADMANAGER::GetPointerInfo() // bool THREADMANAGER::WaitForThreadTermination(DWORD timeout /*= INFINITE*/) { - bool bRet = true; - if (m_ThreadCount != 0) - { - bRet = (WaitForMultipleObjectsEx(m_ThreadCount, m_ThreadHandles, TRUE, timeout, FALSE) != WAIT_TIMEOUT); + bool bRet = true; + if (m_ThreadCount != 0) { + bRet = (WaitForMultipleObjectsEx(m_ThreadCount, m_ThreadHandles, TRUE, timeout, FALSE) != WAIT_TIMEOUT); } - return bRet; + return bRet; } diff --git a/plugins/pluginWinDD/internals/ThreadManager.h b/plugins/pluginWinDD/internals/ThreadManager.h index d710998..2a9157f 100755 --- a/plugins/pluginWinDD/internals/ThreadManager.h +++ b/plugins/pluginWinDD/internals/ThreadManager.h @@ -12,22 +12,22 @@ class THREADMANAGER { - public: - THREADMANAGER(); - ~THREADMANAGER(); - void Clean(); - DUPL_RETURN Initialize(INT SingleOutput, UINT OutputCount, HANDLE UnexpectedErrorEvent, HANDLE ExpectedErrorEvent, HANDLE TerminateThreadsEvent, HANDLE SharedHandle, _In_ const struct tmedia_producer_s* Producer, _In_ RECT* DesktopDim); - PTR_INFO* GetPointerInfo(); - bool WaitForThreadTermination(DWORD timeout = INFINITE); +public: + THREADMANAGER(); + ~THREADMANAGER(); + void Clean(); + DUPL_RETURN Initialize(INT SingleOutput, UINT OutputCount, HANDLE UnexpectedErrorEvent, HANDLE ExpectedErrorEvent, HANDLE TerminateThreadsEvent, HANDLE SharedHandle, _In_ const struct tmedia_producer_s* Producer, _In_ RECT* DesktopDim); + PTR_INFO* GetPointerInfo(); + bool WaitForThreadTermination(DWORD timeout = INFINITE); - private: - DUPL_RETURN InitializeDx(_Out_ DX_RESOURCES* Data); - void CleanDx(_Inout_ DX_RESOURCES* Data); +private: + DUPL_RETURN InitializeDx(_Out_ DX_RESOURCES* Data); + void CleanDx(_Inout_ DX_RESOURCES* Data); - PTR_INFO m_PtrInfo; - UINT m_ThreadCount; - _Field_size_(m_ThreadCount) HANDLE* m_ThreadHandles; - _Field_size_(m_ThreadCount) THREAD_DATA* m_ThreadData; + PTR_INFO m_PtrInfo; + UINT m_ThreadCount; + _Field_size_(m_ThreadCount) HANDLE* m_ThreadHandles; + _Field_size_(m_ThreadCount) THREAD_DATA* m_ThreadData; }; #endif diff --git a/plugins/pluginWinDD/plugin_win_dd_config.h b/plugins/pluginWinDD/plugin_win_dd_config.h index a1d3855..70e6ce5 100755 --- a/plugins/pluginWinDD/plugin_win_dd_config.h +++ b/plugins/pluginWinDD/plugin_win_dd_config.h @@ -48,12 +48,12 @@ # define PLUGIN_WIN_DD_UNDER_X86 1 #endif -// Guards against C++ name mangling +// Guards against C++ name mangling #ifdef __cplusplus # define PLUGIN_WIN_DD_BEGIN_DECLS extern "C" { # define PLUGIN_WIN_DD_END_DECLS } #else -# define PLUGIN_WIN_DD_BEGIN_DECLS +# define PLUGIN_WIN_DD_BEGIN_DECLS # define PLUGIN_WIN_DD_END_DECLS #endif diff --git a/plugins/pluginWinDD/plugin_win_dd_producer.cxx b/plugins/pluginWinDD/plugin_win_dd_producer.cxx index 7c13767..01d857d 100755 --- a/plugins/pluginWinDD/plugin_win_dd_producer.cxx +++ b/plugins/pluginWinDD/plugin_win_dd_producer.cxx @@ -55,28 +55,27 @@ // // plugin_win_dd_producer_t // -typedef struct plugin_win_dd_producer_s -{ - TMEDIA_DECLARE_PRODUCER; - - bool bStarted, bPrepared, bMuted, bWindowHooked, bThreadTerminationDelayed; - tsk_thread_handle_t* ppTread[1]; - - OUTPUTMANAGER *pOutMgr; - THREADMANAGER *pThreadMgr; - - // Window handles - HWND hwndPreview; - WNDPROC wndPreviewProc; - HWND hwndSrc; - - // Synchronization - HANDLE hlUnexpectedErrorEvent; - HANDLE hlExpectedErrorEvent; - HANDLE hlOcclutionEvent; - HANDLE hlTerminateThreadsEvent; - - HCURSOR hcCursor; +typedef struct plugin_win_dd_producer_s { + TMEDIA_DECLARE_PRODUCER; + + bool bStarted, bPrepared, bMuted, bWindowHooked, bThreadTerminationDelayed; + tsk_thread_handle_t* ppTread[1]; + + OUTPUTMANAGER *pOutMgr; + THREADMANAGER *pThreadMgr; + + // Window handles + HWND hwndPreview; + WNDPROC wndPreviewProc; + HWND hwndSrc; + + // Synchronization + HANDLE hlUnexpectedErrorEvent; + HANDLE hlExpectedErrorEvent; + HANDLE hlOcclutionEvent; + HANDLE hlTerminateThreadsEvent; + + HCURSOR hcCursor; } plugin_win_dd_producer_t; @@ -97,11 +96,10 @@ static void* TSK_STDCALL DDThread(void *pArg); // // Class for progressive waits // -typedef struct -{ - UINT WaitTime; - UINT WaitCount; -}WAIT_BAND; +typedef struct { + UINT WaitTime; + UINT WaitCount; +} WAIT_BAND; #define WAIT_BAND_COUNT 3 #define WAIT_BAND_STOP 0 @@ -109,360 +107,316 @@ typedef struct class DYNAMIC_WAIT { public: - DYNAMIC_WAIT(); - ~DYNAMIC_WAIT(); + DYNAMIC_WAIT(); + ~DYNAMIC_WAIT(); - void Wait(); + void Wait(); private: - static const WAIT_BAND m_WaitBands[WAIT_BAND_COUNT]; + static const WAIT_BAND m_WaitBands[WAIT_BAND_COUNT]; - // Period in seconds that a new wait call is considered part of the same wait sequence - static const UINT m_WaitSequenceTimeInSeconds = 2; + // Period in seconds that a new wait call is considered part of the same wait sequence + static const UINT m_WaitSequenceTimeInSeconds = 2; - UINT m_CurrentWaitBandIdx; - UINT m_WaitCountInCurrentBand; - LARGE_INTEGER m_QPCFrequency; - LARGE_INTEGER m_LastWakeUpTime; - BOOL m_QPCValid; + UINT m_CurrentWaitBandIdx; + UINT m_WaitCountInCurrentBand; + LARGE_INTEGER m_QPCFrequency; + LARGE_INTEGER m_LastWakeUpTime; + BOOL m_QPCValid; }; const WAIT_BAND DYNAMIC_WAIT::m_WaitBands[WAIT_BAND_COUNT] = { - { 250, 20 }, - { 2000, 60 }, - { 5000, WAIT_BAND_STOP } // Never move past this band + { 250, 20 }, + { 2000, 60 }, + { 5000, WAIT_BAND_STOP } // Never move past this band }; /* ============ Video DD Producer Interface ================= */ static int plugin_win_dd_producer_set(tmedia_producer_t *p_self, const tmedia_param_t* pc_param) { - int ret = -1; - plugin_win_dd_producer_t* p_dd = (plugin_win_dd_producer_t*)p_self; - - if (!p_dd || !pc_param) - { - DD_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - if (pc_param->value_type == tmedia_pvt_int64) - { - if (tsk_striequals(pc_param->key, "local-hwnd") || tsk_striequals(pc_param->key, "preview-hwnd")) - { - HWND hwnd = (HWND)*((int64_t*)pc_param->value); - ret = SUCCEEDED(HookWindow(p_dd, hwnd)) ? 0 : -1; - } - else if (tsk_striequals(pc_param->key, "src-hwnd")) - { - p_dd->hwndSrc = (HWND)*((int64_t*)pc_param->value); - ret = 0; - } - } - else if (pc_param->value_type == tmedia_pvt_int32) - { - if (tsk_striequals(pc_param->key, "mute")) - { - p_dd->bMuted = (TSK_TO_INT32((uint8_t*)pc_param->value) != 0); - ret = 0; - } - } - - return ret; + int ret = -1; + plugin_win_dd_producer_t* p_dd = (plugin_win_dd_producer_t*)p_self; + + if (!p_dd || !pc_param) { + DD_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + if (pc_param->value_type == tmedia_pvt_int64) { + if (tsk_striequals(pc_param->key, "local-hwnd") || tsk_striequals(pc_param->key, "preview-hwnd")) { + HWND hwnd = (HWND)*((int64_t*)pc_param->value); + ret = SUCCEEDED(HookWindow(p_dd, hwnd)) ? 0 : -1; + } + else if (tsk_striequals(pc_param->key, "src-hwnd")) { + p_dd->hwndSrc = (HWND)*((int64_t*)pc_param->value); + ret = 0; + } + } + else if (pc_param->value_type == tmedia_pvt_int32) { + if (tsk_striequals(pc_param->key, "mute")) { + p_dd->bMuted = (TSK_TO_INT32((uint8_t*)pc_param->value) != 0); + ret = 0; + } + } + + return ret; } static int plugin_win_dd_producer_prepare(tmedia_producer_t* self, const tmedia_codec_t* codec) { - plugin_win_dd_producer_t* pSelf = (plugin_win_dd_producer_t*)self; - HRESULT hr = S_OK; - - if (!pSelf || !codec && codec->plugin) - { - DD_DEBUG_ERROR("Invalid parameter"); - DD_CHECK_HR(hr = E_UNEXPECTED); - } - - if (pSelf->bPrepared) - { - DD_DEBUG_WARN("DD video producer already prepared"); - DD_CHECK_HR(hr = E_UNEXPECTED); - } - - if (pSelf->bThreadTerminationDelayed) - { - DD_DEBUG_INFO("Thread termination was delayed ...cleanup now"); - if (_plugin_win_dd_producer_unprepare(pSelf, true/*cleanup?*/) != 0) - { - DD_CHECK_HR(hr = E_UNEXPECTED); - } - } - - TMEDIA_PRODUCER(pSelf)->video.fps = TMEDIA_CODEC_VIDEO(codec)->out.fps; - TMEDIA_PRODUCER(pSelf)->video.width = TMEDIA_CODEC_VIDEO(codec)->out.width; - TMEDIA_PRODUCER(pSelf)->video.height = TMEDIA_CODEC_VIDEO(codec)->out.height; - TMEDIA_PRODUCER(pSelf)->encoder.codec_id = tmedia_codec_id_none; // means RAW frames as input - - DD_DEBUG_INFO("DD video producer: fps=%d, width=%d, height=%d", - TMEDIA_PRODUCER(pSelf)->video.fps, - TMEDIA_PRODUCER(pSelf)->video.width, - TMEDIA_PRODUCER(pSelf)->video.height); - - // Event used by the threads to signal an unexpected error and we want to quit the app - if (!pSelf->hlUnexpectedErrorEvent && !(pSelf->hlUnexpectedErrorEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr))) - { - ProcessFailure(nullptr, L"UnexpectedErrorEvent creation failed", L"Error", E_UNEXPECTED); - DD_CHECK_HR(hr = E_UNEXPECTED); - } - - // Event for when a thread encounters an expected error - if (!pSelf->hlExpectedErrorEvent && !(pSelf->hlExpectedErrorEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr))) - { - ProcessFailure(nullptr, L"ExpectedErrorEvent creation failed", L"Error", E_UNEXPECTED); - DD_CHECK_HR(hr = E_UNEXPECTED); - } - - // Event for Occlution - if (!pSelf->hlOcclutionEvent && !(pSelf->hlOcclutionEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr))) - { - ProcessFailure(nullptr, L"OcclutionEvent creation failed", L"Error", E_UNEXPECTED); - DD_CHECK_HR(hr = E_UNEXPECTED); - } - - // Event to tell spawned threads to quit - if (!pSelf->hlTerminateThreadsEvent && !(pSelf->hlTerminateThreadsEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr))) - { - ProcessFailure(nullptr, L"TerminateThreadsEvent creation failed", L"Error", E_UNEXPECTED); - DD_CHECK_HR(hr = E_UNEXPECTED); - } - - // Load simple cursor - if (!pSelf->hcCursor && !(pSelf->hcCursor = LoadCursor(nullptr, IDC_ARROW))) - { - ProcessFailure(nullptr, L"Cursor load failed", L"Error", E_UNEXPECTED); - DD_CHECK_HR(hr = E_UNEXPECTED); - } - - if (!pSelf->pOutMgr && !(pSelf->pOutMgr = new OUTPUTMANAGER())) - { - ProcessFailure(nullptr, L"Out manager allocation failed", L"Error", E_OUTOFMEMORY); - DD_CHECK_HR(hr = E_OUTOFMEMORY); - } - - if (!pSelf->pThreadMgr && !(pSelf->pThreadMgr = new THREADMANAGER())) - { - ProcessFailure(nullptr, L"Thread managed allocation failed", L"Error", E_OUTOFMEMORY); - DD_CHECK_HR(hr = E_OUTOFMEMORY); - } + plugin_win_dd_producer_t* pSelf = (plugin_win_dd_producer_t*)self; + HRESULT hr = S_OK; + + if (!pSelf || !codec && codec->plugin) { + DD_DEBUG_ERROR("Invalid parameter"); + DD_CHECK_HR(hr = E_UNEXPECTED); + } + + if (pSelf->bPrepared) { + DD_DEBUG_WARN("DD video producer already prepared"); + DD_CHECK_HR(hr = E_UNEXPECTED); + } + + if (pSelf->bThreadTerminationDelayed) { + DD_DEBUG_INFO("Thread termination was delayed ...cleanup now"); + if (_plugin_win_dd_producer_unprepare(pSelf, true/*cleanup?*/) != 0) { + DD_CHECK_HR(hr = E_UNEXPECTED); + } + } + + TMEDIA_PRODUCER(pSelf)->video.fps = TMEDIA_CODEC_VIDEO(codec)->out.fps; + TMEDIA_PRODUCER(pSelf)->video.width = TMEDIA_CODEC_VIDEO(codec)->out.width; + TMEDIA_PRODUCER(pSelf)->video.height = TMEDIA_CODEC_VIDEO(codec)->out.height; + TMEDIA_PRODUCER(pSelf)->encoder.codec_id = tmedia_codec_id_none; // means RAW frames as input + + DD_DEBUG_INFO("DD video producer: fps=%d, width=%d, height=%d", + TMEDIA_PRODUCER(pSelf)->video.fps, + TMEDIA_PRODUCER(pSelf)->video.width, + TMEDIA_PRODUCER(pSelf)->video.height); + + // Event used by the threads to signal an unexpected error and we want to quit the app + if (!pSelf->hlUnexpectedErrorEvent && !(pSelf->hlUnexpectedErrorEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr))) { + ProcessFailure(nullptr, L"UnexpectedErrorEvent creation failed", L"Error", E_UNEXPECTED); + DD_CHECK_HR(hr = E_UNEXPECTED); + } + + // Event for when a thread encounters an expected error + if (!pSelf->hlExpectedErrorEvent && !(pSelf->hlExpectedErrorEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr))) { + ProcessFailure(nullptr, L"ExpectedErrorEvent creation failed", L"Error", E_UNEXPECTED); + DD_CHECK_HR(hr = E_UNEXPECTED); + } + + // Event for Occlution + if (!pSelf->hlOcclutionEvent && !(pSelf->hlOcclutionEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr))) { + ProcessFailure(nullptr, L"OcclutionEvent creation failed", L"Error", E_UNEXPECTED); + DD_CHECK_HR(hr = E_UNEXPECTED); + } + + // Event to tell spawned threads to quit + if (!pSelf->hlTerminateThreadsEvent && !(pSelf->hlTerminateThreadsEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr))) { + ProcessFailure(nullptr, L"TerminateThreadsEvent creation failed", L"Error", E_UNEXPECTED); + DD_CHECK_HR(hr = E_UNEXPECTED); + } + + // Load simple cursor + if (!pSelf->hcCursor && !(pSelf->hcCursor = LoadCursor(nullptr, IDC_ARROW))) { + ProcessFailure(nullptr, L"Cursor load failed", L"Error", E_UNEXPECTED); + DD_CHECK_HR(hr = E_UNEXPECTED); + } + + if (!pSelf->pOutMgr && !(pSelf->pOutMgr = new OUTPUTMANAGER())) { + ProcessFailure(nullptr, L"Out manager allocation failed", L"Error", E_OUTOFMEMORY); + DD_CHECK_HR(hr = E_OUTOFMEMORY); + } + + if (!pSelf->pThreadMgr && !(pSelf->pThreadMgr = new THREADMANAGER())) { + ProcessFailure(nullptr, L"Thread managed allocation failed", L"Error", E_OUTOFMEMORY); + DD_CHECK_HR(hr = E_OUTOFMEMORY); + } bail: - pSelf->bPrepared = SUCCEEDED(hr); - return SUCCEEDED(hr) ? 0 : -1; + pSelf->bPrepared = SUCCEEDED(hr); + return SUCCEEDED(hr) ? 0 : -1; } static int plugin_win_dd_producer_start(tmedia_producer_t* self) { - plugin_win_dd_producer_t* pSelf = (plugin_win_dd_producer_t*)self; - HRESULT hr = S_OK; - - if (!pSelf) - { - DD_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - if (pSelf->bStarted) - { - DD_DEBUG_INFO("Producer already started"); - goto bail; - } - if (!pSelf->bPrepared) - { - DD_DEBUG_ERROR("Producer not prepared"); - DD_CHECK_HR(hr = E_UNEXPECTED); - } - - DD_CHECK_HR(hr = HookWindow(pSelf, pSelf->hwndPreview)); - - // Start asynchronous watcher thread - pSelf->bStarted = true; - int ret = tsk_thread_create(&pSelf->ppTread[0], DDThread, pSelf); - if (ret != 0) - { - TSK_DEBUG_ERROR("Failed to create thread"); - pSelf->bStarted = false; - if (pSelf->ppTread[0]) - { - tsk_thread_join(&pSelf->ppTread[0]); - } - DD_CHECK_HR(hr = E_UNEXPECTED); - } + plugin_win_dd_producer_t* pSelf = (plugin_win_dd_producer_t*)self; + HRESULT hr = S_OK; + + if (!pSelf) { + DD_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + if (pSelf->bStarted) { + DD_DEBUG_INFO("Producer already started"); + goto bail; + } + if (!pSelf->bPrepared) { + DD_DEBUG_ERROR("Producer not prepared"); + DD_CHECK_HR(hr = E_UNEXPECTED); + } + + DD_CHECK_HR(hr = HookWindow(pSelf, pSelf->hwndPreview)); + + // Start asynchronous watcher thread + pSelf->bStarted = true; + int ret = tsk_thread_create(&pSelf->ppTread[0], DDThread, pSelf); + if (ret != 0) { + TSK_DEBUG_ERROR("Failed to create thread"); + pSelf->bStarted = false; + if (pSelf->ppTread[0]) { + tsk_thread_join(&pSelf->ppTread[0]); + } + DD_CHECK_HR(hr = E_UNEXPECTED); + } bail: - if (FAILED(hr)) - { - UnhookWindow(pSelf); - return -1; - } - pSelf->bStarted = true; - return 0; + if (FAILED(hr)) { + UnhookWindow(pSelf); + return -1; + } + pSelf->bStarted = true; + return 0; } static int plugin_win_dd_producer_pause(tmedia_producer_t* self) { - plugin_win_dd_producer_t* pSelf = (plugin_win_dd_producer_t*)self; - - if (!pSelf) - { - DD_DEBUG_ERROR("Invalid parameter"); - return -1; - } - if (!pSelf->bStarted) - { - DD_DEBUG_INFO("MF video producer not started"); - } - - return 0; + plugin_win_dd_producer_t* pSelf = (plugin_win_dd_producer_t*)self; + + if (!pSelf) { + DD_DEBUG_ERROR("Invalid parameter"); + return -1; + } + if (!pSelf->bStarted) { + DD_DEBUG_INFO("MF video producer not started"); + } + + return 0; } static int plugin_win_dd_producer_stop(tmedia_producer_t* self) { - plugin_win_dd_producer_t* pSelf = (plugin_win_dd_producer_t*)self; - - if (!pSelf) - { - DD_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - pSelf->bStarted = false; - - UnhookWindow(pSelf); - - if (pSelf->hlTerminateThreadsEvent) - { - SetEvent(pSelf->hlTerminateThreadsEvent); - } - if (pSelf->ppTread[0]) - { - tsk_thread_join(&pSelf->ppTread[0]); - } - - // next start() will be called after prepare() - int ret = _plugin_win_dd_producer_unprepare(pSelf); - - return ret; + plugin_win_dd_producer_t* pSelf = (plugin_win_dd_producer_t*)self; + + if (!pSelf) { + DD_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + pSelf->bStarted = false; + + UnhookWindow(pSelf); + + if (pSelf->hlTerminateThreadsEvent) { + SetEvent(pSelf->hlTerminateThreadsEvent); + } + if (pSelf->ppTread[0]) { + tsk_thread_join(&pSelf->ppTread[0]); + } + + // next start() will be called after prepare() + int ret = _plugin_win_dd_producer_unprepare(pSelf); + + return ret; } static int _plugin_win_dd_producer_unprepare(plugin_win_dd_producer_t* pSelf, bool bCleanup /*= false*/) { - HRESULT hr = S_OK; - - if (!pSelf) - { - DD_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - if (pSelf->bStarted) - { - DD_CHECK_HR(hr = E_UNEXPECTED); - } - - pSelf->bThreadTerminationDelayed = false; - - // Thread manager must be destroyed before the events and output manager - if (pSelf->pThreadMgr) - { - // if we are cleaning the producer then all threads must exit only when all threads are destroyed - // https://code.google.com/p/sincity/issues/detail?id=7 - if (pSelf->pThreadMgr->WaitForThreadTermination(bCleanup ? INFINITE : DD_DDPROC_THREAD_TIMEOUT) == true) - { - delete pSelf->pThreadMgr; - pSelf->pThreadMgr = nullptr; - } - else - { - // Thread wait timedout - DD_DEBUG_WARN("DDProc thread termination delayed"); - pSelf->bThreadTerminationDelayed = true; - } - } - - if (!pSelf->bThreadTerminationDelayed) - { - if (pSelf->hlUnexpectedErrorEvent) - { - CloseHandle(pSelf->hlUnexpectedErrorEvent); - pSelf->hlUnexpectedErrorEvent = nullptr; - } - if (pSelf->hlExpectedErrorEvent) - { - CloseHandle(pSelf->hlExpectedErrorEvent); - pSelf->hlExpectedErrorEvent = nullptr; - } - if (pSelf->hlOcclutionEvent) - { - CloseHandle(pSelf->hlOcclutionEvent); - pSelf->hlOcclutionEvent = nullptr; - } - if (pSelf->hlTerminateThreadsEvent) - { - CloseHandle(pSelf->hlTerminateThreadsEvent); - pSelf->hlTerminateThreadsEvent = nullptr; - } - - if (pSelf->hcCursor) - { - DestroyCursor(pSelf->hcCursor); - pSelf->hcCursor = nullptr; - } - - if (pSelf->pOutMgr) - { - delete pSelf->pOutMgr; - pSelf->pOutMgr = nullptr; - } - } - - pSelf->bPrepared = false; + HRESULT hr = S_OK; + + if (!pSelf) { + DD_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + if (pSelf->bStarted) { + DD_CHECK_HR(hr = E_UNEXPECTED); + } + + pSelf->bThreadTerminationDelayed = false; + + // Thread manager must be destroyed before the events and output manager + if (pSelf->pThreadMgr) { + // if we are cleaning the producer then all threads must exit only when all threads are destroyed + // https://code.google.com/p/sincity/issues/detail?id=7 + if (pSelf->pThreadMgr->WaitForThreadTermination(bCleanup ? INFINITE : DD_DDPROC_THREAD_TIMEOUT) == true) { + delete pSelf->pThreadMgr; + pSelf->pThreadMgr = nullptr; + } + else { + // Thread wait timedout + DD_DEBUG_WARN("DDProc thread termination delayed"); + pSelf->bThreadTerminationDelayed = true; + } + } + + if (!pSelf->bThreadTerminationDelayed) { + if (pSelf->hlUnexpectedErrorEvent) { + CloseHandle(pSelf->hlUnexpectedErrorEvent); + pSelf->hlUnexpectedErrorEvent = nullptr; + } + if (pSelf->hlExpectedErrorEvent) { + CloseHandle(pSelf->hlExpectedErrorEvent); + pSelf->hlExpectedErrorEvent = nullptr; + } + if (pSelf->hlOcclutionEvent) { + CloseHandle(pSelf->hlOcclutionEvent); + pSelf->hlOcclutionEvent = nullptr; + } + if (pSelf->hlTerminateThreadsEvent) { + CloseHandle(pSelf->hlTerminateThreadsEvent); + pSelf->hlTerminateThreadsEvent = nullptr; + } + + if (pSelf->hcCursor) { + DestroyCursor(pSelf->hcCursor); + pSelf->hcCursor = nullptr; + } + + if (pSelf->pOutMgr) { + delete pSelf->pOutMgr; + pSelf->pOutMgr = nullptr; + } + } + + pSelf->bPrepared = false; bail: - return 0; + return 0; } static HRESULT HookWindow(struct plugin_win_dd_producer_s *pSelf, HWND hWnd) { - HRESULT hr = S_OK; - - DD_CHECK_HR(hr = UnhookWindow(pSelf)); - - if ((pSelf->hwndPreview = hWnd)) - { - pSelf->wndPreviewProc = (WNDPROC)SetWindowLongPtr(pSelf->hwndPreview, GWLP_WNDPROC, (LONG_PTR)WndProc); - if (!pSelf->wndPreviewProc) - { - DD_DEBUG_ERROR("HookWindowLongPtr() failed with errcode=%d", GetLastError()); - DD_CHECK_HR(hr = E_FAIL); - } - SetProp(pSelf->hwndPreview, L"Self", pSelf); - pSelf->bWindowHooked = true; - } + HRESULT hr = S_OK; + + DD_CHECK_HR(hr = UnhookWindow(pSelf)); + + if ((pSelf->hwndPreview = hWnd)) { + pSelf->wndPreviewProc = (WNDPROC)SetWindowLongPtr(pSelf->hwndPreview, GWLP_WNDPROC, (LONG_PTR)WndProc); + if (!pSelf->wndPreviewProc) { + DD_DEBUG_ERROR("HookWindowLongPtr() failed with errcode=%d", GetLastError()); + DD_CHECK_HR(hr = E_FAIL); + } + SetProp(pSelf->hwndPreview, L"Self", pSelf); + pSelf->bWindowHooked = true; + } bail: - return S_OK; + return S_OK; } static HRESULT UnhookWindow(struct plugin_win_dd_producer_s *pSelf) { - if (pSelf->hwndPreview && pSelf->wndPreviewProc) - { - SetWindowLongPtr(pSelf->hwndPreview, GWLP_WNDPROC, (LONG_PTR)pSelf->wndPreviewProc); - pSelf->wndPreviewProc = NULL; - } - if (pSelf->hwndPreview) - { - ::InvalidateRect(pSelf->hwndPreview, NULL, FALSE); - } - pSelf->bWindowHooked = false; - return S_OK; + if (pSelf->hwndPreview && pSelf->wndPreviewProc) { + SetWindowLongPtr(pSelf->hwndPreview, GWLP_WNDPROC, (LONG_PTR)pSelf->wndPreviewProc); + pSelf->wndPreviewProc = NULL; + } + if (pSelf->hwndPreview) { + ::InvalidateRect(pSelf->hwndPreview, NULL, FALSE); + } + pSelf->bWindowHooked = false; + return S_OK; } // @@ -471,66 +425,61 @@ static HRESULT UnhookWindow(struct plugin_win_dd_producer_s *pSelf) /* constructor */ static tsk_object_t* plugin_win_dd_producer_ctor(tsk_object_t * self, va_list * app) { - plugin_win_dd_producer_t *pSelf = (plugin_win_dd_producer_t *)self; - if (pSelf) - { - /* init base */ - tmedia_producer_init(TMEDIA_PRODUCER(pSelf)); - - /* init self with default values*/ - TMEDIA_PRODUCER(pSelf)->encoder.codec_id = tmedia_codec_id_none; // means RAW frames as input - TMEDIA_PRODUCER(pSelf)->video.chroma = tmedia_chroma_rgb32; - TMEDIA_PRODUCER(pSelf)->video.fps = 15; - TMEDIA_PRODUCER(pSelf)->video.width = 352; - TMEDIA_PRODUCER(pSelf)->video.height = 288; - - DD_DEBUG_INFO("Create Microsoft Desktop Duplication producer"); - } - return self; + plugin_win_dd_producer_t *pSelf = (plugin_win_dd_producer_t *)self; + if (pSelf) { + /* init base */ + tmedia_producer_init(TMEDIA_PRODUCER(pSelf)); + + /* init self with default values*/ + TMEDIA_PRODUCER(pSelf)->encoder.codec_id = tmedia_codec_id_none; // means RAW frames as input + TMEDIA_PRODUCER(pSelf)->video.chroma = tmedia_chroma_rgb32; + TMEDIA_PRODUCER(pSelf)->video.fps = 15; + TMEDIA_PRODUCER(pSelf)->video.width = 352; + TMEDIA_PRODUCER(pSelf)->video.height = 288; + + DD_DEBUG_INFO("Create Microsoft Desktop Duplication producer"); + } + return self; } /* destructor */ static tsk_object_t* plugin_win_dd_producer_dtor(tsk_object_t * self) { - plugin_win_dd_producer_t *pSelf = (plugin_win_dd_producer_t *)self; - if (pSelf) - { - /* stop */ - if (pSelf->bStarted) - { - plugin_win_dd_producer_stop(TMEDIA_PRODUCER(pSelf)); - } - - /* deinit base */ - tmedia_producer_deinit(TMEDIA_PRODUCER(pSelf)); - /* deinit self */ - _plugin_win_dd_producer_unprepare(pSelf, true/*cleanup*/); - - DD_DEBUG_INFO("*** WinDD producer destroyed ***"); - } - - return self; + plugin_win_dd_producer_t *pSelf = (plugin_win_dd_producer_t *)self; + if (pSelf) { + /* stop */ + if (pSelf->bStarted) { + plugin_win_dd_producer_stop(TMEDIA_PRODUCER(pSelf)); + } + + /* deinit base */ + tmedia_producer_deinit(TMEDIA_PRODUCER(pSelf)); + /* deinit self */ + _plugin_win_dd_producer_unprepare(pSelf, true/*cleanup*/); + + DD_DEBUG_INFO("*** WinDD producer destroyed ***"); + } + + return self; } /* object definition */ -static const tsk_object_def_t plugin_win_dd_producer_def_s = -{ - sizeof(plugin_win_dd_producer_t), - plugin_win_dd_producer_ctor, - plugin_win_dd_producer_dtor, - tsk_null, +static const tsk_object_def_t plugin_win_dd_producer_def_s = { + sizeof(plugin_win_dd_producer_t), + plugin_win_dd_producer_ctor, + plugin_win_dd_producer_dtor, + tsk_null, }; /* plugin definition*/ -static const tmedia_producer_plugin_def_t plugin_win_dd_producer_plugin_def_s = -{ - &plugin_win_dd_producer_def_s, +static const tmedia_producer_plugin_def_t plugin_win_dd_producer_plugin_def_s = { + &plugin_win_dd_producer_def_s, - tmedia_bfcp_video, - "Microsoft Windows Desktop Duplication producer (Video)", + tmedia_bfcp_video, + "Microsoft Windows Desktop Duplication producer (Video)", - plugin_win_dd_producer_set, - plugin_win_dd_producer_prepare, - plugin_win_dd_producer_start, - plugin_win_dd_producer_pause, - plugin_win_dd_producer_stop + plugin_win_dd_producer_set, + plugin_win_dd_producer_prepare, + plugin_win_dd_producer_start, + plugin_win_dd_producer_pause, + plugin_win_dd_producer_stop }; const tmedia_producer_plugin_def_t *plugin_win_dd_producer_plugin_def_t = &plugin_win_dd_producer_plugin_def_s; @@ -545,130 +494,115 @@ const tmedia_producer_plugin_def_t *plugin_win_dd_producer_plugin_def_t = &plugi // These are the errors we expect from general Dxgi API due to a transition HRESULT SystemTransitionsExpectedErrors[] = { - DXGI_ERROR_DEVICE_REMOVED, - DXGI_ERROR_ACCESS_LOST, - static_cast<HRESULT>(WAIT_ABANDONED), - S_OK // Terminate list with zero valued HRESULT + DXGI_ERROR_DEVICE_REMOVED, + DXGI_ERROR_ACCESS_LOST, + static_cast<HRESULT>(WAIT_ABANDONED), + S_OK // Terminate list with zero valued HRESULT }; // These are the errors we expect from IDXGIOutput1::DuplicateOutput due to a transition HRESULT CreateDuplicationExpectedErrors[] = { - DXGI_ERROR_DEVICE_REMOVED, - static_cast<HRESULT>(E_ACCESSDENIED), - DXGI_ERROR_UNSUPPORTED, - DXGI_ERROR_SESSION_DISCONNECTED, - S_OK // Terminate list with zero valued HRESULT + DXGI_ERROR_DEVICE_REMOVED, + static_cast<HRESULT>(E_ACCESSDENIED), + DXGI_ERROR_UNSUPPORTED, + DXGI_ERROR_SESSION_DISCONNECTED, + S_OK // Terminate list with zero valued HRESULT }; // These are the errors we expect from IDXGIOutputDuplication methods due to a transition HRESULT FrameInfoExpectedErrors[] = { - DXGI_ERROR_DEVICE_REMOVED, - DXGI_ERROR_ACCESS_LOST, - S_OK // Terminate list with zero valued HRESULT + DXGI_ERROR_DEVICE_REMOVED, + DXGI_ERROR_ACCESS_LOST, + S_OK // Terminate list with zero valued HRESULT }; // These are the errors we expect from IDXGIAdapter::EnumOutputs methods due to outputs becoming stale during a transition HRESULT EnumOutputsExpectedErrors[] = { - DXGI_ERROR_NOT_FOUND, - S_OK // Terminate list with zero valued HRESULT + DXGI_ERROR_NOT_FOUND, + S_OK // Terminate list with zero valued HRESULT }; _Post_satisfies_(return != DUPL_RETURN_SUCCESS) - DUPL_RETURN ProcessFailure(_In_opt_ ID3D11Device* Device, _In_ LPCWSTR Str, _In_ LPCWSTR Title, HRESULT hr, _In_opt_z_ HRESULT* ExpectedErrors) +DUPL_RETURN ProcessFailure(_In_opt_ ID3D11Device* Device, _In_ LPCWSTR Str, _In_ LPCWSTR Title, HRESULT hr, _In_opt_z_ HRESULT* ExpectedErrors) { - HRESULT TranslatedHr; - - // On an error check if the DX device is lost - if (Device) - { - HRESULT DeviceRemovedReason = Device->GetDeviceRemovedReason(); - - switch (DeviceRemovedReason) - { - case DXGI_ERROR_DEVICE_REMOVED: - case DXGI_ERROR_DEVICE_RESET: - case static_cast<HRESULT>(E_OUTOFMEMORY) : - { - // Our device has been stopped due to an external event on the GPU so map them all to - // device removed and continue processing the condition - TranslatedHr = DXGI_ERROR_DEVICE_REMOVED; - break; - } - - case S_OK: - { - // Device is not removed so use original error - TranslatedHr = hr; - break; - } - - default: - { - // Device is removed but not a error we want to remap - TranslatedHr = DeviceRemovedReason; - } - } - } - else - { - TranslatedHr = hr; - } - - // Check if this error was expected or not - if (ExpectedErrors) - { - HRESULT* CurrentResult = ExpectedErrors; - - while (*CurrentResult != S_OK) - { - if (*(CurrentResult++) == TranslatedHr) - { - return DUPL_RETURN_ERROR_EXPECTED; - } - } - } - - // Error was not expected so display the message box - DisplayMsg(Str, Title, TranslatedHr); - - return DUPL_RETURN_ERROR_UNEXPECTED; + HRESULT TranslatedHr; + + // On an error check if the DX device is lost + if (Device) { + HRESULT DeviceRemovedReason = Device->GetDeviceRemovedReason(); + + switch (DeviceRemovedReason) { + case DXGI_ERROR_DEVICE_REMOVED: + case DXGI_ERROR_DEVICE_RESET: + case static_cast<HRESULT>(E_OUTOFMEMORY) : { + // Our device has been stopped due to an external event on the GPU so map them all to + // device removed and continue processing the condition + TranslatedHr = DXGI_ERROR_DEVICE_REMOVED; + break; + } + + case S_OK: { + // Device is not removed so use original error + TranslatedHr = hr; + break; + } + + default: { + // Device is removed but not a error we want to remap + TranslatedHr = DeviceRemovedReason; + } + } + } + else { + TranslatedHr = hr; + } + + // Check if this error was expected or not + if (ExpectedErrors) { + HRESULT* CurrentResult = ExpectedErrors; + + while (*CurrentResult != S_OK) { + if (*(CurrentResult++) == TranslatedHr) { + return DUPL_RETURN_ERROR_EXPECTED; + } + } + } + + // Error was not expected so display the message box + DisplayMsg(Str, Title, TranslatedHr); + + return DUPL_RETURN_ERROR_UNEXPECTED; } LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { - switch (message) - { - case WM_DESTROY: - { - PostQuitMessage(0); - break; - } - case WM_SIZE: - { - // Tell output manager that window size has changed - plugin_win_dd_producer_t* pSelf = static_cast<plugin_win_dd_producer_t*>(GetProp(hWnd, L"Self")); - if (pSelf && pSelf->pOutMgr) - { - pSelf->pOutMgr->WindowResize(); - } - break; - } - case OCCLUSION_STATUS_MSG: - { - plugin_win_dd_producer_t* pSelf = static_cast<plugin_win_dd_producer_t*>(GetProp(hWnd, L"Self")); - if (pSelf && pSelf->hlOcclutionEvent) - { - SetEvent(pSelf->hlOcclutionEvent); - } - break; - } - default: - return DefWindowProc(hWnd, message, wParam, lParam); - } - - return 0; + switch (message) { + case WM_DESTROY: { + PostQuitMessage(0); + break; + } + case WM_SIZE: { + // Tell output manager that window size has changed + plugin_win_dd_producer_t* pSelf = static_cast<plugin_win_dd_producer_t*>(GetProp(hWnd, L"Self")); + if (pSelf && pSelf->pOutMgr) { + pSelf->pOutMgr->WindowResize(); + } + break; + } + case OCCLUSION_STATUS_MSG: { + plugin_win_dd_producer_t* pSelf = static_cast<plugin_win_dd_producer_t*>(GetProp(hWnd, L"Self")); + if (pSelf && pSelf->hlOcclutionEvent) { + SetEvent(pSelf->hlOcclutionEvent); + } + break; + } + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } + + return 0; } // @@ -676,399 +610,357 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) // DWORD WINAPI DDProc(_In_ void* Param) { - DD_DEBUG_INFO("DDProc (producer) - ENTER"); - - // Classes - DISPLAYMANAGER DispMgr; - DUPLICATIONMANAGER DuplMgr; - - // D3D objects - ID3D11Texture2D* SharedSurf = nullptr; - IDXGIKeyedMutex* KeyMutex = nullptr; - - // Data passed in from thread creation - THREAD_DATA* TData = reinterpret_cast<THREAD_DATA*>(Param); - - // Get desktop - DUPL_RETURN Ret; - HDESK CurrentDesktop = nullptr; - CurrentDesktop = OpenInputDesktop(0, FALSE, GENERIC_ALL); - if (!CurrentDesktop) - { - // We do not have access to the desktop so request a retry - SetEvent(TData->ExpectedErrorEvent); - Ret = DUPL_RETURN_ERROR_EXPECTED; - goto Exit; - } - - // Attach desktop to this thread - bool DesktopAttached = SetThreadDesktop(CurrentDesktop) != 0; - CloseDesktop(CurrentDesktop); - CurrentDesktop = nullptr; - if (!DesktopAttached) - { - // We do not have access to the desktop so request a retry - Ret = DUPL_RETURN_ERROR_EXPECTED; - goto Exit; - } - - // New display manager - DispMgr.InitD3D(&TData->DxRes); - - // FPS manager - uint64_t TimeNow, TimeLastFrame = 0; - const uint64_t TimeFrameDuration = 1000 / TData->Producer->video.fps; - - // Obtain handle to sync shared Surface - HRESULT hr = TData->DxRes.Device->OpenSharedResource(TData->TexSharedHandle, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&SharedSurf)); - if (FAILED(hr)) - { - Ret = ProcessFailure(TData->DxRes.Device, L"Opening shared texture failed", L"Error", hr, SystemTransitionsExpectedErrors); - goto Exit; - } - - hr = SharedSurf->QueryInterface(__uuidof(IDXGIKeyedMutex), reinterpret_cast<void**>(&KeyMutex)); - if (FAILED(hr)) - { - Ret = ProcessFailure(nullptr, L"Failed to get keyed mutex interface in spawned thread", L"Error", hr); - goto Exit; - } - - // Make duplication manager - Ret = DuplMgr.InitDupl(TData->DxRes.Device, TData->DxRes.Context ,TData->Output); - if (Ret != DUPL_RETURN_SUCCESS) - { - goto Exit; - } - - // Get output description - DXGI_OUTPUT_DESC DesktopDesc; - RtlZeroMemory(&DesktopDesc, sizeof(DXGI_OUTPUT_DESC)); - DuplMgr.GetOutputDesc(&DesktopDesc); - - // Main duplication loop - bool WaitToProcessCurrentFrame = false; - FRAME_DATA CurrentData; - - while (TData->Producer->is_started && (WaitForSingleObjectEx(TData->TerminateThreadsEvent, 0, FALSE) == WAIT_TIMEOUT)) - { - if (!WaitToProcessCurrentFrame) - { - // Get new frame from desktop duplication - bool TimeOut; - Ret = DuplMgr.GetFrame(&CurrentData, &TimeOut); - if (Ret != DUPL_RETURN_SUCCESS) - { - // An error occurred getting the next frame drop out of loop which - // will check if it was expected or not - break; - } - - // Check for timeout - if (TimeOut) - { - // No new frame at the moment - continue; - } - } - - // We have a new frame so try and process it - // Try to acquire keyed mutex in order to access shared surface - hr = KeyMutex->AcquireSync(0, 1000); - if (hr == static_cast<HRESULT>(WAIT_TIMEOUT)) - { - // Can't use shared surface right now, try again later - WaitToProcessCurrentFrame = true; - continue; - } - else if (FAILED(hr)) - { - // Generic unknown failure - Ret = ProcessFailure(TData->DxRes.Device, L"Unexpected error acquiring KeyMutex", L"Error", hr, SystemTransitionsExpectedErrors); - DuplMgr.DoneWithFrame(); - break; - } - - // We can now process the current frame - WaitToProcessCurrentFrame = false; - - // Get mouse info - Ret = DuplMgr.GetMouse(TData->PtrInfo, &(CurrentData.FrameInfo), TData->OffsetX, TData->OffsetY); - if (Ret != DUPL_RETURN_SUCCESS) - { - DuplMgr.DoneWithFrame(); - KeyMutex->ReleaseSync(1); - break; - } - - // Process new frame - Ret = DispMgr.ProcessFrame(&CurrentData, SharedSurf, TData->OffsetX, TData->OffsetY, &DesktopDesc); - if (Ret != DUPL_RETURN_SUCCESS) - { - DuplMgr.DoneWithFrame(); - KeyMutex->ReleaseSync(1); - break; - } - - // Release acquired keyed mutex - hr = KeyMutex->ReleaseSync(1); - if (FAILED(hr)) - { - Ret = ProcessFailure(TData->DxRes.Device, L"Unexpected error releasing the keyed mutex", L"Error", hr, SystemTransitionsExpectedErrors); - DuplMgr.DoneWithFrame(); - break; - } - - // Send Frame Over the Network - TimeNow = tsk_time_now(); - if ((TimeNow - TimeLastFrame) > TimeFrameDuration) - { - if (!((const plugin_win_dd_producer_t*)TData->Producer)->bMuted) - { - hr = DuplMgr.SendData(const_cast<struct tmedia_producer_s*>(TData->Producer), &CurrentData); - } - if (SUCCEEDED(hr)) - { - TimeLastFrame = TimeNow; - } - } + DD_DEBUG_INFO("DDProc (producer) - ENTER"); + + // Classes + DISPLAYMANAGER DispMgr; + DUPLICATIONMANAGER DuplMgr; + + // D3D objects + ID3D11Texture2D* SharedSurf = nullptr; + IDXGIKeyedMutex* KeyMutex = nullptr; + + // Data passed in from thread creation + THREAD_DATA* TData = reinterpret_cast<THREAD_DATA*>(Param); + + // Get desktop + DUPL_RETURN Ret; + HDESK CurrentDesktop = nullptr; + CurrentDesktop = OpenInputDesktop(0, FALSE, GENERIC_ALL); + if (!CurrentDesktop) { + // We do not have access to the desktop so request a retry + SetEvent(TData->ExpectedErrorEvent); + Ret = DUPL_RETURN_ERROR_EXPECTED; + goto Exit; + } + + // Attach desktop to this thread + bool DesktopAttached = SetThreadDesktop(CurrentDesktop) != 0; + CloseDesktop(CurrentDesktop); + CurrentDesktop = nullptr; + if (!DesktopAttached) { + // We do not have access to the desktop so request a retry + Ret = DUPL_RETURN_ERROR_EXPECTED; + goto Exit; + } + + // New display manager + DispMgr.InitD3D(&TData->DxRes); + + // FPS manager + uint64_t TimeNow, TimeLastFrame = 0; + const uint64_t TimeFrameDuration = 1000 / TData->Producer->video.fps; + + // Obtain handle to sync shared Surface + HRESULT hr = TData->DxRes.Device->OpenSharedResource(TData->TexSharedHandle, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&SharedSurf)); + if (FAILED(hr)) { + Ret = ProcessFailure(TData->DxRes.Device, L"Opening shared texture failed", L"Error", hr, SystemTransitionsExpectedErrors); + goto Exit; + } + + hr = SharedSurf->QueryInterface(__uuidof(IDXGIKeyedMutex), reinterpret_cast<void**>(&KeyMutex)); + if (FAILED(hr)) { + Ret = ProcessFailure(nullptr, L"Failed to get keyed mutex interface in spawned thread", L"Error", hr); + goto Exit; + } + + // Make duplication manager + Ret = DuplMgr.InitDupl(TData->DxRes.Device, TData->DxRes.Context ,TData->Output); + if (Ret != DUPL_RETURN_SUCCESS) { + goto Exit; + } + + // Get output description + DXGI_OUTPUT_DESC DesktopDesc; + RtlZeroMemory(&DesktopDesc, sizeof(DXGI_OUTPUT_DESC)); + DuplMgr.GetOutputDesc(&DesktopDesc); + + // Main duplication loop + bool WaitToProcessCurrentFrame = false; + FRAME_DATA CurrentData; + + while (TData->Producer->is_started && (WaitForSingleObjectEx(TData->TerminateThreadsEvent, 0, FALSE) == WAIT_TIMEOUT)) { + if (!WaitToProcessCurrentFrame) { + // Get new frame from desktop duplication + bool TimeOut; + Ret = DuplMgr.GetFrame(&CurrentData, &TimeOut); + if (Ret != DUPL_RETURN_SUCCESS) { + // An error occurred getting the next frame drop out of loop which + // will check if it was expected or not + break; + } + + // Check for timeout + if (TimeOut) { + // No new frame at the moment + continue; + } + } + + // We have a new frame so try and process it + // Try to acquire keyed mutex in order to access shared surface + hr = KeyMutex->AcquireSync(0, 1000); + if (hr == static_cast<HRESULT>(WAIT_TIMEOUT)) { + // Can't use shared surface right now, try again later + WaitToProcessCurrentFrame = true; + continue; + } + else if (FAILED(hr)) { + // Generic unknown failure + Ret = ProcessFailure(TData->DxRes.Device, L"Unexpected error acquiring KeyMutex", L"Error", hr, SystemTransitionsExpectedErrors); + DuplMgr.DoneWithFrame(); + break; + } + + // We can now process the current frame + WaitToProcessCurrentFrame = false; + + // Get mouse info + Ret = DuplMgr.GetMouse(TData->PtrInfo, &(CurrentData.FrameInfo), TData->OffsetX, TData->OffsetY); + if (Ret != DUPL_RETURN_SUCCESS) { + DuplMgr.DoneWithFrame(); + KeyMutex->ReleaseSync(1); + break; + } + + // Process new frame + Ret = DispMgr.ProcessFrame(&CurrentData, SharedSurf, TData->OffsetX, TData->OffsetY, &DesktopDesc); + if (Ret != DUPL_RETURN_SUCCESS) { + DuplMgr.DoneWithFrame(); + KeyMutex->ReleaseSync(1); + break; + } + + // Release acquired keyed mutex + hr = KeyMutex->ReleaseSync(1); + if (FAILED(hr)) { + Ret = ProcessFailure(TData->DxRes.Device, L"Unexpected error releasing the keyed mutex", L"Error", hr, SystemTransitionsExpectedErrors); + DuplMgr.DoneWithFrame(); + break; + } + + // Send Frame Over the Network + TimeNow = tsk_time_now(); + if ((TimeNow - TimeLastFrame) > TimeFrameDuration) { + if (!((const plugin_win_dd_producer_t*)TData->Producer)->bMuted) { + hr = DuplMgr.SendData(const_cast<struct tmedia_producer_s*>(TData->Producer), &CurrentData); + } + if (SUCCEEDED(hr)) { + TimeLastFrame = TimeNow; + } + } #if 0 - else - { - DD_DEBUG_INFO("Skip frame"); - } + else { + DD_DEBUG_INFO("Skip frame"); + } #endif - // Release frame back to desktop duplication - Ret = DuplMgr.DoneWithFrame(); - if (Ret != DUPL_RETURN_SUCCESS) - { - break; - } - } + // Release frame back to desktop duplication + Ret = DuplMgr.DoneWithFrame(); + if (Ret != DUPL_RETURN_SUCCESS) { + break; + } + } Exit: - if (Ret != DUPL_RETURN_SUCCESS) - { - if (Ret == DUPL_RETURN_ERROR_EXPECTED) - { - // The system is in a transition state so request the duplication be restarted - SetEvent(TData->ExpectedErrorEvent); - } - else - { - // Unexpected error so exit the application - SetEvent(TData->UnexpectedErrorEvent); - } - } - - if (SharedSurf) - { - SharedSurf->Release(); - SharedSurf = nullptr; - } - - if (KeyMutex) - { - KeyMutex->Release(); - KeyMutex = nullptr; - } - - DD_DEBUG_INFO("DDProc (producer) - EXIT"); - - return 0; + if (Ret != DUPL_RETURN_SUCCESS) { + if (Ret == DUPL_RETURN_ERROR_EXPECTED) { + // The system is in a transition state so request the duplication be restarted + SetEvent(TData->ExpectedErrorEvent); + } + else { + // Unexpected error so exit the application + SetEvent(TData->UnexpectedErrorEvent); + } + } + + if (SharedSurf) { + SharedSurf->Release(); + SharedSurf = nullptr; + } + + if (KeyMutex) { + KeyMutex->Release(); + KeyMutex = nullptr; + } + + DD_DEBUG_INFO("DDProc (producer) - EXIT"); + + return 0; } // Run session async thread static void* TSK_STDCALL DDThread(void *pArg) { - plugin_win_dd_producer_t *pSelf = (plugin_win_dd_producer_t *)pArg; - HRESULT hr = S_OK; - INT SingleOutput = -1; - - RECT DeskBounds = {}; - UINT OutputCount = 1; - - bool FirstTime = true; - bool Occluded = true; - bool PreviewChanged = false; - DYNAMIC_WAIT DynamicWait; - HWND hwndPreview = NULL; - - DD_DEBUG_INFO("DDThread (producer) - ENTER"); - - while (pSelf->bStarted) - { - DUPL_RETURN Ret = DUPL_RETURN_SUCCESS; - - // Check if Preview window changed - PreviewChanged = (hwndPreview != pSelf->hwndPreview); - - if (WaitForSingleObjectEx(pSelf->hlOcclutionEvent, 0, FALSE) == WAIT_OBJECT_0) - { - Occluded = false; - } - if (WaitForSingleObjectEx(pSelf->hlUnexpectedErrorEvent, 0, FALSE) == WAIT_OBJECT_0) - { - // Unexpected error occurred so exit the application - DD_CHECK_HR(hr = E_UNEXPECTED); - } - else if (FirstTime || PreviewChanged || WaitForSingleObjectEx(pSelf->hlExpectedErrorEvent, 0, FALSE) == WAIT_OBJECT_0) - { - if (PreviewChanged) - { - hwndPreview = pSelf->hwndPreview; - } - - if (!FirstTime) - { - // Terminate other threads - SetEvent(pSelf->hlTerminateThreadsEvent); - pSelf->pThreadMgr->WaitForThreadTermination(); - ResetEvent(pSelf->hlTerminateThreadsEvent); - ResetEvent(pSelf->hlExpectedErrorEvent); - - // Clean up - pSelf->pThreadMgr->Clean(); - pSelf->pOutMgr->CleanRefs(); - - // As we have encountered an error due to a system transition we wait before trying again, using this dynamic wait - // the wait periods will get progressively long to avoid wasting too much system resource if this state lasts a long time - DynamicWait.Wait(); - } - else - { - // First time through the loop so nothing to clean up - FirstTime = false; - } - - // Re-initialize - Ret = pSelf->pOutMgr->InitOutput(hwndPreview, SingleOutput, &OutputCount, &DeskBounds); - if (Ret == DUPL_RETURN_SUCCESS) - { - HANDLE SharedHandle = pSelf->pOutMgr->GetSharedHandle(); - if (SharedHandle) - { - Ret = pSelf->pThreadMgr->Initialize(SingleOutput, OutputCount, pSelf->hlUnexpectedErrorEvent, pSelf->hlExpectedErrorEvent, pSelf->hlTerminateThreadsEvent, SharedHandle, TMEDIA_PRODUCER(pSelf), &DeskBounds); - } - else - { - DisplayMsg(L"Failed to get handle of shared surface", L"Error", S_OK); - Ret = DUPL_RETURN_ERROR_UNEXPECTED; - } - } - - - // We start off in occluded state and we should immediate get a occlusion status window message - Occluded = true; - } - else - { - // Nothing else to do, so try to present to write out to window if not occluded - if (!Occluded || !pSelf->bWindowHooked) - { - Ret = pSelf->pOutMgr->UpdateApplicationWindow(pSelf->pThreadMgr->GetPointerInfo(), &Occluded); - } - } - - // Check if for errors - if (Ret != DUPL_RETURN_SUCCESS) - { - if (Ret == DUPL_RETURN_ERROR_EXPECTED) - { - // Some type of system transition is occurring so retry - SetEvent(pSelf->hlExpectedErrorEvent); - } - else - { - // Unexpected error so exit - DD_CHECK_HR(hr = E_UNEXPECTED); - break; - } - } - } + plugin_win_dd_producer_t *pSelf = (plugin_win_dd_producer_t *)pArg; + HRESULT hr = S_OK; + INT SingleOutput = -1; + + RECT DeskBounds = {}; + UINT OutputCount = 1; + + bool FirstTime = true; + bool Occluded = true; + bool PreviewChanged = false; + DYNAMIC_WAIT DynamicWait; + HWND hwndPreview = NULL; + + DD_DEBUG_INFO("DDThread (producer) - ENTER"); + + while (pSelf->bStarted) { + DUPL_RETURN Ret = DUPL_RETURN_SUCCESS; + + // Check if Preview window changed + PreviewChanged = (hwndPreview != pSelf->hwndPreview); + + if (WaitForSingleObjectEx(pSelf->hlOcclutionEvent, 0, FALSE) == WAIT_OBJECT_0) { + Occluded = false; + } + if (WaitForSingleObjectEx(pSelf->hlUnexpectedErrorEvent, 0, FALSE) == WAIT_OBJECT_0) { + // Unexpected error occurred so exit the application + DD_CHECK_HR(hr = E_UNEXPECTED); + } + else if (FirstTime || PreviewChanged || WaitForSingleObjectEx(pSelf->hlExpectedErrorEvent, 0, FALSE) == WAIT_OBJECT_0) { + if (PreviewChanged) { + hwndPreview = pSelf->hwndPreview; + } + + if (!FirstTime) { + // Terminate other threads + SetEvent(pSelf->hlTerminateThreadsEvent); + pSelf->pThreadMgr->WaitForThreadTermination(); + ResetEvent(pSelf->hlTerminateThreadsEvent); + ResetEvent(pSelf->hlExpectedErrorEvent); + + // Clean up + pSelf->pThreadMgr->Clean(); + pSelf->pOutMgr->CleanRefs(); + + // As we have encountered an error due to a system transition we wait before trying again, using this dynamic wait + // the wait periods will get progressively long to avoid wasting too much system resource if this state lasts a long time + DynamicWait.Wait(); + } + else { + // First time through the loop so nothing to clean up + FirstTime = false; + } + + // Re-initialize + Ret = pSelf->pOutMgr->InitOutput(hwndPreview, SingleOutput, &OutputCount, &DeskBounds); + if (Ret == DUPL_RETURN_SUCCESS) { + HANDLE SharedHandle = pSelf->pOutMgr->GetSharedHandle(); + if (SharedHandle) { + Ret = pSelf->pThreadMgr->Initialize(SingleOutput, OutputCount, pSelf->hlUnexpectedErrorEvent, pSelf->hlExpectedErrorEvent, pSelf->hlTerminateThreadsEvent, SharedHandle, TMEDIA_PRODUCER(pSelf), &DeskBounds); + } + else { + DisplayMsg(L"Failed to get handle of shared surface", L"Error", S_OK); + Ret = DUPL_RETURN_ERROR_UNEXPECTED; + } + } + + + // We start off in occluded state and we should immediate get a occlusion status window message + Occluded = true; + } + else { + // Nothing else to do, so try to present to write out to window if not occluded + if (!Occluded || !pSelf->bWindowHooked) { + Ret = pSelf->pOutMgr->UpdateApplicationWindow(pSelf->pThreadMgr->GetPointerInfo(), &Occluded); + } + } + + // Check if for errors + if (Ret != DUPL_RETURN_SUCCESS) { + if (Ret == DUPL_RETURN_ERROR_EXPECTED) { + // Some type of system transition is occurring so retry + SetEvent(pSelf->hlExpectedErrorEvent); + } + else { + // Unexpected error so exit + DD_CHECK_HR(hr = E_UNEXPECTED); + break; + } + } + } bail: - - DD_DEBUG_INFO("DDThread (producer) - BAIL"); + + DD_DEBUG_INFO("DDThread (producer) - BAIL"); #if 0 // Done by unprepare() - // Make sure all other threads have exited - if (SetEvent(pSelf->hlTerminateThreadsEvent)) - { - ThreadMgr.WaitForThreadTermination(); - } - - // Clean up - CloseHandle(pSelf->hlUnexpectedErrorEvent); pSelf->hlUnexpectedErrorEvent = NULL; - CloseHandle(pSelf->hlExpectedErrorEvent); pSelf->hlExpectedErrorEvent = NULL; - CloseHandle(pSelf->hlTerminateThreadsEvent); pSelf->hlTerminateThreadsEvent = NULL; + // Make sure all other threads have exited + if (SetEvent(pSelf->hlTerminateThreadsEvent)) { + ThreadMgr.WaitForThreadTermination(); + } + + // Clean up + CloseHandle(pSelf->hlUnexpectedErrorEvent); + pSelf->hlUnexpectedErrorEvent = NULL; + CloseHandle(pSelf->hlExpectedErrorEvent); + pSelf->hlExpectedErrorEvent = NULL; + CloseHandle(pSelf->hlTerminateThreadsEvent); + pSelf->hlTerminateThreadsEvent = NULL; #endif - DD_DEBUG_INFO("DDThread (producer) - EXIT"); + DD_DEBUG_INFO("DDThread (producer) - EXIT"); - return NULL; + return NULL; } // // Displays a message // - void DisplayMsg(_In_ LPCWSTR Str, _In_ LPCWSTR Title, HRESULT hr) +void DisplayMsg(_In_ LPCWSTR Str, _In_ LPCWSTR Title, HRESULT hr) { - const UINT StringLen = (UINT)(wcslen(Str) + sizeof(" with HRESULT 0x########.")); - wchar_t* OutStr = new wchar_t[StringLen]; - if (!OutStr) - { - return; - } - - INT LenWritten = swprintf_s(OutStr, StringLen, L"%s with 0x%X.", Str, hr); - if (LenWritten != -1) - { - DD_DEBUG_ERROR("%ls: %ls", Title, OutStr); - } - - delete[] OutStr; + const UINT StringLen = (UINT)(wcslen(Str) + sizeof(" with HRESULT 0x########.")); + wchar_t* OutStr = new wchar_t[StringLen]; + if (!OutStr) { + return; + } + + INT LenWritten = swprintf_s(OutStr, StringLen, L"%s with 0x%X.", Str, hr); + if (LenWritten != -1) { + DD_DEBUG_ERROR("%ls: %ls", Title, OutStr); + } + + delete[] OutStr; } - DYNAMIC_WAIT::DYNAMIC_WAIT() : m_CurrentWaitBandIdx(0), m_WaitCountInCurrentBand(0) - { - m_QPCValid = QueryPerformanceFrequency(&m_QPCFrequency); - m_LastWakeUpTime.QuadPart = 0L; - } - - DYNAMIC_WAIT::~DYNAMIC_WAIT() - { - } - - void DYNAMIC_WAIT::Wait() - { - LARGE_INTEGER CurrentQPC = { 0 }; - - // Is this wait being called with the period that we consider it to be part of the same wait sequence - QueryPerformanceCounter(&CurrentQPC); - if (m_QPCValid && (CurrentQPC.QuadPart <= (m_LastWakeUpTime.QuadPart + (m_QPCFrequency.QuadPart * m_WaitSequenceTimeInSeconds)))) - { - // We are still in the same wait sequence, lets check if we should move to the next band - if ((m_WaitBands[m_CurrentWaitBandIdx].WaitCount != WAIT_BAND_STOP) && (m_WaitCountInCurrentBand > m_WaitBands[m_CurrentWaitBandIdx].WaitCount)) - { - m_CurrentWaitBandIdx++; - m_WaitCountInCurrentBand = 0; - } - } - else - { - // Either we could not get the current time or we are starting a new wait sequence - m_WaitCountInCurrentBand = 0; - m_CurrentWaitBandIdx = 0; - } - - // Sleep for the required period of time - Sleep(m_WaitBands[m_CurrentWaitBandIdx].WaitTime); - - // Record the time we woke up so we can detect wait sequences - QueryPerformanceCounter(&m_LastWakeUpTime); - m_WaitCountInCurrentBand++; - }
\ No newline at end of file +DYNAMIC_WAIT::DYNAMIC_WAIT() : m_CurrentWaitBandIdx(0), m_WaitCountInCurrentBand(0) +{ + m_QPCValid = QueryPerformanceFrequency(&m_QPCFrequency); + m_LastWakeUpTime.QuadPart = 0L; +} + +DYNAMIC_WAIT::~DYNAMIC_WAIT() +{ +} + +void DYNAMIC_WAIT::Wait() +{ + LARGE_INTEGER CurrentQPC = { 0 }; + + // Is this wait being called with the period that we consider it to be part of the same wait sequence + QueryPerformanceCounter(&CurrentQPC); + if (m_QPCValid && (CurrentQPC.QuadPart <= (m_LastWakeUpTime.QuadPart + (m_QPCFrequency.QuadPart * m_WaitSequenceTimeInSeconds)))) { + // We are still in the same wait sequence, lets check if we should move to the next band + if ((m_WaitBands[m_CurrentWaitBandIdx].WaitCount != WAIT_BAND_STOP) && (m_WaitCountInCurrentBand > m_WaitBands[m_CurrentWaitBandIdx].WaitCount)) { + m_CurrentWaitBandIdx++; + m_WaitCountInCurrentBand = 0; + } + } + else { + // Either we could not get the current time or we are starting a new wait sequence + m_WaitCountInCurrentBand = 0; + m_CurrentWaitBandIdx = 0; + } + + // Sleep for the required period of time + Sleep(m_WaitBands[m_CurrentWaitBandIdx].WaitTime); + + // Record the time we woke up so we can detect wait sequences + QueryPerformanceCounter(&m_LastWakeUpTime); + m_WaitCountInCurrentBand++; +}
\ No newline at end of file |