shadow: improve DXGI support

This commit is contained in:
Marc-André Moreau 2014-08-12 16:57:58 -04:00
parent 90d202ab87
commit 1ba42dccf3
5 changed files with 136 additions and 34 deletions

View File

@ -30,7 +30,7 @@ if(FREERDP_VENDOR)
add_subdirectory(Mac)
endif()
else()
add_subdirectory(Windows)
#add_subdirectory(Windows)
endif()
if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/FreeRDS")

View File

@ -25,6 +25,7 @@
#include "../shadow_screen.h"
#include "../shadow_surface.h"
#include "../shadow_capture.h"
#include "win_shadow.h"
@ -212,6 +213,8 @@ const char* GetDxgiErrorString(HRESULT hr)
return "DXGI_DDI_ERR_UNSUPPORTED";
case DXGI_DDI_ERR_NONEXCLUSIVE:
return "DXGI_DDI_ERR_NONEXCLUSIVE";
case 0x80070005:
return "DXGI_ERROR_ACCESS_DENIED";
}
return "DXGI_ERROR_UNKNOWN";
@ -368,6 +371,7 @@ int win_shadow_dxgi_init(winShadowSubsystem* subsystem)
{
UINT i = 0;
HRESULT hr;
int status;
UINT DriverTypeIndex;
IDXGIDevice* DxgiDevice = NULL;
IDXGIAdapter* DxgiAdapter = NULL;
@ -395,9 +399,9 @@ int win_shadow_dxgi_init(winShadowSubsystem* subsystem)
return -1;
}
win_shadow_dxgi_init_duplication(subsystem);
status = win_shadow_dxgi_init_duplication(subsystem);
return 1;
return status;
}
int win_shadow_dxgi_uninit(winShadowSubsystem* subsystem)
@ -438,12 +442,13 @@ int win_shadow_dxgi_uninit(winShadowSubsystem* subsystem)
int win_shadow_dxgi_fetch_frame_data(winShadowSubsystem* subsystem,
BYTE** ppDstData, int* pnDstStep, int x, int y, int width, int height)
{
int status;
HRESULT hr;
D3D11_BOX Box;
DXGI_MAPPED_RECT mappedRect;
if ((width * height) < 1)
return 1;
return 0;
Box.top = x;
Box.left = y;
@ -453,7 +458,7 @@ int win_shadow_dxgi_fetch_frame_data(winShadowSubsystem* subsystem,
Box.back = 1;
subsystem->dxgiDeviceContext->lpVtbl->CopySubresourceRegion(subsystem->dxgiDeviceContext,
(ID3D11Resource*) subsystem->dxgiStage, 0, x, y, 0, (ID3D11Resource*) subsystem->dxgiDesktopImage, 0, &Box);
(ID3D11Resource*) subsystem->dxgiStage, 0, 0, 0, 0, (ID3D11Resource*) subsystem->dxgiDesktopImage, 0, &Box);
hr = subsystem->dxgiStage->lpVtbl->QueryInterface(subsystem->dxgiStage,
&IID_IDXGISurface, (void**) &(subsystem->dxgiSurface));
@ -471,6 +476,19 @@ int win_shadow_dxgi_fetch_frame_data(winShadowSubsystem* subsystem,
{
fprintf(stderr, "IDXGISurface::Map failure: %s 0x%04X\n",
GetDxgiErrorString(hr), hr);
if (hr == DXGI_ERROR_DEVICE_REMOVED)
{
win_shadow_dxgi_uninit(subsystem);
status = win_shadow_dxgi_init(subsystem);
if (status < 0)
return -1;
return 0;
}
return -1;
}
@ -496,10 +514,13 @@ int win_shadow_dxgi_release_frame_data(winShadowSubsystem* subsystem)
subsystem->dxgiSurface = NULL;
}
if (subsystem->dxgiFrameAcquired)
if (subsystem->dxgiOutputDuplication)
{
subsystem->dxgiOutputDuplication->lpVtbl->ReleaseFrame(subsystem->dxgiOutputDuplication);
subsystem->dxgiFrameAcquired = FALSE;
if (subsystem->dxgiFrameAcquired)
{
subsystem->dxgiOutputDuplication->lpVtbl->ReleaseFrame(subsystem->dxgiOutputDuplication);
subsystem->dxgiFrameAcquired = FALSE;
}
}
subsystem->pendingFrames = 0;
@ -512,6 +533,7 @@ int win_shadow_dxgi_get_next_frame(winShadowSubsystem* subsystem)
UINT i = 0;
int status;
HRESULT hr = 0;
UINT timeout = 15;
UINT DataBufferSize = 0;
BYTE* DataBuffer = NULL;
@ -527,7 +549,7 @@ int win_shadow_dxgi_get_next_frame(winShadowSubsystem* subsystem)
}
hr = subsystem->dxgiOutputDuplication->lpVtbl->AcquireNextFrame(subsystem->dxgiOutputDuplication,
0, &(subsystem->dxgiFrameInfo), &(subsystem->dxgiResource));
timeout, &(subsystem->dxgiFrameInfo), &(subsystem->dxgiResource));
if (SUCCEEDED(hr))
{
@ -545,6 +567,8 @@ int win_shadow_dxgi_get_next_frame(winShadowSubsystem* subsystem)
if (hr == DXGI_ERROR_ACCESS_LOST)
{
win_shadow_dxgi_release_frame_data(subsystem);
if (subsystem->dxgiDesktopImage)
{
subsystem->dxgiDesktopImage->lpVtbl->Release(subsystem->dxgiDesktopImage);
@ -564,6 +588,17 @@ int win_shadow_dxgi_get_next_frame(winShadowSubsystem* subsystem)
return 0;
}
else if (hr == DXGI_ERROR_INVALID_CALL)
{
win_shadow_dxgi_uninit(subsystem);
status = win_shadow_dxgi_init(subsystem);
if (status < 0)
return -1;
return 0;
}
return -1;
}
@ -868,12 +903,14 @@ int win_shadow_surface_copy(winShadowSubsystem* subsystem)
int x, y;
int width;
int height;
int count;
int status = 1;
int nDstStep = 0;
BYTE* pDstData = NULL;
rdpShadowServer* server;
rdpShadowSurface* surface;
RECTANGLE_16 surfaceRect;
RECTANGLE_16 invalidRect;
const RECTANGLE_16* extents;
server = subsystem->server;
@ -884,19 +921,28 @@ int win_shadow_surface_copy(winShadowSubsystem* subsystem)
surfaceRect.right = surface->x + surface->width;
surfaceRect.bottom = surface->y + surface->height;
region16_clear(&(surface->invalidRegion));
region16_copy(&(surface->invalidRegion), &(subsystem->invalidRegion));
region16_intersect_rect(&(surface->invalidRegion), &(surface->invalidRegion), &surfaceRect);
region16_intersect_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &surfaceRect);
if (region16_is_empty(&(surface->invalidRegion)))
if (region16_is_empty(&(subsystem->invalidRegion)))
return 1;
extents = region16_extents(&(surface->invalidRegion));
extents = region16_extents(&(subsystem->invalidRegion));
CopyMemory(&invalidRect, extents, sizeof(RECTANGLE_16));
x = extents->left;
y = extents->top;
width = extents->right - extents->left;
height = extents->bottom - extents->top;
shadow_capture_align_clip_rect(&invalidRect, &surfaceRect);
x = invalidRect.left;
y = invalidRect.top;
width = invalidRect.right - invalidRect.left;
height = invalidRect.bottom - invalidRect.top;
if (0)
{
x = 0;
y = 0;
width = surface->width;
height = surface->height;
}
printf("SurfaceCopy x: %d y: %d width: %d height: %d right: %d bottom: %d\n",
x, y, width, height, x + width, y + height);
@ -905,16 +951,26 @@ int win_shadow_surface_copy(winShadowSubsystem* subsystem)
status = win_shadow_dxgi_fetch_frame_data(subsystem, &pDstData, &nDstStep, x, y, width, height);
#endif
if (status < 0)
return -1;
EnterCriticalSection(&(surface->lock));
if (status <= 0)
return status;
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);
pDstData, PIXEL_FORMAT_XRGB32, nDstStep, 0, 0);
LeaveCriticalSection(&(surface->lock));
count = ArrayList_Count(server->clients);
InitializeSynchronizationBarrier(&(subsystem->barrier), count + 1, -1);
SetEvent(subsystem->updateEvent);
EnterSynchronizationBarrier(&(subsystem->barrier), 0);
DeleteSynchronizationBarrier(&(subsystem->barrier));
ResetEvent(subsystem->updateEvent);
region16_clear(&(subsystem->invalidRegion));
return 1;
}
@ -940,8 +996,6 @@ 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;
@ -961,16 +1015,13 @@ 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 (dxgi_status > 0)
dxgi_status = win_shadow_dxgi_get_invalid_region(subsystem);
if (subsystem->SurfaceUpdate)
subsystem->SurfaceUpdate((rdpShadowSubsystem*) subsystem, &(subsystem->invalidRegion));
region16_clear(&(subsystem->invalidRegion));
if (dxgi_status > 0)
win_shadow_surface_copy(subsystem);
#endif
dwInterval = 1000 / fps;

View File

@ -27,6 +27,55 @@
#include "shadow_capture.h"
int shadow_capture_align_clip_rect(RECTANGLE_16* rect, RECTANGLE_16* clip)
{
int dx, dy;
dx = (rect->left % 16);
if (dx != 0)
{
rect->left -= dx;
rect->right += dx;
}
dx = (rect->right % 16);
if (dx != 0)
{
rect->right += (16 - dx);
}
dy = (rect->top % 16);
if (dy != 0)
{
rect->top -= dy;
rect->bottom += dy;
}
dy = (rect->bottom % 16);
if (dy != 0)
{
rect->bottom += (16 - dy);
}
if (rect->left < clip->left)
rect->left = clip->left;
if (rect->top < clip->top)
rect->top = clip->top;
if (rect->right > clip->right)
rect->right = clip->right;
if (rect->bottom > clip->bottom)
rect->bottom = clip->bottom;
return 1;
}
int shadow_capture_compare(BYTE* pData1, int nStep1, int nWidth, int nHeight, BYTE* pData2, int nStep2, RECTANGLE_16* rect)
{
BOOL equal;

View File

@ -38,6 +38,7 @@ struct rdp_shadow_capture
extern "C" {
#endif
int shadow_capture_align_clip_rect(RECTANGLE_16* rect, RECTANGLE_16* clip);
int shadow_capture_compare(BYTE* pData1, int nStep1, int nWidth, int nHeight, BYTE* pData2, int nStep2, RECTANGLE_16* rect);
rdpShadowCapture* shadow_capture_new(rdpShadowServer* server);

View File

@ -549,6 +549,7 @@ DWORD WINAPI WTSGetActiveConsoleSessionId(void)
BOOL WTSRegisterWtsApiFunctionTable(PWtsApiFunctionTable table)
{
g_WtsApi = table;
g_Initialized = TRUE;
return TRUE;
}