diff --git a/libfreerdp/codec/color.c b/libfreerdp/codec/color.c index 59dc92a5f..a7cc42229 100644 --- a/libfreerdp/codec/color.c +++ b/libfreerdp/codec/color.c @@ -41,6 +41,16 @@ #define TAG FREERDP_TAG("color") +static INLINE BOOL FreeRDPWriteColorIgnoreAlpha_int(BYTE* WINPR_RESTRICT dst, UINT32 format, + UINT32 color); +static INLINE BOOL FreeRDPWriteColor_int(BYTE* WINPR_RESTRICT dst, UINT32 format, UINT32 color); +static INLINE UINT32 FreeRDPReadColor_int(const BYTE* WINPR_RESTRICT src, UINT32 format); +static INLINE DWORD FreeRDPAreColorFormatsEqualNoAlpha_int(DWORD first, DWORD second) +{ + const DWORD mask = (DWORD) ~(8UL << 12UL); + return (first & mask) == (second & mask); +} + BYTE* freerdp_glyph_convert(UINT32 width, UINT32 height, const BYTE* data) { /* @@ -118,9 +128,9 @@ BOOL freerdp_image_copy_from_monochrome(BYTE* WINPR_RESTRICT pDstData, UINT32 Ds } if (monoPixel) - FreeRDPWriteColor(pDstPixel, DstFormat, backColor); + FreeRDPWriteColor_int(pDstPixel, DstFormat, backColor); else - FreeRDPWriteColor(pDstPixel, DstFormat, foreColor); + FreeRDPWriteColor_int(pDstPixel, DstFormat, foreColor); } } @@ -169,7 +179,7 @@ static void fill_gdi_palette_for_icon(const BYTE* colorTable, UINT16 cbColorTabl for (UINT16 i = 0; i < cbColorTable / 4; i++) { - palette->palette[i] = FreeRDPReadColor(&colorTable[4 * i], palette->format); + palette->palette[i] = FreeRDPReadColor_int(&colorTable[4 * i], palette->format); } } @@ -275,10 +285,10 @@ BOOL freerdp_image_copy_from_icon_data(BYTE* WINPR_RESTRICT pDstData, UINT32 Dst BYTE alpha = (*maskByte & nextBit) ? 0x00 : 0xFF; /* read color back, add alpha and write it back */ - color = FreeRDPReadColor(dstBuf, DstFormat); + color = FreeRDPReadColor_int(dstBuf, DstFormat); FreeRDPSplitColor(color, DstFormat, &r, &g, &b, NULL, &palette); color = FreeRDPGetColor(DstFormat, r, g, b, alpha); - FreeRDPWriteColor(dstBuf, DstFormat, color); + FreeRDPWriteColor_int(dstBuf, DstFormat, color); nextBit >>= 1; dstBuf += dstBpp; @@ -372,7 +382,7 @@ static BOOL freerdp_image_copy_from_pointer_data_1bpp( else if (andPixel && xorPixel) color = freerdp_image_inverted_pointer_color(x, y, DstFormat); /* inverted */ - FreeRDPWriteColor(pDstPixel, DstFormat, color); + FreeRDPWriteColor_int(pDstPixel, DstFormat, color); pDstPixel += FreeRDPGetBytesPerPixel(DstFormat); } } @@ -454,12 +464,12 @@ static BOOL freerdp_image_copy_from_pointer_data_xbpp( if (xorBpp == 32) { pixelFormat = PIXEL_FORMAT_BGRA32; - xorPixel = FreeRDPReadColor(xorBits, pixelFormat); + xorPixel = FreeRDPReadColor_int(xorBits, pixelFormat); } else if (xorBpp == 16) { pixelFormat = PIXEL_FORMAT_RGB15; - xorPixel = FreeRDPReadColor(xorBits, pixelFormat); + xorPixel = FreeRDPReadColor_int(xorBits, pixelFormat); } else if (xorBpp == 8) { @@ -469,7 +479,7 @@ static BOOL freerdp_image_copy_from_pointer_data_xbpp( else { pixelFormat = PIXEL_FORMAT_BGR24; - xorPixel = FreeRDPReadColor(xorBits, pixelFormat); + xorPixel = FreeRDPReadColor_int(xorBits, pixelFormat); } xorPixel = FreeRDPConvertColor(xorPixel, pixelFormat, PIXEL_FORMAT_ARGB32, palette); @@ -496,7 +506,7 @@ static BOOL freerdp_image_copy_from_pointer_data_xbpp( } color = FreeRDPConvertColor(xorPixel, PIXEL_FORMAT_ARGB32, DstFormat, palette); - FreeRDPWriteColor(pDstPixel, DstFormat, color); + FreeRDPWriteColor_int(pDstPixel, DstFormat, color); pDstPixel += FreeRDPGetBytesPerPixel(DstFormat); } } @@ -623,29 +633,29 @@ BOOL freerdp_image_copy_no_overlap(BYTE* WINPR_RESTRICT pDstData, DWORD DstForma BYTE* WINPR_RESTRICT dstLine = &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset]; - UINT32 color = FreeRDPReadColor(&srcLine[nXSrc * srcByte], SrcFormat); + UINT32 color = FreeRDPReadColor_int(&srcLine[nXSrc * srcByte], SrcFormat); UINT32 oldColor = color; UINT32 dstColor = FreeRDPConvertColor(color, SrcFormat, DstFormat, palette); - FreeRDPWriteColorIgnoreAlpha(&dstLine[nXDst * dstByte], DstFormat, dstColor); + FreeRDPWriteColorIgnoreAlpha_int(&dstLine[nXDst * dstByte], DstFormat, dstColor); for (SSIZE_T x = 1; x < nWidth; x++) { - color = FreeRDPReadColor(&srcLine[(x + nXSrc) * srcByte], SrcFormat); + color = FreeRDPReadColor_int(&srcLine[(x + nXSrc) * srcByte], SrcFormat); if (color == oldColor) { - FreeRDPWriteColorIgnoreAlpha(&dstLine[(x + nXDst) * dstByte], DstFormat, - dstColor); + FreeRDPWriteColorIgnoreAlpha_int(&dstLine[(x + nXDst) * dstByte], DstFormat, + dstColor); } else { oldColor = color; dstColor = FreeRDPConvertColor(color, SrcFormat, DstFormat, palette); - FreeRDPWriteColorIgnoreAlpha(&dstLine[(x + nXDst) * dstByte], DstFormat, - dstColor); + FreeRDPWriteColorIgnoreAlpha_int(&dstLine[(x + nXDst) * dstByte], DstFormat, + dstColor); } } } } - else if (FreeRDPAreColorFormatsEqualNoAlpha(SrcFormat, DstFormat)) + else if (FreeRDPAreColorFormatsEqualNoAlpha_int(SrcFormat, DstFormat)) { if (!vSrcVFlip && (nDstStep == nSrcStep) && (xSrcOffset == 0) && (xDstOffset == 0)) { @@ -674,22 +684,22 @@ BOOL freerdp_image_copy_no_overlap(BYTE* WINPR_RESTRICT pDstData, DWORD DstForma BYTE* WINPR_RESTRICT dstLine = &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset]; - UINT32 color = FreeRDPReadColor(&srcLine[nXSrc * srcByte], SrcFormat); + UINT32 color = FreeRDPReadColor_int(&srcLine[nXSrc * srcByte], SrcFormat); UINT32 oldColor = color; UINT32 dstColor = FreeRDPConvertColor(color, SrcFormat, DstFormat, palette); - FreeRDPWriteColor(&dstLine[nXDst * dstByte], DstFormat, dstColor); + FreeRDPWriteColor_int(&dstLine[nXDst * dstByte], DstFormat, dstColor); for (SSIZE_T x = 1; x < nWidth; x++) { - color = FreeRDPReadColor(&srcLine[(x + nXSrc) * srcByte], SrcFormat); + color = FreeRDPReadColor_int(&srcLine[(x + nXSrc) * srcByte], SrcFormat); if (color == oldColor) { - FreeRDPWriteColor(&dstLine[(x + nXDst) * dstByte], DstFormat, dstColor); + FreeRDPWriteColor_int(&dstLine[(x + nXDst) * dstByte], DstFormat, dstColor); } else { oldColor = color; dstColor = FreeRDPConvertColor(color, SrcFormat, DstFormat, palette); - FreeRDPWriteColor(&dstLine[(x + nXDst) * dstByte], DstFormat, dstColor); + FreeRDPWriteColor_int(&dstLine[(x + nXDst) * dstByte], DstFormat, dstColor); } } } @@ -742,29 +752,29 @@ BOOL freerdp_image_copy_overlap(BYTE* pDstData, DWORD DstFormat, UINT32 nDstStep const BYTE* srcLine = &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset]; BYTE* dstLine = &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset]; - UINT32 color = FreeRDPReadColor(&srcLine[nXSrc * srcByte], SrcFormat); + UINT32 color = FreeRDPReadColor_int(&srcLine[nXSrc * srcByte], SrcFormat); UINT32 oldColor = color; UINT32 dstColor = FreeRDPConvertColor(color, SrcFormat, DstFormat, palette); - FreeRDPWriteColorIgnoreAlpha(&dstLine[nXDst * dstByte], DstFormat, dstColor); + FreeRDPWriteColorIgnoreAlpha_int(&dstLine[nXDst * dstByte], DstFormat, dstColor); for (UINT32 x = 1; x < nWidth; x++) { - color = FreeRDPReadColor(&srcLine[(x + nXSrc) * srcByte], SrcFormat); + color = FreeRDPReadColor_int(&srcLine[(x + nXSrc) * srcByte], SrcFormat); if (color == oldColor) { - FreeRDPWriteColorIgnoreAlpha(&dstLine[(x + nXDst) * dstByte], DstFormat, - dstColor); + FreeRDPWriteColorIgnoreAlpha_int(&dstLine[(x + nXDst) * dstByte], DstFormat, + dstColor); } else { oldColor = color; dstColor = FreeRDPConvertColor(color, SrcFormat, DstFormat, palette); - FreeRDPWriteColorIgnoreAlpha(&dstLine[(x + nXDst) * dstByte], DstFormat, - dstColor); + FreeRDPWriteColorIgnoreAlpha_int(&dstLine[(x + nXDst) * dstByte], DstFormat, + dstColor); } } } } - else if (FreeRDPAreColorFormatsEqualNoAlpha(SrcFormat, DstFormat)) + else if (FreeRDPAreColorFormatsEqualNoAlpha_int(SrcFormat, DstFormat)) { /* Copy down */ if (nYDst < nYSrc) @@ -822,22 +832,22 @@ BOOL freerdp_image_copy_overlap(BYTE* pDstData, DWORD DstFormat, UINT32 nDstStep const BYTE* srcLine = &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset]; BYTE* dstLine = &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset]; - UINT32 color = FreeRDPReadColor(&srcLine[nXSrc * srcByte], SrcFormat); + UINT32 color = FreeRDPReadColor_int(&srcLine[nXSrc * srcByte], SrcFormat); UINT32 oldColor = color; UINT32 dstColor = FreeRDPConvertColor(color, SrcFormat, DstFormat, palette); - FreeRDPWriteColor(&dstLine[nXDst * dstByte], DstFormat, dstColor); + FreeRDPWriteColor_int(&dstLine[nXDst * dstByte], DstFormat, dstColor); for (SSIZE_T x = 1; x < nWidth; x++) { - color = FreeRDPReadColor(&srcLine[(x + nXSrc) * srcByte], SrcFormat); + color = FreeRDPReadColor_int(&srcLine[(x + nXSrc) * srcByte], SrcFormat); if (color == oldColor) { - FreeRDPWriteColor(&dstLine[(x + nXDst) * dstByte], DstFormat, dstColor); + FreeRDPWriteColor_int(&dstLine[(x + nXDst) * dstByte], DstFormat, dstColor); } else { oldColor = color; dstColor = FreeRDPConvertColor(color, SrcFormat, DstFormat, palette); - FreeRDPWriteColor(&dstLine[(x + nXDst) * dstByte], DstFormat, dstColor); + FreeRDPWriteColor_int(&dstLine[(x + nXDst) * dstByte], DstFormat, dstColor); } } } @@ -898,7 +908,7 @@ BOOL freerdp_image_fill(BYTE* WINPR_RESTRICT pDstData, DWORD DstFormat, UINT32 n for (UINT32 x = 0; x < nWidth; x++) { BYTE* pDst = &pFirstDstLine[(x + nXDst) * bpp]; - FreeRDPWriteColor(pDst, DstFormat, color); + FreeRDPWriteColor_int(pDst, DstFormat, color); } for (UINT32 y = 1; y < nHeight; y++) @@ -1030,8 +1040,7 @@ BOOL freerdp_image_scale(BYTE* WINPR_RESTRICT pDstData, DWORD DstFormat, UINT32 DWORD FreeRDPAreColorFormatsEqualNoAlpha(DWORD first, DWORD second) { - const DWORD mask = (DWORD) ~(8UL << 12UL); - return (first & mask) == (second & mask); + return FreeRDPAreColorFormatsEqualNoAlpha_int(first, second); } const char* FreeRDPGetColorFormatName(UINT32 format) @@ -1496,6 +1505,11 @@ void FreeRDPSplitColor(UINT32 color, UINT32 format, BYTE* _r, BYTE* _g, BYTE* _b } BOOL FreeRDPWriteColorIgnoreAlpha(BYTE* WINPR_RESTRICT dst, UINT32 format, UINT32 color) +{ + return FreeRDPWriteColorIgnoreAlpha_int(dst, format, color); +} + +BOOL FreeRDPWriteColorIgnoreAlpha_int(BYTE* WINPR_RESTRICT dst, UINT32 format, UINT32 color) { switch (format) { @@ -1505,7 +1519,7 @@ BOOL FreeRDPWriteColorIgnoreAlpha(BYTE* WINPR_RESTRICT dst, UINT32 format, UINT3 case PIXEL_FORMAT_ARGB32: { const UINT32 tmp = ((UINT32)dst[0] << 24ULL) | (color & 0x00FFFFFFULL); - return FreeRDPWriteColor(dst, format, tmp); + return FreeRDPWriteColor_int(dst, format, tmp); } case PIXEL_FORMAT_BGRX32: case PIXEL_FORMAT_RGBX32: @@ -1513,14 +1527,18 @@ BOOL FreeRDPWriteColorIgnoreAlpha(BYTE* WINPR_RESTRICT dst, UINT32 format, UINT3 case PIXEL_FORMAT_RGBA32: { const UINT32 tmp = ((UINT32)dst[3]) | (color & 0xFFFFFF00ULL); - return FreeRDPWriteColor(dst, format, tmp); + return FreeRDPWriteColor_int(dst, format, tmp); } default: - return FreeRDPWriteColor(dst, format, color); + return FreeRDPWriteColor_int(dst, format, color); } } BOOL FreeRDPWriteColor(BYTE* WINPR_RESTRICT dst, UINT32 format, UINT32 color) +{ + return FreeRDPWriteColor_int(dst, format, color); +} +BOOL FreeRDPWriteColor_int(BYTE* WINPR_RESTRICT dst, UINT32 format, UINT32 color) { switch (FreeRDPGetBitsPerPixel(format)) { @@ -1563,6 +1581,11 @@ BOOL FreeRDPWriteColor(BYTE* WINPR_RESTRICT dst, UINT32 format, UINT32 color) } UINT32 FreeRDPReadColor(const BYTE* WINPR_RESTRICT src, UINT32 format) +{ + return FreeRDPReadColor_int(src, format); +} + +UINT32 FreeRDPReadColor_int(const BYTE* WINPR_RESTRICT src, UINT32 format) { UINT32 color = 0; diff --git a/libfreerdp/codec/test/CMakeLists.txt b/libfreerdp/codec/test/CMakeLists.txt index ebc7b8e00..d02d253e0 100644 --- a/libfreerdp/codec/test/CMakeLists.txt +++ b/libfreerdp/codec/test/CMakeLists.txt @@ -11,6 +11,7 @@ set(${MODULE_PREFIX}_TESTS TestFreeRDPCodecXCrush.c TestFreeRDPCodecZGfx.c TestFreeRDPCodecPlanar.c + TestFreeRDPCodecCopy.c TestFreeRDPCodecClear.c TestFreeRDPCodecInterleaved.c TestFreeRDPCodecProgressive.c diff --git a/libfreerdp/codec/test/TestFreeRDPCodecCopy.c b/libfreerdp/codec/test/TestFreeRDPCodecCopy.c new file mode 100644 index 000000000..247fca501 --- /dev/null +++ b/libfreerdp/codec/test/TestFreeRDPCodecCopy.c @@ -0,0 +1,110 @@ + +#include + +#include + +#include +#include + +#define TEST_RUNS 2 + +static BOOL TestFreeRDPImageCopy(UINT32 w, UINT32 h, UINT32 srcFormat, UINT32 dstFormat, + size_t runs) +{ + BOOL rc = FALSE; + const size_t sbpp = FreeRDPGetBytesPerPixel(srcFormat); + const size_t dbpp = FreeRDPGetBytesPerPixel(dstFormat); + const size_t srcStep = w * sbpp; + const size_t dstStep = w * dbpp; + char* src = calloc(h, srcStep); + char* dst = calloc(h, dstStep); + if (!src || !dst) + goto fail; + + for (size_t x = 0; x < runs; x++) + { + winpr_RAND_pseudo(src, h * srcStep); + const UINT64 start = winpr_GetUnixTimeNS(); + rc = freerdp_image_copy(dst, dstFormat, dstStep, 0, 0, w, h, src, srcFormat, srcStep, 0, 0, + NULL, 0); + const UINT64 end = winpr_GetUnixTimeNS(); + + double ms = end - start; + ms /= 1000000.0; + + fprintf(stdout, "[%s] copied %" PRIu32 "x%" PRIu32 " [%-20s] -> [%-20s] in %lf ms [%s]\n", + __func__, w, h, FreeRDPGetColorFormatName(srcFormat), + FreeRDPGetColorFormatName(dstFormat), ms, rc ? "success" : "failure"); + if (!rc) + break; + } + +fail: + free(src); + free(dst); + return rc; +} + +static BOOL TestFreeRDPImageCopy_no_overlap(UINT32 w, UINT32 h, UINT32 srcFormat, UINT32 dstFormat, + size_t runs) +{ + BOOL rc = FALSE; + const size_t sbpp = FreeRDPGetBytesPerPixel(srcFormat); + const size_t dbpp = FreeRDPGetBytesPerPixel(dstFormat); + const size_t srcStep = w * sbpp; + const size_t dstStep = w * dbpp; + char* src = calloc(h, srcStep); + char* dst = calloc(h, dstStep); + if (!src || !dst) + goto fail; + + for (size_t x = 0; x < runs; x++) + { + winpr_RAND_pseudo(src, h * srcStep); + const UINT64 start = winpr_GetUnixTimeNS(); + rc = freerdp_image_copy_no_overlap(dst, dstFormat, dstStep, 0, 0, w, h, src, srcFormat, + srcStep, 0, 0, NULL, 0); + const UINT64 end = winpr_GetUnixTimeNS(); + + double ms = end - start; + ms /= 1000000.0; + + fprintf(stdout, "[%s] copied %" PRIu32 "x%" PRIu32 " [%-20s] -> [%-20s] in %lf ms [%s]\n", + __func__, w, h, FreeRDPGetColorFormatName(srcFormat), + FreeRDPGetColorFormatName(dstFormat), ms, rc ? "success" : "failure"); + if (!rc) + break; + } + +fail: + free(src); + free(dst); + return rc; +} +int TestFreeRDPCodecCopy(int argc, char* argv[]) +{ + WINPR_UNUSED(argc); + WINPR_UNUSED(argv); + + const UINT32 formats[] = { + PIXEL_FORMAT_ABGR15, PIXEL_FORMAT_ARGB15, PIXEL_FORMAT_BGR15, PIXEL_FORMAT_BGR16, + PIXEL_FORMAT_BGR24, PIXEL_FORMAT_RGB15, PIXEL_FORMAT_RGB16, PIXEL_FORMAT_RGB24, + PIXEL_FORMAT_ABGR32, PIXEL_FORMAT_ARGB32, PIXEL_FORMAT_XBGR32, PIXEL_FORMAT_XRGB32, + PIXEL_FORMAT_BGRA32, PIXEL_FORMAT_RGBA32, PIXEL_FORMAT_BGRX32, PIXEL_FORMAT_RGBX32, + }; + + for (size_t x = 0; x < ARRAYSIZE(formats); x++) + { + const UINT32 SrcFormat = formats[x]; + for (size_t y = 0; y < ARRAYSIZE(formats); y++) + { + const UINT32 DstFormat = formats[y]; + if (!TestFreeRDPImageCopy(1920, 1080, SrcFormat, DstFormat, TEST_RUNS)) + return -1; + if (!TestFreeRDPImageCopy_no_overlap(1920, 1080, SrcFormat, DstFormat, TEST_RUNS)) + return -1; + } + } + + return 0; +}