From 67f0d18add5ea7e9338267bc4156f2fe5a0f343f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 17 Jul 2014 22:38:10 -0400 Subject: [PATCH] shadow: initial Win8 DXGI 1.2 support --- server/shadow/Win/win_shadow.c | 505 ++++++++++++++++++++++++++++----- server/shadow/Win/win_shadow.h | 23 ++ 2 files changed, 462 insertions(+), 66 deletions(-) diff --git a/server/shadow/Win/win_shadow.c b/server/shadow/Win/win_shadow.c index 5a3318c29..68695fe80 100644 --- a/server/shadow/Win/win_shadow.c +++ b/server/shadow/Win/win_shadow.c @@ -30,13 +30,6 @@ #ifdef WITH_DXGI_1_2 -#ifndef CINTERFACE -#define CINTERFACE -#endif - -#include -#include - static D3D_DRIVER_TYPE DriverTypes[] = { D3D_DRIVER_TYPE_HARDWARE, @@ -56,18 +49,6 @@ static D3D_FEATURE_LEVEL FeatureLevels[] = static UINT NumFeatureLevels = ARRAYSIZE(FeatureLevels); -static D3D_FEATURE_LEVEL FeatureLevel; - -static ID3D11Device* gDevice = NULL; -static ID3D11DeviceContext* gContext = NULL; -static IDXGIOutputDuplication* gOutputDuplication = NULL; -static ID3D11Texture2D* gAcquiredDesktopImage = NULL; - -static IDXGISurface* surf; -static ID3D11Texture2D* sStage; - -static DXGI_OUTDUPL_FRAME_INFO FrameInfo; - static HMODULE d3d11_module = NULL; typedef HRESULT (WINAPI * fnD3D11CreateDevice)( @@ -82,6 +63,50 @@ static fnD3D11CreateDevice pfnD3D11CreateDevice = NULL; #include +/* d3d11.h GUIDs */ + +DEFINE_GUID(IID_ID3D11DeviceChild,0x1841e5c8,0x16b0,0x489b,0xbc,0xc8,0x44,0xcf,0xb0,0xd5,0xde,0xae); +DEFINE_GUID(IID_ID3D11DepthStencilState,0x03823efb,0x8d8f,0x4e1c,0x9a,0xa2,0xf6,0x4b,0xb2,0xcb,0xfd,0xf1); +DEFINE_GUID(IID_ID3D11BlendState,0x75b68faa,0x347d,0x4159,0x8f,0x45,0xa0,0x64,0x0f,0x01,0xcd,0x9a); +DEFINE_GUID(IID_ID3D11RasterizerState,0x9bb4ab81,0xab1a,0x4d8f,0xb5,0x06,0xfc,0x04,0x20,0x0b,0x6e,0xe7); +DEFINE_GUID(IID_ID3D11Resource,0xdc8e63f3,0xd12b,0x4952,0xb4,0x7b,0x5e,0x45,0x02,0x6a,0x86,0x2d); +DEFINE_GUID(IID_ID3D11Buffer,0x48570b85,0xd1ee,0x4fcd,0xa2,0x50,0xeb,0x35,0x07,0x22,0xb0,0x37); +DEFINE_GUID(IID_ID3D11Texture1D,0xf8fb5c27,0xc6b3,0x4f75,0xa4,0xc8,0x43,0x9a,0xf2,0xef,0x56,0x4c); +DEFINE_GUID(IID_ID3D11Texture2D,0x6f15aaf2,0xd208,0x4e89,0x9a,0xb4,0x48,0x95,0x35,0xd3,0x4f,0x9c); +DEFINE_GUID(IID_ID3D11Texture3D,0x037e866e,0xf56d,0x4357,0xa8,0xaf,0x9d,0xab,0xbe,0x6e,0x25,0x0e); +DEFINE_GUID(IID_ID3D11View,0x839d1216,0xbb2e,0x412b,0xb7,0xf4,0xa9,0xdb,0xeb,0xe0,0x8e,0xd1); +DEFINE_GUID(IID_ID3D11ShaderResourceView,0xb0e06fe0,0x8192,0x4e1a,0xb1,0xca,0x36,0xd7,0x41,0x47,0x10,0xb2); +DEFINE_GUID(IID_ID3D11RenderTargetView,0xdfdba067,0x0b8d,0x4865,0x87,0x5b,0xd7,0xb4,0x51,0x6c,0xc1,0x64); +DEFINE_GUID(IID_ID3D11DepthStencilView,0x9fdac92a,0x1876,0x48c3,0xaf,0xad,0x25,0xb9,0x4f,0x84,0xa9,0xb6); +DEFINE_GUID(IID_ID3D11UnorderedAccessView,0x28acf509,0x7f5c,0x48f6,0x86,0x11,0xf3,0x16,0x01,0x0a,0x63,0x80); +DEFINE_GUID(IID_ID3D11VertexShader,0x3b301d64,0xd678,0x4289,0x88,0x97,0x22,0xf8,0x92,0x8b,0x72,0xf3); +DEFINE_GUID(IID_ID3D11HullShader,0x8e5c6061,0x628a,0x4c8e,0x82,0x64,0xbb,0xe4,0x5c,0xb3,0xd5,0xdd); +DEFINE_GUID(IID_ID3D11DomainShader,0xf582c508,0x0f36,0x490c,0x99,0x77,0x31,0xee,0xce,0x26,0x8c,0xfa); +DEFINE_GUID(IID_ID3D11GeometryShader,0x38325b96,0xeffb,0x4022,0xba,0x02,0x2e,0x79,0x5b,0x70,0x27,0x5c); +DEFINE_GUID(IID_ID3D11PixelShader,0xea82e40d,0x51dc,0x4f33,0x93,0xd4,0xdb,0x7c,0x91,0x25,0xae,0x8c); +DEFINE_GUID(IID_ID3D11ComputeShader,0x4f5b196e,0xc2bd,0x495e,0xbd,0x01,0x1f,0xde,0xd3,0x8e,0x49,0x69); +DEFINE_GUID(IID_ID3D11InputLayout,0xe4819ddc,0x4cf0,0x4025,0xbd,0x26,0x5d,0xe8,0x2a,0x3e,0x07,0xb7); +DEFINE_GUID(IID_ID3D11SamplerState,0xda6fea51,0x564c,0x4487,0x98,0x10,0xf0,0xd0,0xf9,0xb4,0xe3,0xa5); +DEFINE_GUID(IID_ID3D11Asynchronous,0x4b35d0cd,0x1e15,0x4258,0x9c,0x98,0x1b,0x13,0x33,0xf6,0xdd,0x3b); +DEFINE_GUID(IID_ID3D11Query,0xd6c00747,0x87b7,0x425e,0xb8,0x4d,0x44,0xd1,0x08,0x56,0x0a,0xfd); +DEFINE_GUID(IID_ID3D11Predicate,0x9eb576dd,0x9f77,0x4d86,0x81,0xaa,0x8b,0xab,0x5f,0xe4,0x90,0xe2); +DEFINE_GUID(IID_ID3D11Counter,0x6e8c49fb,0xa371,0x4770,0xb4,0x40,0x29,0x08,0x60,0x22,0xb7,0x41); +DEFINE_GUID(IID_ID3D11ClassInstance,0xa6cd7faa,0xb0b7,0x4a2f,0x94,0x36,0x86,0x62,0xa6,0x57,0x97,0xcb); +DEFINE_GUID(IID_ID3D11ClassLinkage,0xddf57cba,0x9543,0x46e4,0xa1,0x2b,0xf2,0x07,0xa0,0xfe,0x7f,0xed); +DEFINE_GUID(IID_ID3D11CommandList,0xa24bc4d1,0x769e,0x43f7,0x80,0x13,0x98,0xff,0x56,0x6c,0x18,0xe2); +DEFINE_GUID(IID_ID3D11DeviceContext,0xc0bfa96c,0xe089,0x44fb,0x8e,0xaf,0x26,0xf8,0x79,0x61,0x90,0xda); +DEFINE_GUID(IID_ID3D11VideoDecoder,0x3C9C5B51,0x995D,0x48d1,0x9B,0x8D,0xFA,0x5C,0xAE,0xDE,0xD6,0x5C); +DEFINE_GUID(IID_ID3D11VideoProcessorEnumerator,0x31627037,0x53AB,0x4200,0x90,0x61,0x05,0xFA,0xA9,0xAB,0x45,0xF9); +DEFINE_GUID(IID_ID3D11VideoProcessor,0x1D7B0652,0x185F,0x41c6,0x85,0xCE,0x0C,0x5B,0xE3,0xD4,0xAE,0x6C); +DEFINE_GUID(IID_ID3D11AuthenticatedChannel,0x3015A308,0xDCBD,0x47aa,0xA7,0x47,0x19,0x24,0x86,0xD1,0x4D,0x4A); +DEFINE_GUID(IID_ID3D11CryptoSession,0x9B32F9AD,0xBDCC,0x40a6,0xA3,0x9D,0xD5,0xC8,0x65,0x84,0x57,0x20); +DEFINE_GUID(IID_ID3D11VideoDecoderOutputView,0xC2931AEA,0x2A85,0x4f20,0x86,0x0F,0xFB,0xA1,0xFD,0x25,0x6E,0x18); +DEFINE_GUID(IID_ID3D11VideoProcessorInputView,0x11EC5A5F,0x51DC,0x4945,0xAB,0x34,0x6E,0x8C,0x21,0x30,0x0E,0xA5); +DEFINE_GUID(IID_ID3D11VideoProcessorOutputView,0xA048285E,0x25A9,0x4527,0xBD,0x93,0xD6,0x8B,0x68,0xC4,0x42,0x54); +DEFINE_GUID(IID_ID3D11VideoContext,0x61F21C45,0x3C0E,0x4a74,0x9C,0xEA,0x67,0x10,0x0D,0x9A,0xD5,0xE4); +DEFINE_GUID(IID_ID3D11VideoDevice,0x10EC4D5B,0x975A,0x4689,0xB9,0xE4,0xD0,0xAA,0xC3,0x0F,0xE3,0x33); +DEFINE_GUID(IID_ID3D11Device,0xdb6f6ddb,0xac77,0x4e88,0x82,0x53,0x81,0x9d,0xf9,0xbb,0xf1,0x40); + /* dxgi.h GUIDs */ DEFINE_GUID(IID_IDXGIObject, 0xaec22fb8, 0x76f3, 0x4639, 0x9b, 0xe0, 0x28, 0xeb, 0x43, 0xa6, 0x7a, 0x2e); @@ -124,11 +149,10 @@ static void win_shadow_d3d11_module_init() pfnD3D11CreateDevice = (fnD3D11CreateDevice) GetProcAddress(d3d11_module, "D3D11CreateDevice"); } -int win_shadow_dxgi_init(winShadowSubsystem* subsystem) +int win_shadow_dxgi_init_duplication(winShadowSubsystem* subsystem) { - HRESULT status; + HRESULT hr; UINT dTop, i = 0; - UINT DriverTypeIndex; DXGI_OUTPUT_DESC desc; IDXGIOutput* pOutput; IDXGIDevice* DxgiDevice = NULL; @@ -136,6 +160,75 @@ int win_shadow_dxgi_init(winShadowSubsystem* subsystem) IDXGIOutput* DxgiOutput = NULL; IDXGIOutput1* DxgiOutput1 = NULL; + hr = subsystem->dxgiDevice->lpVtbl->QueryInterface(subsystem->dxgiDevice, &IID_IDXGIDevice, (void**) &DxgiDevice); + + if (FAILED(hr)) + return -1; + + hr = DxgiDevice->lpVtbl->GetParent(DxgiDevice, &IID_IDXGIAdapter, (void**) &DxgiAdapter); + DxgiDevice->lpVtbl->Release(DxgiDevice); + DxgiDevice = NULL; + + if (FAILED(hr)) + return -1; + + ZeroMemory(&desc, sizeof(desc)); + pOutput = NULL; + + while (DxgiAdapter->lpVtbl->EnumOutputs(DxgiAdapter, i, &pOutput) != DXGI_ERROR_NOT_FOUND) + { + DXGI_OUTPUT_DESC* pDesc = &desc; + + hr = pOutput->lpVtbl->GetDesc(pOutput, pDesc); + + if (FAILED(hr)) + return -1; + + if (pDesc->AttachedToDesktop) + dTop = i; + + pOutput->lpVtbl->Release(pOutput); + ++i; + } + + dTop = 0; /* screen id */ + + hr = DxgiAdapter->lpVtbl->EnumOutputs(DxgiAdapter, dTop, &DxgiOutput); + DxgiAdapter->lpVtbl->Release(DxgiAdapter); + DxgiAdapter = NULL; + + if (FAILED(hr)) + return -1; + + hr = DxgiOutput->lpVtbl->QueryInterface(DxgiOutput, &IID_IDXGIOutput1, (void**) &DxgiOutput1); + DxgiOutput->lpVtbl->Release(DxgiOutput); + DxgiOutput = NULL; + + if (FAILED(hr)) + return -1; + + hr = DxgiOutput1->lpVtbl->DuplicateOutput(DxgiOutput1, (IUnknown*) subsystem->dxgiDevice, + &(subsystem->dxgiOutputDuplication)); + + DxgiOutput1->lpVtbl->Release(DxgiOutput1); + DxgiOutput1 = NULL; + + if (FAILED(hr)) + return -1; + + return 1; +} + +int win_shadow_dxgi_init(winShadowSubsystem* subsystem) +{ + UINT i = 0; + HRESULT hr; + UINT DriverTypeIndex; + IDXGIDevice* DxgiDevice = NULL; + IDXGIAdapter* DxgiAdapter = NULL; + IDXGIOutput* DxgiOutput = NULL; + IDXGIOutput1* DxgiOutput1 = NULL; + win_shadow_d3d11_module_init(); if (!pfnD3D11CreateDevice) @@ -143,69 +236,287 @@ int win_shadow_dxgi_init(winShadowSubsystem* subsystem) for (DriverTypeIndex = 0; DriverTypeIndex < NumDriverTypes; ++DriverTypeIndex) { - status = pfnD3D11CreateDevice(NULL, DriverTypes[DriverTypeIndex], NULL, 0, FeatureLevels, - NumFeatureLevels, D3D11_SDK_VERSION, &gDevice, &FeatureLevel, &gContext); + hr = pfnD3D11CreateDevice(NULL, DriverTypes[DriverTypeIndex], NULL, 0, FeatureLevels, + NumFeatureLevels, D3D11_SDK_VERSION, &(subsystem->dxgiDevice), &(subsystem->featureLevel), + &(subsystem->dxgiDeviceContext)); - if (SUCCEEDED(status)) + if (SUCCEEDED(hr)) break; } - if (FAILED(status)) + if (FAILED(hr)) return -1; - status = gDevice->lpVtbl->QueryInterface(gDevice, &IID_IDXGIDevice, (void**) &DxgiDevice); + win_shadow_dxgi_init_duplication(subsystem); - if (FAILED(status)) - return -1; + return 1; +} - status = DxgiDevice->lpVtbl->GetParent(DxgiDevice, &IID_IDXGIAdapter, (void**) &DxgiAdapter); - DxgiDevice->lpVtbl->Release(DxgiDevice); - DxgiDevice = NULL; - - if (FAILED(status)) - return -1; - - ZeroMemory(&desc, sizeof(desc)); - pOutput = NULL; - - while (DxgiAdapter->lpVtbl->EnumOutputs(DxgiAdapter, i, &pOutput) != DXGI_ERROR_NOT_FOUND) +int win_shadow_dxgi_uninit(winShadowSubsystem* subsystem) +{ + if (subsystem->dxgiDesktopImage) { - DXGI_OUTPUT_DESC* pDesc = &desc; - - status = pOutput->lpVtbl->GetDesc(pOutput, pDesc); - - if (FAILED(status)) - return -1; - - if (pDesc->AttachedToDesktop) - dTop = i; - - pOutput->lpVtbl->Release(pOutput); - ++i; + subsystem->dxgiDesktopImage->lpVtbl->Release(subsystem->dxgiDesktopImage); + subsystem->dxgiDesktopImage = NULL; } - dTop = 0; /* screen id */ + if (subsystem->dxgiOutputDuplication) + { + subsystem->dxgiOutputDuplication->lpVtbl->Release(subsystem->dxgiOutputDuplication); + subsystem->dxgiOutputDuplication = NULL; + } - status = DxgiAdapter->lpVtbl->EnumOutputs(DxgiAdapter, dTop, &DxgiOutput); - DxgiAdapter->lpVtbl->Release(DxgiAdapter); - DxgiAdapter = NULL; + if (subsystem->dxgiDeviceContext) + { + subsystem->dxgiDeviceContext->lpVtbl->Release(subsystem->dxgiDeviceContext); + subsystem->dxgiDeviceContext = NULL; + } - if (FAILED(status)) + if (subsystem->dxgiDevice) + { + subsystem->dxgiDevice->lpVtbl->Release(subsystem->dxgiDevice); + subsystem->dxgiDevice = NULL; + } + + return 1; +} + +int win_shadow_dxgi_fetch_frame_data(winShadowSubsystem* subsystem, + BYTE** ppDstData, int* pnDstStep, int x, int y, int width, int height) +{ + HRESULT hr; + D3D11_BOX Box; + DXGI_MAPPED_RECT mappedRect; + D3D11_TEXTURE2D_DESC tDesc; + + tDesc.Width = width; + tDesc.Height = height; + tDesc.MipLevels = 1; + tDesc.ArraySize = 1; + tDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + tDesc.SampleDesc.Count = 1; + tDesc.SampleDesc.Quality = 0; + tDesc.Usage = D3D11_USAGE_STAGING; + tDesc.BindFlags = 0; + tDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + tDesc.MiscFlags = 0; + + Box.top = x; + Box.left = y; + Box.right = x + width; + Box.bottom = y + height; + Box.front = 0; + Box.back = 1; + + hr = subsystem->dxgiDevice->lpVtbl->CreateTexture2D(subsystem->dxgiDevice, &tDesc, NULL, &(subsystem->dxgiStage)); + + if (FAILED(hr)) return -1; - status = DxgiOutput->lpVtbl->QueryInterface(DxgiOutput, &IID_IDXGIOutput1, (void**) &DxgiOutput1); - DxgiOutput->lpVtbl->Release(DxgiOutput); - DxgiOutput = NULL; + subsystem->dxgiDeviceContext->lpVtbl->CopySubresourceRegion(subsystem->dxgiDeviceContext, + (ID3D11Resource*) subsystem->dxgiStage, 0, 0, 0, 0, (ID3D11Resource*) subsystem->dxgiDesktopImage, 0, &Box); - if (FAILED(status)) + hr = subsystem->dxgiStage->lpVtbl->QueryInterface(subsystem->dxgiStage, + &IID_IDXGISurface, (void**) &(subsystem->dxgiSurface)); + + if (FAILED(hr)) return -1; - status = DxgiOutput1->lpVtbl->DuplicateOutput(DxgiOutput1, (IUnknown*) gDevice, &gOutputDuplication); - DxgiOutput1->lpVtbl->Release(DxgiOutput1); - DxgiOutput1 = NULL; + hr = subsystem->dxgiSurface->lpVtbl->Map(subsystem->dxgiSurface, &mappedRect, DXGI_MAP_READ); - if (FAILED(status)) + if (FAILED(hr)) return -1; + + *ppDstData = mappedRect.pBits; + *pnDstStep = mappedRect.Pitch; + + return 1; +} + +int win_shadow_dxgi_release_frame_data(winShadowSubsystem* subsystem) +{ + HRESULT hr; + + if (subsystem->dxgiSurface) + { + subsystem->dxgiSurface->lpVtbl->Unmap(subsystem->dxgiSurface); + subsystem->dxgiSurface->lpVtbl->Release(subsystem->dxgiSurface); + subsystem->dxgiSurface = NULL; + } + + if (subsystem->dxgiStage) + { + subsystem->dxgiStage->lpVtbl->Release(subsystem->dxgiStage); + subsystem->dxgiStage = NULL; + } + + hr = subsystem->dxgiOutputDuplication->lpVtbl->ReleaseFrame(subsystem->dxgiOutputDuplication); + + if (FAILED(hr)) + return -1; + + subsystem->pendingFrames = 0; + + return 1; +} + +int win_shadow_dxgi_get_next_frame(winShadowSubsystem* subsystem) +{ + UINT i = 0; + int status; + HRESULT hr = 0; + UINT DataBufferSize = 0; + BYTE* DataBuffer = NULL; + IDXGIResource* DesktopResource = NULL; + + if (subsystem->pendingFrames > 0) + { + win_shadow_dxgi_release_frame_data(subsystem); + } + + if (subsystem->dxgiDesktopImage) + { + subsystem->dxgiDesktopImage->lpVtbl->Release(subsystem->dxgiDesktopImage); + subsystem->dxgiDesktopImage = NULL; + } + + hr = subsystem->dxgiOutputDuplication->lpVtbl->AcquireNextFrame(subsystem->dxgiOutputDuplication, + 0, &(subsystem->dxgiFrameInfo), &DesktopResource); + + if (hr == DXGI_ERROR_WAIT_TIMEOUT) + return 0; + + if (FAILED(hr)) + { + if (hr == DXGI_ERROR_ACCESS_LOST) + { + if (subsystem->dxgiDesktopImage) + { + subsystem->dxgiDesktopImage->lpVtbl->Release(subsystem->dxgiDesktopImage); + subsystem->dxgiDesktopImage = NULL; + } + + if (subsystem->dxgiOutputDuplication) + { + subsystem->dxgiOutputDuplication->lpVtbl->Release(subsystem->dxgiOutputDuplication); + subsystem->dxgiOutputDuplication = NULL; + } + + status = win_shadow_dxgi_init_duplication(subsystem); + + if (status < 0) + return -1; + + return 0; + } + else + { + hr = subsystem->dxgiOutputDuplication->lpVtbl->ReleaseFrame(subsystem->dxgiOutputDuplication); + + if (FAILED(hr)) + return -1; + + return -1; + } + } + + hr = DesktopResource->lpVtbl->QueryInterface(DesktopResource, + &IID_ID3D11Texture2D, (void**) &(subsystem->dxgiDesktopImage)); + + DesktopResource->lpVtbl->Release(DesktopResource); + DesktopResource = NULL; + + if (FAILED(hr)) + return -1; + + subsystem->pendingFrames = subsystem->dxgiFrameInfo.AccumulatedFrames; + + if (subsystem->dxgiFrameInfo.AccumulatedFrames == 0) + { + hr = subsystem->dxgiOutputDuplication->lpVtbl->ReleaseFrame(subsystem->dxgiOutputDuplication); + + if (FAILED(hr)) + return -1; + } + + return 1; +} + +int win_shadow_dxgi_get_invalid_region(winShadowSubsystem* subsystem) +{ + UINT i; + HRESULT hr; + UINT BufSize; + RECT* pRect; + UINT numRects; + BYTE* DirtyRects; + rdpShadowServer* server; + rdpShadowScreen* screen; + UINT DataBufferSize = 0; + BYTE* DataBuffer = NULL; + RECTANGLE_16 invalidRect; + + server = subsystem->server; + screen = server->screen; + + if (subsystem->dxgiFrameInfo.AccumulatedFrames == 0) + return 0; + + if (subsystem->dxgiFrameInfo.TotalMetadataBufferSize) + { + if (subsystem->dxgiFrameInfo.TotalMetadataBufferSize > DataBufferSize) + { + if (DataBuffer) + { + free(DataBuffer); + DataBuffer = NULL; + } + + DataBuffer = (BYTE*) malloc(subsystem->dxgiFrameInfo.TotalMetadataBufferSize); + + if (!DataBuffer) + return -1; + + DataBufferSize = subsystem->dxgiFrameInfo.TotalMetadataBufferSize; + } + + BufSize = subsystem->dxgiFrameInfo.TotalMetadataBufferSize; + + hr = subsystem->dxgiOutputDuplication->lpVtbl->GetFrameMoveRects(subsystem->dxgiOutputDuplication, + BufSize, (DXGI_OUTDUPL_MOVE_RECT*) DataBuffer, &BufSize); + + if (FAILED(hr)) + return -1; + + DirtyRects = DataBuffer + BufSize; + BufSize = subsystem->dxgiFrameInfo.TotalMetadataBufferSize - BufSize; + + hr = subsystem->dxgiOutputDuplication->lpVtbl->GetFrameDirtyRects(subsystem->dxgiOutputDuplication, + BufSize, (RECT*) DirtyRects, &BufSize); + + if (FAILED(hr)) + return -1; + + numRects = BufSize / sizeof(RECT); + + pRect = (RECT*) DirtyRects; + + EnterCriticalSection(&(screen->lock)); + + for (i = 0; i < numRects; i++) + { + invalidRect.left = (UINT16) pRect->left; + invalidRect.top = (UINT16) pRect->top; + invalidRect.right = (UINT16) pRect->right; + invalidRect.bottom = (UINT16) pRect->bottom; + + region16_union_rect(&(screen->invalidRegion), &(screen->invalidRegion), &invalidRect); + + pRect++; + } + + LeaveCriticalSection(&(screen->lock)); + } return 1; } @@ -385,6 +696,51 @@ int win_shadow_invalidate_region(winShadowSubsystem* subsystem, int x, int y, in int win_shadow_surface_copy(winShadowSubsystem* subsystem) { + int x, y; + int width; + int height; + int status; + int nDstStep = 0; + BYTE* pDstData = NULL; + rdpShadowScreen* screen; + rdpShadowServer* server; + rdpShadowSurface* surface; + RECTANGLE_16 surfaceRect; + const RECTANGLE_16* extents; + + server = subsystem->server; + surface = server->surface; + screen = server->screen; + + surfaceRect.left = surface->x; + surfaceRect.top = surface->y; + surfaceRect.right = surface->x + surface->width; + surfaceRect.bottom = surface->y + surface->height; + + region16_clear(&(surface->invalidRegion)); + region16_intersect_rect(&(surface->invalidRegion), &(screen->invalidRegion), &surfaceRect); + + if (region16_is_empty(&(surface->invalidRegion))) + return 1; + + extents = region16_extents(&(surface->invalidRegion)); + + x = extents->left; + y = extents->top; + width = extents->right - extents->left; + height = extents->bottom - extents->top; + + printf("x: %d y: %d width: %d height: %d\n", x, y, width, height); + + status = win_shadow_dxgi_fetch_frame_data(subsystem, &pDstData, &nDstStep, x, y, width, height); + + if (status < 0) + return -1; + + freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, + surface->scanline, x - surface->x, y - surface->y, width, height, + pDstData, PIXEL_FORMAT_XRGB32, nDstStep, 0, 0); + return 1; } @@ -409,6 +765,8 @@ void* win_shadow_subsystem_thread(winShadowSubsystem* subsystem) dwInterval = 1000 / fps; frameTime = GetTickCount64() + dwInterval; + win_shadow_invalidate_region(subsystem, 0, 0, subsystem->width, subsystem->height); + while (1) { dwTimeout = INFINITE; @@ -425,7 +783,18 @@ void* win_shadow_subsystem_thread(winShadowSubsystem* subsystem) if ((status == WAIT_TIMEOUT) || (GetTickCount64() > frameTime)) { - win_shadow_invalidate_region(subsystem, 0, 0, subsystem->width, subsystem->height); +#ifdef WITH_DXGI_1_2 + int dxgi_status; + + dxgi_status = win_shadow_dxgi_get_next_frame(subsystem); + + if (subsystem->pendingFrames > 0) + { + dxgi_status = win_shadow_dxgi_get_invalid_region(subsystem); + + win_shadow_invalidate_region(subsystem, 0, 0, subsystem->width, subsystem->height); + } +#endif dwInterval = 1000 / fps; frameTime += dwInterval; @@ -490,6 +859,10 @@ int win_shadow_subsystem_uninit(winShadowSubsystem* subsystem) if (!subsystem) return -1; +#ifdef WITH_DXGI_1_2 + win_shadow_dxgi_uninit(subsystem); +#endif + return 1; } diff --git a/server/shadow/Win/win_shadow.h b/server/shadow/Win/win_shadow.h index 9da11e371..a84a8d540 100644 --- a/server/shadow/Win/win_shadow.h +++ b/server/shadow/Win/win_shadow.h @@ -33,6 +33,17 @@ typedef struct win_shadow_subsystem winShadowSubsystem; #define WITH_DXGI_1_2 1 #endif +#ifdef WITH_DXGI_1_2 + +#ifndef CINTERFACE +#define CINTERFACE +#endif + +#include +#include + +#endif + struct win_shadow_subsystem { RDP_SHADOW_SUBSYSTEM_COMMON(); @@ -40,6 +51,18 @@ struct win_shadow_subsystem int bpp; int width; int height; + +#ifdef WITH_DXGI_1_2 + UINT pendingFrames; + ID3D11Device* dxgiDevice; + IDXGISurface* dxgiSurface; + ID3D11Texture2D* dxgiStage; + D3D_FEATURE_LEVEL featureLevel; + ID3D11Texture2D* dxgiDesktopImage; + DXGI_OUTDUPL_FRAME_INFO dxgiFrameInfo; + ID3D11DeviceContext* dxgiDeviceContext; + IDXGIOutputDuplication* dxgiOutputDuplication; +#endif }; #ifdef __cplusplus