19#include <freerdp/config.h> 
   22#include <winpr/print.h> 
   24#include <freerdp/log.h> 
   26#include "shadow_surface.h" 
   28#include "shadow_capture.h" 
   34  dx = (rect->left % 16);
 
   42  dx = (rect->right % 16);
 
   46    rect->right += (16 - dx);
 
   49  dy = (rect->top % 16);
 
   57  dy = (rect->bottom % 16);
 
   61    rect->bottom += (16 - dy);
 
   64  if (rect->left < clip->left)
 
   65    rect->left = clip->left;
 
   67  if (rect->top < clip->top)
 
   68    rect->top = clip->top;
 
   70  if (rect->right > clip->right)
 
   71    rect->right = clip->right;
 
   73  if (rect->bottom > clip->bottom)
 
   74    rect->bottom = clip->bottom;
 
   79#if !defined(WITHOUT_FREERDP_3x_DEPRECATED) 
   80int shadow_capture_compare(
const BYTE* WINPR_RESTRICT pData1, UINT32 nStep1, UINT32 nWidth,
 
   81                           UINT32 nHeight, 
const BYTE* WINPR_RESTRICT pData2, UINT32 nStep2,
 
   84  return shadow_capture_compare_with_format(pData1, PIXEL_FORMAT_BGRX32, nStep1, nWidth, nHeight,
 
   85                                            pData2, PIXEL_FORMAT_BGRX32, nStep2, rect);
 
   89static BOOL color_equal(UINT32 colorA, UINT32 formatA, UINT32 colorB, UINT32 formatB)
 
   99  FreeRDPSplitColor(colorA, formatA, &ar, &ag, &ab, &aa, NULL);
 
  100  FreeRDPSplitColor(colorB, formatB, &br, &bg, &bb, &ba, NULL);
 
  113static BOOL pixel_equal(
const BYTE* WINPR_RESTRICT a, UINT32 formatA, 
const BYTE* WINPR_RESTRICT b,
 
  114                        UINT32 formatB, 
size_t count)
 
  116  const size_t bppA = FreeRDPGetBytesPerPixel(formatA);
 
  117  const size_t bppB = FreeRDPGetBytesPerPixel(formatB);
 
  119  for (
size_t x = 0; x < count; x++)
 
  121    const UINT32 colorA = FreeRDPReadColor(&a[bppA * x], formatA);
 
  122    const UINT32 colorB = FreeRDPReadColor(&b[bppB * x], formatB);
 
  123    if (!color_equal(colorA, formatA, colorB, formatB))
 
  130static BOOL color_equal_no_alpha(UINT32 colorA, UINT32 formatA, UINT32 colorB, UINT32 formatB)
 
  138  FreeRDPSplitColor(colorA, formatA, &ar, &ag, &ab, NULL, NULL);
 
  139  FreeRDPSplitColor(colorB, formatB, &br, &bg, &bb, NULL, NULL);
 
  150static BOOL pixel_equal_no_alpha(
const BYTE* WINPR_RESTRICT a, UINT32 formatA,
 
  151                                 const BYTE* WINPR_RESTRICT b, UINT32 formatB, 
size_t count)
 
  153  const size_t bppA = FreeRDPGetBytesPerPixel(formatA);
 
  154  const size_t bppB = FreeRDPGetBytesPerPixel(formatB);
 
  156  for (
size_t x = 0; x < count; x++)
 
  158    const UINT32 colorA = FreeRDPReadColor(&a[bppA * x], formatA);
 
  159    const UINT32 colorB = FreeRDPReadColor(&b[bppB * x], formatB);
 
  160    if (!color_equal_no_alpha(colorA, formatA, colorB, formatB))
 
  167static BOOL pixel_equal_same_format(
const BYTE* WINPR_RESTRICT a, UINT32 formatA,
 
  168                                    const BYTE* WINPR_RESTRICT b, UINT32 formatB, 
size_t count)
 
  170  if (formatA != formatB)
 
  172  const size_t bppA = FreeRDPGetBytesPerPixel(formatA);
 
  173  return memcmp(a, b, count * bppA) == 0;
 
  176typedef BOOL (*pixel_equal_fn_t)(
const BYTE* WINPR_RESTRICT a, UINT32 formatA,
 
  177                                 const BYTE* WINPR_RESTRICT b, UINT32 formatB, 
size_t count);
 
  179static pixel_equal_fn_t get_comparison_fn(DWORD format1, DWORD format2)
 
  182  if (format1 == format2)
 
  183    return pixel_equal_same_format;
 
  185  const UINT32 bpp1 = FreeRDPGetBitsPerPixel(format1);
 
  187  if (!FreeRDPColorHasAlpha(format1) || !FreeRDPColorHasAlpha(format2))
 
  191    if ((bpp1 == 32) && FreeRDPAreColorFormatsEqualNoAlpha(format1, format2))
 
  195        case PIXEL_FORMAT_ARGB32:
 
  196        case PIXEL_FORMAT_XRGB32:
 
  197        case PIXEL_FORMAT_ABGR32:
 
  198        case PIXEL_FORMAT_XBGR32:
 
  200        case PIXEL_FORMAT_RGBA32:
 
  201        case PIXEL_FORMAT_RGBX32:
 
  202        case PIXEL_FORMAT_BGRA32:
 
  203        case PIXEL_FORMAT_BGRX32:
 
  209    return pixel_equal_no_alpha;
 
  212    return pixel_equal_no_alpha;
 
  215int shadow_capture_compare_with_format(
const BYTE* WINPR_RESTRICT pData1, UINT32 format1,
 
  216                                       UINT32 nStep1, UINT32 nWidth, UINT32 nHeight,
 
  217                                       const BYTE* WINPR_RESTRICT pData2, UINT32 format2,
 
  220  pixel_equal_fn_t pixel_equal_fn = get_comparison_fn(format1, format2);
 
  221  BOOL allEqual = TRUE;
 
  223  const UINT32 nrow = (nHeight + 15) / 16;
 
  224  const UINT32 ncol = (nWidth + 15) / 16;
 
  229  const size_t bppA = FreeRDPGetBytesPerPixel(format1);
 
  230  const size_t bppB = FreeRDPGetBytesPerPixel(format2);
 
  236  for (
size_t ty = 0; ty < nrow; ty++)
 
  238    BOOL rowEqual = TRUE;
 
  239    size_t th = ((ty + 1) == nrow) ? (nHeight % 16) : 16;
 
  244    for (
size_t tx = 0; tx < ncol; tx++)
 
  247      tw = ((tx + 1) == ncol) ? (nWidth % 16) : 16;
 
  252      const BYTE* p1 = &pData1[(ty * 16ULL * nStep1) + (tx * 16ull * bppA)];
 
  253      const BYTE* p2 = &pData2[(ty * 16ULL * nStep2) + (tx * 16ull * bppB)];
 
  255      for (
size_t k = 0; k < th; k++)
 
  257        if (!pixel_equal_fn(p1, format1, p2, format2, tw))
 
  293  WINPR_ASSERT(l * 16 <= UINT16_MAX);
 
  294  WINPR_ASSERT(t * 16 <= UINT16_MAX);
 
  295  WINPR_ASSERT((r + 1) * 16 <= UINT16_MAX);
 
  296  WINPR_ASSERT((b + 1) * 16 <= UINT16_MAX);
 
  297  rect->left = (UINT16)l * 16;
 
  298  rect->top = (UINT16)t * 16;
 
  299  rect->right = (UINT16)(r + 1) * 16;
 
  300  rect->bottom = (UINT16)(b + 1) * 16;
 
  302  WINPR_ASSERT(nWidth <= UINT16_MAX);
 
  303  if (rect->right > nWidth)
 
  304    rect->right = (UINT16)nWidth;
 
  306  WINPR_ASSERT(nHeight <= UINT16_MAX);
 
  307  if (rect->bottom > nHeight)
 
  308    rect->bottom = (UINT16)nHeight;
 
  313rdpShadowCapture* shadow_capture_new(rdpShadowServer* server)
 
  315  WINPR_ASSERT(server);
 
  317  rdpShadowCapture* capture = (rdpShadowCapture*)calloc(1, 
sizeof(rdpShadowCapture));
 
  322  capture->server = server;
 
  324  if (!InitializeCriticalSectionAndSpinCount(&(capture->lock), 4000))
 
  326    WINPR_PRAGMA_DIAG_PUSH
 
  327    WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
 
  328    shadow_capture_free(capture);
 
  329    WINPR_PRAGMA_DIAG_POP
 
  336void shadow_capture_free(rdpShadowCapture* capture)
 
  341  DeleteCriticalSection(&(capture->lock));