From fdab87cba084af83232c9a5d9b2ca2e8569e426a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 7 Aug 2014 12:36:45 -0400 Subject: [PATCH] shadow: improve invalid region detection --- server/shadow/X11/x11_shadow.c | 133 +++++---------------------------- server/shadow/shadow_capture.c | 19 ++++- server/shadow/shadow_client.c | 22 +++--- 3 files changed, 46 insertions(+), 128 deletions(-) diff --git a/server/shadow/X11/x11_shadow.c b/server/shadow/X11/x11_shadow.c index 430c5b482..a18ab8b7c 100644 --- a/server/shadow/X11/x11_shadow.c +++ b/server/shadow/X11/x11_shadow.c @@ -185,85 +185,6 @@ int x11_shadow_invalidate_region(x11ShadowSubsystem* subsystem, int x, int y, in return 1; } -int x11_shadow_surface_copy(x11ShadowSubsystem* subsystem) -{ - int x, y; - int width; - int height; - XImage* image; - 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_copy(&(surface->invalidRegion), &(subsystem->invalidRegion)); - region16_intersect_rect(&(surface->invalidRegion), &(surface->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; - - XLockDisplay(subsystem->display); - - if (subsystem->use_xshm) - { - XCopyArea(subsystem->display, subsystem->root_window, subsystem->fb_pixmap, - subsystem->xshm_gc, x, y, width, height, x, y); - - XSync(subsystem->display, False); - - image = subsystem->fb_image; - - EnterCriticalSection(&(surface->lock)); - - freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, - surface->scanline, x - surface->x, y - surface->y, width, height, - (BYTE*) image->data, PIXEL_FORMAT_XRGB32, - image->bytes_per_line, x, y); - - LeaveCriticalSection(&(surface->lock)); - } - else - { - image = XGetImage(subsystem->display, subsystem->root_window, - x, y, width, height, AllPlanes, ZPixmap); - - EnterCriticalSection(&(surface->lock)); - - freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, - surface->scanline, x - surface->x, y - surface->y, width, height, - (BYTE*) image->data, PIXEL_FORMAT_XRGB32, - image->bytes_per_line, 0, 0); - - LeaveCriticalSection(&(surface->lock)); - - XDestroyImage(image); - } - - x11_shadow_validate_region(subsystem, x, y, width, height); - - XUnlockDisplay(subsystem->display); - - return 1; -} - int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem) { int status; @@ -290,7 +211,7 @@ int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem) image = subsystem->fb_image; - EnterCriticalSection(&(surface->lock)); + EnterCriticalSection(&(screen->lock)); status = shadow_capture_compare(surface->data, surface->scanline, surface->width, surface->height, (BYTE*) image->data, image->bytes_per_line, &invalidRect); @@ -302,28 +223,27 @@ int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem) width = invalidRect.right - invalidRect.left; height = invalidRect.bottom - invalidRect.top; - if (width > subsystem->width) - width = subsystem->width; - - if (height > subsystem->height) - height = subsystem->height; - freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, x - surface->x, y - surface->y, width, height, (BYTE*) image->data, PIXEL_FORMAT_XRGB32, image->bytes_per_line, x, y); - x11_shadow_invalidate_region(subsystem, x, y, width, height); + region16_union_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &invalidRect); + + if (subsystem->SurfaceUpdate) + subsystem->SurfaceUpdate((rdpShadowSubsystem*) subsystem, &(subsystem->invalidRegion)); + + region16_clear(&(subsystem->invalidRegion)); } - LeaveCriticalSection(&(surface->lock)); + LeaveCriticalSection(&(screen->lock)); } else { image = XGetImage(subsystem->display, subsystem->root_window, 0, 0, subsystem->width, subsystem->height, AllPlanes, ZPixmap); - EnterCriticalSection(&(surface->lock)); + EnterCriticalSection(&(screen->lock)); status = shadow_capture_compare(surface->data, surface->scanline, surface->width, surface->height, (BYTE*) image->data, image->bytes_per_line, &invalidRect); @@ -335,21 +255,20 @@ int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem) width = invalidRect.right - invalidRect.left; height = invalidRect.bottom - invalidRect.top; - if (width > subsystem->width) - width = subsystem->width; - - if (height > subsystem->height) - height = subsystem->height; - freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, - surface->scanline, x, y, width, height, + surface->scanline, x - surface->x, y - surface->y, width, height, (BYTE*) image->data, PIXEL_FORMAT_XRGB32, image->bytes_per_line, x, y); - x11_shadow_invalidate_region(subsystem, x, y, width, height); + region16_union_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &invalidRect); + + if (subsystem->SurfaceUpdate) + subsystem->SurfaceUpdate((rdpShadowSubsystem*) subsystem, &(subsystem->invalidRegion)); + + region16_clear(&(subsystem->invalidRegion)); } - LeaveCriticalSection(&(surface->lock)); + LeaveCriticalSection(&(screen->lock)); XDestroyImage(image); } @@ -380,13 +299,10 @@ void* x11_shadow_subsystem_thread(x11ShadowSubsystem* subsystem) events[nCount++] = StopEvent; events[nCount++] = subsystem->event; - fps = 16; + fps = 24; dwInterval = 1000 / fps; frameTime = GetTickCount64() + dwInterval; - //x11_shadow_invalidate_region(subsystem, 0, 0, subsystem->width, subsystem->height); - //x11_shadow_surface_copy(subsystem); - while (1) { dwTimeout = INFINITE; @@ -428,17 +344,6 @@ void* x11_shadow_subsystem_thread(x11ShadowSubsystem* subsystem) { x11_shadow_screen_grab(subsystem); - if (0) - { - x11_shadow_invalidate_region(subsystem, 0, 0, subsystem->width, subsystem->height); - x11_shadow_surface_copy(subsystem); - } - - if (subsystem->SurfaceUpdate) - subsystem->SurfaceUpdate((rdpShadowSubsystem*) subsystem, &(subsystem->invalidRegion)); - - region16_clear(&(subsystem->invalidRegion)); - dwInterval = 1000 / fps; frameTime += dwInterval; } @@ -866,8 +771,6 @@ x11ShadowSubsystem* x11_shadow_subsystem_new(rdpShadowServer* server) subsystem->Stop = (pfnShadowSubsystemStop) x11_shadow_subsystem_stop; subsystem->Free = (pfnShadowSubsystemFree) x11_shadow_subsystem_free; - subsystem->SurfaceCopy = (pfnShadowSurfaceCopy) x11_shadow_surface_copy; - subsystem->SynchronizeEvent = (pfnShadowSynchronizeEvent) x11_shadow_input_synchronize_event; subsystem->KeyboardEvent = (pfnShadowKeyboardEvent) x11_shadow_input_keyboard_event; subsystem->UnicodeKeyboardEvent = (pfnShadowUnicodeKeyboardEvent) x11_shadow_input_unicode_keyboard_event; diff --git a/server/shadow/shadow_capture.c b/server/shadow/shadow_capture.c index 5b8d0eac1..db73a1ff6 100644 --- a/server/shadow/shadow_capture.c +++ b/server/shadow/shadow_capture.c @@ -57,19 +57,26 @@ int shadow_capture_compare(BYTE* pData1, int nStep1, int nWidth, int nHeight, BY for (ty = 0; ty < nrow; ty++) { - th = ((ty + 1) == nrow) ? nHeight % 16 : 16; + th = ((ty + 1) == nrow) ? (nHeight % 16) : 16; + + if (!th) + th = 16; for (tx = 0; tx < ncol; tx++) { equal = TRUE; - tw = ((tx + 1) == ncol) ? nWidth % 16 : 16; + + tw = ((tx + 1) == ncol) ? (nWidth % 16) : 16; + + if (!tw) + tw = 16; p1 = &pData1[(ty * 16 * nStep1) + (tx * 16 * 4)]; p2 = &pData2[(ty * 16 * nStep2) + (tx * 16 * 4)]; for (k = 0; k < th; k++) { - if (memcmp(p1, p2, tw) != 0) + if (memcmp(p1, p2, tw * 4) != 0) { equal = FALSE; break; @@ -113,6 +120,12 @@ int shadow_capture_compare(BYTE* pData1, int nStep1, int nWidth, int nHeight, BY rect->right = (r + 1) * 16; rect->bottom = (b + 1) * 16; + if (rect->right > nWidth) + rect->right = nWidth; + + if (rect->bottom > nHeight) + rect->bottom = nHeight; + if (0) { printf("\n"); diff --git a/server/shadow/shadow_client.c b/server/shadow/shadow_client.c index 3d80ec08f..e3f08a44e 100644 --- a/server/shadow/shadow_client.c +++ b/server/shadow/shadow_client.c @@ -103,6 +103,7 @@ BOOL shadow_client_capabilities(freerdp_peer* peer) BOOL shadow_client_post_connect(freerdp_peer* peer) { + int width, height; rdpSettings* settings; rdpShadowClient* client; rdpShadowSurface* lobby; @@ -124,7 +125,17 @@ BOOL shadow_client_post_connect(freerdp_peer* peer) shadow_client_channels_post_connect(client); - lobby = client->lobby = shadow_surface_new(client->server, 0, 0, settings->DesktopWidth, settings->DesktopHeight); + width = settings->DesktopWidth; + height = settings->DesktopHeight; + + invalidRect.left = 0; + invalidRect.top = 0; + invalidRect.right = width; + invalidRect.bottom = height; + + region16_union_rect(&(client->invalidRegion), &(client->invalidRegion), &invalidRect); + + lobby = client->lobby = shadow_surface_new(client->server, 0, 0, width, height); if (!client->lobby) return FALSE; @@ -132,11 +143,6 @@ BOOL shadow_client_post_connect(freerdp_peer* peer) freerdp_image_fill(lobby->data, PIXEL_FORMAT_XRGB32, lobby->scanline, 0, 0, lobby->width, lobby->height, 0x3BB9FF); - invalidRect.left = 0; - invalidRect.top = 0; - invalidRect.right = lobby->width; - invalidRect.bottom = lobby->height; - region16_union_rect(&(lobby->invalidRegion), &(lobby->invalidRegion), &invalidRect); return TRUE; @@ -694,11 +700,7 @@ void* shadow_client_thread(rdpShadowClient* client) { EnterCriticalSection(&(screen->lock)); - if (subsystem->SurfaceCopy) - subsystem->SurfaceCopy(subsystem); - shadow_client_send_surface_update(client); - region16_clear(&(screen->invalidRegion)); LeaveCriticalSection(&(screen->lock)); }