From 68b3d0476bd54b4ccc7f71362687df02e327338f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 19 Aug 2014 14:48:09 -0400 Subject: [PATCH] libfreerdp-codec: start work on progressive inverse DWT --- client/X11/xf_gfx.c | 67 +++++++++++--- include/freerdp/codec/progressive.h | 6 ++ libfreerdp/codec/progressive.c | 131 ++++++++++++++++++++++++++++ libfreerdp/codec/rfx_decode.c | 4 +- libfreerdp/codec/rfx_dwt.c | 12 +-- libfreerdp/codec/rfx_sse2.c | 6 +- 6 files changed, 203 insertions(+), 23 deletions(-) diff --git a/client/X11/xf_gfx.c b/client/X11/xf_gfx.c index b99fd5e37..823e1fce8 100644 --- a/client/X11/xf_gfx.c +++ b/client/X11/xf_gfx.c @@ -477,10 +477,21 @@ int xf_SurfaceCommand_Alpha(xfContext* xfc, RdpgfxClientContext* context, RDPGFX int xf_SurfaceCommand_Progressive(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd) { - int status = 0; - BYTE* DstData = NULL; + int i, j; + int status; + BYTE* DstData; + RFX_RECT* rect; + int nXDst, nYDst; + int nWidth, nHeight; + int nbUpdateRects; xfGfxSurface* surface; - RECTANGLE_16 invalidRect; + REGION16 updateRegion; + RECTANGLE_16 updateRect; + RECTANGLE_16* updateRects; + REGION16 clippingRects; + RECTANGLE_16 clippingRect; + RFX_PROGRESSIVE_TILE* tile; + PROGRESSIVE_BLOCK_REGION* region; surface = (xfGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId); @@ -500,17 +511,51 @@ int xf_SurfaceCommand_Progressive(xfContext* xfc, RdpgfxClientContext* context, printf("xf_SurfaceCommand_Progressive: status: %d\n", status); - /* fill with blue for now to distinguish from the rest */ + region = &(xfc->progressive->region); - freerdp_image_fill(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, - cmd->left, cmd->top, cmd->width, cmd->height, 0x0000FF); + region16_init(&clippingRects); - invalidRect.left = cmd->left; - invalidRect.top = cmd->top; - invalidRect.right = cmd->right; - invalidRect.bottom = cmd->bottom; + for (i = 0; i < region->numRects; i++) + { + rect = &(region->rects[i]); - region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect); + clippingRect.left = cmd->left + rect->x; + clippingRect.top = cmd->top + rect->y; + clippingRect.right = clippingRect.left + rect->width; + clippingRect.bottom = clippingRect.top + rect->height; + + region16_union_rect(&clippingRects, &clippingRects, &clippingRect); + } + + for (i = 0; i < region->numTiles; i++) + { + tile = &(region->tiles[i]); + + updateRect.left = cmd->left + tile->x; + updateRect.top = cmd->top + tile->y; + updateRect.right = updateRect.left + 64; + updateRect.bottom = updateRect.top + 64; + + region16_init(&updateRegion); + region16_intersect_rect(&updateRegion, &clippingRects, &updateRect); + updateRects = (RECTANGLE_16*) region16_rects(&updateRegion, &nbUpdateRects); + + for (j = 0; j < nbUpdateRects; j++) + { + nXDst = updateRects[j].left; + nYDst = updateRects[j].top; + nWidth = updateRects[j].right - updateRects[j].left; + nHeight = updateRects[j].bottom - updateRects[j].top; + + freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, + nXDst, nYDst, nWidth, nHeight, + tile->data, PIXEL_FORMAT_XRGB32, 64 * 4, 0, 0); + + region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &updateRects[j]); + } + + region16_uninit(&updateRegion); + } if (!xfc->inGfxFrame) xf_OutputUpdate(xfc); diff --git a/include/freerdp/codec/progressive.h b/include/freerdp/codec/progressive.h index e22ab10fc..c94d2b876 100644 --- a/include/freerdp/codec/progressive.h +++ b/include/freerdp/codec/progressive.h @@ -205,6 +205,12 @@ struct _RFX_PROGRESSIVE_TILE BYTE* cbRawData; BYTE* crSrlData; BYTE* crRawData; + + int x; + int y; + int width; + int height; + BYTE* data; }; typedef struct _RFX_PROGRESSIVE_TILE RFX_PROGRESSIVE_TILE; diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index c36b29a8a..08b3268c1 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -94,10 +94,106 @@ const char* progressive_get_block_type_string(UINT16 blockType) * LL3 4015 9x9 81 */ +static void progressive_rfx_dwt_2d_decode_block(INT16* buffer, INT16* dwt, int N) +{ + int N2; + int x, y, k; + INT16 *dst, *l, *h; + INT16 *l_dst, *h_dst; + INT16 *HL, *LH, *HH, *LL; + + N2 = N << 1; + + /* Inverse DWT in horizontal direction, results in 2 sub-bands in L, H order in tmp buffer idwt. */ + /* The 4 sub-bands are stored in HL(0), LH(1), HH(2), LL(3) order. */ + /* The lower part L uses LL(3) and HL(0). */ + /* The higher part H uses LH(1) and HH(2). */ + + LL = &buffer[(N * N) * 3]; + HL = &buffer[0]; + l_dst = &dwt[0]; + + LH = &buffer[N * N]; + HH = &buffer[(N * N) * 2]; + h_dst = &dwt[(N * N) * 2]; + + for (y = 0; y < N; y++) + { + /* Even coefficients */ + l_dst[0] = LL[0] - ((HL[0] + HL[0] + 1) >> 1); + h_dst[0] = LH[0] - ((HH[0] + HH[0] + 1) >> 1); + + for (k = 1; k < N; k++) + { + x = k << 1; + l_dst[x] = LL[k] - ((HL[k-1] + HL[k] + 1) >> 1); + h_dst[x] = LH[k] - ((HH[k-1] + HH[k] + 1) >> 1); + } + + /* Odd coefficients */ + for (k = 0; k < N-1; k++) + { + x = k << 1; + l_dst[x + 1] = (HL[k] << 1) + ((l_dst[x] + l_dst[x + 2]) >> 1); + h_dst[x + 1] = (HH[k] << 1) + ((h_dst[x] + h_dst[x + 2]) >> 1); + } + + x = k << 1; + l_dst[x + 1] = (HL[k] << 1) + (l_dst[x]); + h_dst[x + 1] = (HH[k] << 1) + (h_dst[x]); + + LL += N; + HL += N; + l_dst += N2; + + LH += N; + HH += N; + h_dst += N2; + } + + /* Inverse DWT in vertical direction, results are stored in original buffer. */ + for (x = 0; x < N2; x++) + { + /* Even coefficients */ + for (k = 0; k < N; k++) + { + y = k << 1; + dst = buffer + y * N2 + x; + l = dwt + k * N2 + x; + h = l + N * N2; + dst[0] = *l - (((k > 0 ? *(h - N2) : *h) + (*h) + 1) >> 1); + } + + /* Odd coefficients */ + for (k = 0; k < N; k++) + { + y = k << 1; + dst = buffer + y * N2 + x; + l = dwt + k * N2 + x; + h = l + N * N2; + dst[N2] = (*h << 1) + ((dst[0] + dst[k < N - 1 ? 2 * N2 : 0]) >> 1); + } + } +} + +void progressive_rfx_dwt_2d_decode(INT16* buffer, INT16* dwt) +{ +#if 0 + progressive_rfx_dwt_2d_decode_block(&buffer[3807], dwt, 8); + progressive_rfx_dwt_2d_decode_block(&buffer[3007], dwt, 16); + //progressive_rfx_dwt_2d_decode_block(&buffer[0], dwt, 32); +#else + progressive_rfx_dwt_2d_decode_block(&buffer[3840], dwt, 8); + progressive_rfx_dwt_2d_decode_block(&buffer[3072], dwt, 16); + progressive_rfx_dwt_2d_decode_block(&buffer[0], dwt, 32); +#endif +} + int progressive_rfx_decode_component(PROGRESSIVE_CONTEXT* progressive, RFX_COMPONENT_CODEC_QUANT* quant, const BYTE* data, int length, INT16* buffer) { int status; + INT16* dwt; const primitives_t* prims = primitives_get(); status = rfx_rlgr_decode(data, length, buffer, 4096, 1); @@ -118,6 +214,12 @@ int progressive_rfx_decode_component(PROGRESSIVE_CONTEXT* progressive, rfx_quantization_decode_block(prims, &buffer[3951], 64, (quant->HH3 - 1)); /* HH3 */ rfx_quantization_decode_block(prims, &buffer[4015], 81, (quant->LL3 - 1)); /* LL3 */ + dwt = (INT16*) BufferPool_Take(progressive->bufferPool, -1); /* DWT buffer */ + + progressive_rfx_dwt_2d_decode(buffer, dwt); + + BufferPool_Return(progressive->bufferPool, dwt); + return 1; } @@ -130,6 +232,8 @@ int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progressive, RFX_PROG RFX_COMPONENT_CODEC_QUANT* quantCb; RFX_COMPONENT_CODEC_QUANT* quantCr; RFX_PROGRESSIVE_CODEC_QUANT* quantProgVal; + static const prim_size_t roi_64x64 = { 64, 64 }; + const primitives_t* prims = primitives_get(); printf("ProgressiveTileFirst: quantIdx Y: %d Cb: %d Cr: %d xIdx: %d yIdx: %d flags: %d quality: %d yLen: %d cbLen: %d crLen: %d tailLen: %d\n", tile->quantIdxY, tile->quantIdxCb, tile->quantIdxCr, tile->xIdx, tile->yIdx, tile->flags, tile->quality, tile->yLen, tile->cbLen, tile->crLen, tile->tailLen); @@ -164,6 +268,7 @@ int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progressive, RFX_PROG } pBuffer = (BYTE*) BufferPool_Take(progressive->bufferPool, -1); + pSrcDst[0] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 0) + 16])); /* Y/R buffer */ pSrcDst[1] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 1) + 16])); /* Cb/G buffer */ pSrcDst[2] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 2) + 16])); /* Cr/B buffer */ @@ -172,6 +277,17 @@ int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progressive, RFX_PROG progressive_rfx_decode_component(progressive, quantCb, tile->cbData, tile->cbLen, pSrcDst[1]); /* Cb */ progressive_rfx_decode_component(progressive, quantCr, tile->crData, tile->crLen, pSrcDst[2]); /* Cr */ + prims->yCbCrToRGB_16s16s_P3P3((const INT16**) pSrcDst, 64 * sizeof(INT16), + pSrcDst, 64 * sizeof(INT16), &roi_64x64); + + if (!tile->data) + { + tile->data = _aligned_malloc(64 * 64 * 4, 16); + } + + prims->RGBToRGB_16s8u_P3AC4R((const INT16**) pSrcDst, 64 * sizeof(INT16), + tile->data, 64 * 4, &roi_64x64); + BufferPool_Return(progressive->bufferPool, pBuffer); return 1; @@ -296,6 +412,11 @@ int progressive_process_tiles(PROGRESSIVE_CONTEXT* progressive, BYTE* blocks, UI tile->tailData = &block[boffset]; boffset += tile->tailLen; + tile->width = 64; + tile->height = 64; + tile->x = tile->xIdx * 64; + tile->y = tile->yIdx * 64; + break; case PROGRESSIVE_WBT_TILE_FIRST: @@ -340,6 +461,11 @@ int progressive_process_tiles(PROGRESSIVE_CONTEXT* progressive, BYTE* blocks, UI tile->tailData = &block[boffset]; boffset += tile->tailLen; + tile->width = 64; + tile->height = 64; + tile->x = tile->xIdx * 64; + tile->y = tile->yIdx * 64; + break; case PROGRESSIVE_WBT_TILE_UPGRADE: @@ -397,6 +523,11 @@ int progressive_process_tiles(PROGRESSIVE_CONTEXT* progressive, BYTE* blocks, UI tile->crRawData = &block[boffset]; boffset += tile->crRawLen; + tile->width = 64; + tile->height = 64; + tile->x = tile->xIdx * 64; + tile->y = tile->yIdx * 64; + break; default: diff --git a/libfreerdp/codec/rfx_decode.c b/libfreerdp/codec/rfx_decode.c index d3baf5462..d14aff8a2 100644 --- a/libfreerdp/codec/rfx_decode.c +++ b/libfreerdp/codec/rfx_decode.c @@ -38,7 +38,7 @@ #include "rfx_decode.h" /* stride is bytes between rows in the output buffer. */ -static void rfx_decode_format_rgb(INT16* r_buf, INT16* g_buf, INT16* b_buf, +void rfx_decode_format_rgb(INT16* r_buf, INT16* g_buf, INT16* b_buf, RDP_PIXEL_FORMAT pixel_format, BYTE* dst_buf, int stride) { primitives_t *prims = primitives_get(); @@ -146,9 +146,7 @@ BOOL rfx_decode_rgb(RFX_CONTEXT* context, RFX_TILE* tile, BYTE* rgb_buffer, int pSrcDst[2] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 2) + 16])); /* cr_b_buffer */ rfx_decode_component(context, y_quants, tile->YData, tile->YLen, pSrcDst[0]); /* YData */ - rfx_decode_component(context, cb_quants, tile->CbData, tile->CbLen, pSrcDst[1]); /* CbData */ - rfx_decode_component(context, cr_quants, tile->CrData, tile->CrLen, pSrcDst[2]); /* CrData */ PROFILER_ENTER(context->priv->prof_rfx_ycbcr_to_rgb); diff --git a/libfreerdp/codec/rfx_dwt.c b/libfreerdp/codec/rfx_dwt.c index 0b8448b9e..7e3b3ccc4 100644 --- a/libfreerdp/codec/rfx_dwt.c +++ b/libfreerdp/codec/rfx_dwt.c @@ -110,9 +110,9 @@ static void rfx_dwt_2d_decode_block(INT16* buffer, INT16* idwt, int subband_widt void rfx_dwt_2d_decode(INT16* buffer, INT16* dwt_buffer) { - rfx_dwt_2d_decode_block(buffer + 3840, dwt_buffer, 8); - rfx_dwt_2d_decode_block(buffer + 3072, dwt_buffer, 16); - rfx_dwt_2d_decode_block(buffer, dwt_buffer, 32); + rfx_dwt_2d_decode_block(&buffer[3840], dwt_buffer, 8); + rfx_dwt_2d_decode_block(&buffer[3072], dwt_buffer, 16); + rfx_dwt_2d_decode_block(&buffer[0], dwt_buffer, 32); } static void rfx_dwt_2d_encode_block(INT16* buffer, INT16* dwt, int subband_width) @@ -192,7 +192,7 @@ static void rfx_dwt_2d_encode_block(INT16* buffer, INT16* dwt, int subband_width void rfx_dwt_2d_encode(INT16* buffer, INT16* dwt_buffer) { - rfx_dwt_2d_encode_block(buffer, dwt_buffer, 32); - rfx_dwt_2d_encode_block(buffer + 3072, dwt_buffer, 16); - rfx_dwt_2d_encode_block(buffer + 3840, dwt_buffer, 8); + rfx_dwt_2d_encode_block(&buffer[0], dwt_buffer, 32); + rfx_dwt_2d_encode_block(&buffer[3072], dwt_buffer, 16); + rfx_dwt_2d_encode_block(&buffer[3840], dwt_buffer, 8); } diff --git a/libfreerdp/codec/rfx_sse2.c b/libfreerdp/codec/rfx_sse2.c index 4f54d17cd..f89efe81e 100644 --- a/libfreerdp/codec/rfx_sse2.c +++ b/libfreerdp/codec/rfx_sse2.c @@ -340,9 +340,9 @@ static void rfx_dwt_2d_decode_sse2(INT16* buffer, INT16* dwt_buffer) { _mm_prefetch_buffer((char*) buffer, 4096 * sizeof(INT16)); - rfx_dwt_2d_decode_block_sse2(buffer + 3840, dwt_buffer, 8); - rfx_dwt_2d_decode_block_sse2(buffer + 3072, dwt_buffer, 16); - rfx_dwt_2d_decode_block_sse2(buffer, dwt_buffer, 32); + rfx_dwt_2d_decode_block_sse2(&buffer[3840], dwt_buffer, 8); + rfx_dwt_2d_decode_block_sse2(&buffer[3072], dwt_buffer, 16); + rfx_dwt_2d_decode_block_sse2(&buffer[0], dwt_buffer, 32); } static __inline void __attribute__((ATTRIBUTES))