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