summaryrefslogtreecommitdiffstats
path: root/server/shadow/shadow_capture.c
diff options
context:
space:
mode:
Diffstat (limited to 'server/shadow/shadow_capture.c')
-rw-r--r--server/shadow/shadow_capture.c214
1 files changed, 131 insertions, 83 deletions
diff --git a/server/shadow/shadow_capture.c b/server/shadow/shadow_capture.c
index 4711ded..887f229 100644
--- a/server/shadow/shadow_capture.c
+++ b/server/shadow/shadow_capture.c
@@ -29,7 +29,7 @@
#define TAG SERVER_TAG("shadow")
-int shadow_capture_align_clip_rect(RECTANGLE_16* rect, RECTANGLE_16* clip)
+int shadow_capture_align_clip_rect(RECTANGLE_16* rect, const RECTANGLE_16* clip)
{
int dx = 0;
int dy = 0;
@@ -78,59 +78,151 @@ int shadow_capture_align_clip_rect(RECTANGLE_16* rect, RECTANGLE_16* clip)
return 1;
}
-int shadow_capture_compare(BYTE* pData1, UINT32 nStep1, UINT32 nWidth, UINT32 nHeight, BYTE* pData2,
- UINT32 nStep2, RECTANGLE_16* rect)
+int shadow_capture_compare(const BYTE* WINPR_RESTRICT pData1, UINT32 nStep1, UINT32 nWidth,
+ UINT32 nHeight, const BYTE* WINPR_RESTRICT pData2, UINT32 nStep2,
+ RECTANGLE_16* WINPR_RESTRICT rect)
{
- BOOL equal = 0;
- BOOL allEqual = 0;
+ return shadow_capture_compare_with_format(pData1, PIXEL_FORMAT_BGRX32, nStep1, nWidth, nHeight,
+ pData2, PIXEL_FORMAT_BGRX32, nStep2, rect);
+}
+
+static BOOL color_equal(UINT32 colorA, UINT32 formatA, UINT32 colorB, UINT32 formatB)
+{
+ BYTE ar = 0;
+ BYTE ag = 0;
+ BYTE ab = 0;
+ BYTE aa = 0;
+ BYTE br = 0;
+ BYTE bg = 0;
+ BYTE bb = 0;
+ BYTE ba = 0;
+ FreeRDPSplitColor(colorA, formatA, &ar, &ag, &ab, &aa, NULL);
+ FreeRDPSplitColor(colorB, formatB, &br, &bg, &bb, &ba, NULL);
+
+ if (ar != br)
+ return FALSE;
+ if (ag != bg)
+ return FALSE;
+ if (ab != bb)
+ return FALSE;
+ if (aa != ba)
+ return FALSE;
+ return TRUE;
+}
+
+static BOOL pixel_equal(const BYTE* WINPR_RESTRICT a, UINT32 formatA, const BYTE* WINPR_RESTRICT b,
+ UINT32 formatB, size_t count)
+{
+ const size_t bppA = FreeRDPGetBytesPerPixel(formatA);
+ const size_t bppB = FreeRDPGetBytesPerPixel(formatB);
+
+ for (size_t x = 0; x < count; x++)
+ {
+ const UINT32 colorA = FreeRDPReadColor(&a[bppA * x], formatA);
+ const UINT32 colorB = FreeRDPReadColor(&b[bppB * x], formatB);
+ if (!color_equal(colorA, formatA, colorB, formatB))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static BOOL color_equal_no_alpha(UINT32 colorA, UINT32 formatA, UINT32 colorB, UINT32 formatB)
+{
+ BYTE ar = 0;
+ BYTE ag = 0;
+ BYTE ab = 0;
+ BYTE br = 0;
+ BYTE bg = 0;
+ BYTE bb = 0;
+ FreeRDPSplitColor(colorA, formatA, &ar, &ag, &ab, NULL, NULL);
+ FreeRDPSplitColor(colorB, formatB, &br, &bg, &bb, NULL, NULL);
+
+ if (ar != br)
+ return FALSE;
+ if (ag != bg)
+ return FALSE;
+ if (ab != bb)
+ return FALSE;
+ return TRUE;
+}
+
+static BOOL pixel_equal_no_alpha(const BYTE* WINPR_RESTRICT a, UINT32 formatA,
+ const BYTE* WINPR_RESTRICT b, UINT32 formatB, size_t count)
+{
+ const size_t bppA = FreeRDPGetBytesPerPixel(formatA);
+ const size_t bppB = FreeRDPGetBytesPerPixel(formatB);
+
+ for (size_t x = 0; x < count; x++)
+ {
+ const UINT32 colorA = FreeRDPReadColor(&a[bppA * x], formatA);
+ const UINT32 colorB = FreeRDPReadColor(&b[bppB * x], formatB);
+ if (!color_equal_no_alpha(colorA, formatA, colorB, formatB))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static BOOL pixel_equal_same_format(const BYTE* WINPR_RESTRICT a, UINT32 formatA,
+ const BYTE* WINPR_RESTRICT b, UINT32 formatB, size_t count)
+{
+ if (formatA != formatB)
+ return FALSE;
+ const size_t bppA = FreeRDPGetBytesPerPixel(formatA);
+ return memcmp(a, b, count * bppA) == 0;
+}
+
+int shadow_capture_compare_with_format(const BYTE* WINPR_RESTRICT pData1, UINT32 format1,
+ UINT32 nStep1, UINT32 nWidth, UINT32 nHeight,
+ const BYTE* WINPR_RESTRICT pData2, UINT32 format2,
+ UINT32 nStep2, RECTANGLE_16* WINPR_RESTRICT rect)
+{
+ BOOL(*pixel_equal_fn)
+ (const BYTE* a, UINT32 formatA, const BYTE* b, UINT32 formatB, size_t count) = pixel_equal;
+
+ if (format1 == format2)
+ pixel_equal_fn = pixel_equal_same_format;
+ else if (!FreeRDPColorHasAlpha(format1) || !FreeRDPColorHasAlpha(format2))
+ pixel_equal_fn = pixel_equal_no_alpha;
+
+ BOOL allEqual = TRUE;
UINT32 tw = 0;
- UINT32 th = 0;
- UINT32 nrow = 0;
- UINT32 ncol = 0;
- UINT32 l = 0;
- UINT32 t = 0;
+ const UINT32 nrow = (nHeight + 15) / 16;
+ const UINT32 ncol = (nWidth + 15) / 16;
+ UINT32 l = ncol + 1;
+ UINT32 t = nrow + 1;
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++)
+ const size_t bppA = FreeRDPGetBytesPerPixel(format1);
+ const size_t bppB = FreeRDPGetBytesPerPixel(format2);
+ const RECTANGLE_16 empty = { 0 };
+ WINPR_ASSERT(rect);
+
+ *rect = empty;
+
+ for (size_t ty = 0; ty < nrow; ty++)
{
- th = ((ty + 1) == nrow) ? (nHeight % 16) : 16;
+ BOOL rowEqual = TRUE;
+ size_t th = ((ty + 1) == nrow) ? (nHeight % 16) : 16;
if (!th)
th = 16;
- for (UINT32 tx = 0; tx < ncol; tx++)
+ for (size_t tx = 0; tx < ncol; tx++)
{
- equal = TRUE;
+ BOOL 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)];
+ const BYTE* p1 = &pData1[(ty * 16 * nStep1) + (tx * 16ull * bppA)];
+ const BYTE* p2 = &pData2[(ty * 16 * nStep2) + (tx * 16ull * bppB)];
- for (UINT32 k = 0; k < th; k++)
+ for (size_t k = 0; k < th; k++)
{
- if (memcmp(p1, p2, tw * 4) != 0)
+ if (!pixel_equal_fn(p1, format1, p2, format2, tw))
{
equal = FALSE;
break;
@@ -142,11 +234,7 @@ int shadow_capture_compare(BYTE* pData1, UINT32 nStep1, UINT32 nWidth, UINT32 nH
if (!equal)
{
- rows[ty] = FALSE;
-#ifdef WITH_DEBUG_SHADOW_CAPTURE
- cols[tx] = FALSE;
-#endif
-
+ rowEqual = FALSE;
if (l > tx)
l = tx;
@@ -155,7 +243,7 @@ int shadow_capture_compare(BYTE* pData1, UINT32 nStep1, UINT32 nWidth, UINT32 nH
}
}
- if (!rows[ty])
+ if (!rowEqual)
{
allEqual = FALSE;
@@ -187,46 +275,6 @@ int shadow_capture_compare(BYTE* pData1, UINT32 nStep1, UINT32 nWidth, UINT32 nH
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;
}