shadow: start detecting invalid regions manually
This commit is contained in:
parent
4f41f03ad7
commit
d9d9bf3609
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
172
server/shadow/shadow_capture.c
Normal file
172
server/shadow/shadow_capture.c
Normal 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);
|
||||
}
|
||||
|
50
server/shadow/shadow_capture.h
Normal file
50
server/shadow/shadow_capture.h
Normal 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 */
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user