shadow: improve DXGI 1.2 error checking

This commit is contained in:
Marc-André Moreau 2014-07-18 17:26:21 -04:00
parent eae6efd23f
commit c45ddc783e
7 changed files with 410 additions and 170 deletions

View File

@ -55,6 +55,7 @@ typedef int (*pfnShadowSubsystemStop)(rdpShadowSubsystem* subsystem);
typedef void (*pfnShadowSubsystemFree)(rdpShadowSubsystem* subsystem);
typedef int (*pfnShadowSurfaceCopy)(rdpShadowSubsystem* subsystem);
typedef int (*pfnShadowSurfaceUpdate)(rdpShadowSubsystem* subsystem, REGION16* region);
typedef int (*pfnShadowSynchronizeEvent)(rdpShadowSubsystem* subsystem, UINT32 flags);
typedef int (*pfnShadowKeyboardEvent)(rdpShadowSubsystem* subsystem, UINT16 flags, UINT16 code);
@ -72,8 +73,11 @@ struct rdp_shadow_client
BOOL mayView;
BOOL mayInteract;
HANDLE StopEvent;
CRITICAL_SECTION lock;
REGION16 invalidRegion;
rdpShadowServer* server;
rdpShadowSurface* lobby;
rdpShadowEncoder* encoder;
HANDLE vcm;
EncomspServerContext* encomsp;
@ -85,15 +89,18 @@ struct rdp_shadow_server
void* ext;
HANDLE thread;
HANDLE StopEvent;
wArrayList* clients;
rdpShadowScreen* screen;
rdpShadowSurface* surface;
rdpShadowEncoder* encoder;
rdpShadowSubsystem* subsystem;
DWORD port;
BOOL mayView;
BOOL mayInteract;
char* ConfigPath;
char* CertificateFile;
char* PrivateKeyFile;
CRITICAL_SECTION lock;
freerdp_listener* listener;
pfnShadowCreateSubsystem CreateSubsystem;
};
@ -103,6 +110,7 @@ struct rdp_shadow_server
int monitorCount; \
MONITOR_DEF monitors[16]; \
MONITOR_DEF virtualScreen; \
REGION16 invalidRegion; \
\
pfnShadowSubsystemInit Init; \
pfnShadowSubsystemUninit Uninit; \
@ -111,6 +119,7 @@ struct rdp_shadow_server
pfnShadowSubsystemFree Free; \
\
pfnShadowSurfaceCopy SurfaceCopy; \
pfnShadowSurfaceUpdate SurfaceUpdate; \
\
pfnShadowSynchronizeEvent SynchronizeEvent; \
pfnShadowKeyboardEvent KeyboardEvent; \

View File

@ -136,6 +136,87 @@ DEFINE_GUID(IID_IDXGIFactory2, 0x50c83a1c, 0xe072, 0x4c48, 0x87, 0xb0, 0x36, 0x3
DEFINE_GUID(IID_IDXGIAdapter2, 0x0AA1AE0A, 0xFA0E, 0x4B84, 0x86, 0x44, 0xE0, 0x5F, 0xF8, 0xE5, 0xAC, 0xB5);
DEFINE_GUID(IID_IDXGIOutput1, 0x00cddea8, 0x939b, 0x4b83, 0xa3, 0x40, 0xa6, 0x85, 0x22, 0x66, 0x66, 0xcc);
const char* GetDxgiErrorString(HRESULT hr)
{
switch (hr)
{
case DXGI_STATUS_OCCLUDED:
return "DXGI_STATUS_OCCLUDED";
case DXGI_STATUS_CLIPPED:
return "DXGI_STATUS_CLIPPED";
case DXGI_STATUS_NO_REDIRECTION:
return "DXGI_STATUS_NO_REDIRECTION";
case DXGI_STATUS_NO_DESKTOP_ACCESS:
return "DXGI_STATUS_NO_DESKTOP_ACCESS";
case DXGI_STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE:
return "DXGI_STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE";
case DXGI_STATUS_MODE_CHANGED:
return "DXGI_STATUS_MODE_CHANGED";
case DXGI_STATUS_MODE_CHANGE_IN_PROGRESS:
return "DXGI_STATUS_MODE_CHANGE_IN_PROGRESS";
case DXGI_ERROR_INVALID_CALL:
return "DXGI_ERROR_INVALID_CALL";
case DXGI_ERROR_NOT_FOUND:
return "DXGI_ERROR_NOT_FOUND";
case DXGI_ERROR_MORE_DATA:
return "DXGI_ERROR_MORE_DATA";
case DXGI_ERROR_UNSUPPORTED:
return "DXGI_ERROR_UNSUPPORTED";
case DXGI_ERROR_DEVICE_REMOVED:
return "DXGI_ERROR_DEVICE_REMOVED";
case DXGI_ERROR_DEVICE_HUNG:
return "DXGI_ERROR_DEVICE_HUNG";
case DXGI_ERROR_DEVICE_RESET:
return "DXGI_ERROR_DEVICE_RESET";
case DXGI_ERROR_WAS_STILL_DRAWING:
return "DXGI_ERROR_WAS_STILL_DRAWING";
case DXGI_ERROR_FRAME_STATISTICS_DISJOINT:
return "DXGI_ERROR_FRAME_STATISTICS_DISJOINT";
case DXGI_ERROR_GRAPHICS_VIDPN_SOURCE_IN_USE:
return "DXGI_ERROR_GRAPHICS_VIDPN_SOURCE_IN_USE";
case DXGI_ERROR_DRIVER_INTERNAL_ERROR:
return "DXGI_ERROR_DRIVER_INTERNAL_ERROR";
case DXGI_ERROR_NONEXCLUSIVE:
return "DXGI_ERROR_NONEXCLUSIVE";
case DXGI_ERROR_NOT_CURRENTLY_AVAILABLE:
return "DXGI_ERROR_NOT_CURRENTLY_AVAILABLE";
case DXGI_ERROR_REMOTE_CLIENT_DISCONNECTED:
return "DXGI_ERROR_REMOTE_CLIENT_DISCONNECTED";
case DXGI_ERROR_REMOTE_OUTOFMEMORY:
return "DXGI_ERROR_REMOTE_OUTOFMEMORY";
case DXGI_ERROR_ACCESS_LOST:
return "DXGI_ERROR_ACCESS_LOST";
case DXGI_ERROR_WAIT_TIMEOUT:
return "DXGI_ERROR_WAIT_TIMEOUT";
case DXGI_ERROR_SESSION_DISCONNECTED:
return "DXGI_ERROR_SESSION_DISCONNECTED";
case DXGI_ERROR_RESTRICT_TO_OUTPUT_STALE:
return "DXGI_ERROR_RESTRICT_TO_OUTPUT_STALE";
case DXGI_ERROR_CANNOT_PROTECT_CONTENT:
return "DXGI_ERROR_CANNOT_PROTECT_CONTENT";
case DXGI_ERROR_ACCESS_DENIED:
return "DXGI_ERROR_ACCESS_DENIED";
case DXGI_ERROR_NAME_ALREADY_EXISTS:
return "DXGI_ERROR_NAME_ALREADY_EXISTS";
case DXGI_ERROR_SDK_COMPONENT_MISSING:
return "DXGI_ERROR_SDK_COMPONENT_MISSING";
case DXGI_STATUS_UNOCCLUDED:
return "DXGI_STATUS_UNOCCLUDED";
case DXGI_STATUS_DDA_WAS_STILL_DRAWING:
return "DXGI_STATUS_DDA_WAS_STILL_DRAWING";
case DXGI_ERROR_MODE_CHANGE_IN_PROGRESS:
return "DXGI_ERROR_MODE_CHANGE_IN_PROGRESS";
case DXGI_DDI_ERR_WASSTILLDRAWING:
return "DXGI_DDI_ERR_WASSTILLDRAWING";
case DXGI_DDI_ERR_UNSUPPORTED:
return "DXGI_DDI_ERR_UNSUPPORTED";
case DXGI_DDI_ERR_NONEXCLUSIVE:
return "DXGI_DDI_ERR_NONEXCLUSIVE";
}
return "DXGI_ERROR_UNKNOWN";
}
static void win_shadow_d3d11_module_init()
{
if (d3d11_module)
@ -155,39 +236,55 @@ int win_shadow_dxgi_init_duplication(winShadowSubsystem* subsystem)
UINT dTop, i = 0;
IDXGIOutput* pOutput;
DXGI_OUTPUT_DESC outputDesc;
DXGI_OUTPUT_DESC* pOutputDesc;
D3D11_TEXTURE2D_DESC textureDesc;
IDXGIDevice* DxgiDevice = NULL;
IDXGIAdapter* DxgiAdapter = NULL;
IDXGIOutput* DxgiOutput = NULL;
IDXGIOutput1* DxgiOutput1 = NULL;
IDXGIDevice* dxgiDevice = NULL;
IDXGIAdapter* dxgiAdapter = NULL;
IDXGIOutput* dxgiOutput = NULL;
IDXGIOutput1* dxgiOutput1 = NULL;
hr = subsystem->dxgiDevice->lpVtbl->QueryInterface(subsystem->dxgiDevice,
&IID_IDXGIDevice, (void**) &DxgiDevice);
&IID_IDXGIDevice, (void**) &dxgiDevice);
if (FAILED(hr))
{
fprintf(stderr, "ID3D11Device::QueryInterface(IDXGIDevice) failure: %s (0x%04X)\n",
GetDxgiErrorString(hr), hr);
return -1;
}
hr = DxgiDevice->lpVtbl->GetParent(DxgiDevice, &IID_IDXGIAdapter, (void**) &DxgiAdapter);
hr = dxgiDevice->lpVtbl->GetParent(dxgiDevice, &IID_IDXGIAdapter, (void**) &dxgiAdapter);
DxgiDevice->lpVtbl->Release(DxgiDevice);
DxgiDevice = NULL;
if (dxgiDevice)
{
dxgiDevice->lpVtbl->Release(dxgiDevice);
dxgiDevice = NULL;
}
if (FAILED(hr))
{
fprintf(stderr, "IDXGIDevice::GetParent(IDXGIAdapter) failure: %s (0x%04X)\n",
GetDxgiErrorString(hr), hr);
return -1;
}
pOutput = NULL;
ZeroMemory(&outputDesc, sizeof(outputDesc));
while (DxgiAdapter->lpVtbl->EnumOutputs(DxgiAdapter, i, &pOutput) != DXGI_ERROR_NOT_FOUND)
while (dxgiAdapter->lpVtbl->EnumOutputs(dxgiAdapter, i, &pOutput) != DXGI_ERROR_NOT_FOUND)
{
DXGI_OUTPUT_DESC* pDesc = &outputDesc;
pOutputDesc = &outputDesc;
hr = pOutput->lpVtbl->GetDesc(pOutput, pDesc);
hr = pOutput->lpVtbl->GetDesc(pOutput, pOutputDesc);
if (FAILED(hr))
{
fprintf(stderr, "IDXGIOutput::GetDesc failure: %s (0x%04X)\n",
GetDxgiErrorString(hr), hr);
return -1;
}
if (pDesc->AttachedToDesktop)
if (pOutputDesc->AttachedToDesktop)
dTop = i;
pOutput->lpVtbl->Release(pOutput);
@ -196,30 +293,51 @@ int win_shadow_dxgi_init_duplication(winShadowSubsystem* subsystem)
dTop = 0; /* screen id */
hr = DxgiAdapter->lpVtbl->EnumOutputs(DxgiAdapter, dTop, &DxgiOutput);
hr = dxgiAdapter->lpVtbl->EnumOutputs(dxgiAdapter, dTop, &dxgiOutput);
DxgiAdapter->lpVtbl->Release(DxgiAdapter);
DxgiAdapter = NULL;
if (dxgiAdapter)
{
dxgiAdapter->lpVtbl->Release(dxgiAdapter);
dxgiAdapter = NULL;
}
if (FAILED(hr))
{
fprintf(stderr, "IDXGIAdapter::EnumOutputs failure: %s (0x%04X)\n",
GetDxgiErrorString(hr), hr);
return -1;
}
hr = DxgiOutput->lpVtbl->QueryInterface(DxgiOutput, &IID_IDXGIOutput1, (void**) &DxgiOutput1);
hr = dxgiOutput->lpVtbl->QueryInterface(dxgiOutput, &IID_IDXGIOutput1, (void**) &dxgiOutput1);
DxgiOutput->lpVtbl->Release(DxgiOutput);
DxgiOutput = NULL;
if (dxgiOutput)
{
dxgiOutput->lpVtbl->Release(dxgiOutput);
dxgiOutput = NULL;
}
if (FAILED(hr))
{
fprintf(stderr, "IDXGIOutput::QueryInterface(IDXGIOutput1) failure: %s (0x%04X)\n",
GetDxgiErrorString(hr), hr);
return -1;
}
hr = DxgiOutput1->lpVtbl->DuplicateOutput(DxgiOutput1, (IUnknown*) subsystem->dxgiDevice,
hr = dxgiOutput1->lpVtbl->DuplicateOutput(dxgiOutput1, (IUnknown*) subsystem->dxgiDevice,
&(subsystem->dxgiOutputDuplication));
DxgiOutput1->lpVtbl->Release(DxgiOutput1);
DxgiOutput1 = NULL;
if (dxgiOutput1)
{
dxgiOutput1->lpVtbl->Release(dxgiOutput1);
dxgiOutput1 = NULL;
}
if (FAILED(hr))
{
fprintf(stderr, "IDXGIOutput1::DuplicateOutput failure: %s (0x%04X)\n",
GetDxgiErrorString(hr), hr);
return -1;
}
textureDesc.Width = subsystem->width;
textureDesc.Height = subsystem->height;
@ -237,7 +355,11 @@ int win_shadow_dxgi_init_duplication(winShadowSubsystem* subsystem)
&textureDesc, NULL, &(subsystem->dxgiStage));
if (FAILED(hr))
{
fprintf(stderr, "ID3D11Device::CreateTexture2D failure: %s (0x%04X)\n",
GetDxgiErrorString(hr), hr);
return -1;
}
return 1;
}
@ -268,7 +390,10 @@ int win_shadow_dxgi_init(winShadowSubsystem* subsystem)
}
if (FAILED(hr))
{
fprintf(stderr, "D3D11CreateDevice failure: 0x%04X\n", hr);
return -1;
}
win_shadow_dxgi_init_duplication(subsystem);
@ -317,6 +442,9 @@ int win_shadow_dxgi_fetch_frame_data(winShadowSubsystem* subsystem,
D3D11_BOX Box;
DXGI_MAPPED_RECT mappedRect;
if ((width * height) < 1)
return 1;
Box.top = x;
Box.left = y;
Box.right = x + width;
@ -331,12 +459,22 @@ int win_shadow_dxgi_fetch_frame_data(winShadowSubsystem* subsystem,
&IID_IDXGISurface, (void**) &(subsystem->dxgiSurface));
if (FAILED(hr))
{
fprintf(stderr, "ID3D11Texture2D::QueryInterface(IDXGISurface) failure: %s 0x%04X\n",
GetDxgiErrorString(hr), hr);
return -1;
}
hr = subsystem->dxgiSurface->lpVtbl->Map(subsystem->dxgiSurface, &mappedRect, DXGI_MAP_READ);
if (FAILED(hr))
{
fprintf(stderr, "IDXGISurface::Map failure: %s 0x%04X\n",
GetDxgiErrorString(hr), hr);
return -1;
}
subsystem->dxgiSurfaceMapped = TRUE;
*ppDstData = mappedRect.pBits;
*pnDstStep = mappedRect.Pitch;
@ -346,22 +484,26 @@ int win_shadow_dxgi_fetch_frame_data(winShadowSubsystem* subsystem,
int win_shadow_dxgi_release_frame_data(winShadowSubsystem* subsystem)
{
HRESULT hr;
if (subsystem->dxgiSurface)
{
subsystem->dxgiSurface->lpVtbl->Unmap(subsystem->dxgiSurface);
if (subsystem->dxgiSurfaceMapped)
{
subsystem->dxgiSurface->lpVtbl->Unmap(subsystem->dxgiSurface);
subsystem->dxgiSurfaceMapped = FALSE;
}
subsystem->dxgiSurface->lpVtbl->Release(subsystem->dxgiSurface);
subsystem->dxgiSurface = NULL;
}
hr = subsystem->dxgiOutputDuplication->lpVtbl->ReleaseFrame(subsystem->dxgiOutputDuplication);
if (subsystem->dxgiFrameAcquired)
{
subsystem->dxgiOutputDuplication->lpVtbl->ReleaseFrame(subsystem->dxgiOutputDuplication);
subsystem->dxgiFrameAcquired = FALSE;
}
subsystem->pendingFrames = 0;
if (FAILED(hr))
return -1;
return 1;
}
@ -373,7 +515,7 @@ int win_shadow_dxgi_get_next_frame(winShadowSubsystem* subsystem)
UINT DataBufferSize = 0;
BYTE* DataBuffer = NULL;
if (subsystem->pendingFrames > 0)
if (subsystem->dxgiFrameAcquired)
{
win_shadow_dxgi_release_frame_data(subsystem);
}
@ -387,11 +529,20 @@ int win_shadow_dxgi_get_next_frame(winShadowSubsystem* subsystem)
hr = subsystem->dxgiOutputDuplication->lpVtbl->AcquireNextFrame(subsystem->dxgiOutputDuplication,
0, &(subsystem->dxgiFrameInfo), &(subsystem->dxgiResource));
if (SUCCEEDED(hr))
{
subsystem->dxgiFrameAcquired = TRUE;
subsystem->pendingFrames = subsystem->dxgiFrameInfo.AccumulatedFrames;
}
if (hr == DXGI_ERROR_WAIT_TIMEOUT)
return 0;
if (FAILED(hr))
{
fprintf(stderr, "IDXGIOutputDuplication::AcquireNextFrame failure: %s (0x%04X)\n",
GetDxgiErrorString(hr), hr);
if (hr == DXGI_ERROR_ACCESS_LOST)
{
if (subsystem->dxgiDesktopImage)
@ -413,34 +564,24 @@ int win_shadow_dxgi_get_next_frame(winShadowSubsystem* subsystem)
return 0;
}
else
{
hr = subsystem->dxgiOutputDuplication->lpVtbl->ReleaseFrame(subsystem->dxgiOutputDuplication);
if (FAILED(hr))
return -1;
return -1;
}
return -1;
}
hr = subsystem->dxgiResource->lpVtbl->QueryInterface(subsystem->dxgiResource,
&IID_ID3D11Texture2D, (void**) &(subsystem->dxgiDesktopImage));
subsystem->dxgiResource->lpVtbl->Release(subsystem->dxgiResource);
subsystem->dxgiResource = NULL;
if (subsystem->dxgiResource)
{
subsystem->dxgiResource->lpVtbl->Release(subsystem->dxgiResource);
subsystem->dxgiResource = NULL;
}
if (FAILED(hr))
return -1;
subsystem->pendingFrames = subsystem->dxgiFrameInfo.AccumulatedFrames;
if (subsystem->pendingFrames == 0)
{
hr = subsystem->dxgiOutputDuplication->lpVtbl->ReleaseFrame(subsystem->dxgiOutputDuplication);
if (FAILED(hr))
return -1;
fprintf(stderr, "IDXGIResource::QueryInterface(ID3D11Texture2D) failure: %s (0x%04X)\n",
GetDxgiErrorString(hr), hr);
return -1;
}
return 1;
@ -456,21 +597,13 @@ int win_shadow_dxgi_get_invalid_region(winShadowSubsystem* subsystem)
UINT numMoveRects;
UINT numDirtyRects;
UINT UsedBufferSize;
rdpShadowServer* server;
rdpShadowScreen* screen;
RECTANGLE_16 invalidRect;
UINT MetadataBufferSize;
UINT MoveRectsBufferSize;
UINT DirtyRectsBufferSize;
UINT PointerShapeBufferSize;
RECT* pDirtyRectsBuffer;
void* pPointerShapeBuffer;
DXGI_OUTDUPL_MOVE_RECT* pMoveRect;
DXGI_OUTDUPL_MOVE_RECT* pMoveRectBuffer;
DXGI_OUTDUPL_POINTER_SHAPE_INFO PointerShapeInfo;
server = subsystem->server;
screen = server->screen;
if (subsystem->dxgiFrameInfo.AccumulatedFrames == 0)
return 0;
@ -501,7 +634,11 @@ int win_shadow_dxgi_get_invalid_region(winShadowSubsystem* subsystem)
MoveRectsBufferSize, pMoveRectBuffer, &MoveRectsBufferSize);
if (FAILED(hr))
{
fprintf(stderr, "IDXGIOutputDuplication::GetFrameMoveRects failure: %s (0x%04X) Size: %d Total %d Used: %d\n",
GetDxgiErrorString(hr), hr, MoveRectsBufferSize, MetadataBufferSize, UsedBufferSize);
return -1;
}
/* GetFrameDirtyRects */
@ -514,22 +651,11 @@ int win_shadow_dxgi_get_invalid_region(winShadowSubsystem* subsystem)
DirtyRectsBufferSize, pDirtyRectsBuffer, &DirtyRectsBufferSize);
if (FAILED(hr))
{
fprintf(stderr, "IDXGIOutputDuplication::GetFrameDirtyRects failure: %s (0x%04X) Size: %d Total %d Used: %d\n",
GetDxgiErrorString(hr), hr, DirtyRectsBufferSize, MetadataBufferSize, UsedBufferSize);
return -1;
/* GetFramePointerShape */
UsedBufferSize += MoveRectsBufferSize;
PointerShapeBufferSize = MetadataBufferSize - UsedBufferSize;
pPointerShapeBuffer = (void*) &(subsystem->MetadataBuffer[UsedBufferSize]);
hr = subsystem->dxgiOutputDuplication->lpVtbl->GetFramePointerShape(subsystem->dxgiOutputDuplication,
PointerShapeBufferSize, pPointerShapeBuffer, &PointerShapeBufferSize, &PointerShapeInfo);
if (FAILED(hr))
return -1;
EnterCriticalSection(&(screen->lock));
}
numMoveRects = MoveRectsBufferSize / sizeof(DXGI_OUTDUPL_MOVE_RECT);
@ -544,7 +670,7 @@ int win_shadow_dxgi_get_invalid_region(winShadowSubsystem* subsystem)
invalidRect.right = (UINT16) pDstRect->right;
invalidRect.bottom = (UINT16) pDstRect->bottom;
region16_union_rect(&(screen->invalidRegion), &(screen->invalidRegion), &invalidRect);
region16_union_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &invalidRect);
}
numDirtyRects = DirtyRectsBufferSize / sizeof(RECT);
@ -558,11 +684,9 @@ int win_shadow_dxgi_get_invalid_region(winShadowSubsystem* subsystem)
invalidRect.right = (UINT16) pDirtyRect->right;
invalidRect.bottom = (UINT16) pDirtyRect->bottom;
region16_union_rect(&(screen->invalidRegion), &(screen->invalidRegion), &invalidRect);
region16_union_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &invalidRect);
}
LeaveCriticalSection(&(screen->lock));
return 1;
}
@ -747,7 +871,6 @@ int win_shadow_surface_copy(winShadowSubsystem* subsystem)
int status;
int nDstStep = 0;
BYTE* pDstData = NULL;
rdpShadowScreen* screen;
rdpShadowServer* server;
rdpShadowSurface* surface;
RECTANGLE_16 surfaceRect;
@ -755,7 +878,6 @@ int win_shadow_surface_copy(winShadowSubsystem* subsystem)
server = subsystem->server;
surface = server->surface;
screen = server->screen;
surfaceRect.left = surface->x;
surfaceRect.top = surface->y;
@ -763,7 +885,8 @@ int win_shadow_surface_copy(winShadowSubsystem* subsystem)
surfaceRect.bottom = surface->y + surface->height;
region16_clear(&(surface->invalidRegion));
region16_intersect_rect(&(surface->invalidRegion), &(screen->invalidRegion), &surfaceRect);
region16_copy(&(surface->invalidRegion), &(subsystem->invalidRegion));
region16_intersect_rect(&(surface->invalidRegion), &(surface->invalidRegion), &surfaceRect);
if (region16_is_empty(&(surface->invalidRegion)))
return 1;
@ -775,7 +898,7 @@ int win_shadow_surface_copy(winShadowSubsystem* subsystem)
width = extents->right - extents->left;
height = extents->bottom - extents->top;
printf("x: %d y: %d width: %d height: %d right: %d bottom: %d\n",
printf("SurfaceCopy x: %d y: %d width: %d height: %d right: %d bottom: %d\n",
x, y, width, height, x + width, y + height);
status = win_shadow_dxgi_fetch_frame_data(subsystem, &pDstData, &nDstStep, x, y, width, height);
@ -783,10 +906,14 @@ int win_shadow_surface_copy(winShadowSubsystem* subsystem)
if (status < 0)
return -1;
EnterCriticalSection(&(surface->lock));
freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32,
surface->scanline, x - surface->x, y - surface->y, width, height,
pDstData, PIXEL_FORMAT_XRGB32, nDstStep, x, y);
LeaveCriticalSection(&(surface->lock));
return 1;
}
@ -832,14 +959,16 @@ void* win_shadow_subsystem_thread(winShadowSubsystem* subsystem)
#ifdef WITH_DXGI_1_2
int dxgi_status;
//win_shadow_invalidate_region(subsystem, 0, 0, subsystem->width, subsystem->height);
dxgi_status = win_shadow_dxgi_get_next_frame(subsystem);
dxgi_status = win_shadow_dxgi_get_invalid_region(subsystem);
win_shadow_surface_copy(subsystem);
if (subsystem->pendingFrames > 0)
{
dxgi_status = win_shadow_dxgi_get_invalid_region(subsystem);
if (subsystem->SurfaceUpdate)
subsystem->SurfaceUpdate((rdpShadowSubsystem*) subsystem, &(subsystem->invalidRegion));
win_shadow_invalidate_region(subsystem, 0, 0, subsystem->width, subsystem->height);
}
region16_clear(&(subsystem->invalidRegion));
#endif
dwInterval = 1000 / fps;
@ -941,6 +1070,8 @@ void win_shadow_subsystem_free(winShadowSubsystem* subsystem)
win_shadow_subsystem_uninit(subsystem);
region16_uninit(&(subsystem->invalidRegion));
free(subsystem);
}
@ -955,6 +1086,8 @@ winShadowSubsystem* win_shadow_subsystem_new(rdpShadowServer* server)
subsystem->server = server;
region16_init(&(subsystem->invalidRegion));
subsystem->Init = (pfnShadowSubsystemInit) win_shadow_subsystem_init;
subsystem->Uninit = (pfnShadowSubsystemInit) win_shadow_subsystem_uninit;
subsystem->Start = (pfnShadowSubsystemStart) win_shadow_subsystem_start;

View File

@ -56,6 +56,8 @@ struct win_shadow_subsystem
UINT pendingFrames;
BYTE* MetadataBuffer;
UINT MetadataBufferSize;
BOOL dxgiSurfaceMapped;
BOOL dxgiFrameAcquired;
ID3D11Device* dxgiDevice;
IDXGISurface* dxgiSurface;
ID3D11Texture2D* dxgiStage;

View File

@ -27,69 +27,8 @@
#include <winpr/thread.h>
#include <winpr/sysinfo.h>
#include <winpr/tools/makecert.h>
#include "shadow.h"
static const char* makecert_argv[6] =
{
"makecert",
"-rdp",
"-live",
"-silent",
"-y", "5"
};
static int makecert_argc = (sizeof(makecert_argv) / sizeof(char*));
int shadow_generate_certificate(rdpShadowClient* client)
{
char* filepath;
rdpContext* context;
rdpSettings* settings;
MAKECERT_CONTEXT* makecert;
rdpShadowServer* server = client->server;
context = (rdpContext*) client;
settings = context->settings;
if (!PathFileExistsA(server->ConfigPath))
CreateDirectoryA(server->ConfigPath, 0);
filepath = GetCombinedPath(server->ConfigPath, "shadow");
if (!filepath)
return -1;
if (!PathFileExistsA(filepath))
CreateDirectoryA(filepath, 0);
settings->CertificateFile = GetCombinedPath(filepath, "shadow.crt");
settings->PrivateKeyFile = GetCombinedPath(filepath, "shadow.key");
if ((!PathFileExistsA(settings->CertificateFile)) ||
(!PathFileExistsA(settings->PrivateKeyFile)))
{
makecert = makecert_context_new();
makecert_context_process(makecert, makecert_argc, (char**) makecert_argv);
makecert_context_set_output_file_name(makecert, "shadow");
if (!PathFileExistsA(settings->CertificateFile))
makecert_context_output_certificate_file(makecert, filepath);
if (!PathFileExistsA(settings->PrivateKeyFile))
makecert_context_output_private_key_file(makecert, filepath);
makecert_context_free(makecert);
}
free(filepath);
return 1;
}
void shadow_client_context_new(freerdp_peer* peer, rdpShadowClient* client)
{
rdpSettings* settings;
@ -110,19 +49,36 @@ void shadow_client_context_new(freerdp_peer* peer, rdpShadowClient* client)
settings->TlsSecurity = TRUE;
settings->NlaSecurity = FALSE;
shadow_generate_certificate(client);
settings->CertificateFile = _strdup(server->CertificateFile);
settings->PrivateKeyFile = _strdup(server->PrivateKeyFile);
client->inLobby = TRUE;
client->mayView = server->mayView;
client->mayInteract = server->mayInteract;
InitializeCriticalSectionAndSpinCount(&(client->lock), 4000);
region16_init(&(client->invalidRegion));
client->vcm = WTSOpenServerA((LPSTR) peer->context);
client->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
client->encoder = shadow_encoder_new(server);
ArrayList_Add(server->clients, (void*) client);
}
void shadow_client_context_free(freerdp_peer* peer, rdpShadowClient* client)
{
rdpShadowServer* server = client->server;
ArrayList_Remove(server->clients, (void*) client);
DeleteCriticalSection(&(client->lock));
region16_uninit(&(client->invalidRegion));
WTSCloseServer((HANDLE) client->vcm);
CloseHandle(client->StopEvent);
@ -132,6 +88,12 @@ void shadow_client_context_free(freerdp_peer* peer, rdpShadowClient* client)
shadow_surface_free(client->lobby);
client->lobby = NULL;
}
if (client->encoder)
{
shadow_encoder_free(client->encoder);
client->encoder = NULL;
}
}
BOOL shadow_client_capabilities(freerdp_peer* peer)
@ -189,7 +151,7 @@ BOOL shadow_client_activate(freerdp_peer* peer)
client->activated = TRUE;
client->inLobby = client->mayView ? FALSE : TRUE;
shadow_encoder_reset(client->server->encoder);
shadow_encoder_reset(client->encoder);
return TRUE;
}
@ -199,7 +161,7 @@ void shadow_client_surface_frame_acknowledge(rdpShadowClient* client, UINT32 fra
SURFACE_FRAME* frame;
wListDictionary* frameList;
frameList = client->server->encoder->frameList;
frameList = client->encoder->frameList;
frame = (SURFACE_FRAME*) ListDictionary_GetItemValue(frameList, (void*) (size_t) frameId);
if (frame)
@ -248,7 +210,7 @@ int shadow_client_send_surface_bits(rdpShadowClient* client, rdpShadowSurface* s
settings = context->settings;
server = client->server;
encoder = server->encoder;
encoder = client->encoder;
pSrcData = surface->data;
nSrcStep = surface->scanline;
@ -336,8 +298,6 @@ int shadow_client_send_surface_bits(rdpShadowClient* client, rdpShadowSurface* s
free(messages);
}
region16_clear(&(surface->invalidRegion));
if (encoder->frameAck)
{
shadow_client_send_surface_frame_marker(client, SURFACECMD_FRAMEACTION_END, frameId);
@ -372,7 +332,7 @@ int shadow_client_send_bitmap_update(rdpShadowClient* client, rdpShadowSurface*
settings = context->settings;
server = client->server;
encoder = server->encoder;
encoder = client->encoder;
pSrcData = surface->data;
nSrcStep = surface->scanline;
@ -562,27 +522,39 @@ int shadow_client_send_surface_update(rdpShadowClient* client)
rdpShadowServer* server;
rdpShadowSurface* surface;
rdpShadowEncoder* encoder;
REGION16 invalidRegion;
RECTANGLE_16 surfaceRect;
const RECTANGLE_16* extents;
context = (rdpContext*) client;
settings = context->settings;
server = client->server;
encoder = server->encoder;
encoder = client->encoder;
surface = client->inLobby ? client->lobby : server->surface;
EnterCriticalSection(&(client->lock));
region16_init(&invalidRegion);
region16_copy(&invalidRegion, &(client->invalidRegion));
region16_clear(&(client->invalidRegion));
LeaveCriticalSection(&(client->lock));
surfaceRect.left = surface->x;
surfaceRect.top = surface->y;
surfaceRect.right = surface->x + surface->width;
surfaceRect.bottom = surface->y + surface->height;
region16_intersect_rect(&(surface->invalidRegion), &(surface->invalidRegion), &surfaceRect);
region16_intersect_rect(&invalidRegion, &invalidRegion, &surfaceRect);
if (region16_is_empty(&(surface->invalidRegion)))
if (region16_is_empty(&invalidRegion))
{
region16_uninit(&invalidRegion);
return 1;
}
extents = region16_extents(&(surface->invalidRegion));
extents = region16_extents(&invalidRegion);
nXSrc = extents->left - surface->x;
nYSrc = extents->top - surface->y;
@ -608,9 +580,31 @@ int shadow_client_send_surface_update(rdpShadowClient* client)
status = shadow_client_send_bitmap_update(client, surface, nXSrc, nYSrc, nWidth, nHeight);
}
region16_uninit(&invalidRegion);
return status;
}
int shadow_client_surface_update(rdpShadowClient* client, REGION16* region)
{
int index;
int numRects = 0;
const RECTANGLE_16* rects;
EnterCriticalSection(&(client->lock));
rects = region16_rects(region, &numRects);
for (index = 0; index < numRects; index++)
{
region16_union_rect(&(client->invalidRegion), &(client->invalidRegion), &rects[index]);
}
LeaveCriticalSection(&(client->lock));
return 1;
}
void* shadow_client_thread(rdpShadowClient* client)
{
int fps;
@ -633,7 +627,7 @@ void* shadow_client_thread(rdpShadowClient* client)
server = client->server;
screen = server->screen;
encoder = server->encoder;
encoder = client->encoder;
subsystem = server->subsystem;
peer = ((rdpContext*) client)->peer;

View File

@ -25,6 +25,7 @@
extern "C" {
#endif
int shadow_client_surface_update(rdpShadowClient* client, REGION16* region);
void shadow_client_accepted(freerdp_listener* instance, freerdp_peer* client);
#ifdef __cplusplus

View File

@ -83,7 +83,7 @@ static int encomsp_change_participant_control_level(EncomspServerContext* contex
if (inLobby != client->inLobby)
{
shadow_encoder_reset(client->server->encoder);
shadow_encoder_reset(client->encoder);
client->inLobby = inLobby;
}

View File

@ -27,6 +27,8 @@
#include <freerdp/version.h>
#include <winpr/tools/makecert.h>
#ifndef _WIN32
#include <sys/select.h>
#include <sys/signal.h>
@ -226,6 +228,32 @@ int shadow_server_parse_command_line(rdpShadowServer* server, int argc, char** a
return status;
}
int shadow_server_surface_update(rdpShadowSubsystem* subsystem, REGION16* region)
{
int index;
int count;
wArrayList* clients;
rdpShadowServer* server;
rdpShadowClient* client;
server = subsystem->server;
clients = server->clients;
ArrayList_Lock(clients);
count = ArrayList_Count(clients);
for (index = 0; index < count; index++)
{
client = ArrayList_GetItem(clients, index);
shadow_client_surface_update(client, region);
}
ArrayList_Unlock(clients);
return 1;
}
void* shadow_server_thread(rdpShadowServer* server)
{
DWORD status;
@ -317,6 +345,59 @@ int shadow_server_stop(rdpShadowServer* server)
return 0;
}
int shadow_server_init_certificate(rdpShadowServer* server)
{
char* filepath;
MAKECERT_CONTEXT* makecert;
const char* makecert_argv[6] =
{
"makecert",
"-rdp",
"-live",
"-silent",
"-y", "5"
};
int makecert_argc = (sizeof(makecert_argv) / sizeof(char*));
if (!PathFileExistsA(server->ConfigPath))
CreateDirectoryA(server->ConfigPath, 0);
filepath = GetCombinedPath(server->ConfigPath, "shadow");
if (!filepath)
return -1;
if (!PathFileExistsA(filepath))
CreateDirectoryA(filepath, 0);
server->CertificateFile = GetCombinedPath(filepath, "shadow.crt");
server->PrivateKeyFile = GetCombinedPath(filepath, "shadow.key");
if ((!PathFileExistsA(server->CertificateFile)) ||
(!PathFileExistsA(server->PrivateKeyFile)))
{
makecert = makecert_context_new();
makecert_context_process(makecert, makecert_argc, (char**) makecert_argv);
makecert_context_set_output_file_name(makecert, "shadow");
if (!PathFileExistsA(server->CertificateFile))
makecert_context_output_certificate_file(makecert, filepath);
if (!PathFileExistsA(server->PrivateKeyFile))
makecert_context_output_private_key_file(makecert, filepath);
makecert_context_free(makecert);
}
free(filepath);
return 1;
}
int shadow_server_init(rdpShadowServer* server)
{
int status;
@ -325,6 +406,11 @@ int shadow_server_init(rdpShadowServer* server)
server->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
status = shadow_server_init_certificate(server);
if (status < 0)
return -1;
server->listener = freerdp_listener_new();
if (!server->listener)
@ -351,6 +437,8 @@ int shadow_server_init(rdpShadowServer* server)
if (!server->subsystem)
return -1;
server->subsystem->SurfaceUpdate = shadow_server_surface_update;
if (server->subsystem->Init)
{
status = server->subsystem->Init(server->subsystem);
@ -364,11 +452,6 @@ int shadow_server_init(rdpShadowServer* server)
if (!server->screen)
return -1;
server->encoder = shadow_encoder_new(server);
if (!server->encoder)
return -1;
return 1;
}
@ -382,18 +465,24 @@ int shadow_server_uninit(rdpShadowServer* server)
server->listener = NULL;
}
if (server->encoder)
{
shadow_encoder_free(server->encoder);
server->encoder = NULL;
}
if (server->subsystem)
{
server->subsystem->Free(server->subsystem);
server->subsystem = NULL;
}
if (server->CertificateFile)
{
free(server->CertificateFile);
server->CertificateFile = NULL;
}
if (server->PrivateKeyFile)
{
free(server->PrivateKeyFile);
server->PrivateKeyFile = NULL;
}
return 1;
}
@ -417,6 +506,10 @@ rdpShadowServer* shadow_server_new()
if (!server->ConfigPath)
server->ConfigPath = GetKnownSubPath(KNOWN_PATH_XDG_CONFIG_HOME, "freerdp");
InitializeCriticalSectionAndSpinCount(&(server->lock), 4000);
server->clients = ArrayList_New(TRUE);
return server;
}
@ -425,6 +518,14 @@ void shadow_server_free(rdpShadowServer* server)
if (!server)
return;
DeleteCriticalSection(&(server->lock));
if (server->clients)
{
ArrayList_Free(server->clients);
server->clients = NULL;
}
shadow_server_uninit(server);
free(server);