shadow: start detecting invalid regions manually

This commit is contained in:
Marc-André Moreau 2014-08-06 17:51:38 -04:00
parent 4f41f03ad7
commit d9d9bf3609
7 changed files with 338 additions and 2 deletions

View File

@ -44,6 +44,7 @@ typedef struct rdp_shadow_server rdpShadowServer;
typedef struct rdp_shadow_screen rdpShadowScreen;
typedef struct rdp_shadow_surface rdpShadowSurface;
typedef struct rdp_shadow_encoder rdpShadowEncoder;
typedef struct rdp_shadow_capture rdpShadowCapture;
typedef struct rdp_shadow_subsystem rdpShadowSubsystem;
typedef rdpShadowSubsystem* (*pfnShadowCreateSubsystem)(rdpShadowServer* server);
@ -92,6 +93,7 @@ struct rdp_shadow_server
wArrayList* clients;
rdpShadowScreen* screen;
rdpShadowSurface* surface;
rdpShadowCapture* capture;
rdpShadowSubsystem* subsystem;
DWORD port;

View File

@ -126,6 +126,8 @@ set(${MODULE_PREFIX}_SRCS
shadow_surface.h
shadow_encoder.c
shadow_encoder.h
shadow_capture.c
shadow_capture.h
shadow_channels.c
shadow_channels.h
shadow_encomsp.c

View File

@ -38,6 +38,7 @@
#include <freerdp/codec/region.h>
#include "../shadow_screen.h"
#include "../shadow_capture.h"
#include "../shadow_surface.h"
#include "x11_shadow.h"
@ -263,6 +264,101 @@ int x11_shadow_surface_copy(x11ShadowSubsystem* subsystem)
return 1;
}
int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem)
{
int status;
int x, y;
int width, height;
XImage* image;
rdpShadowScreen* screen;
rdpShadowServer* server;
rdpShadowSurface* surface;
RECTANGLE_16 invalidRect;
server = subsystem->server;
surface = server->surface;
screen = server->screen;
XLockDisplay(subsystem->display);
if (subsystem->use_xshm)
{
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;
EnterCriticalSection(&(surface->lock));
status = shadow_capture_compare(surface->data, surface->scanline, surface->width, surface->height,
(BYTE*) image->data, image->bytes_per_line, &invalidRect);
if (status > 0)
{
x = invalidRect.left;
y = invalidRect.top;
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);
}
LeaveCriticalSection(&(surface->lock));
}
else
{
image = XGetImage(subsystem->display, subsystem->root_window,
0, 0, subsystem->width, subsystem->height, AllPlanes, ZPixmap);
EnterCriticalSection(&(surface->lock));
status = shadow_capture_compare(surface->data, surface->scanline, surface->width, surface->height,
(BYTE*) image->data, image->bytes_per_line, &invalidRect);
if (status > 0)
{
x = invalidRect.left;
y = invalidRect.top;
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,
(BYTE*) image->data, PIXEL_FORMAT_XRGB32,
image->bytes_per_line, x, y);
x11_shadow_invalidate_region(subsystem, x, y, width, height);
}
LeaveCriticalSection(&(surface->lock));
XDestroyImage(image);
}
XUnlockDisplay(subsystem->display);
return 1;
}
void* x11_shadow_subsystem_thread(x11ShadowSubsystem* subsystem)
{
int fps;
@ -288,6 +384,9 @@ void* x11_shadow_subsystem_thread(x11ShadowSubsystem* subsystem)
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;
@ -327,8 +426,13 @@ void* x11_shadow_subsystem_thread(x11ShadowSubsystem* subsystem)
{
if ((status == WAIT_TIMEOUT) || (GetTickCount64() > frameTime))
{
x11_shadow_invalidate_region(subsystem, 0, 0, subsystem->width, subsystem->height);
x11_shadow_surface_copy(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));

View File

@ -26,6 +26,7 @@
#include "shadow_screen.h"
#include "shadow_surface.h"
#include "shadow_encoder.h"
#include "shadow_capture.h"
#include "shadow_channels.h"
#ifdef __cplusplus

View File

@ -0,0 +1,172 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
*
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <winpr/crt.h>
#include <winpr/print.h>
#include "shadow_surface.h"
#include "shadow_capture.h"
int shadow_capture_compare(BYTE* pData1, int nStep1, int nWidth, int nHeight, BYTE* pData2, int nStep2, RECTANGLE_16* rect)
{
BOOL equal;
BOOL allEqual;
int tw, th;
int tx, ty, k;
int nrow, ncol;
int l, t, r, b;
BYTE *p1, *p2;
BOOL rows[1024];
BOOL cols[1024];
BOOL grid[1024][1024];
allEqual = TRUE;
FillMemory(rows, sizeof(rows), 0xFF);
FillMemory(cols, sizeof(cols), 0xFF);
FillMemory(grid, sizeof(grid), 0xFF);
ZeroMemory(rect, sizeof(RECTANGLE_16));
nrow = (nHeight + 15) / 16;
ncol = (nWidth + 15) / 16;
l = ncol + 1;
r = -1;
t = nrow + 1;
b = -1;
for (ty = 0; ty < nrow; ty++)
{
th = ((ty + 1) == nrow) ? nHeight % 16 : 16;
for (tx = 0; tx < ncol; tx++)
{
equal = TRUE;
tw = ((tx + 1) == ncol) ? nWidth % 16 : 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)
{
equal = FALSE;
break;
}
p1 += nStep1;
p2 += nStep2;
}
if (!equal)
{
grid[ty][tx] = FALSE;
rows[ty] = FALSE;
cols[tx] = FALSE;
if (l > tx)
l = tx;
if (r < tx)
r = tx;
}
}
if (!rows[ty])
{
allEqual = FALSE;
if (t > ty)
t = ty;
if (b < ty)
b = ty;
}
}
if (allEqual)
return 0;
rect->left = l * 16;
rect->top = t * 16;
rect->right = (r + 1) * 16;
rect->bottom = (b + 1) * 16;
if (0)
{
printf("\n");
for (tx = 0; tx < ncol; tx++)
printf("-");
printf("\n");
for (tx = 0; tx < ncol; tx++)
printf("%s", cols[tx] ? "O" : "X");
printf("\n");
for (tx = 0; tx < ncol; tx++)
printf("-");
printf("\n");
for (ty = 0; ty < nrow; ty++)
{
for (tx = 0; tx < ncol; tx++)
{
printf("%s", grid[ty][tx] ? "O" : "X");
}
printf("|%s|\n", rows[ty] ? "O" : "X");
}
}
return 1;
}
rdpShadowCapture* shadow_capture_new(rdpShadowServer* server)
{
rdpShadowCapture* capture;
capture = (rdpShadowCapture*) calloc(1, sizeof(rdpShadowCapture));
if (!capture)
return NULL;
capture->server = server;
if (!InitializeCriticalSectionAndSpinCount(&(capture->lock), 4000))
return NULL;
return capture;
}
void shadow_capture_free(rdpShadowCapture* capture)
{
if (!capture)
return;
DeleteCriticalSection(&(capture->lock));
free(capture);
}

View File

@ -0,0 +1,50 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
*
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FREERDP_SHADOW_SERVER_CAPTURE_H
#define FREERDP_SHADOW_SERVER_CAPTURE_H
#include <freerdp/server/shadow.h>
#include <winpr/crt.h>
#include <winpr/synch.h>
struct rdp_shadow_capture
{
rdpShadowServer* server;
int width;
int height;
CRITICAL_SECTION lock;
};
#ifdef __cplusplus
extern "C" {
#endif
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);
void shadow_capture_free(rdpShadowCapture* capture);
#ifdef __cplusplus
}
#endif
#endif /* FREERDP_SHADOW_SERVER_CAPTURE_H */

View File

@ -463,6 +463,11 @@ int shadow_server_init(rdpShadowServer* server)
if (!server->screen)
return -1;
server->capture = shadow_capture_new(server);
if (!server->capture)
return -1;
return 1;
}