progressive: fix multiple regions in one gfx frame.
authorVic Lee <llyzs.vic@gmail.com>
Thu, 4 Feb 2021 05:01:38 +0000 (13:01 +0800)
committerakallabeth <akallabeth@users.noreply.github.com>
Thu, 25 Feb 2021 08:51:41 +0000 (09:51 +0100)
(cherry picked from commit 7f94095a0670f6d0bc19021e6e1439cf934edf52)

include/freerdp/codec/progressive.h
include/freerdp/gdi/gdi.h
libfreerdp/codec/progressive.c
libfreerdp/codec/progressive.h
libfreerdp/codec/test/TestFreeRDPCodecProgressive.c
libfreerdp/gdi/gfx.c

index 37b289a..57a81f9 100644 (file)
@@ -46,7 +46,8 @@ extern "C"
        FREERDP_API INT32 progressive_decompress(PROGRESSIVE_CONTEXT* progressive, const BYTE* pSrcData,
                                                 UINT32 SrcSize, BYTE* pDstData, UINT32 DstFormat,
                                                 UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,
-                                                REGION16* invalidRegion, UINT16 surfaceId);
+                                                REGION16* invalidRegion, UINT16 surfaceId,
+                                                UINT32 frameId);
 
        FREERDP_API INT32 progressive_create_surface_context(PROGRESSIVE_CONTEXT* progressive,
                                                             UINT16 surfaceId, UINT32 width,
index ddb310b..790f5df 100644 (file)
@@ -520,6 +520,7 @@ struct rdp_gdi
        BOOL graphicsReset; /* deprecated, remove with FreeRDP v3 */
        BOOL suppressOutput;
        UINT16 outputSurfaceId;
+       UINT32 frameId;
        RdpgfxClientContext* gfx;
        VideoClientContext* video;
        GeometryClientContext* geometry;
index d67b11f..da2ac78 100644 (file)
@@ -396,6 +396,7 @@ static void progressive_surface_context_free(PROGRESSIVE_SURFACE_CONTEXT* surfac
        }
 
        free(surface->tiles);
+       free(surface->updatedTileIndices);
        free(surface);
 }
 
@@ -449,8 +450,9 @@ static PROGRESSIVE_SURFACE_CONTEXT* progressive_surface_context_new(UINT16 surfa
        surface->gridHeight = (height + (64 - height % 64)) / 64;
        surface->gridSize = surface->gridWidth * surface->gridHeight;
        surface->tiles = (RFX_PROGRESSIVE_TILE*)calloc(surface->gridSize, sizeof(RFX_PROGRESSIVE_TILE));
+       surface->updatedTileIndices = (UINT32*)calloc(surface->gridSize, sizeof(UINT32));
 
-       if (!surface->tiles)
+       if (!surface->tiles || !surface->updatedTileIndices)
        {
                free(surface);
                return NULL;
@@ -542,8 +544,14 @@ static BOOL progressive_surface_tile_replace(PROGRESSIVE_SURFACE_CONTEXT* surfac
                         region->numTiles, region->usedTiles);
                return FALSE;
        }
+       if (surface->numUpdatedTiles >= surface->gridSize)
+       {
+               WLog_ERR(TAG, "Invalid total tile count, maximum %" PRIu32, surface->gridSize);
+               return FALSE;
+       }
 
        region->tiles[region->usedTiles++] = t;
+       surface->updatedTileIndices[surface->numUpdatedTiles++] = (UINT32)zIdx;
        return TRUE;
 }
 
@@ -1732,7 +1740,7 @@ static INLINE int progressive_process_tiles(PROGRESSIVE_CONTEXT* progressive, wS
                }
        }
 
-       return (int)end - start;
+       return (int)(end - start);
 }
 
 static INLINE INT32 progressive_wb_sync(PROGRESSIVE_CONTEXT* progressive, wStream* s,
@@ -2146,10 +2154,11 @@ static INLINE INT32 progressive_wb_region(PROGRESSIVE_CONTEXT* progressive, wStr
 
 INT32 progressive_decompress(PROGRESSIVE_CONTEXT* progressive, const BYTE* pSrcData, UINT32 SrcSize,
                              BYTE* pDstData, UINT32 DstFormat, UINT32 nDstStep, UINT32 nXDst,
-                             UINT32 nYDst, REGION16* invalidRegion, UINT16 surfaceId)
+                             UINT32 nYDst, REGION16* invalidRegion, UINT16 surfaceId,
+                             UINT32 frameId)
 {
        INT32 rc = 1;
-       UINT16 i, j;
+       UINT32 i, j;
        UINT16 blockType;
        UINT32 blockLen;
        UINT32 count = 0;
@@ -2172,6 +2181,12 @@ INT32 progressive_decompress(PROGRESSIVE_CONTEXT* progressive, const BYTE* pSrcD
                return -1001;
        }
 
+       if (surface->frameId != frameId)
+       {
+               surface->frameId = frameId;
+               surface->numUpdatedTiles = 0;
+       }
+
        Stream_StaticInit(&ss, sconv.bp, SrcSize);
        s = &ss;
 
@@ -2274,12 +2289,12 @@ INT32 progressive_decompress(PROGRESSIVE_CONTEXT* progressive, const BYTE* pSrcD
                region16_union_rect(&clippingRects, &clippingRects, &clippingRect);
        }
 
-       for (i = 0; i < region->numTiles; i++)
+       for (i = 0; i < surface->numUpdatedTiles; i++)
        {
                UINT32 nbUpdateRects;
                const RECTANGLE_16* updateRects;
                RECTANGLE_16 updateRect;
-               RFX_PROGRESSIVE_TILE* tile = region->tiles[i];
+               RFX_PROGRESSIVE_TILE* tile = &surface->tiles[surface->updatedTileIndices[i]];
 
                updateRect.left = nXDst + tile->x;
                updateRect.top = nYDst + tile->y;
index 418af40..3b4469b 100644 (file)
@@ -200,6 +200,9 @@ struct _PROGRESSIVE_SURFACE_CONTEXT
        UINT32 gridHeight;
        UINT32 gridSize;
        RFX_PROGRESSIVE_TILE* tiles;
+       UINT32 frameId;
+       UINT32 numUpdatedTiles;
+       UINT32* updatedTileIndices;
 };
 typedef struct _PROGRESSIVE_SURFACE_CONTEXT PROGRESSIVE_SURFACE_CONTEXT;
 
index 54e3e83..f9ab7b6 100644 (file)
@@ -839,8 +839,9 @@ static int test_progressive_decode(PROGRESSIVE_CONTEXT* progressive, EGFX_SAMPLE
 
        for (pass = 0; pass < count; pass++)
        {
-               status = progressive_decompress(progressive, files[pass].buffer, files[pass].size,
-                                               g_DstData, PIXEL_FORMAT_XRGB32, g_DstStep, 0, 0, NULL, 0);
+               status =
+                   progressive_decompress(progressive, files[pass].buffer, files[pass].size, g_DstData,
+                                          PIXEL_FORMAT_XRGB32, g_DstStep, 0, 0, NULL, 0, 0);
                printf("ProgressiveDecompress: status: %d pass: %d\n", status, pass + 1);
                region = &(progressive->region);
 
@@ -1077,7 +1078,7 @@ static BOOL test_encode_decode(const char* path)
                goto fail;
 
        rc = progressive_decompress(progressiveDec, dstData, dstSize, resultData, ColorFormat,
-                                   image->scanline, 0, 0, &invalidRegion, 0);
+                                   image->scanline, 0, 0, &invalidRegion, 0, 0);
        if (rc < 0)
                goto fail;
 
index c210332..3d50c80 100644 (file)
@@ -221,6 +221,7 @@ static UINT gdi_StartFrame(RdpgfxClientContext* context, const RDPGFX_START_FRAM
 {
        rdpGdi* gdi = (rdpGdi*)context->custom;
        gdi->inGfxFrame = TRUE;
+       gdi->frameId = startFrame->frameId;
        return CHANNEL_RC_OK;
 }
 
@@ -826,7 +827,7 @@ static UINT gdi_SurfaceCommand_Progressive(rdpGdi* gdi, RdpgfxClientContext* con
        region16_init(&invalidRegion);
        rc = progressive_decompress(surface->codecs->progressive, cmd->data, cmd->length, surface->data,
                                    surface->format, surface->scanline, cmd->left, cmd->top,
-                                   &invalidRegion, cmd->surfaceId);
+                                   &invalidRegion, cmd->surfaceId, gdi->frameId);
 
        if (rc < 0)
        {