shadow: improve invalid region detection

This commit is contained in:
Marc-André Moreau 2014-08-07 12:36:45 -04:00
parent d9d9bf3609
commit fdab87cba0
3 changed files with 46 additions and 128 deletions

View File

@ -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;

View File

@ -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");

View File

@ -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));
}