diff options
Diffstat (limited to 'server/shadow/shadow_capture.c')
-rw-r--r-- | server/shadow/shadow_capture.c | 263 |
1 files changed, 263 insertions, 0 deletions
diff --git a/server/shadow/shadow_capture.c b/server/shadow/shadow_capture.c new file mode 100644 index 0000000..4711ded --- /dev/null +++ b/server/shadow/shadow_capture.c @@ -0,0 +1,263 @@ +/** + * 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. + */ + +#include <freerdp/config.h> + +#include <winpr/crt.h> +#include <winpr/print.h> + +#include <freerdp/log.h> + +#include "shadow_surface.h" + +#include "shadow_capture.h" + +#define TAG SERVER_TAG("shadow") + +int shadow_capture_align_clip_rect(RECTANGLE_16* rect, RECTANGLE_16* clip) +{ + int dx = 0; + int dy = 0; + dx = (rect->left % 16); + + if (dx != 0) + { + rect->left -= dx; + rect->right += dx; + } + + dx = (rect->right % 16); + + if (dx != 0) + { + rect->right += (16 - dx); + } + + dy = (rect->top % 16); + + if (dy != 0) + { + rect->top -= dy; + rect->bottom += dy; + } + + dy = (rect->bottom % 16); + + if (dy != 0) + { + rect->bottom += (16 - dy); + } + + if (rect->left < clip->left) + rect->left = clip->left; + + if (rect->top < clip->top) + rect->top = clip->top; + + if (rect->right > clip->right) + rect->right = clip->right; + + if (rect->bottom > clip->bottom) + rect->bottom = clip->bottom; + + return 1; +} + +int shadow_capture_compare(BYTE* pData1, UINT32 nStep1, UINT32 nWidth, UINT32 nHeight, BYTE* pData2, + UINT32 nStep2, RECTANGLE_16* rect) +{ + BOOL equal = 0; + BOOL allEqual = 0; + UINT32 tw = 0; + UINT32 th = 0; + UINT32 nrow = 0; + UINT32 ncol = 0; + UINT32 l = 0; + UINT32 t = 0; + UINT32 r = 0; + UINT32 b = 0; + BYTE* p1 = NULL; + BYTE* p2 = NULL; + BOOL rows[1024]; +#ifdef WITH_DEBUG_SHADOW_CAPTURE + BOOL cols[1024] = { FALSE }; +#endif + allEqual = TRUE; + ZeroMemory(rect, sizeof(RECTANGLE_16)); + FillMemory(rows, sizeof(rows), 0xFF); +#ifdef WITH_DEBUG_SHADOW_CAPTURE + FillMemory(cols, sizeof(cols), 0xFF); +#endif + nrow = (nHeight + 15) / 16; + ncol = (nWidth + 15) / 16; + l = ncol + 1; + r = 0; + t = nrow + 1; + b = 0; + + for (UINT32 ty = 0; ty < nrow; ty++) + { + th = ((ty + 1) == nrow) ? (nHeight % 16) : 16; + + if (!th) + th = 16; + + for (UINT32 tx = 0; tx < ncol; tx++) + { + equal = TRUE; + 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 (UINT32 k = 0; k < th; k++) + { + if (memcmp(p1, p2, tw * 4) != 0) + { + equal = FALSE; + break; + } + + p1 += nStep1; + p2 += nStep2; + } + + if (!equal) + { + rows[ty] = FALSE; +#ifdef WITH_DEBUG_SHADOW_CAPTURE + cols[tx] = FALSE; +#endif + + 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; + + WINPR_ASSERT(l * 16 <= UINT16_MAX); + WINPR_ASSERT(t * 16 <= UINT16_MAX); + WINPR_ASSERT((r + 1) * 16 <= UINT16_MAX); + WINPR_ASSERT((b + 1) * 16 <= UINT16_MAX); + rect->left = (UINT16)l * 16; + rect->top = (UINT16)t * 16; + rect->right = (UINT16)(r + 1) * 16; + rect->bottom = (UINT16)(b + 1) * 16; + + WINPR_ASSERT(nWidth <= UINT16_MAX); + if (rect->right > nWidth) + rect->right = (UINT16)nWidth; + + WINPR_ASSERT(nHeight <= UINT16_MAX); + if (rect->bottom > nHeight) + rect->bottom = (UINT16)nHeight; + +#ifdef WITH_DEBUG_SHADOW_CAPTURE + size_t size = ncol + 1; + char* col_str = calloc(size, sizeof(char)); + + if (!col_str) + { + WLog_ERR(TAG, "calloc failed!"); + return 1; + } + + for (UINT32 tx = 0; tx < ncol; tx++) + sprintf_s(&col_str[tx], size - tx, "-"); + + WLog_INFO(TAG, "%s", col_str); + + for (UINT32 tx = 0; tx < ncol; tx++) + sprintf_s(&col_str[tx], size - tx, "%c", cols[tx] ? 'O' : 'X'); + + WLog_INFO(TAG, "%s", col_str); + + for (UINT32 tx = 0; tx < ncol; tx++) + sprintf_s(&col_str[tx], size - tx, "-"); + + WLog_INFO(TAG, "%s", col_str); + + for (UINT32 ty = 0; ty < nrow; ty++) + { + for (UINT32 tx = 0; tx < ncol; tx++) + sprintf_s(&col_str[tx], size - tx, "%c", cols[tx] ? 'O' : 'X'); + + WLog_INFO(TAG, "%s", col_str); + WLog_INFO(TAG, "|%s|", rows[ty] ? "O" : "X"); + } + + WLog_INFO(TAG, + "left: %" PRIu32 " top: %" PRIu32 " right: %" PRIu32 " bottom: %" PRIu32 + " ncol: %" PRIu32 " nrow: %" PRIu32, + l, t, r, b, ncol, nrow); + free(col_str); +#endif + return 1; +} + +rdpShadowCapture* shadow_capture_new(rdpShadowServer* server) +{ + WINPR_ASSERT(server); + + rdpShadowCapture* capture = (rdpShadowCapture*)calloc(1, sizeof(rdpShadowCapture)); + + if (!capture) + return NULL; + + capture->server = server; + + if (!InitializeCriticalSectionAndSpinCount(&(capture->lock), 4000)) + { + WINPR_PRAGMA_DIAG_PUSH + WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC + shadow_capture_free(capture); + WINPR_PRAGMA_DIAG_POP + return NULL; + } + + return capture; +} + +void shadow_capture_free(rdpShadowCapture* capture) +{ + if (!capture) + return; + + DeleteCriticalSection(&(capture->lock)); + free(capture); +} |