diff --git a/include/freerdp/server/shadow.h b/include/freerdp/server/shadow.h index baaac3e5c..0620cf626 100644 --- a/include/freerdp/server/shadow.h +++ b/include/freerdp/server/shadow.h @@ -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; \ diff --git a/server/shadow/Win/win_shadow.c b/server/shadow/Win/win_shadow.c index e9e746675..46a8fa636 100644 --- a/server/shadow/Win/win_shadow.c +++ b/server/shadow/Win/win_shadow.c @@ -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; diff --git a/server/shadow/X11/x11_shadow.c b/server/shadow/X11/x11_shadow.c index a18ab8b7c..a96d55d31 100644 --- a/server/shadow/X11/x11_shadow.c +++ b/server/shadow/X11/x11_shadow.c @@ -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; diff --git a/server/shadow/shadow_client.c b/server/shadow/shadow_client.c index e3f08a44e..7bf20441b 100644 --- a/server/shadow/shadow_client.c +++ b/server/shadow/shadow_client.c @@ -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);