shadow: make use of synchronization barrier

This commit is contained in:
Marc-André Moreau 2014-08-08 18:47:46 -04:00
parent edde16e9d5
commit 8b4cf07c8a
4 changed files with 72 additions and 46 deletions

View File

@ -113,7 +113,9 @@ struct rdp_shadow_server
int monitorCount; \
MONITOR_DEF monitors[16]; \
MONITOR_DEF virtualScreen; \
HANDLE updateEvent; \
REGION16 invalidRegion; \
SYNCHRONIZATION_BARRIER barrier; \
\
pfnShadowSubsystemInit Init; \
pfnShadowSubsystemUninit Uninit; \

View File

@ -1072,6 +1072,8 @@ void win_shadow_subsystem_free(winShadowSubsystem* subsystem)
region16_uninit(&(subsystem->invalidRegion));
CloseHandle(subsystem->updateEvent);
free(subsystem);
}
@ -1086,6 +1088,8 @@ winShadowSubsystem* win_shadow_subsystem_new(rdpShadowServer* server)
subsystem->server = server;
subsystem->updateEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
region16_init(&(subsystem->invalidRegion));
subsystem->Init = (pfnShadowSubsystemInit) win_shadow_subsystem_init;

View File

@ -187,6 +187,7 @@ int x11_shadow_invalidate_region(x11ShadowSubsystem* subsystem, int x, int y, in
int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem)
{
int count;
int status;
int x, y;
int width, height;
@ -200,18 +201,18 @@ int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem)
surface = server->surface;
screen = server->screen;
XLockDisplay(subsystem->display);
if (subsystem->use_xshm)
{
XLockDisplay(subsystem->display);
XCopyArea(subsystem->display, subsystem->root_window, subsystem->fb_pixmap,
subsystem->xshm_gc, 0, 0, subsystem->width, subsystem->height, 0, 0);
XSync(subsystem->display, False);
image = subsystem->fb_image;
XUnlockDisplay(subsystem->display);
EnterCriticalSection(&(screen->lock));
image = subsystem->fb_image;
status = shadow_capture_compare(surface->data, surface->scanline, surface->width, surface->height,
(BYTE*) image->data, image->bytes_per_line, &invalidRect);
@ -230,20 +231,29 @@ int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem)
region16_union_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &invalidRect);
if (subsystem->SurfaceUpdate)
subsystem->SurfaceUpdate((rdpShadowSubsystem*) subsystem, &(subsystem->invalidRegion));
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));
}
LeaveCriticalSection(&(screen->lock));
}
else
{
XLockDisplay(subsystem->display);
image = XGetImage(subsystem->display, subsystem->root_window,
0, 0, subsystem->width, subsystem->height, AllPlanes, ZPixmap);
EnterCriticalSection(&(screen->lock));
XUnlockDisplay(subsystem->display);
status = shadow_capture_compare(surface->data, surface->scanline, surface->width, surface->height,
(BYTE*) image->data, image->bytes_per_line, &invalidRect);
@ -262,19 +272,24 @@ int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem)
region16_union_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &invalidRect);
if (subsystem->SurfaceUpdate)
subsystem->SurfaceUpdate((rdpShadowSubsystem*) subsystem, &(subsystem->invalidRegion));
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));
}
LeaveCriticalSection(&(screen->lock));
XDestroyImage(image);
}
XUnlockDisplay(subsystem->display);
return 1;
}
@ -299,7 +314,7 @@ void* x11_shadow_subsystem_thread(x11ShadowSubsystem* subsystem)
events[nCount++] = StopEvent;
events[nCount++] = subsystem->event;
fps = 24;
fps = 16;
dwInterval = 1000 / fps;
frameTime = GetTickCount64() + dwInterval;
@ -749,6 +764,8 @@ void x11_shadow_subsystem_free(x11ShadowSubsystem* subsystem)
region16_uninit(&(subsystem->invalidRegion));
CloseHandle(subsystem->updateEvent);
free(subsystem);
}
@ -763,6 +780,8 @@ x11ShadowSubsystem* x11_shadow_subsystem_new(rdpShadowServer* server)
subsystem->server = server;
subsystem->updateEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
region16_init(&(subsystem->invalidRegion));
subsystem->Init = (pfnShadowSubsystemInit) x11_shadow_subsystem_init;

View File

@ -613,17 +613,13 @@ int shadow_client_surface_update(rdpShadowClient* client, REGION16* region)
void* shadow_client_thread(rdpShadowClient* client)
{
int fps;
DWORD status;
DWORD nCount;
UINT64 cTime;
DWORD dwTimeout;
DWORD dwInterval;
UINT64 frameTime;
HANDLE events[32];
HANDLE StopEvent;
HANDLE ClientEvent;
HANDLE ChannelEvent;
HANDLE UpdateEvent;
freerdp_peer* peer;
rdpSettings* settings;
rdpShadowServer* server;
@ -651,11 +647,8 @@ void* shadow_client_thread(rdpShadowClient* client)
shadow_client_surface_frame_acknowledge;
peer->update->SuppressOutput = (pSuppressOutput) shadow_client_suppress_output;
fps = 16;
dwInterval = 1000 / fps;
frameTime = GetTickCount64() + dwInterval;
StopEvent = client->StopEvent;
UpdateEvent = subsystem->updateEvent;
ClientEvent = peer->GetEventHandle(peer);
ChannelEvent = WTSVirtualChannelManagerGetEventHandle(client->vcm);
@ -663,19 +656,43 @@ void* shadow_client_thread(rdpShadowClient* client)
{
nCount = 0;
events[nCount++] = StopEvent;
events[nCount++] = UpdateEvent;
events[nCount++] = ClientEvent;
events[nCount++] = ChannelEvent;
cTime = GetTickCount64();
dwTimeout = (DWORD) ((cTime > frameTime) ? 0 : frameTime - cTime);
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
status = WaitForMultipleObjects(nCount, events, FALSE, dwTimeout);
if (WaitForSingleObject(client->StopEvent, 0) == WAIT_OBJECT_0)
if (WaitForSingleObject(StopEvent, 0) == WAIT_OBJECT_0)
{
if (WaitForSingleObject(UpdateEvent, 0) == WAIT_OBJECT_0)
{
EnterSynchronizationBarrier(&(subsystem->barrier), 0);
}
break;
}
if (WaitForSingleObject(UpdateEvent, 0) == WAIT_OBJECT_0)
{
if (client->activated)
{
int index;
int numRects = 0;
const RECTANGLE_16* rects;
rects = region16_rects(&(subsystem->invalidRegion), &numRects);
for (index = 0; index < numRects; index++)
{
region16_union_rect(&(client->invalidRegion), &(client->invalidRegion), &rects[index]);
}
shadow_client_send_surface_update(client);
}
EnterSynchronizationBarrier(&(subsystem->barrier), 0);
}
if (WaitForSingleObject(ClientEvent, 0) == WAIT_OBJECT_0)
{
if (!peer->CheckFileDescriptor(peer))
@ -693,22 +710,6 @@ void* shadow_client_thread(rdpShadowClient* client)
break;
}
}
if ((status == WAIT_TIMEOUT) || (GetTickCount64() > frameTime))
{
if (client->activated)
{
EnterCriticalSection(&(screen->lock));
shadow_client_send_surface_update(client);
LeaveCriticalSection(&(screen->lock));
}
fps = encoder->fps;
dwInterval = 1000 / fps;
frameTime += dwInterval;
}
}
peer->Disconnect(peer);