From 9dba98598f39e95a76868d969b1edabe6ff04c5c Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Tue, 14 Feb 2017 12:11:55 +0100 Subject: [PATCH 01/16] SSSE3 YUV444ToRGB process 16 pixel per loop. --- libfreerdp/primitives/prim_YUV_opt.c | 171 ++++++++++++++++----------- 1 file changed, 104 insertions(+), 67 deletions(-) diff --git a/libfreerdp/primitives/prim_YUV_opt.c b/libfreerdp/primitives/prim_YUV_opt.c index 6b1be6d54..1e655ceb3 100644 --- a/libfreerdp/primitives/prim_YUV_opt.c +++ b/libfreerdp/primitives/prim_YUV_opt.c @@ -359,6 +359,71 @@ static pstatus_t ssse3_YUV420ToRGB( } } +static __m128i* ssse3_YUV444Pixel(__m128i* dst, __m128i Yraw, __m128i Uraw, __m128i Vraw, + __m128i mapY, __m128i mapUV) +{ + const __m128i c128 = _mm_set1_epi16(128); + __m128i BGRX = _mm_set_epi32(0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000); + { + __m128i C, D, E; + /* Load Y values and expand to 32 bit */ + { + C = _mm_shuffle_epi8(Yraw, mapY); /* Reorder and multiply by 256 */ + } + /* Load U values and expand to 32 bit */ + { + const __m128i U = _mm_shuffle_epi8(Uraw, mapUV); /* Reorder dcba */ + D = _mm_sub_epi16(U, c128); /* D = U - 128 */ + } + /* Load V values and expand to 32 bit */ + { + const __m128i V = _mm_shuffle_epi8(Vraw, mapUV); /* Reorder dcba */ + E = _mm_sub_epi16(V, c128); /* E = V - 128 */ + } + /* Get the R value */ + { + const __m128i c403 = _mm_set1_epi16(403); + const __m128i e403 = _mm_unpackhi_epi16(_mm_mullo_epi16(E, c403), _mm_mulhi_epi16(E, c403)); + const __m128i Rs = _mm_add_epi32(C, e403); + const __m128i R32 = _mm_srai_epi32(Rs, 8); + const __m128i R16 = _mm_packs_epi32(R32, _mm_setzero_si128()); + const __m128i R = _mm_packus_epi16(R16, _mm_setzero_si128()); + const __m128i mask = _mm_set_epi32(0x80038080, 0x80028080, 0x80018080, 0x80008080); + const __m128i packed = _mm_shuffle_epi8(R, mask); + BGRX = _mm_or_si128(BGRX, packed); + } + /* Get the G value */ + { + const __m128i c48 = _mm_set1_epi16(48); + const __m128i d48 = _mm_unpackhi_epi16(_mm_mullo_epi16(D, c48), _mm_mulhi_epi16(D, c48)); + const __m128i c120 = _mm_set1_epi16(120); + const __m128i e120 = _mm_unpackhi_epi16(_mm_mullo_epi16(E, c120), _mm_mulhi_epi16(E, c120)); + const __m128i de = _mm_add_epi32(d48, e120); + const __m128i Gs = _mm_sub_epi32(C, de); + const __m128i G32 = _mm_srai_epi32(Gs, 8); + const __m128i G16 = _mm_packs_epi32(G32, _mm_setzero_si128()); + const __m128i G = _mm_packus_epi16(G16, _mm_setzero_si128()); + const __m128i mask = _mm_set_epi32(0x80800380, 0x80800280, 0x80800180, 0x80800080); + const __m128i packed = _mm_shuffle_epi8(G, mask); + BGRX = _mm_or_si128(BGRX, packed); + } + /* Get the B value */ + { + const __m128i c475 = _mm_set1_epi16(475); + const __m128i d475 = _mm_unpackhi_epi16(_mm_mullo_epi16(D, c475), _mm_mulhi_epi16(D, c475)); + const __m128i Bs = _mm_add_epi32(C, d475); + const __m128i B32 = _mm_srai_epi32(Bs, 8); + const __m128i B16 = _mm_packs_epi32(B32, _mm_setzero_si128()); + const __m128i B = _mm_packus_epi16(B16, _mm_setzero_si128()); + const __m128i mask = _mm_set_epi32(0x80808003, 0x80808002, 0x80808001, 0x80808000); + const __m128i packed = _mm_shuffle_epi8(B, mask); + BGRX = _mm_or_si128(BGRX, packed); + } + } + _mm_store_si128(dst++, BGRX); + return dst; +} + static pstatus_t ssse3_YUV444ToRGB_8u_P3AC4R_BGRX( const BYTE** pSrc, const UINT32* srcStep, BYTE* pDst, UINT32 dstStep, @@ -366,9 +431,7 @@ static pstatus_t ssse3_YUV444ToRGB_8u_P3AC4R_BGRX( { const UINT32 nWidth = roi->width; const UINT32 nHeight = roi->height; - const __m128i c128 = _mm_set1_epi16(128); - const __m128i mapY = _mm_set_epi32(0x80800380, 0x80800280, 0x80800180, 0x80800080); - const __m128i map = _mm_set_epi32(0x80038002, 0x80018000, 0x80808080, 0x80808080); + const UINT32 pad = roi->width % 16; UINT32 y; for (y = 0; y < nHeight; y++) @@ -379,72 +442,45 @@ static pstatus_t ssse3_YUV444ToRGB_8u_P3AC4R_BGRX( const BYTE* UData = pSrc[1] + y * srcStep[1]; const BYTE* VData = pSrc[2] + y * srcStep[2]; - for (x = 0; x < nWidth; x += 4) + for (x = 0; x < nWidth - pad; x += 16) { - __m128i BGRX = _mm_set_epi32(0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000); + __m128i Y = _mm_load_si128((__m128i*)YData); + __m128i U = _mm_load_si128((__m128i*)UData); + __m128i V = _mm_load_si128((__m128i*)VData); + YData += 16; + UData += 16; + VData += 16; { - __m128i C, D, E; - /* Load Y values and expand to 32 bit */ - { - const __m128i Yraw = _mm_loadu_si128((__m128i*)YData); - C = _mm_shuffle_epi8(Yraw, mapY); /* Reorder and multiply by 256 */ - } - /* Load U values and expand to 32 bit */ - { - const __m128i Uraw = _mm_loadu_si128((__m128i*)UData); - const __m128i U = _mm_shuffle_epi8(Uraw, map); /* Reorder dcba */ - D = _mm_sub_epi16(U, c128); /* D = U - 128 */ - } - /* Load V values and expand to 32 bit */ - { - const __m128i Vraw = _mm_loadu_si128((__m128i*)VData); - const __m128i V = _mm_shuffle_epi8(Vraw, map); /* Reorder dcba */ - E = _mm_sub_epi16(V, c128); /* E = V - 128 */ - } - /* Get the R value */ - { - const __m128i c403 = _mm_set1_epi16(403); - const __m128i e403 = _mm_unpackhi_epi16(_mm_mullo_epi16(E, c403), _mm_mulhi_epi16(E, c403)); - const __m128i Rs = _mm_add_epi32(C, e403); - const __m128i R32 = _mm_srai_epi32(Rs, 8); - const __m128i R16 = _mm_packs_epi32(R32, _mm_setzero_si128()); - const __m128i R = _mm_packus_epi16(R16, _mm_setzero_si128()); - const __m128i mask = _mm_set_epi32(0x80038080, 0x80028080, 0x80018080, 0x80008080); - const __m128i packed = _mm_shuffle_epi8(R, mask); - BGRX = _mm_or_si128(BGRX, packed); - } - /* Get the G value */ - { - const __m128i c48 = _mm_set1_epi16(48); - const __m128i d48 = _mm_unpackhi_epi16(_mm_mullo_epi16(D, c48), _mm_mulhi_epi16(D, c48)); - const __m128i c120 = _mm_set1_epi16(120); - const __m128i e120 = _mm_unpackhi_epi16(_mm_mullo_epi16(E, c120), _mm_mulhi_epi16(E, c120)); - const __m128i de = _mm_add_epi32(d48, e120); - const __m128i Gs = _mm_sub_epi32(C, de); - const __m128i G32 = _mm_srai_epi32(Gs, 8); - const __m128i G16 = _mm_packs_epi32(G32, _mm_setzero_si128()); - const __m128i G = _mm_packus_epi16(G16, _mm_setzero_si128()); - const __m128i mask = _mm_set_epi32(0x80800380, 0x80800280, 0x80800180, 0x80800080); - const __m128i packed = _mm_shuffle_epi8(G, mask); - BGRX = _mm_or_si128(BGRX, packed); - } - /* Get the B value */ - { - const __m128i c475 = _mm_set1_epi16(475); - const __m128i d475 = _mm_unpackhi_epi16(_mm_mullo_epi16(D, c475), _mm_mulhi_epi16(D, c475)); - const __m128i Bs = _mm_add_epi32(C, d475); - const __m128i B32 = _mm_srai_epi32(Bs, 8); - const __m128i B16 = _mm_packs_epi32(B32, _mm_setzero_si128()); - const __m128i B = _mm_packus_epi16(B16, _mm_setzero_si128()); - const __m128i mask = _mm_set_epi32(0x80808003, 0x80808002, 0x80808001, 0x80808000); - const __m128i packed = _mm_shuffle_epi8(B, mask); - BGRX = _mm_or_si128(BGRX, packed); - } + const __m128i mapY = _mm_set_epi32(0x80800380, 0x80800280, 0x80800180, 0x80800080); + const __m128i mapUV = _mm_set_epi32(0x80038002, 0x80018000, 0x80808080, 0x80808080); + dst = ssse3_YUV444Pixel(dst, Y, U, V, mapY, mapUV); } - _mm_storeu_si128(dst++, BGRX); - YData += 4; - UData += 4; - VData += 4; + { + const __m128i mapY = _mm_set_epi32(0x80800780, 0x80800680, 0x80800580, 0x80800480); + const __m128i mapUV = _mm_set_epi32(0x80078006, 0x80058004, 0x80808080, 0x80808080); + dst = ssse3_YUV444Pixel(dst, Y, U, V, mapY, mapUV); + } + { + const __m128i mapY = _mm_set_epi32(0x80800B80, 0x80800A80, 0x80800980, 0x80800880); + const __m128i mapUV = _mm_set_epi32(0x800B800A, 0x80098008, 0x80808080, 0x80808080); + dst = ssse3_YUV444Pixel(dst, Y, U, V, mapY, mapUV); + } + { + const __m128i mapY = _mm_set_epi32(0x80800F80, 0x80800E80, 0x80800D80, 0x80800C80); + const __m128i mapUV = _mm_set_epi32(0x800F800E, 0x800D800C, 0x80808080, 0x80808080); + dst = ssse3_YUV444Pixel(dst, Y, U, V, mapY, mapUV); + } + } + + for (x = 0; x < pad; x++) + { + const BYTE Y = *YData++; + const BYTE U = *UData++; + const BYTE V = *VData++; + const BYTE r = YUV2R(Y, U, V); + const BYTE g = YUV2G(Y, U, V); + const BYTE b = YUV2B(Y, U, V); + dst = (__m128i*)writePixelBGRX((BYTE*)dst, 4, PIXEL_FORMAT_BGRX32, r, g, b, 0xFF); } } @@ -455,7 +491,8 @@ static pstatus_t ssse3_YUV444ToRGB_8u_P3AC4R(const BYTE** pSrc, const UINT32* sr BYTE* pDst, UINT32 dstStep, UINT32 DstFormat, const prim_size_t* roi) { - if (roi->width % 4 != 0) + if ((unsigned long)pSrc[0] % 16 || (unsigned long)pSrc[1] % 16 || (unsigned long)pSrc[2] % 16 || + (unsigned long)pDst % 16) return generic->YUV444ToRGB_8u_P3AC4R(pSrc, srcStep, pDst, dstStep, DstFormat, roi); switch (DstFormat) From f324b0ef9c0a59dcb691c51057ee9c2ce37460b3 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Tue, 14 Feb 2017 12:12:24 +0100 Subject: [PATCH 02/16] Use aligned malloc/free for GFX surfaces/buffers --- libfreerdp/codec/h264.c | 31 +++++++++---------- libfreerdp/gdi/gfx.c | 4 +-- .../primitives/test/TestPrimitivesYUV.c | 19 +++++++++--- 3 files changed, 31 insertions(+), 23 deletions(-) diff --git a/libfreerdp/codec/h264.c b/libfreerdp/codec/h264.c index 270cd3b9e..4b9d7c4a3 100644 --- a/libfreerdp/codec/h264.c +++ b/libfreerdp/codec/h264.c @@ -1600,17 +1600,17 @@ INT32 avc420_compress(H264_CONTEXT* h264, const BYTE* pSrcData, DWORD SrcFormat, nWidth = (nSrcWidth + 1) & ~1; nHeight = (nSrcHeight + 1) & ~1; - if (!(pYUVData[0] = (BYTE*) malloc(nWidth * nHeight))) + if (!(pYUVData[0] = (BYTE*) _aligned_malloc(nWidth * nHeight, 16))) return -1; iStride[0] = nWidth; - if (!(pYUVData[1] = (BYTE*) malloc(nWidth * nHeight))) + if (!(pYUVData[1] = (BYTE*) _aligned_malloc(nWidth * nHeight, 16))) goto error_1; iStride[1] = nWidth / 2; - if (!(pYUVData[2] = (BYTE*) malloc(nWidth * nHeight))) + if (!(pYUVData[2] = (BYTE*) _aligned_malloc(nWidth * nHeight, 16))) goto error_2; iStride[2] = nWidth / 2; @@ -1619,13 +1619,13 @@ INT32 avc420_compress(H264_CONTEXT* h264, const BYTE* pSrcData, DWORD SrcFormat, prims->RGBToYUV420_8u_P3AC4R(pSrcData, SrcFormat, nSrcStep, pYUVData, iStride, &roi); status = h264->subsystem->Compress(h264, ppDstData, pDstSize, 0); - free(pYUVData[2]); + _aligned_free(pYUVData[2]); pYUVData[2] = NULL; error_2: - free(pYUVData[1]); + _aligned_free(pYUVData[1]); pYUVData[1] = NULL; error_1: - free(pYUVData[0]); + _aligned_free(pYUVData[0]); pYUVData[0] = NULL; return status; } @@ -1737,15 +1737,14 @@ static BOOL avc444_combine_yuv(H264_CONTEXT* h264, { for (x = 0; x < 3; x++) { - BYTE* ppYUVTmpData; piDstStride[x] = piMainStride[0]; piDstSize[x] = piDstStride[x] * padDstHeight; - ppYUVTmpData = realloc(ppYUVDstData[x], piDstSize[x]); + _aligned_free(ppYUVDstData[x]); + ppYUVDstData[x] = _aligned_malloc(piDstSize[x], 16); - if (!ppYUVTmpData) + if (!ppYUVDstData[x]) goto fail; - ppYUVDstData[x] = ppYUVTmpData; memset(ppYUVDstData[x], 0, piDstSize[x]); } } @@ -1766,9 +1765,9 @@ static BOOL avc444_combine_yuv(H264_CONTEXT* h264, return TRUE; fail: - free(ppYUVDstData[0]); - free(ppYUVDstData[1]); - free(ppYUVDstData[2]); + _aligned_free(ppYUVDstData[0]); + _aligned_free(ppYUVDstData[1]); + _aligned_free(ppYUVDstData[2]); ppYUVDstData[0] = NULL; ppYUVDstData[1] = NULL; ppYUVDstData[2] = NULL; @@ -1976,9 +1975,9 @@ void h264_context_free(H264_CONTEXT* h264) if (h264) { h264->subsystem->Uninit(h264); - free(h264->pYUV444Data[0]); - free(h264->pYUV444Data[1]); - free(h264->pYUV444Data[2]); + _aligned_free(h264->pYUV444Data[0]); + _aligned_free(h264->pYUV444Data[1]); + _aligned_free(h264->pYUV444Data[2]); free(h264); } } diff --git a/libfreerdp/gdi/gfx.c b/libfreerdp/gdi/gfx.c index 97c723cc3..6ea833fbe 100644 --- a/libfreerdp/gdi/gfx.c +++ b/libfreerdp/gdi/gfx.c @@ -700,7 +700,7 @@ static UINT gdi_CreateSurface(RdpgfxClientContext* context, } surface->scanline = gfx_align_scanline(surface->width * 4, 16); - surface->data = (BYTE*) calloc(1, surface->scanline * surface->height); + surface->data = (BYTE*) _aligned_malloc(surface->scanline * surface->height, 16); if (!surface->data) { @@ -731,7 +731,7 @@ static UINT gdi_DeleteSurface(RdpgfxClientContext* context, { region16_uninit(&surface->invalidRegion); codecs = surface->codecs; - free(surface->data); + _aligned_free(surface->data); free(surface); } diff --git a/libfreerdp/primitives/test/TestPrimitivesYUV.c b/libfreerdp/primitives/test/TestPrimitivesYUV.c index 67599362d..1b798935a 100644 --- a/libfreerdp/primitives/test/TestPrimitivesYUV.c +++ b/libfreerdp/primitives/test/TestPrimitivesYUV.c @@ -140,18 +140,19 @@ static void* set_padding(size_t size, size_t padding) { size_t halfPad = (padding + 1) / 2; BYTE* psrc; - BYTE* src = calloc(1, size + 2 * halfPad); + BYTE* src = _aligned_malloc(size + 2 * halfPad, 16); if (!src) return NULL; memset(&src[0], 'A', halfPad); + memset(&src[halfPad], 0, size); memset(&src[halfPad + size], 'A', halfPad); psrc = &src[halfPad]; if (!check_padding(psrc, size, padding, "init")) { - free(src); + _aligned_free(src); return NULL; } @@ -166,7 +167,7 @@ static void free_padding(void* src, size_t padding) return; ptr = ((BYTE*)src) - (padding + 1) / 2; - free(ptr); + _aligned_free(ptr); } /* Create 2 pseudo YUV420 frames of same size. @@ -369,7 +370,7 @@ static BOOL TestPrimitiveYUV(primitives_t* prims, prim_size_t roi, BOOL use444) BYTE* rgb_dst = NULL; size_t size; size_t uvsize, uvwidth; - size_t padding = 10000; + size_t padding = 100 * 16; size_t stride; const UINT32 formats[] = { @@ -567,7 +568,15 @@ int TestPrimitivesYUV(int argc, char* argv[]) for (x = 0; x < 10; x++) { prim_size_t roi; - get_size(large, &roi.width, &roi.height); + + if (argc > 1) + { + roi.width = 1920; + roi.height = 1080; + } + else + get_size(large, &roi.width, &roi.height); + printf("-------------------- GENERIC ------------------------\n"); if (!TestPrimitiveYUV(generic, roi, TRUE)) From ef4515a674373db2f6494fb7cce1d7b5be44b77f Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Tue, 14 Feb 2017 12:28:58 +0100 Subject: [PATCH 03/16] Added FPS in profiler print. --- libfreerdp/utils/profiler.c | 38 ++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/libfreerdp/utils/profiler.c b/libfreerdp/utils/profiler.c index 7ed61f118..fe714a195 100644 --- a/libfreerdp/utils/profiler.c +++ b/libfreerdp/utils/profiler.c @@ -32,13 +32,14 @@ PROFILER* profiler_create(char* name) { PROFILER* profiler; - profiler = (PROFILER*) malloc(sizeof(PROFILER)); + if (!profiler) return NULL; - + profiler->name = name; profiler->stopwatch = stopwatch_create(); + if (!profiler->stopwatch) { free(profiler); @@ -49,9 +50,8 @@ PROFILER* profiler_create(char* name) } void profiler_free(PROFILER* profiler) -{ +{ stopwatch_free(profiler->stopwatch); - free(profiler); } @@ -65,24 +65,32 @@ void profiler_exit(PROFILER* profiler) stopwatch_stop(profiler->stopwatch); } -void profiler_print_header() +void profiler_print_header(void) { - WLog_INFO(TAG, " |-----------------------|"); - WLog_INFO(TAG, " PROFILER | elapsed seconds |"); - WLog_INFO(TAG, "|--------------------------------------------|-----------------------|"); - WLog_INFO(TAG, "| code section | iterations | total | avg. |"); - WLog_INFO(TAG, "|-------------------------------|------------|-----------|-----------|"); + WLog_INFO(TAG, + " |-----------------------|-----------------------|"); + WLog_INFO(TAG, + " PROFILER | elapsed seconds | FPS |"); + WLog_INFO(TAG, + "|--------------------------------------------|-----------------------|-----------------------"); + WLog_INFO(TAG, + "| code section | iterations | total | avg. | total | avg. |"); + WLog_INFO(TAG, + "|-------------------------------|------------|-----------|-----------|-----------|-----------|"); } void profiler_print(PROFILER* profiler) { - double elapsed_sec = stopwatch_get_elapsed_time_in_seconds(profiler->stopwatch); - double avg_sec = elapsed_sec / (double) profiler->stopwatch->count; - WLog_INFO(TAG, "| %-30.30s| %10"PRIu32" | %9f | %9f |", - profiler->name, profiler->stopwatch->count, elapsed_sec, avg_sec); + const double elapsed_sec = stopwatch_get_elapsed_time_in_seconds(profiler->stopwatch); + const double avg_sec = elapsed_sec / (double) profiler->stopwatch->count; + const double fps = 1.0 / elapsed_sec; + const double avg_fps = 1.0 / avg_sec; + WLog_INFO(TAG, "| %-30.30s| %10"PRIu32" | %9f | %9f | %9f | %9f |", + profiler->name, profiler->stopwatch->count, elapsed_sec, avg_sec, + fps, avg_fps); } -void profiler_print_footer() +void profiler_print_footer(void) { WLog_INFO(TAG, "|--------------------------------------------------------------------|"); } From 24635750839f2cdfcbf758a4fd0ec80d617f5957 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Tue, 14 Feb 2017 12:29:07 +0100 Subject: [PATCH 04/16] Print profiler header and footer. --- libfreerdp/primitives/test/TestPrimitivesColors.c | 2 ++ libfreerdp/primitives/test/TestPrimitivesYCbCr.c | 2 ++ libfreerdp/primitives/test/TestPrimitivesYCoCg.c | 2 ++ libfreerdp/primitives/test/TestPrimitivesYUV.c | 12 ++++++++++++ 4 files changed, 18 insertions(+) diff --git a/libfreerdp/primitives/test/TestPrimitivesColors.c b/libfreerdp/primitives/test/TestPrimitivesColors.c index fc375c00c..820ea8603 100644 --- a/libfreerdp/primitives/test/TestPrimitivesColors.c +++ b/libfreerdp/primitives/test/TestPrimitivesColors.c @@ -103,8 +103,10 @@ static BOOL test_RGBToRGB_16s8u_P3AC4R_func(prim_size_t roi, DWORD DstFormat) } printf("Results for %lux%lu [%s]", roi.width, roi.height, GetColorFormatName(DstFormat)); + PROFILER_PRINT_HEADER; PROFILER_PRINT(genericProf); PROFILER_PRINT(optProf); + PROFILER_PRINT_FOOTER; fail: PROFILER_FREE(genericProf); PROFILER_FREE(optProf); diff --git a/libfreerdp/primitives/test/TestPrimitivesYCbCr.c b/libfreerdp/primitives/test/TestPrimitivesYCbCr.c index 2abf87485..4a68b6eac 100644 --- a/libfreerdp/primitives/test/TestPrimitivesYCbCr.c +++ b/libfreerdp/primitives/test/TestPrimitivesYCbCr.c @@ -2238,7 +2238,9 @@ static int test_PrimitivesYCbCr(const primitives_t* prims, UINT32 format, prim_s printf("B: diff: %d (%f%%)\n", cnt[0], err[0]); } + PROFILER_PRINT_HEADER; PROFILER_PRINT(prof); + PROFILER_PRINT_FOOTER; fail: _aligned_free(actual); PROFILER_FREE(prof); diff --git a/libfreerdp/primitives/test/TestPrimitivesYCoCg.c b/libfreerdp/primitives/test/TestPrimitivesYCoCg.c index 24371fbb0..8239e95dd 100644 --- a/libfreerdp/primitives/test/TestPrimitivesYCoCg.c +++ b/libfreerdp/primitives/test/TestPrimitivesYCoCg.c @@ -95,8 +95,10 @@ static BOOL test_YCoCgRToRGB_8u_AC4R_func(UINT32 width, UINT32 height) } } + PROFILER_PRINT_HEADER; PROFILER_PRINT(genericProf); PROFILER_PRINT(optProf); + PROFILER_PRINT_FOOTER; } fail: diff --git a/libfreerdp/primitives/test/TestPrimitivesYUV.c b/libfreerdp/primitives/test/TestPrimitivesYUV.c index 1b798935a..9c0309f02 100644 --- a/libfreerdp/primitives/test/TestPrimitivesYUV.c +++ b/libfreerdp/primitives/test/TestPrimitivesYUV.c @@ -254,7 +254,9 @@ static BOOL TestPrimitiveYUVCombine(primitives_t* prims, prim_size_t roi) } PROFILER_EXIT(yuvCombine); + PROFILER_PRINT_HEADER; PROFILER_PRINT(yuvCombine); + PROFILER_PRINT_FOOTER; for (x = 0; x < 3; x++) { @@ -282,7 +284,9 @@ static BOOL TestPrimitiveYUVCombine(primitives_t* prims, prim_size_t roi) } PROFILER_EXIT(yuvSplit); + PROFILER_PRINT_HEADER; PROFILER_PRINT(yuvSplit); + PROFILER_PRINT_FOOTER; for (x = 0; x < 3; x++) { @@ -468,7 +472,9 @@ static BOOL TestPrimitiveYUV(primitives_t* prims, prim_size_t roi, BOOL use444) } PROFILER_EXIT(rgbToYUV444); + PROFILER_PRINT_HEADER; PROFILER_PRINT(rgbToYUV444); + PROFILER_PRINT_FOOTER; } else { @@ -483,7 +489,9 @@ static BOOL TestPrimitiveYUV(primitives_t* prims, prim_size_t roi, BOOL use444) } PROFILER_EXIT(rgbToYUV420); + PROFILER_PRINT_HEADER; PROFILER_PRINT(rgbToYUV420); + PROFILER_PRINT_FOOTER; } if (!check_padding(rgb, size * sizeof(UINT32), padding, "rgb")) @@ -507,7 +515,9 @@ static BOOL TestPrimitiveYUV(primitives_t* prims, prim_size_t roi, BOOL use444) } PROFILER_EXIT(yuv444ToRGB); + PROFILER_PRINT_HEADER; PROFILER_PRINT(yuv444ToRGB); + PROFILER_PRINT_FOOTER; } else { @@ -521,7 +531,9 @@ static BOOL TestPrimitiveYUV(primitives_t* prims, prim_size_t roi, BOOL use444) } PROFILER_EXIT(yuv420ToRGB); + PROFILER_PRINT_HEADER; PROFILER_PRINT(yuv420ToRGB); + PROFILER_PRINT_FOOTER; } if (!check_padding(rgb_dst, size * sizeof(UINT32), padding, "rgb dst")) From 2f8e206c587b491b4c1ad7fa999317b4fc84e9ef Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Tue, 14 Feb 2017 12:53:14 +0100 Subject: [PATCH 05/16] Fixed freerdp_client_parse_rdp_file_buffer The parser function needs a modifyable copy of the input buffer. --- client/common/file.c | 218 +++++++++++++++---------- client/common/test/TestClientRdpFile.c | 129 ++++++++------- 2 files changed, 195 insertions(+), 152 deletions(-) diff --git a/client/common/file.c b/client/common/file.c index b66262169..110868d08 100644 --- a/client/common/file.c +++ b/client/common/file.c @@ -59,10 +59,10 @@ static WCHAR CR_LF_STR_W[] = { '\r', '\n', '\0' }; * */ -static int freerdp_client_rdp_file_set_integer(rdpFile* file, const char* name, int value, int index) +static int freerdp_client_rdp_file_set_integer(rdpFile* file, const char* name, int value, + int index) { int standard = 1; - #ifdef DEBUG_CLIENT_FILE WLog_DBG(TAG, "%s:i:%d", name, value); #endif @@ -201,10 +201,11 @@ static int freerdp_client_rdp_file_set_integer(rdpFile* file, const char* name, if (index >= 0) { file->lines[index].name = _strdup(name); + if (!file->lines[index].name) return -1; - file->lines[index].iValue = (DWORD) value; + file->lines[index].iValue = (DWORD) value; file->lines[index].flags = RDP_FILE_LINE_FLAG_FORMATTED; file->lines[index].flags |= RDP_FILE_LINE_FLAG_TYPE_INTEGER; @@ -217,32 +218,35 @@ static int freerdp_client_rdp_file_set_integer(rdpFile* file, const char* name, return standard; } -static BOOL freerdp_client_parse_rdp_file_integer_unicode(rdpFile* file, WCHAR* name, WCHAR* value, int index) +static BOOL freerdp_client_parse_rdp_file_integer_unicode(rdpFile* file, const WCHAR* name, + const WCHAR* value, int index) { int length; int ivalue; char* nameA; char* valueA; BOOL ret = TRUE; - length = (int) _wcslen(name); nameA = (char*) malloc(length + 1); + if (!nameA) return FALSE; + WideCharToMultiByte(CP_UTF8, 0, name, length, nameA, length, NULL, NULL); nameA[length] = '\0'; - length = (int) _wcslen(value); valueA = (char*) malloc(length + 1); + if (!valueA) { free(nameA); return FALSE; } + WideCharToMultiByte(CP_UTF8, 0, value, length, valueA, length, NULL, NULL); valueA[length] = '\0'; - ivalue = atoi(valueA); + if (freerdp_client_rdp_file_set_integer(file, nameA, ivalue, index) < 0) ret = FALSE; @@ -251,11 +255,14 @@ static BOOL freerdp_client_parse_rdp_file_integer_unicode(rdpFile* file, WCHAR* return ret; } -static BOOL freerdp_client_parse_rdp_file_integer_ascii(rdpFile* file, const char* name, const char* value, int index) +static BOOL freerdp_client_parse_rdp_file_integer_ascii(rdpFile* file, const char* name, + const char* value, int index) { int ivalue = atoi(value); + if (freerdp_client_rdp_file_set_integer(file, name, ivalue, index) < 0) return FALSE; + return TRUE; } @@ -268,11 +275,11 @@ static BOOL freerdp_client_parse_rdp_file_integer_ascii(rdpFile* file, const cha * @return 0 on success, 1 if the key wasn't found (not a standard key), -1 on error */ -static int freerdp_client_rdp_file_set_string(rdpFile* file, const char* name, const char* value, int index) +static int freerdp_client_rdp_file_set_string(rdpFile* file, const char* name, const char* value, + int index) { int standard = 0; - LPSTR *tmp = NULL; - + LPSTR* tmp = NULL; #ifdef DEBUG_CLIENT_FILE WLog_DBG(TAG, "%s:s:%s", name, value); #endif @@ -331,6 +338,7 @@ static int freerdp_client_rdp_file_set_string(rdpFile* file, const char* name, c file->lines[index].name = _strdup(name); file->lines[index].sValue = _strdup(value); + if (!file->lines[index].name || !file->lines[index].sValue) { free(file->lines[index].name); @@ -355,19 +363,22 @@ static BOOL freerdp_client_add_option(rdpFile* file, char* option) while ((file->argc + 1) > file->argSize) { int new_size; - char **new_argv; - + char** new_argv; new_size = file->argSize * 2; new_argv = (char**) realloc(file->argv, new_size * sizeof(char*)); + if (!new_argv) return FALSE; + file->argv = new_argv; file->argSize = new_size; } file->argv[file->argc] = _strdup(option); + if (!file->argv[file->argc]) return FALSE; + (file->argc)++; return TRUE; } @@ -380,33 +391,35 @@ static int freerdp_client_parse_rdp_file_add_line(rdpFile* file, char* line, int while ((file->lineCount + 1) > file->lineSize) { int new_size; - rdpFileLine *new_line; - + rdpFileLine* new_line; new_size = file->lineSize * 2; new_line = (rdpFileLine*) realloc(file->lines, new_size * sizeof(rdpFileLine)); + if (!new_line) return -1; + file->lines = new_line; file->lineSize = new_size; } ZeroMemory(&(file->lines[file->lineCount]), sizeof(rdpFileLine)); file->lines[file->lineCount].text = _strdup(line); + if (!file->lines[file->lineCount].text) return -1; file->lines[file->lineCount].index = index; (file->lineCount)++; - return index; } -static BOOL freerdp_client_parse_rdp_file_add_line_unicode(rdpFile* file, WCHAR* line, int index) +static BOOL freerdp_client_parse_rdp_file_add_line_unicode(rdpFile* file, const WCHAR* line, + int index) { char* lineA = NULL; BOOL ret = TRUE; - ConvertFromUnicode(CP_UTF8, 0, line, -1, &lineA, 0, NULL, NULL); + if (!lineA) return FALSE; @@ -421,30 +434,34 @@ static BOOL freerdp_client_parse_rdp_file_add_line_ascii(rdpFile* file, char* li { if (freerdp_client_parse_rdp_file_add_line(file, line, index) == -1) return FALSE; + return TRUE; } -static BOOL freerdp_client_parse_rdp_file_string_unicode(rdpFile* file, WCHAR* name, WCHAR* value, int index) +static BOOL freerdp_client_parse_rdp_file_string_unicode(rdpFile* file, const WCHAR* name, + const WCHAR* value, int index) { int length; char* nameA; char* valueA; BOOL ret = TRUE; - length = (int) _wcslen(name); nameA = (char*) malloc(length + 1); + if (!nameA) return FALSE; + WideCharToMultiByte(CP_UTF8, 0, name, length, nameA, length, NULL, NULL); nameA[length] = '\0'; - length = (int) _wcslen(value); valueA = (char*) malloc(length + 1); + if (!valueA) { free(nameA); return FALSE; } + WideCharToMultiByte(CP_UTF8, 0, value, length, valueA, length, NULL, NULL); valueA[length] = '\0'; @@ -456,10 +473,12 @@ static BOOL freerdp_client_parse_rdp_file_string_unicode(rdpFile* file, WCHAR* n return ret; } -static BOOL freerdp_client_parse_rdp_file_string_ascii(rdpFile* file, char* name, char* value, int index) +static BOOL freerdp_client_parse_rdp_file_string_ascii(rdpFile* file, char* name, char* value, + int index) { BOOL ret = TRUE; char* valueA = _strdup(value); + if (!valueA) return FALSE; @@ -470,18 +489,18 @@ static BOOL freerdp_client_parse_rdp_file_string_ascii(rdpFile* file, char* name return ret; } -static BOOL freerdp_client_parse_rdp_file_option_unicode(rdpFile* file, WCHAR* option, int index) +static BOOL freerdp_client_parse_rdp_file_option_unicode(rdpFile* file, const WCHAR* option, + int index) { char* optionA = NULL; BOOL ret; - ConvertFromUnicode(CP_UTF8, 0, option, -1, &optionA, 0, NULL, NULL); + if (!optionA) return FALSE; ret = freerdp_client_add_option(file, optionA); free(optionA); - return ret; } @@ -490,19 +509,25 @@ static BOOL freerdp_client_parse_rdp_file_option_ascii(rdpFile* file, char* opti return freerdp_client_add_option(file, option); } -static BOOL freerdp_client_parse_rdp_file_buffer_ascii(rdpFile* file, const BYTE* buffer, size_t size) +static BOOL freerdp_client_parse_rdp_file_buffer_ascii(rdpFile* file, const BYTE* buffer, + size_t size) { int index; int length; char* line; char* type; char* context; - char *d1, *d2; - char *beg, *end; - char *name, *value; + char* d1, *d2; + char* beg, *end; + char* name, *value; + char* copy = calloc(1, size + sizeof(BYTE)); + if (!copy) + return FALSE; + + memcpy(copy, buffer, size); index = 0; - line = strtok_s((char*) buffer, "\r\n", &context); + line = strtok_s(copy, "\r\n", &context); while (line) { @@ -538,7 +563,6 @@ static BOOL freerdp_client_parse_rdp_file_buffer_ascii(rdpFile* file, const BYTE if ((d2 - d1) != 2) goto next_line; /* improper type length */ - *d1 = 0; *d2 = 0; name = beg; @@ -562,27 +586,33 @@ static BOOL freerdp_client_parse_rdp_file_buffer_ascii(rdpFile* file, const BYTE } } -next_line: + next_line: line = strtok_s(NULL, "\r\n", &context); index++; } + free(copy); return TRUE; } -static BOOL freerdp_client_parse_rdp_file_buffer_unicode(rdpFile* file, const BYTE* buffer, size_t size) +static BOOL freerdp_client_parse_rdp_file_buffer_unicode(rdpFile* file, const BYTE* buffer, + size_t size) { int index; int length; - WCHAR* line; + const WCHAR* line; WCHAR* type; WCHAR* context; - WCHAR *d1, *d2; - WCHAR *beg, *end; - WCHAR *name, *value; + WCHAR* d1, *d2; + const WCHAR* name, *value; + WCHAR* copy = (WCHAR*)calloc(1, size + sizeof(WCHAR)); + if (!copy) + return FALSE; + + memcpy(copy, buffer, size); index = 0; - line = wcstok_s((WCHAR*) buffer, CR_LF_STR_W, &context); + line = wcstok_s(copy, CR_LF_STR_W, &context); while (line != NULL) { @@ -590,8 +620,8 @@ static BOOL freerdp_client_parse_rdp_file_buffer_unicode(rdpFile* file, const BY if (length > 1) { - beg = line; - end = &line[length - 1]; + const WCHAR* beg = line; + const WCHAR* end = &line[length - 1]; if (!freerdp_client_parse_rdp_file_add_line_unicode(file, line, index)) return FALSE; @@ -617,7 +647,6 @@ static BOOL freerdp_client_parse_rdp_file_buffer_unicode(rdpFile* file, const BY if ((d2 - d1) != 2) goto next_line; /* improper type length */ - *d1 = 0; *d2 = 0; name = beg; @@ -641,11 +670,12 @@ static BOOL freerdp_client_parse_rdp_file_buffer_unicode(rdpFile* file, const BY } } -next_line: + next_line: line = wcstok_s(NULL, CR_LF_STR_W, &context); index++; } + free(copy); return TRUE; } @@ -667,7 +697,6 @@ BOOL freerdp_client_parse_rdp_file(rdpFile* file, const char* name) FILE* fp = NULL; size_t read_size; long int file_size; - fp = fopen(name, "r"); if (!fp) @@ -684,11 +713,13 @@ BOOL freerdp_client_parse_rdp_file(rdpFile* file, const char* name) } buffer = (BYTE*) malloc(file_size + 2); + if (!buffer) { fclose(fp); return FALSE; } + read_size = fread(buffer, file_size, 1, fp); if (!read_size) @@ -696,6 +727,7 @@ BOOL freerdp_client_parse_rdp_file(rdpFile* file, const char* name) if (!ferror(fp)) read_size = file_size; } + fclose(fp); if (read_size < 1) @@ -706,11 +738,8 @@ BOOL freerdp_client_parse_rdp_file(rdpFile* file, const char* name) buffer[file_size] = '\0'; buffer[file_size + 1] = '\0'; - status = freerdp_client_parse_rdp_file_buffer(file, buffer, file_size); - free(buffer); - return status; } @@ -718,8 +747,8 @@ BOOL freerdp_client_parse_rdp_file(rdpFile* file, const char* name) #define SETTING_MODIFIED(_settings, _field) (WRITE_ALL_SETTINGS || _settings->SettingsModified[FreeRDP_##_field]) #define SETTING_MODIFIED_SET(_target, _settings, _field) if SETTING_MODIFIED(_settings, _field) _target = _settings->_field #define SETTING_MODIFIED_SET_STRING(_target, _settings, _field) do { if SETTING_MODIFIED(_settings, _field) _target = _strdup(_settings->_field); \ - if (!_target) return FALSE; \ - } while (0) + if (!_target) return FALSE; \ + } while (0) BOOL freerdp_client_populate_rdp_file_from_settings(rdpFile* file, const rdpSettings* settings) { @@ -751,7 +780,6 @@ BOOL freerdp_client_populate_rdp_file_from_settings(rdpFile* file, const rdpSett SETTING_MODIFIED_SET_STRING(file->GatewayHostname, settings, GatewayHostname); SETTING_MODIFIED_SET(file->GatewayUsageMethod, settings, GatewayUsageMethod); SETTING_MODIFIED_SET(file->PromptCredentialOnce, settings, GatewayUseSameCredentials); - SETTING_MODIFIED_SET(file->RemoteApplicationMode, settings, RemoteApplicationMode); SETTING_MODIFIED_SET_STRING(file->RemoteApplicationProgram, settings, RemoteApplicationProgram); SETTING_MODIFIED_SET_STRING(file->RemoteApplicationName, settings, RemoteApplicationName); @@ -759,10 +787,8 @@ BOOL freerdp_client_populate_rdp_file_from_settings(rdpFile* file, const rdpSett SETTING_MODIFIED_SET_STRING(file->RemoteApplicationFile, settings, RemoteApplicationFile); SETTING_MODIFIED_SET_STRING(file->RemoteApplicationGuid, settings, RemoteApplicationGuid); SETTING_MODIFIED_SET_STRING(file->RemoteApplicationCmdLine, settings, RemoteApplicationCmdLine); - SETTING_MODIFIED_SET(file->SpanMonitors, settings, SpanMonitors); SETTING_MODIFIED_SET(file->UseMultiMon, settings, UseMultimon); - return TRUE; } @@ -773,7 +799,6 @@ BOOL freerdp_client_write_rdp_file(const rdpFile* file, const char* name, BOOL u char* buffer; int status = 0; WCHAR* unicodestr = NULL; - length = (int) freerdp_client_write_rdp_file_buffer(file, NULL, 0); if (length < 0) @@ -801,7 +826,7 @@ BOOL freerdp_client_write_rdp_file(const rdpFile* file, const char* name, BOOL u /* Write multi-byte header */ if (fwrite(BOM_UTF16_LE, sizeof(BYTE), 2, fp) != 2 || - fwrite(unicodestr, 2, length, fp) != length) + fwrite(unicodestr, 2, length, fp) != length) { free(buffer); free(unicodestr); @@ -826,7 +851,6 @@ BOOL freerdp_client_write_rdp_file(const rdpFile* file, const char* name, BOOL u } free(buffer); - return (status == 0) ? TRUE : FALSE; } @@ -845,7 +869,6 @@ size_t freerdp_client_write_rdp_file_buffer(const rdpFile* file, char* buffer, s for (index = 0; index < file->lineCount; index++) { line = &(file->lines[index]); - length = (int) strlen(line->text); if (!buffer) @@ -882,6 +905,7 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings* if (!freerdp_parse_username(file->Username, &user, &domain)) return FALSE; + if (freerdp_set_param_string(settings, FreeRDP_Username, user) != 0) return FALSE; @@ -917,26 +941,35 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings* if (~file->DesktopWidth) freerdp_set_param_uint32(settings, FreeRDP_DesktopWidth, file->DesktopWidth); + if (~file->DesktopHeight) freerdp_set_param_uint32(settings, FreeRDP_DesktopHeight, file->DesktopHeight); + if (~file->SessionBpp) freerdp_set_param_uint32(settings, FreeRDP_ColorDepth, file->SessionBpp); + if (~file->ConnectToConsole) freerdp_set_param_bool(settings, FreeRDP_ConsoleSession, file->ConnectToConsole); + if (~file->AdministrativeSession) freerdp_set_param_bool(settings, FreeRDP_ConsoleSession, file->AdministrativeSession); + if (~file->NegotiateSecurityLayer) freerdp_set_param_bool(settings, FreeRDP_NegotiateSecurityLayer, file->NegotiateSecurityLayer); + if (~file->EnableCredSSPSupport) freerdp_set_param_bool(settings, FreeRDP_NlaSecurity, file->EnableCredSSPSupport); + if (~((size_t) file->AlternateShell)) { - if(freerdp_set_param_string(settings, FreeRDP_AlternateShell, file->AlternateShell) != 0) + if (freerdp_set_param_string(settings, FreeRDP_AlternateShell, file->AlternateShell) != 0) return FALSE; } + if (~((size_t) file->ShellWorkingDirectory)) { - if (freerdp_set_param_string(settings, FreeRDP_ShellWorkingDirectory, file->ShellWorkingDirectory) != 0) + if (freerdp_set_param_string(settings, FreeRDP_ShellWorkingDirectory, + file->ShellWorkingDirectory) != 0) return FALSE; } @@ -954,22 +987,23 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings* * 1: The remote session will appear in a window. * 2: The remote session will appear full screen. */ - freerdp_set_param_bool(settings, FreeRDP_Fullscreen, - (file->ScreenModeId == 2) ? TRUE : FALSE); + (file->ScreenModeId == 2) ? TRUE : FALSE); } if (~((size_t) file->SmartSizing)) { freerdp_set_param_bool(settings, FreeRDP_SmartSizing, - (file->SmartSizing == 1) ? TRUE : FALSE); + (file->SmartSizing == 1) ? TRUE : FALSE); } if (~((size_t) file->LoadBalanceInfo)) { settings->LoadBalanceInfo = (BYTE*) _strdup(file->LoadBalanceInfo); + if (!settings->LoadBalanceInfo) return FALSE; + settings->LoadBalanceInfoLength = (int) strlen((char*) settings->LoadBalanceInfo); } @@ -989,9 +1023,8 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings* * 2: If server authentication fails, show a warning and allow me to connect or refuse the connection (Warn me). * 3: No authentication requirement is specified. */ - freerdp_set_param_bool(settings, FreeRDP_IgnoreCertificate, - (file->AuthenticationLevel == 0) ? TRUE : FALSE); + (file->AuthenticationLevel == 0) ? TRUE : FALSE); } if (~file->ConnectionType) @@ -1039,50 +1072,66 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings* if (~file->PromptCredentialOnce) freerdp_set_param_bool(settings, FreeRDP_GatewayUseSameCredentials, file->PromptCredentialOnce); - + if (~file->RemoteApplicationMode) freerdp_set_param_bool(settings, FreeRDP_RemoteApplicationMode, file->RemoteApplicationMode); + if (~((size_t) file->RemoteApplicationProgram)) { - if (freerdp_set_param_string(settings, FreeRDP_RemoteApplicationProgram, file->RemoteApplicationProgram) != 0) + if (freerdp_set_param_string(settings, FreeRDP_RemoteApplicationProgram, + file->RemoteApplicationProgram) != 0) return FALSE; } + if (~((size_t) file->RemoteApplicationName)) { - if (freerdp_set_param_string(settings, FreeRDP_RemoteApplicationName, file->RemoteApplicationName) != 0) + if (freerdp_set_param_string(settings, FreeRDP_RemoteApplicationName, + file->RemoteApplicationName) != 0) return FALSE; } + if (~((size_t) file->RemoteApplicationIcon)) { - if (freerdp_set_param_string(settings, FreeRDP_RemoteApplicationIcon, file->RemoteApplicationIcon) != 0) + if (freerdp_set_param_string(settings, FreeRDP_RemoteApplicationIcon, + file->RemoteApplicationIcon) != 0) return FALSE; } + if (~((size_t) file->RemoteApplicationFile)) { - if (freerdp_set_param_string(settings, FreeRDP_RemoteApplicationGuid, file->RemoteApplicationGuid) != 0) + if (freerdp_set_param_string(settings, FreeRDP_RemoteApplicationGuid, + file->RemoteApplicationGuid) != 0) return FALSE; } + if (~((size_t) file->RemoteApplicationCmdLine)) { - if (freerdp_set_param_string(settings, FreeRDP_RemoteApplicationCmdLine, file->RemoteApplicationCmdLine) != 0) + if (freerdp_set_param_string(settings, FreeRDP_RemoteApplicationCmdLine, + file->RemoteApplicationCmdLine) != 0) return FALSE; } if (~file->SpanMonitors) freerdp_set_param_bool(settings, FreeRDP_SpanMonitors, file->SpanMonitors); + if (~file->UseMultiMon) freerdp_set_param_bool(settings, FreeRDP_UseMultimon, file->UseMultiMon); if (~file->AllowFontSmoothing) freerdp_set_param_bool(settings, FreeRDP_AllowFontSmoothing, file->AllowFontSmoothing); + if (~file->DisableWallpaper) freerdp_set_param_bool(settings, FreeRDP_DisableWallpaper, file->DisableWallpaper); + if (~file->DisableFullWindowDrag) freerdp_set_param_bool(settings, FreeRDP_DisableFullWindowDrag, file->DisableFullWindowDrag); + if (~file->DisableMenuAnims) freerdp_set_param_bool(settings, FreeRDP_DisableMenuAnims, file->DisableMenuAnims); + if (~file->DisableThemes) freerdp_set_param_bool(settings, FreeRDP_DisableThemes, file->DisableThemes); + if (~file->AllowDesktopComposition) freerdp_set_param_bool(settings, FreeRDP_AllowDesktopComposition, file->AllowDesktopComposition); @@ -1090,10 +1139,12 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings* freerdp_set_param_bool(settings, FreeRDP_BitmapCachePersistEnabled, file->BitmapCachePersistEnable); if (~file->DisableRemoteAppCapsCheck) - freerdp_set_param_bool(settings, FreeRDP_DisableRemoteAppCapsCheck, file->DisableRemoteAppCapsCheck); + freerdp_set_param_bool(settings, FreeRDP_DisableRemoteAppCapsCheck, + file->DisableRemoteAppCapsCheck); if (~file->AutoReconnectionEnabled) freerdp_set_param_bool(settings, FreeRDP_AutoReconnectionEnabled, file->AutoReconnectionEnabled); + if (~file->AutoReconnectMaxRetries) freerdp_set_param_uint32(settings, FreeRDP_AutoReconnectMaxRetries, file->AutoReconnectMaxRetries); @@ -1152,7 +1203,6 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings* * devicestoredirect:s:USB\VID_04A9&PID_30C1\6&4BD985D&0&2;,DynamicDevices * */ - freerdp_set_param_bool(settings, FreeRDP_RedirectDrives, TRUE); } @@ -1164,7 +1214,6 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings* * Very similar to DevicesToRedirect, but can contain a * comma-separated list of drive letters to redirect. */ - freerdp_set_param_bool(settings, FreeRDP_RedirectDrives, TRUE); } @@ -1176,10 +1225,11 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings* if (file->argc > 1) { char* ConnectionFile = settings->ConnectionFile; - settings->ConnectionFile = NULL; + if (freerdp_client_settings_parse_command_line(settings, file->argc, file->argv, FALSE) < 0) return FALSE; + settings->ConnectionFile = ConnectionFile; } @@ -1189,9 +1239,7 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings* static rdpFileLine* freerdp_client_rdp_file_find_line_index(rdpFile* file, int index) { rdpFileLine* line; - line = &(file->lines[index]); - return line; } @@ -1232,19 +1280,21 @@ int freerdp_client_rdp_file_set_string_option(rdpFile* file, const char* name, c int length; char* text; rdpFileLine* line; - length = _scprintf("%s:s:%s", name, value); text = (char*) malloc(length + 1); + if (!text) return -1; + sprintf_s(text, length + 1, "%s:s:%s", name, value ? value : ""); text[length] = '\0'; - line = freerdp_client_rdp_file_find_line_by_name(file, name); + if (line) { free(line->sValue); line->sValue = _strdup(value); + if (!line->sValue) goto out_fail; @@ -1254,6 +1304,7 @@ int freerdp_client_rdp_file_set_string_option(rdpFile* file, const char* name, c else { index = freerdp_client_parse_rdp_file_add_line(file, text, -1); + if (index == -1) goto out_fail; @@ -1267,17 +1318,14 @@ int freerdp_client_rdp_file_set_string_option(rdpFile* file, const char* name, c } return 0; - out_fail: free(text); return -1; - } const char* freerdp_client_rdp_file_get_string_option(rdpFile* file, const char* name) { rdpFileLine* line; - line = freerdp_client_rdp_file_find_line_by_name(file, name); if (!line) @@ -1295,9 +1343,7 @@ int freerdp_client_rdp_file_set_integer_option(rdpFile* file, const char* name, int length; char* text; rdpFileLine* line; - line = freerdp_client_rdp_file_find_line_by_name(file, name); - length = _scprintf("%s:i:%d", name, value); text = (char*) malloc(length + 1); sprintf_s(text, length + 1, "%s:i:%d", name, value); @@ -1306,18 +1352,19 @@ int freerdp_client_rdp_file_set_integer_option(rdpFile* file, const char* name, if (line) { line->iValue = value; - free(line->text); line->text = text; } else { index = freerdp_client_parse_rdp_file_add_line(file, text, -1); + if (index < 0) { free(text); return -1; } + line = freerdp_client_rdp_file_find_line_index(file, index); if (freerdp_client_rdp_file_set_integer(file, (char*) name, value, index) < 0) @@ -1335,7 +1382,6 @@ int freerdp_client_rdp_file_set_integer_option(rdpFile* file, const char* name, int freerdp_client_rdp_file_get_integer_option(rdpFile* file, const char* name) { rdpFileLine* line; - line = freerdp_client_rdp_file_find_line_by_name(file, name); if (!line) @@ -1356,26 +1402,25 @@ static void freerdp_client_file_string_check_free(LPSTR str) rdpFile* freerdp_client_rdp_file_new() { rdpFile* file; - file = (rdpFile*) malloc(sizeof(rdpFile)); if (file) { FillMemory(file, sizeof(rdpFile), 0xFF); - file->lineCount = 0; file->lineSize = 32; file->lines = (rdpFileLine*) malloc(file->lineSize * sizeof(rdpFileLine)); + if (!file->lines) { free(file); return NULL; } - file->argc = 0; file->argSize = 32; file->argv = (char**) malloc(file->argSize * sizeof(char*)); + if (!file->argv) { free(file->lines); @@ -1440,7 +1485,6 @@ void freerdp_client_rdp_file_free(rdpFile* file) freerdp_client_file_string_check_free(file->DrivesToRedirect); freerdp_client_file_string_check_free(file->DevicesToRedirect); freerdp_client_file_string_check_free(file->WinPosStr); - free(file); } } diff --git a/client/common/test/TestClientRdpFile.c b/client/common/test/TestClientRdpFile.c index f952d18b9..0052f314c 100644 --- a/client/common/test/TestClientRdpFile.c +++ b/client/common/test/TestClientRdpFile.c @@ -5,7 +5,7 @@ #include -static BYTE testRdpFileUTF16[] = +static const BYTE testRdpFileUTF16[] = { 0xff, 0xfe, 0x73, 0x00, 0x63, 0x00, 0x72, 0x00, 0x65, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x6d, 0x00, 0x6f, 0x00, 0x64, 0x00, 0x65, 0x00, @@ -210,55 +210,55 @@ static BYTE testRdpFileUTF16[] = }; static char testRdpFileUTF8[] = - "screen mode id:i:2\n" - "use multimon:i:0\n" - "desktopwidth:i:1920\n" - "desktopheight:i:1080\n" - "session bpp:i:32\n" - "winposstr:s:0,1,553,211,1353,811\n" - "compression:i:1\n" - "keyboardhook:i:2\n" - "audiocapturemode:i:0\n" - "videoplaybackmode:i:1\n" - "connection type:i:7\n" - "networkautodetect:i:1\n" - "bandwidthautodetect:i:1\n" - "displayconnectionbar:i:1\n" - "enableworkspacereconnect:i:0\n" - "disable wallpaper:i:0\n" - "allow font smoothing:i:0\n" - "allow desktop composition:i:0\n" - "disable full window drag:i:1\n" - "disable menu anims:i:1\n" - "disable themes:i:0\n" - "disable cursor setting:i:0\n" - "bitmapcachepersistenable:i:1\n" - "full address:s:LAB1-W7-DM-01.lab1.awake.local\n" - "audiomode:i:0\n" - "redirectprinters:i:1\n" - "redirectcomports:i:0\n" - "redirectsmartcards:i:1\n" - "redirectclipboard:i:1\n" - "redirectposdevices:i:0\n" - "autoreconnection enabled:i:1\n" - "authentication level:i:2\n" - "prompt for credentials:i:0\n" - "negotiate security layer:i:1\n" - "remoteapplicationmode:i:0\n" - "alternate shell:s:\n" - "shell working directory:s:\n" - "gatewayhostname:s:LAB1-W2K8R2-GW.lab1.awake.local\n" - "gatewayusagemethod:i:1\n" - "gatewaycredentialssource:i:0\n" - "gatewayprofileusagemethod:i:1\n" - "promptcredentialonce:i:1\n" - "use redirection server name:i:0\n" - "rdgiskdcproxy:i:0\n" - "kdcproxyname:s:\n" - "drivestoredirect:s:*\n" - "username:s:LAB1\\JohnDoe\n" - "vendor integer:i:123\n" - "vendor string:s:microsoft\n"; + "screen mode id:i:2\n" + "use multimon:i:0\n" + "desktopwidth:i:1920\n" + "desktopheight:i:1080\n" + "session bpp:i:32\n" + "winposstr:s:0,1,553,211,1353,811\n" + "compression:i:1\n" + "keyboardhook:i:2\n" + "audiocapturemode:i:0\n" + "videoplaybackmode:i:1\n" + "connection type:i:7\n" + "networkautodetect:i:1\n" + "bandwidthautodetect:i:1\n" + "displayconnectionbar:i:1\n" + "enableworkspacereconnect:i:0\n" + "disable wallpaper:i:0\n" + "allow font smoothing:i:0\n" + "allow desktop composition:i:0\n" + "disable full window drag:i:1\n" + "disable menu anims:i:1\n" + "disable themes:i:0\n" + "disable cursor setting:i:0\n" + "bitmapcachepersistenable:i:1\n" + "full address:s:LAB1-W7-DM-01.lab1.awake.local\n" + "audiomode:i:0\n" + "redirectprinters:i:1\n" + "redirectcomports:i:0\n" + "redirectsmartcards:i:1\n" + "redirectclipboard:i:1\n" + "redirectposdevices:i:0\n" + "autoreconnection enabled:i:1\n" + "authentication level:i:2\n" + "prompt for credentials:i:0\n" + "negotiate security layer:i:1\n" + "remoteapplicationmode:i:0\n" + "alternate shell:s:\n" + "shell working directory:s:\n" + "gatewayhostname:s:LAB1-W2K8R2-GW.lab1.awake.local\n" + "gatewayusagemethod:i:1\n" + "gatewaycredentialssource:i:0\n" + "gatewayprofileusagemethod:i:1\n" + "promptcredentialonce:i:1\n" + "use redirection server name:i:0\n" + "rdgiskdcproxy:i:0\n" + "kdcproxyname:s:\n" + "drivestoredirect:s:*\n" + "username:s:LAB1\\JohnDoe\n" + "vendor integer:i:123\n" + "vendor string:s:microsoft\n"; int TestClientRdpFile(int argc, char* argv[]) { @@ -267,15 +267,15 @@ int TestClientRdpFile(int argc, char* argv[]) char* sValue; rdpFile* file; rdpFileLine* line; - /* Unicode */ - file = freerdp_client_rdp_file_new(); + if (!file) { printf("rdp_file_new failed\n"); return -1; } + freerdp_client_parse_rdp_file_buffer(file, testRdpFileUTF16, sizeof(testRdpFileUTF16)); if (file->UseMultiMon != 0) @@ -292,21 +292,20 @@ int TestClientRdpFile(int argc, char* argv[]) if (file->GatewayProfileUsageMethod != 1) { - printf("GatewayProfileUsageMethod mismatch: Actual: %"PRIu32", Expected: 1\n", file->GatewayProfileUsageMethod); + printf("GatewayProfileUsageMethod mismatch: Actual: %"PRIu32", Expected: 1\n", + file->GatewayProfileUsageMethod); return -1; } if (strcmp(file->GatewayHostname, "LAB1-W2K8R2-GW.lab1.awake.local") != 0) { printf("GatewayHostname mismatch: Actual: %s, Expected: %s\n", - file->GatewayHostname, "LAB1-W2K8R2-GW.lab1.awake.local"); + file->GatewayHostname, "LAB1-W2K8R2-GW.lab1.awake.local"); return -1; } freerdp_client_rdp_file_free(file); - /* Ascii */ - file = freerdp_client_rdp_file_new(); freerdp_client_parse_rdp_file_buffer(file, (BYTE*) testRdpFileUTF8, sizeof(testRdpFileUTF8)); @@ -324,18 +323,20 @@ int TestClientRdpFile(int argc, char* argv[]) if (file->GatewayProfileUsageMethod != 1) { - printf("GatewayProfileUsageMethod mismatch: Actual: %"PRIu32", Expected: 1\n", file->GatewayProfileUsageMethod); + printf("GatewayProfileUsageMethod mismatch: Actual: %"PRIu32", Expected: 1\n", + file->GatewayProfileUsageMethod); return -1; } if (strcmp(file->GatewayHostname, "LAB1-W2K8R2-GW.lab1.awake.local") != 0) { printf("GatewayHostname mismatch: Actual: %s, Expected: %s\n", - file->GatewayHostname, "LAB1-W2K8R2-GW.lab1.awake.local"); + file->GatewayHostname, "LAB1-W2K8R2-GW.lab1.awake.local"); return -1; } iValue = freerdp_client_rdp_file_get_integer_option(file, "vendor integer"); + if (freerdp_client_rdp_file_set_integer_option(file, "vendor integer", 456) == -1) { printf("failed to set integer: vendor integer"); @@ -343,12 +344,11 @@ int TestClientRdpFile(int argc, char* argv[]) } iValue = freerdp_client_rdp_file_get_integer_option(file, "vendor integer"); - sValue = (char*) freerdp_client_rdp_file_get_string_option(file, "vendor string"); freerdp_client_rdp_file_set_string_option(file, "vendor string", "apple"); sValue = (char*) freerdp_client_rdp_file_get_string_option(file, "vendor string"); - freerdp_client_rdp_file_set_string_option(file, "fruits", "banana,oranges"); + if (freerdp_client_rdp_file_set_integer_option(file, "numbers", 123456789) == -1) { printf("failed to set integer: numbers"); @@ -364,19 +364,18 @@ int TestClientRdpFile(int argc, char* argv[]) if (line->flags & RDP_FILE_LINE_FLAG_TYPE_STRING) { printf("line %02d: name: %s value: %s, %s\n", - line->index, line->name, line->sValue, - (line->flags & RDP_FILE_LINE_FLAG_STANDARD) ? "standard" : "non-standard"); + line->index, line->name, line->sValue, + (line->flags & RDP_FILE_LINE_FLAG_STANDARD) ? "standard" : "non-standard"); } else if (line->flags & RDP_FILE_LINE_FLAG_TYPE_INTEGER) { printf("line %02d: name: %s value: %"PRIu32", %s\n", - line->index, line->name, line->iValue, - (line->flags & RDP_FILE_LINE_FLAG_STANDARD) ? "standard" : "non-standard"); + line->index, line->name, line->iValue, + (line->flags & RDP_FILE_LINE_FLAG_STANDARD) ? "standard" : "non-standard"); } } } freerdp_client_rdp_file_free(file); - return 0; } From d41d65575c3da56bd13e5194b803b13bbecefb7d Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Tue, 14 Feb 2017 13:39:25 +0100 Subject: [PATCH 06/16] Use bitmap color format in gdi_BitBlt --- libfreerdp/gdi/bitmap.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libfreerdp/gdi/bitmap.c b/libfreerdp/gdi/bitmap.c index 478b9a799..49f8da6b6 100644 --- a/libfreerdp/gdi/bitmap.c +++ b/libfreerdp/gdi/bitmap.c @@ -483,9 +483,9 @@ BOOL gdi_BitBlt(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest, hSrcBmp = (HGDI_BITMAP) hdcSrc->selectedObject; hDstBmp = (HGDI_BITMAP) hdcDest->selectedObject; - if (!freerdp_image_copy(hDstBmp->data, hdcDest->format, hDstBmp->scanline, + if (!freerdp_image_copy(hDstBmp->data, hDstBmp->format, hDstBmp->scanline, nXDest, nYDest, nWidth, nHeight, - hSrcBmp->data, hdcSrc->format, hSrcBmp->scanline, nXSrc, nYSrc, palette, FREERDP_FLIP_NONE)) + hSrcBmp->data, hSrcBmp->format, hSrcBmp->scanline, nXSrc, nYSrc, palette, FREERDP_FLIP_NONE)) return FALSE; break; @@ -494,9 +494,9 @@ BOOL gdi_BitBlt(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest, hSrcBmp = (HGDI_BITMAP) hdcDest->selectedObject; hDstBmp = (HGDI_BITMAP) hdcDest->selectedObject; - if (!freerdp_image_copy(hDstBmp->data, hdcDest->format, hDstBmp->scanline, + if (!freerdp_image_copy(hDstBmp->data, hDstBmp->format, hDstBmp->scanline, nXDest, nYDest, nWidth, nHeight, - hSrcBmp->data, hdcSrc->format, hSrcBmp->scanline, nXSrc, nYSrc, palette, FREERDP_FLIP_NONE)) + hSrcBmp->data, hSrcBmp->format, hSrcBmp->scanline, nXSrc, nYSrc, palette, FREERDP_FLIP_NONE)) return FALSE; break; From e44158ee293af2ab7f6c2d69a3ec1722acbdf7fa Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Tue, 14 Feb 2017 14:42:33 +0100 Subject: [PATCH 07/16] Reordered SSSE3 YUV444ToRGB --- libfreerdp/primitives/prim_YUV_opt.c | 62 ++++++++++++++-------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/libfreerdp/primitives/prim_YUV_opt.c b/libfreerdp/primitives/prim_YUV_opt.c index 1e655ceb3..989cb567e 100644 --- a/libfreerdp/primitives/prim_YUV_opt.c +++ b/libfreerdp/primitives/prim_YUV_opt.c @@ -359,25 +359,44 @@ static pstatus_t ssse3_YUV420ToRGB( } } -static __m128i* ssse3_YUV444Pixel(__m128i* dst, __m128i Yraw, __m128i Uraw, __m128i Vraw, - __m128i mapY, __m128i mapUV) +static __m128i* ssse3_YUV444Pixel(__m128i* dst, __m128i Yraw, __m128i Uraw, __m128i Vraw, UINT8 pos) { + const __m128i mapY[] = + { + _mm_set_epi32(0x80800380, 0x80800280, 0x80800180, 0x80800080), + _mm_set_epi32(0x80800780, 0x80800680, 0x80800580, 0x80800480), + _mm_set_epi32(0x80800B80, 0x80800A80, 0x80800980, 0x80800880), + _mm_set_epi32(0x80800F80, 0x80800E80, 0x80800D80, 0x80800C80) + }; + const __m128i mapUV[] = + { + _mm_set_epi32(0x80038002, 0x80018000, 0x80808080, 0x80808080), + _mm_set_epi32(0x80078006, 0x80058004, 0x80808080, 0x80808080), + _mm_set_epi32(0x800B800A, 0x80098008, 0x80808080, 0x80808080), + _mm_set_epi32(0x800F800E, 0x800D800C, 0x80808080, 0x80808080) + }; + const __m128i mask[] = + { + _mm_set_epi32(0x80038080, 0x80028080, 0x80018080, 0x80008080), + _mm_set_epi32(0x80800380, 0x80800280, 0x80800180, 0x80800080), + _mm_set_epi32(0x80808003, 0x80808002, 0x80808001, 0x80808000) + }; const __m128i c128 = _mm_set1_epi16(128); __m128i BGRX = _mm_set_epi32(0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000); { __m128i C, D, E; /* Load Y values and expand to 32 bit */ { - C = _mm_shuffle_epi8(Yraw, mapY); /* Reorder and multiply by 256 */ + C = _mm_shuffle_epi8(Yraw, mapY[pos]); /* Reorder and multiply by 256 */ } /* Load U values and expand to 32 bit */ { - const __m128i U = _mm_shuffle_epi8(Uraw, mapUV); /* Reorder dcba */ + const __m128i U = _mm_shuffle_epi8(Uraw, mapUV[pos]); /* Reorder dcba */ D = _mm_sub_epi16(U, c128); /* D = U - 128 */ } /* Load V values and expand to 32 bit */ { - const __m128i V = _mm_shuffle_epi8(Vraw, mapUV); /* Reorder dcba */ + const __m128i V = _mm_shuffle_epi8(Vraw, mapUV[pos]); /* Reorder dcba */ E = _mm_sub_epi16(V, c128); /* E = V - 128 */ } /* Get the R value */ @@ -388,8 +407,7 @@ static __m128i* ssse3_YUV444Pixel(__m128i* dst, __m128i Yraw, __m128i Uraw, __m1 const __m128i R32 = _mm_srai_epi32(Rs, 8); const __m128i R16 = _mm_packs_epi32(R32, _mm_setzero_si128()); const __m128i R = _mm_packus_epi16(R16, _mm_setzero_si128()); - const __m128i mask = _mm_set_epi32(0x80038080, 0x80028080, 0x80018080, 0x80008080); - const __m128i packed = _mm_shuffle_epi8(R, mask); + const __m128i packed = _mm_shuffle_epi8(R, mask[0]); BGRX = _mm_or_si128(BGRX, packed); } /* Get the G value */ @@ -403,8 +421,7 @@ static __m128i* ssse3_YUV444Pixel(__m128i* dst, __m128i Yraw, __m128i Uraw, __m1 const __m128i G32 = _mm_srai_epi32(Gs, 8); const __m128i G16 = _mm_packs_epi32(G32, _mm_setzero_si128()); const __m128i G = _mm_packus_epi16(G16, _mm_setzero_si128()); - const __m128i mask = _mm_set_epi32(0x80800380, 0x80800280, 0x80800180, 0x80800080); - const __m128i packed = _mm_shuffle_epi8(G, mask); + const __m128i packed = _mm_shuffle_epi8(G, mask[1]); BGRX = _mm_or_si128(BGRX, packed); } /* Get the B value */ @@ -415,8 +432,7 @@ static __m128i* ssse3_YUV444Pixel(__m128i* dst, __m128i Yraw, __m128i Uraw, __m1 const __m128i B32 = _mm_srai_epi32(Bs, 8); const __m128i B16 = _mm_packs_epi32(B32, _mm_setzero_si128()); const __m128i B = _mm_packus_epi16(B16, _mm_setzero_si128()); - const __m128i mask = _mm_set_epi32(0x80808003, 0x80808002, 0x80808001, 0x80808000); - const __m128i packed = _mm_shuffle_epi8(B, mask); + const __m128i packed = _mm_shuffle_epi8(B, mask[2]); BGRX = _mm_or_si128(BGRX, packed); } } @@ -450,26 +466,10 @@ static pstatus_t ssse3_YUV444ToRGB_8u_P3AC4R_BGRX( YData += 16; UData += 16; VData += 16; - { - const __m128i mapY = _mm_set_epi32(0x80800380, 0x80800280, 0x80800180, 0x80800080); - const __m128i mapUV = _mm_set_epi32(0x80038002, 0x80018000, 0x80808080, 0x80808080); - dst = ssse3_YUV444Pixel(dst, Y, U, V, mapY, mapUV); - } - { - const __m128i mapY = _mm_set_epi32(0x80800780, 0x80800680, 0x80800580, 0x80800480); - const __m128i mapUV = _mm_set_epi32(0x80078006, 0x80058004, 0x80808080, 0x80808080); - dst = ssse3_YUV444Pixel(dst, Y, U, V, mapY, mapUV); - } - { - const __m128i mapY = _mm_set_epi32(0x80800B80, 0x80800A80, 0x80800980, 0x80800880); - const __m128i mapUV = _mm_set_epi32(0x800B800A, 0x80098008, 0x80808080, 0x80808080); - dst = ssse3_YUV444Pixel(dst, Y, U, V, mapY, mapUV); - } - { - const __m128i mapY = _mm_set_epi32(0x80800F80, 0x80800E80, 0x80800D80, 0x80800C80); - const __m128i mapUV = _mm_set_epi32(0x800F800E, 0x800D800C, 0x80808080, 0x80808080); - dst = ssse3_YUV444Pixel(dst, Y, U, V, mapY, mapUV); - } + dst = ssse3_YUV444Pixel(dst, Y, U, V, 0); + dst = ssse3_YUV444Pixel(dst, Y, U, V, 1); + dst = ssse3_YUV444Pixel(dst, Y, U, V, 2); + dst = ssse3_YUV444Pixel(dst, Y, U, V, 3); } for (x = 0; x < pad; x++) From 2c99c17078b90c56c3955c297b5621f2e26b52fb Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Tue, 14 Feb 2017 16:34:02 +0100 Subject: [PATCH 08/16] Fixed libavcodec issues. --- libfreerdp/codec/h264.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/libfreerdp/codec/h264.c b/libfreerdp/codec/h264.c index 4b9d7c4a3..4a184c6e2 100644 --- a/libfreerdp/codec/h264.c +++ b/libfreerdp/codec/h264.c @@ -42,6 +42,13 @@ static int dummy_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, UINT32 Src return -1; } +static int dummy_compress(H264_CONTEXT* h264, BYTE** ppDstData, UINT32* pDstSize, + UINT32 plane) +{ + //H264_CONTEXT_X264* sys = (H264_CONTEXT_X264*) h264->pSystemData; + return -1; +} + static void dummy_uninit(H264_CONTEXT* h264) { } @@ -56,7 +63,8 @@ static H264_CONTEXT_SUBSYSTEM g_Subsystem_dummy = "dummy", dummy_init, dummy_uninit, - dummy_decompress + dummy_decompress, + dummy_compress }; /** @@ -1353,6 +1361,12 @@ static int libavcodec_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, return 1; } +static int libavcodec_compress(H264_CONTEXT* h264, BYTE** ppDstData, UINT32* pDstSize, + UINT32 plane) +{ + return -1; +} + static void libavcodec_uninit(H264_CONTEXT* h264) { H264_CONTEXT_LIBAVCODEC* sys = (H264_CONTEXT_LIBAVCODEC*) h264->pSystemData; @@ -1365,7 +1379,7 @@ static void libavcodec_uninit(H264_CONTEXT* h264) #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 18, 102) av_frame_free(&sys->videoFrame); #else - av_free(&sys->videoFrame); + av_free(sys->videoFrame); #endif } @@ -1377,7 +1391,11 @@ static void libavcodec_uninit(H264_CONTEXT* h264) if (sys->codecContext) { avcodec_close(sys->codecContext); +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 69, 100) + avcodec_free_context(&sys->codecContext); +#else av_free(sys->codecContext); +#endif } free(sys); @@ -1454,7 +1472,8 @@ static H264_CONTEXT_SUBSYSTEM g_Subsystem_libavcodec = "libavcodec", libavcodec_init, libavcodec_uninit, - libavcodec_decompress + libavcodec_decompress, + libavcodec_compress }; #endif From f24b112514ef893e269a6c03ccd75b5da378ae04 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 15 Feb 2017 09:28:10 +0100 Subject: [PATCH 09/16] Refactored AVC444 decoding to single YUV420 buffer Since not all H264 decoders support multiple YUV420 output buffers process H264 decoding and YUV to RGB conversion sequentially to avoid overriding the input data. --- include/freerdp/codec/h264.h | 42 ++--- libfreerdp/codec/h264.c | 290 +++++++++++++++-------------------- 2 files changed, 143 insertions(+), 189 deletions(-) diff --git a/include/freerdp/codec/h264.h b/include/freerdp/codec/h264.h index 69e02890a..899132682 100644 --- a/include/freerdp/codec/h264.h +++ b/include/freerdp/codec/h264.h @@ -30,9 +30,9 @@ typedef BOOL (*pfnH264SubsystemInit)(H264_CONTEXT* h264); typedef void (*pfnH264SubsystemUninit)(H264_CONTEXT* h264); typedef int (*pfnH264SubsystemDecompress)(H264_CONTEXT* h264, const BYTE* pSrcData, - UINT32 SrcSize, UINT32 plane); + UINT32 SrcSize); typedef int (*pfnH264SubsystemCompress)(H264_CONTEXT* h264, BYTE** ppDstData, - UINT32* pDstSize, UINT32 plane); + UINT32* pDstSize); struct _H264_CONTEXT_SUBSYSTEM { @@ -64,8 +64,8 @@ struct _H264_CONTEXT UINT32 QP; UINT32 NumberOfThreads; - UINT32 iStride[2][3]; - BYTE* pYUVData[2][3]; + UINT32 iStride[3]; + BYTE* pYUVData[3]; UINT32 iYUV444Size[3]; UINT32 iYUV444Stride[3]; @@ -81,29 +81,29 @@ extern "C" { #endif FREERDP_API INT32 avc420_compress(H264_CONTEXT* h264, const BYTE* pSrcData, - DWORD SrcFormat, UINT32 nSrcStep, - UINT32 nSrcWidth, UINT32 nSrcHeight, - BYTE** ppDstData, UINT32* pDstSize); + DWORD SrcFormat, UINT32 nSrcStep, + UINT32 nSrcWidth, UINT32 nSrcHeight, + BYTE** ppDstData, UINT32* pDstSize); FREERDP_API INT32 avc420_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, - UINT32 SrcSize, BYTE* pDstData, - DWORD DstFormat, UINT32 nDstStep, - UINT32 nDstWidth, UINT32 nDstHeight, - RECTANGLE_16* regionRects, UINT32 numRegionRect); + UINT32 SrcSize, BYTE* pDstData, + DWORD DstFormat, UINT32 nDstStep, + UINT32 nDstWidth, UINT32 nDstHeight, + RECTANGLE_16* regionRects, UINT32 numRegionRect); FREERDP_API INT32 avc444_compress(H264_CONTEXT* h264, const BYTE* pSrcData, DWORD SrcFormat, - UINT32 nSrcStep, UINT32 nSrcWidth, UINT32 nSrcHeight, - BYTE* op, - BYTE** pDstData, UINT32* pDstSize, - BYTE** pAuxDstData, UINT32* pAuxDstSize); + UINT32 nSrcStep, UINT32 nSrcWidth, UINT32 nSrcHeight, + BYTE* op, + BYTE** pDstData, UINT32* pDstSize, + BYTE** pAuxDstData, UINT32* pAuxDstSize); FREERDP_API INT32 avc444_decompress(H264_CONTEXT* h264, BYTE op, - RECTANGLE_16* regionRects, UINT32 numRegionRect, - const BYTE* pSrcData, UINT32 SrcSize, - RECTANGLE_16* auxRegionRects, UINT32 numAuxRegionRect, - const BYTE* pAuxSrcData, UINT32 AuxSrcSize, - BYTE* pDstData, DWORD DstFormat, - UINT32 nDstStep, UINT32 nDstWidth, UINT32 nDstHeight); + RECTANGLE_16* regionRects, UINT32 numRegionRect, + const BYTE* pSrcData, UINT32 SrcSize, + RECTANGLE_16* auxRegionRects, UINT32 numAuxRegionRect, + const BYTE* pAuxSrcData, UINT32 AuxSrcSize, + BYTE* pDstData, DWORD DstFormat, + UINT32 nDstStep, UINT32 nDstWidth, UINT32 nDstHeight); FREERDP_API BOOL h264_context_reset(H264_CONTEXT* h264, UINT32 width, UINT32 height); diff --git a/libfreerdp/codec/h264.c b/libfreerdp/codec/h264.c index 4a184c6e2..2c91cea01 100644 --- a/libfreerdp/codec/h264.c +++ b/libfreerdp/codec/h264.c @@ -36,14 +36,12 @@ * Dummy subsystem */ -static int dummy_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, UINT32 SrcSize, - UINT32 plane) +static int dummy_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, UINT32 SrcSize) { return -1; } -static int dummy_compress(H264_CONTEXT* h264, BYTE** ppDstData, UINT32* pDstSize, - UINT32 plane) +static int dummy_compress(H264_CONTEXT* h264, BYTE** ppDstData, UINT32* pDstSize) { //H264_CONTEXT_X264* sys = (H264_CONTEXT_X264*) h264->pSystemData; return -1; @@ -268,8 +266,7 @@ error: return hr; } -static int mf_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize, - UINT32 plane) +static int mf_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize) { HRESULT hr; BYTE* pbBuffer = NULL; @@ -281,8 +278,8 @@ static int mf_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize, IMFMediaBuffer* outputBuffer = NULL; MFT_OUTPUT_DATA_BUFFER outputDataBuffer; H264_CONTEXT_MF* sys = (H264_CONTEXT_MF*) h264->pSystemData; - INT32* iStride = h264->iStride[plane]; - BYTE** pYUVData = h264->pYUVData[plane]; + INT32* iStride = h264->iStride; + BYTE** pYUVData = h264->pYUVData; hr = sys->MFCreateMemoryBuffer(SrcSize, &inputBuffer); if (FAILED(hr)) @@ -494,8 +491,7 @@ error: return -1; } -static int mf_compress(H264_CONTEXT* h264, BYTE** ppDstData, UINT32* pDstSize, - UINT32 plane) +static int mf_compress(H264_CONTEXT* h264, BYTE** ppDstData, UINT32* pDstSize) { H264_CONTEXT_MF* sys = (H264_CONTEXT_MF*) h264->pSystemData; return 1; @@ -743,18 +739,16 @@ struct _H264_CONTEXT_X264 }; typedef struct _H264_CONTEXT_X264 H264_CONTEXT_X264; -static int x264_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize, - UINT32 plane) +static int x264_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize) { //H264_CONTEXT_X264* sys = (H264_CONTEXT_X264*) h264->pSystemData; - return 1; + return -1; } -static int x264_compress(H264_CONTEXT* h264, BYTE** ppDstData, UINT32* pDstSize, - UINT32 plane) +static int x264_compress(H264_CONTEXT* h264, BYTE** ppDstData, UINT32* pDstSize) { //H264_CONTEXT_X264* sys = (H264_CONTEXT_X264*) h264->pSystemData; - return 1; + return -1; } static void x264_uninit(H264_CONTEXT* h264) @@ -856,14 +850,14 @@ static void openh264_trace_callback(H264_CONTEXT* h264, int level, } static int openh264_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, - UINT32 SrcSize, UINT32 plane) + UINT32 SrcSize) { DECODING_STATE state; SBufferInfo sBufferInfo; SSysMEMBuffer* pSystemBuffer; H264_CONTEXT_OPENH264* sys = (H264_CONTEXT_OPENH264*) h264->pSystemData; - UINT32* iStride = h264->iStride[plane]; - BYTE** pYUVData = h264->pYUVData[plane]; + UINT32* iStride = h264->iStride; + BYTE** pYUVData = h264->pYUVData; if (!sys->pDecoder) return -2001; @@ -935,7 +929,7 @@ static int openh264_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, } static int openh264_compress(H264_CONTEXT* h264, BYTE** ppDstData, - UINT32* pDstSize, UINT32 plane) + UINT32* pDstSize) { int i, j; int status; @@ -943,8 +937,8 @@ static int openh264_compress(H264_CONTEXT* h264, BYTE** ppDstData, SSourcePicture pic; SBitrateInfo bitrate; H264_CONTEXT_OPENH264* sys; - BYTE** pYUVData = h264->pYUVData[plane]; - UINT32* iStride = h264->iStride[plane]; + BYTE** pYUVData = h264->pYUVData; + UINT32* iStride = h264->iStride; sys = &((H264_CONTEXT_OPENH264*) h264->pSystemData)[0]; if (!sys->pEncoder) @@ -1296,14 +1290,14 @@ struct _H264_CONTEXT_LIBAVCODEC typedef struct _H264_CONTEXT_LIBAVCODEC H264_CONTEXT_LIBAVCODEC; static int libavcodec_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, - UINT32 SrcSize, UINT32 plane) + UINT32 SrcSize) { int status; int gotFrame = 0; AVPacket packet; H264_CONTEXT_LIBAVCODEC* sys = (H264_CONTEXT_LIBAVCODEC*) h264->pSystemData; - BYTE** pYUVData = h264->pYUVData[plane]; - UINT32* iStride = h264->iStride[plane]; + BYTE** pYUVData = h264->pYUVData; + UINT32* iStride = h264->iStride; av_init_packet(&packet); packet.data = (BYTE*)pSrcData; packet.size = SrcSize; @@ -1361,8 +1355,7 @@ static int libavcodec_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, return 1; } -static int libavcodec_compress(H264_CONTEXT* h264, BYTE** ppDstData, UINT32* pDstSize, - UINT32 plane) +static int libavcodec_compress(H264_CONTEXT* h264, BYTE** ppDstData, UINT32* pDstSize) { return -1; } @@ -1523,8 +1516,8 @@ static BOOL avc_yuv_to_rgb(H264_CONTEXT* h264, const RECTANGLE_16* regionRects, } else { - iStride = h264->iStride[0]; - ppYUVData = h264->pYUVData[0]; + iStride = h264->iStride; + ppYUVData = h264->pYUVData; } if (!check_rect(h264, rect, nDstWidth, nDstHeight)) @@ -1582,7 +1575,7 @@ INT32 avc420_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, UINT32 SrcSize if (!h264) return -1001; - status = h264->subsystem->Decompress(h264, pSrcData, SrcSize, 0); + status = h264->subsystem->Decompress(h264, pSrcData, SrcSize); if (status == 0) return 1; @@ -1614,8 +1607,8 @@ INT32 avc420_compress(H264_CONTEXT* h264, const BYTE* pSrcData, DWORD SrcFormat, if (!h264->subsystem->Compress) return -1; - iStride = h264->iStride[0]; - pYUVData = h264->pYUVData[0]; + iStride = h264->iStride; + pYUVData = h264->pYUVData; nWidth = (nSrcWidth + 1) & ~1; nHeight = (nSrcHeight + 1) & ~1; @@ -1637,7 +1630,7 @@ INT32 avc420_compress(H264_CONTEXT* h264, const BYTE* pSrcData, DWORD SrcFormat, roi.height = nSrcHeight; prims->RGBToYUV420_8u_P3AC4R(pSrcData, SrcFormat, nSrcStep, pYUVData, iStride, &roi); - status = h264->subsystem->Compress(h264, ppDstData, pDstSize, 0); + status = h264->subsystem->Compress(h264, ppDstData, pDstSize); _aligned_free(pYUVData[2]); pYUVData[2] = NULL; error_2: @@ -1657,95 +1650,12 @@ INT32 avc444_compress(H264_CONTEXT* h264, const BYTE* pSrcData, DWORD SrcFormat, return -1; } -static BOOL avc444_process_rect(H264_CONTEXT* h264, - UINT32 nDstWidth, UINT32 nDstHeight, - const RECTANGLE_16* mainRects, UINT32 nrMainRects, - const RECTANGLE_16* auxRects, UINT32 nrAuxRects) -{ - const primitives_t* prims = primitives_get(); - UINT32 x; - const BYTE* pYUVMainPoint[3] = { NULL, NULL, NULL }; - const BYTE* pYUVAuxPoint[3] = { NULL, NULL, NULL }; - BYTE* pYUVDstPoint[3]; - UINT32* piDstStride = h264->iYUV444Stride; - BYTE** ppYUVDstData = h264->pYUV444Data; - const UINT32* piAuxStride = h264->iStride[1]; - const UINT32* piMainStride = h264->iStride[0]; - BYTE** ppYUVAuxData = h264->pYUVData[1]; - BYTE** ppYUVMainData = h264->pYUVData[0]; - for (x = 0; x < nrMainRects; x++) - { - const RECTANGLE_16* rect = &mainRects[x]; - prim_size_t roi; - - if (!check_rect(h264, rect, nDstWidth, nDstHeight)) - continue; - - pYUVMainPoint[0] = ppYUVMainData[0] + rect->top * piMainStride[0] + - rect->left; - pYUVMainPoint[1] = ppYUVMainData[1] + rect->top / 2 * piMainStride[1] + - rect->left / 2; - pYUVMainPoint[2] = ppYUVMainData[2] + rect->top / 2 * piMainStride[2] + - rect->left / 2; - pYUVDstPoint[0] = ppYUVDstData[0] + rect->top * piDstStride[0] + - rect->left; - pYUVDstPoint[1] = ppYUVDstData[1] + rect->top * piDstStride[1] + - rect->left; - pYUVDstPoint[2] = ppYUVDstData[2] + rect->top * piDstStride[2] + - rect->left; - roi.width = rect->right - rect->left + 1; - roi.height = rect->bottom - rect->top + 1; - - if (prims->YUV420CombineToYUV444(pYUVMainPoint, piMainStride, - NULL, NULL, - pYUVDstPoint, piDstStride, - &roi) != PRIMITIVES_SUCCESS) - return FALSE; - } - - for (x = 0; x < nrAuxRects; x++) - { - const RECTANGLE_16* rect = &auxRects[x]; - prim_size_t roi; - - if (!check_rect(h264, rect, nDstWidth, nDstHeight)) - continue; - - pYUVAuxPoint[0] = ppYUVAuxData[0] + rect->top * piAuxStride[0] + - rect->left; - pYUVAuxPoint[1] = ppYUVAuxData[1] + rect->top / 2 * piAuxStride[1] + - rect->left / 2; - pYUVAuxPoint[2] = ppYUVAuxData[2] + rect->top / 2 * piAuxStride[2] + - rect->left / 2; - pYUVDstPoint[0] = ppYUVDstData[0] + rect->top * piDstStride[0] + - rect->left; - pYUVDstPoint[1] = ppYUVDstData[1] + rect->top * piDstStride[1] + - rect->left; - pYUVDstPoint[2] = ppYUVDstData[2] + rect->top * piDstStride[2] + - rect->left; - roi.width = rect->right - rect->left + 1; - roi.height = rect->bottom - rect->top + 1; - - if (prims->YUV420CombineToYUV444(NULL, NULL, - pYUVAuxPoint, piAuxStride, - pYUVDstPoint, piDstStride, - &roi) != PRIMITIVES_SUCCESS) - return FALSE; - } - - return TRUE; -} - -static BOOL avc444_combine_yuv(H264_CONTEXT* h264, - const RECTANGLE_16* mainRegionRects, - UINT32 numMainRegionRect, - const RECTANGLE_16* auxRegionRects, - UINT32 numAuxRegionRect, UINT32 nDstWidth, - DWORD nDstHeight) +static BOOL avc444_ensure_buffer(H264_CONTEXT* h264, + DWORD nDstHeight) { UINT32 x; - const UINT32* piMainStride = h264->iStride[0]; + const UINT32* piMainStride = h264->iStride; UINT32* piDstSize = h264->iYUV444Size; UINT32* piDstStride = h264->iYUV444Stride; BYTE** ppYUVDstData = h264->pYUV444Data; @@ -1777,11 +1687,6 @@ static BOOL avc444_combine_yuv(H264_CONTEXT* h264, } } - if (!avc444_process_rect(h264, nDstWidth, nDstHeight, - mainRegionRects, numMainRegionRect, - auxRegionRects, numAuxRegionRect)) - goto fail; - return TRUE; fail: _aligned_free(ppYUVDstData[0]); @@ -1793,6 +1698,75 @@ fail: return FALSE; } +static BOOL avc444_process_rects(H264_CONTEXT* h264, const BYTE* pSrcData, + UINT32 SrcSize, BYTE* pDstData, UINT32 DstFormat, UINT32 nDstStep, + UINT32 nDstWidth, UINT32 nDstHeight, + const RECTANGLE_16* rects, UINT32 nrRects, + BOOL main) +{ + const primitives_t* prims = primitives_get(); + UINT32 x; + const BYTE* pYUVPoint[3] = { NULL, NULL, NULL }; + BYTE* pYUVDstPoint[3]; + UINT32* piDstStride = h264->iYUV444Stride; + BYTE** ppYUVDstData = h264->pYUV444Data; + const UINT32* piStride = h264->iStride; + BYTE** ppYUVData = h264->pYUVData; + + if (h264->subsystem->Decompress(h264, pSrcData, SrcSize) < 0) + return FALSE; + + if (!avc444_ensure_buffer(h264, nDstHeight)) + return FALSE; + + for (x = 0; x < nrRects; x++) + { + const RECTANGLE_16* rect = &rects[x]; + prim_size_t roi; + + if (!check_rect(h264, rect, nDstWidth, nDstHeight)) + continue; + + pYUVPoint[0] = ppYUVData[0] + rect->top * piStride[0] + + rect->left; + pYUVPoint[1] = ppYUVData[1] + rect->top / 2 * piStride[1] + + rect->left / 2; + pYUVPoint[2] = ppYUVData[2] + rect->top / 2 * piStride[2] + + rect->left / 2; + pYUVDstPoint[0] = ppYUVDstData[0] + rect->top * piDstStride[0] + + rect->left; + pYUVDstPoint[1] = ppYUVDstData[1] + rect->top * piDstStride[1] + + rect->left; + pYUVDstPoint[2] = ppYUVDstData[2] + rect->top * piDstStride[2] + + rect->left; + roi.width = rect->right - rect->left + 1; + roi.height = rect->bottom - rect->top + 1; + + if (main) + { + if (prims->YUV420CombineToYUV444(pYUVPoint, piStride, + NULL, NULL, + pYUVDstPoint, piDstStride, + &roi) != PRIMITIVES_SUCCESS) + return FALSE; + } + else + { + if (prims->YUV420CombineToYUV444(NULL, NULL, + pYUVPoint, piStride, + pYUVDstPoint, piDstStride, + &roi) != PRIMITIVES_SUCCESS) + return FALSE; + } + } + + if (!avc_yuv_to_rgb(h264, rects, nrRects, nDstWidth, + nDstHeight, nDstStep, pDstData, DstFormat, TRUE)) + return FALSE; + + return TRUE; +} + #if defined(AVC444_FRAME_STAT) static UINT64 op1 = 0; static double op1sum = 0; @@ -1818,10 +1792,6 @@ INT32 avc444_decompress(H264_CONTEXT* h264, BYTE op, UINT32 nDstStep, UINT32 nDstWidth, UINT32 nDstHeight) { INT32 status = -1; - UINT32 numYuvRects = 0; - RECTANGLE_16* yuvRects = NULL; - UINT32 numChromaRects = 0; - RECTANGLE_16* chromaRects = NULL; if (!h264 || !regionRects || !pSrcData || !pDstData) @@ -1831,27 +1801,37 @@ INT32 avc444_decompress(H264_CONTEXT* h264, BYTE op, { case 0: /* YUV420 in stream 1 * Chroma420 in stream 2 */ - numYuvRects = numRegionRects; - yuvRects = regionRects; - numChromaRects = numAuxRegionRect; - chromaRects = auxRegionRects; - status = h264->subsystem->Decompress(h264, pSrcData, SrcSize, 0); - - if (status >= 0) - status = h264->subsystem->Decompress(h264, pAuxSrcData, AuxSrcSize, 1); + if (!avc444_process_rects(h264, pSrcData, SrcSize, pDstData, DstFormat, nDstStep, nDstWidth, + nDstHeight, + regionRects, numRegionRects, TRUE)) + status = -1; + else if (!avc444_process_rects(h264, pAuxSrcData, AuxSrcSize, pDstData, DstFormat, nDstStep, + nDstWidth, nDstHeight, + auxRegionRects, numAuxRegionRect, FALSE)) + status = -1; + else + status = 0; break; case 2: /* Chroma420 in stream 1 */ - status = h264->subsystem->Decompress(h264, pSrcData, SrcSize, 1); - numChromaRects = numRegionRects; - chromaRects = regionRects; + if (!avc444_process_rects(h264, pSrcData, SrcSize, pDstData, DstFormat, nDstStep, nDstWidth, + nDstHeight, + regionRects, numRegionRects, FALSE)) + status = -1; + else + status = 0; + break; case 1: /* YUV420 in stream 1 */ - status = h264->subsystem->Decompress(h264, pSrcData, SrcSize, 0); - numYuvRects = numRegionRects; - yuvRects = regionRects; + if (!avc444_process_rects(h264, pSrcData, SrcSize, pDstData, DstFormat, nDstStep, nDstWidth, + nDstHeight, + regionRects, numRegionRects, TRUE)) + status = -1; + else + status = 0; + break; default: /* WTF? */ @@ -1882,32 +1862,6 @@ INT32 avc444_decompress(H264_CONTEXT* h264, BYTE op, "luma=%"PRIu64" [avg=%lf] chroma=%"PRIu64" [avg=%lf] combined=%"PRIu64" [avg=%lf]", op1, op1sum, op2, op2sum, op3, op3sum); #endif - - if (status >= 0) - { - if (!avc444_combine_yuv(h264, yuvRects, numYuvRects, - chromaRects, numChromaRects, - nDstWidth, nDstHeight)) - status = -1002; - else - { - if (numYuvRects > 0) - { - if (!avc_yuv_to_rgb(h264, yuvRects, numYuvRects, nDstWidth, - nDstHeight, nDstStep, pDstData, DstFormat, TRUE)) - status = -1003; - } - - if (numChromaRects > 0) - { - if (!avc_yuv_to_rgb(h264, chromaRects, numChromaRects, - nDstWidth, nDstHeight, nDstStep, pDstData, - DstFormat, TRUE)) - status = -1004; - } - } - } - return status; } From 03abaf1aeeec47f59302f89bd519a42b3490f70d Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 15 Feb 2017 11:56:50 +0100 Subject: [PATCH 10/16] Align scanline to multiple of 16, required for ASM --- client/X11/xf_gfx.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/client/X11/xf_gfx.c b/client/X11/xf_gfx.c index 9b229055d..1e4719489 100644 --- a/client/X11/xf_gfx.c +++ b/client/X11/xf_gfx.c @@ -176,8 +176,9 @@ UINT xf_OutputExpose(xfContext* xfc, UINT32 x, UINT32 y, return status; } -static INLINE UINT32 x11_pad_scanline(UINT32 scanline, UINT32 inPad) +UINT32 x11_pad_scanline(UINT32 scanline, UINT32 inPad) { + /* Ensure X11 alignment is met */ if (inPad > 0) { const UINT32 align = inPad / 8; @@ -187,6 +188,10 @@ static INLINE UINT32 x11_pad_scanline(UINT32 scanline, UINT32 inPad) scanline += pad; } + /* 16 byte alingment is required for ASM optimized code */ + if (scanline % 16) + scanline += 16 - scanline % 16; + return scanline; } From dce3604bcf63a0b327f7e91c7bc5b73e5a15b282 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 15 Feb 2017 12:04:11 +0100 Subject: [PATCH 11/16] Refined alignment checks for SSSE3 YUV444ToRGB --- libfreerdp/primitives/prim_YUV_opt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfreerdp/primitives/prim_YUV_opt.c b/libfreerdp/primitives/prim_YUV_opt.c index 989cb567e..320b80699 100644 --- a/libfreerdp/primitives/prim_YUV_opt.c +++ b/libfreerdp/primitives/prim_YUV_opt.c @@ -492,7 +492,7 @@ static pstatus_t ssse3_YUV444ToRGB_8u_P3AC4R(const BYTE** pSrc, const UINT32* sr const prim_size_t* roi) { if ((unsigned long)pSrc[0] % 16 || (unsigned long)pSrc[1] % 16 || (unsigned long)pSrc[2] % 16 || - (unsigned long)pDst % 16) + (unsigned long)pDst % 16 || dstStep % 16 || srcStep[0] % 16 || srcStep[1] % 16 || srcStep[2] % 16) return generic->YUV444ToRGB_8u_P3AC4R(pSrc, srcStep, pDst, dstStep, DstFormat, roi); switch (DstFormat) From 01d24264d2805948691dcd8811c3f6150e13bd5e Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 15 Feb 2017 12:37:37 +0100 Subject: [PATCH 12/16] Using aligned RFX buffers. --- libfreerdp/codec/rfx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libfreerdp/codec/rfx.c b/libfreerdp/codec/rfx.c index c887846e9..a4a1ad8c7 100644 --- a/libfreerdp/codec/rfx.c +++ b/libfreerdp/codec/rfx.c @@ -167,7 +167,7 @@ static RFX_TILE* rfx_decoder_tile_new(void) if (!(tile = (RFX_TILE*) calloc(1, sizeof(RFX_TILE)))) return NULL; - if (!(tile->data = (BYTE*) malloc(4 * 64 * 64))) + if (!(tile->data = (BYTE*) _aligned_malloc(4 * 64 * 64, 16))) { free(tile); return NULL; @@ -182,7 +182,7 @@ static void rfx_decoder_tile_free(RFX_TILE* tile) if (tile) { if (tile->allocated) - free(tile->data); + _aligned_free(tile->data); free(tile); } From 1b78c45eca73bd3d763341ccaf5c37e1be6a4f55 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 15 Feb 2017 12:38:26 +0100 Subject: [PATCH 13/16] Fixed alignment checks for SSE yCbCrToRGB --- libfreerdp/primitives/prim_colors_opt.c | 53 ++++++++----------------- 1 file changed, 17 insertions(+), 36 deletions(-) diff --git a/libfreerdp/primitives/prim_colors_opt.c b/libfreerdp/primitives/prim_colors_opt.c index 3e53da017..24e19c53c 100644 --- a/libfreerdp/primitives/prim_colors_opt.c +++ b/libfreerdp/primitives/prim_colors_opt.c @@ -204,7 +204,7 @@ static pstatus_t sse2_yCbCrToRGB_16s16s_P3P3( /*---------------------------------------------------------------------------*/ static pstatus_t sse2_yCbCrToRGB_16s8u_P3AC4R_BGRX( const INT16* pSrc[3], UINT32 srcStep, - BYTE* pDst, UINT32 dstStep, UINT32 DstFormat, + BYTE* pDst, UINT32 dstStep, const prim_size_t* roi) /* region of interest */ { __m128i zero, max, r_cr, g_cb, g_cr, b_cb, c4096; @@ -212,22 +212,6 @@ static pstatus_t sse2_yCbCrToRGB_16s8u_P3AC4R_BGRX( __m128i* d_buf; int srcbump, dstbump, yp, imax; size_t dstPad, yPad, cbPad, crPad; - - if (((ULONG_PTR)(pSrc[0]) & 0x0f) - || ((ULONG_PTR)(pSrc[1]) & 0x0f) - || ((ULONG_PTR)(pSrc[2]) & 0x0f) - || ((ULONG_PTR)(pDst[0]) & 0x0f) - || ((ULONG_PTR)(pDst[1]) & 0x0f) - || ((ULONG_PTR)(pDst[2]) & 0x0f) - || (roi->width & 0x07) - || (srcStep & 127) - || (dstStep & 127)) - { - /* We can't maintain 16-byte alignment. */ - return generic->yCbCrToRGB_16s8u_P3AC4R(pSrc, srcStep, - pDst, dstStep, DstFormat, roi); - } - zero = _mm_setzero_si128(); max = _mm_set1_epi16(255); y_buf = (const __m128i*)(pSrc[0]); @@ -390,7 +374,7 @@ static pstatus_t sse2_yCbCrToRGB_16s8u_P3AC4R_BGRX( /*---------------------------------------------------------------------------*/ static pstatus_t sse2_yCbCrToRGB_16s8u_P3AC4R_RGBX( const INT16* pSrc[3], UINT32 srcStep, - BYTE* pDst, UINT32 dstStep, UINT32 DstFormat, + BYTE* pDst, UINT32 dstStep, const prim_size_t* roi) /* region of interest */ { __m128i zero, max, r_cr, g_cb, g_cr, b_cb, c4096; @@ -398,22 +382,6 @@ static pstatus_t sse2_yCbCrToRGB_16s8u_P3AC4R_RGBX( __m128i* d_buf; int srcbump, dstbump, yp, imax; size_t dstPad, yPad, cbPad, crPad; - - if (((ULONG_PTR)(pSrc[0]) & 0x0f) - || ((ULONG_PTR)(pSrc[1]) & 0x0f) - || ((ULONG_PTR)(pSrc[2]) & 0x0f) - || ((ULONG_PTR)(pDst[0]) & 0x0f) - || ((ULONG_PTR)(pDst[1]) & 0x0f) - || ((ULONG_PTR)(pDst[2]) & 0x0f) - || (roi->width & 0x07) - || (srcStep & 127) - || (dstStep & 127)) - { - /* We can't maintain 16-byte alignment. */ - return generic->yCbCrToRGB_16s8u_P3AC4R(pSrc, srcStep, - pDst, dstStep, DstFormat, roi); - } - zero = _mm_setzero_si128(); max = _mm_set1_epi16(255); y_buf = (const __m128i*)(pSrc[0]); @@ -578,15 +546,28 @@ static pstatus_t sse2_yCbCrToRGB_16s8u_P3AC4R( BYTE* pDst, UINT32 dstStep, UINT32 DstFormat, const prim_size_t* roi) /* region of interest */ { + if (((ULONG_PTR)(pSrc[0]) & 0x0f) + || ((ULONG_PTR)(pSrc[1]) & 0x0f) + || ((ULONG_PTR)(pSrc[2]) & 0x0f) + || ((ULONG_PTR)(pDst) & 0x0f) + || (roi->width & 0x07) + || (srcStep & 127) + || (dstStep & 127)) + { + /* We can't maintain 16-byte alignment. */ + return generic->yCbCrToRGB_16s8u_P3AC4R(pSrc, srcStep, + pDst, dstStep, DstFormat, roi); + } + switch (DstFormat) { case PIXEL_FORMAT_BGRA32: case PIXEL_FORMAT_BGRX32: - return sse2_yCbCrToRGB_16s8u_P3AC4R_BGRX(pSrc, srcStep, pDst, dstStep, DstFormat, roi); + return sse2_yCbCrToRGB_16s8u_P3AC4R_BGRX(pSrc, srcStep, pDst, dstStep, roi); case PIXEL_FORMAT_RGBA32: case PIXEL_FORMAT_RGBX32: - return sse2_yCbCrToRGB_16s8u_P3AC4R_RGBX(pSrc, srcStep, pDst, dstStep, DstFormat, roi); + return sse2_yCbCrToRGB_16s8u_P3AC4R_RGBX(pSrc, srcStep, pDst, dstStep, roi); default: return generic->yCbCrToRGB_16s8u_P3AC4R(pSrc, srcStep, pDst, dstStep, DstFormat, roi); From 291362e2df56cd7c4acd3011aafddbccf4057af2 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 15 Feb 2017 14:22:15 +0100 Subject: [PATCH 14/16] Fixed possible memory leak. --- client/common/file.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/client/common/file.c b/client/common/file.c index 110868d08..3547875b0 100644 --- a/client/common/file.c +++ b/client/common/file.c @@ -512,6 +512,7 @@ static BOOL freerdp_client_parse_rdp_file_option_ascii(rdpFile* file, char* opti static BOOL freerdp_client_parse_rdp_file_buffer_ascii(rdpFile* file, const BYTE* buffer, size_t size) { + BOOL rc = FALSE; int index; int length; char* line; @@ -572,13 +573,13 @@ static BOOL freerdp_client_parse_rdp_file_buffer_ascii(rdpFile* file, const BYTE { /* integer type */ if (!freerdp_client_parse_rdp_file_integer_ascii(file, name, value, index)) - return FALSE; + goto fail; } else if (*type == 's') { /* string type */ if (!freerdp_client_parse_rdp_file_string_ascii(file, name, value, index)) - return FALSE; + goto fail; } else if (*type == 'b') { @@ -591,13 +592,16 @@ static BOOL freerdp_client_parse_rdp_file_buffer_ascii(rdpFile* file, const BYTE index++; } + rc = TRUE; +fail: free(copy); - return TRUE; + return rc; } static BOOL freerdp_client_parse_rdp_file_buffer_unicode(rdpFile* file, const BYTE* buffer, size_t size) { + BOOL rc = FALSE; int index; int length; const WCHAR* line; @@ -624,7 +628,7 @@ static BOOL freerdp_client_parse_rdp_file_buffer_unicode(rdpFile* file, const BY const WCHAR* end = &line[length - 1]; if (!freerdp_client_parse_rdp_file_add_line_unicode(file, line, index)) - return FALSE; + goto fail; if (beg[0] == '/') { @@ -656,13 +660,13 @@ static BOOL freerdp_client_parse_rdp_file_buffer_unicode(rdpFile* file, const BY { /* integer type */ if (!freerdp_client_parse_rdp_file_integer_unicode(file, name, value, index)) - return FALSE; + goto fail; } else if (*type == 's') { /* string type */ if (!freerdp_client_parse_rdp_file_string_unicode(file, name, value, index)) - return FALSE; + goto fail; } else if (*type == 'b') { @@ -675,8 +679,10 @@ static BOOL freerdp_client_parse_rdp_file_buffer_unicode(rdpFile* file, const BY index++; } + rc = TRUE; +fail: free(copy); - return TRUE; + return rc; } BOOL freerdp_client_parse_rdp_file_buffer(rdpFile* file, const BYTE* buffer, size_t size) From 359077e8d3a65e45d25faaa9e38135aaeaa42ef3 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 15 Feb 2017 15:34:12 +0100 Subject: [PATCH 15/16] Closing dynamic channels on shutdown. --- channels/drdynvc/client/drdynvc_main.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/channels/drdynvc/client/drdynvc_main.c b/channels/drdynvc/client/drdynvc_main.c index 579f0a536..acf873c07 100644 --- a/channels/drdynvc/client/drdynvc_main.c +++ b/channels/drdynvc/client/drdynvc_main.c @@ -1269,6 +1269,21 @@ static void* drdynvc_virtual_channel_client_thread(void* arg) } } + { + /* Disconnect remaining dynamic channels that the server did not. + * This is required to properly shut down channels by calling the appropriate + * event handlers. */ + DVCMAN* drdynvcMgr = (DVCMAN*)drdynvc->channel_mgr; + + while (ArrayList_Count(drdynvcMgr->channels) > 0) + { + IWTSVirtualChannel* channel = (IWTSVirtualChannel*) + ArrayList_GetItem(drdynvcMgr->channels, 0); + const UINT32 ChannelId = drdynvc->channel_mgr->GetChannelId(channel); + dvcman_close_channel(drdynvc->channel_mgr, ChannelId); + } + } + if (error && drdynvc->rdpcontext) setChannelError(drdynvc->rdpcontext, error, "drdynvc_virtual_channel_client_thread reported an error"); From 6960ca209b454e1c0e8d7a5ca09e93e146822b0b Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 15 Feb 2017 15:34:50 +0100 Subject: [PATCH 16/16] Added GFX surface command profiler. --- channels/rdpgfx/client/rdpgfx_codec.c | 45 ++++++++++++++------------- include/freerdp/client/rdpgfx.h | 3 ++ libfreerdp/gdi/gfx.c | 5 +++ 3 files changed, 31 insertions(+), 22 deletions(-) diff --git a/channels/rdpgfx/client/rdpgfx_codec.c b/channels/rdpgfx/client/rdpgfx_codec.c index 74cce39d8..7ea72c4be 100644 --- a/channels/rdpgfx/client/rdpgfx_codec.c +++ b/channels/rdpgfx/client/rdpgfx_codec.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "rdpgfx_common.h" @@ -39,13 +40,12 @@ * @return 0 on success, otherwise a Win32 error code */ static UINT rdpgfx_read_h264_metablock(RDPGFX_PLUGIN* gfx, wStream* s, - RDPGFX_H264_METABLOCK* meta) + RDPGFX_H264_METABLOCK* meta) { UINT32 index; RECTANGLE_16* regionRect; RDPGFX_H264_QUANT_QUALITY* quantQualityVal; UINT error = ERROR_INVALID_DATA; - meta->regionRects = NULL; meta->quantQualityVals = NULL; @@ -72,7 +72,8 @@ static UINT rdpgfx_read_h264_metablock(RDPGFX_PLUGIN* gfx, wStream* s, goto error_out; } - meta->quantQualityVals = (RDPGFX_H264_QUANT_QUALITY*) malloc(meta->numRegionRects * sizeof(RDPGFX_H264_QUANT_QUALITY)); + meta->quantQualityVals = (RDPGFX_H264_QUANT_QUALITY*) malloc(meta->numRegionRects * sizeof( + RDPGFX_H264_QUANT_QUALITY)); if (!meta->quantQualityVals) { @@ -86,13 +87,16 @@ static UINT rdpgfx_read_h264_metablock(RDPGFX_PLUGIN* gfx, wStream* s, for (index = 0; index < meta->numRegionRects; index++) { regionRect = &(meta->regionRects[index]); + if ((error = rdpgfx_read_rect16(s, regionRect))) { WLog_ERR(TAG, "rdpgfx_read_rect16 failed with error %"PRIu32"!", error); goto error_out; } - WLog_DBG(TAG, "regionRects[%"PRIu32"]: left: %"PRIu16" top: %"PRIu16" right: %"PRIu16" bottom: %"PRIu16"", - index, regionRect->left, regionRect->top, regionRect->right, regionRect->bottom); + + WLog_DBG(TAG, + "regionRects[%"PRIu32"]: left: %"PRIu16" top: %"PRIu16" right: %"PRIu16" bottom: %"PRIu16"", + index, regionRect->left, regionRect->top, regionRect->right, regionRect->bottom); } if (Stream_GetRemainingLength(s) < (meta->numRegionRects * 2)) @@ -107,12 +111,12 @@ static UINT rdpgfx_read_h264_metablock(RDPGFX_PLUGIN* gfx, wStream* s, quantQualityVal = &(meta->quantQualityVals[index]); Stream_Read_UINT8(s, quantQualityVal->qpVal); /* qpVal (1 byte) */ Stream_Read_UINT8(s, quantQualityVal->qualityVal); /* qualityVal (1 byte) */ - quantQualityVal->qp = quantQualityVal->qpVal & 0x3F; quantQualityVal->r = (quantQualityVal->qpVal >> 6) & 1; quantQualityVal->p = (quantQualityVal->qpVal >> 7) & 1; - WLog_DBG(TAG, "quantQualityVals[%"PRIu32"]: qp: %"PRIu8" r: %"PRIu8" p: %"PRIu8" qualityVal: %"PRIu8"", - index, quantQualityVal->qp, quantQualityVal->r, quantQualityVal->p, quantQualityVal->qualityVal); + WLog_DBG(TAG, + "quantQualityVals[%"PRIu32"]: qp: %"PRIu8" r: %"PRIu8" p: %"PRIu8" qualityVal: %"PRIu8"", + index, quantQualityVal->qp, quantQualityVal->r, quantQualityVal->p, quantQualityVal->qualityVal); } return CHANNEL_RC_OK; @@ -135,7 +139,6 @@ static UINT rdpgfx_decode_AVC420(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd wStream* s; RDPGFX_AVC420_BITMAP_STREAM h264; RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; - s = Stream_New(cmd->data, cmd->length); if (!s) @@ -152,21 +155,19 @@ static UINT rdpgfx_decode_AVC420(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd h264.data = Stream_Pointer(s); h264.length = (UINT32) Stream_GetRemainingLength(s); - Stream_Free(s, FALSE); - cmd->extra = (void*) &h264; if (context) { IFCALLRET(context->SurfaceCommand, error, context, cmd); + if (error) WLog_ERR(TAG, "context->SurfaceCommand failed with error %"PRIu32"", error); } free(h264.meta.regionRects); free(h264.meta.quantQualityVals); - return error; } @@ -183,7 +184,6 @@ static UINT rdpgfx_decode_AVC444(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd wStream* s; RDPGFX_AVC444_BITMAP_STREAM h264; RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; - s = Stream_New(cmd->data, cmd->length); if (!s) @@ -203,18 +203,20 @@ static UINT rdpgfx_decode_AVC444(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd return ERROR_INVALID_DATA; pos1 = Stream_GetPosition(s); + if ((error = rdpgfx_read_h264_metablock(gfx, s, &(h264.bitstream[0].meta)))) { WLog_ERR(TAG, "rdpgfx_read_h264_metablock failed with error %"PRIu32"!", error); return error; } - pos2 = Stream_GetPosition(s); + pos2 = Stream_GetPosition(s); h264.bitstream[0].data = Stream_Pointer(s); if (h264.LC == 0) { tmp = h264.cbAvc420EncodedBitstream1 - pos2 + pos1; + if (Stream_GetRemainingLength(s) < tmp) return ERROR_INVALID_DATA; @@ -237,12 +239,12 @@ static UINT rdpgfx_decode_AVC444(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd } Stream_Free(s, FALSE); - cmd->extra = (void*) &h264; if (context) { IFCALLRET(context->SurfaceCommand, error, context, cmd); + if (error) WLog_ERR(TAG, "context->SurfaceCommand failed with error %"PRIu32"", error); } @@ -251,7 +253,6 @@ static UINT rdpgfx_decode_AVC444(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd free(h264.bitstream[0].meta.quantQualityVals); free(h264.bitstream[1].meta.regionRects); free(h264.bitstream[1].meta.quantQualityVals); - return error; } @@ -264,34 +265,34 @@ UINT rdpgfx_decode(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd) { UINT error = CHANNEL_RC_OK; RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; + PROFILER_ENTER(context->SurfaceProfiler); switch (cmd->codecId) { case RDPGFX_CODECID_AVC420: if ((error = rdpgfx_decode_AVC420(gfx, cmd))) - { WLog_ERR(TAG, "rdpgfx_decode_AVC420 failed with error %"PRIu32"", error); - return error; - } + break; case RDPGFX_CODECID_AVC444: if ((error = rdpgfx_decode_AVC444(gfx, cmd))) - { WLog_ERR(TAG, "rdpgfx_decode_AVC444 failed with error %"PRIu32"", error); - return error; - } + break; default: if (context) { IFCALLRET(context->SurfaceCommand, error, context, cmd); + if (error) WLog_ERR(TAG, "context->SurfaceCommand failed with error %"PRIu32"", error); } + break; } + PROFILER_EXIT(context->SurfaceProfiler); return error; } diff --git a/include/freerdp/client/rdpgfx.h b/include/freerdp/client/rdpgfx.h index b7f391053..6fe5dc729 100644 --- a/include/freerdp/client/rdpgfx.h +++ b/include/freerdp/client/rdpgfx.h @@ -23,6 +23,7 @@ #define FREERDP_CHANNEL_CLIENT_RDPGFX_H #include +#include /** * Client Interface @@ -105,6 +106,8 @@ struct _rdpgfx_client_context pcRdpgfxGetCacheSlotData GetCacheSlotData; pcRdpgfxUpdateSurfaces UpdateSurfaces; + + PROFILER_DEFINE(SurfaceProfiler); }; #endif /* FREERDP_CHANNEL_CLIENT_RDPGFX_H */ diff --git a/libfreerdp/gdi/gfx.c b/libfreerdp/gdi/gfx.c index 6ea833fbe..1a0975431 100644 --- a/libfreerdp/gdi/gfx.c +++ b/libfreerdp/gdi/gfx.c @@ -1051,6 +1051,7 @@ void gdi_graphics_pipeline_init(rdpGdi* gdi, RdpgfxClientContext* gfx) gfx->MapSurfaceToOutput = gdi_MapSurfaceToOutput; gfx->MapSurfaceToWindow = gdi_MapSurfaceToWindow; gfx->UpdateSurfaces = gdi_UpdateSurfaces; + PROFILER_CREATE(gfx->SurfaceProfiler, "GFX-PROFILER"); } void gdi_graphics_pipeline_uninit(rdpGdi* gdi, RdpgfxClientContext* gfx) @@ -1058,5 +1059,9 @@ void gdi_graphics_pipeline_uninit(rdpGdi* gdi, RdpgfxClientContext* gfx) region16_uninit(&(gdi->invalidRegion)); gdi->gfx = NULL; gfx->custom = NULL; + PROFILER_PRINT_HEADER; + PROFILER_PRINT(gfx->SurfaceProfiler); + PROFILER_PRINT_FOOTER; + PROFILER_FREE(gfx->SurfaceProfiler); }