Added a GFX area update callback.
authorArmin Novak <armin.novak@thincast.com>
Wed, 19 Apr 2017 11:00:26 +0000 (13:00 +0200)
committerArmin Novak <armin.novak@thincast.com>
Wed, 3 May 2017 06:48:03 +0000 (08:48 +0200)
include/freerdp/client/rdpgfx.h
libfreerdp/gdi/gfx.c

index 6fe5dc7..333f30e 100644 (file)
@@ -77,6 +77,9 @@ typedef void* (*pcRdpgfxGetCacheSlotData)(RdpgfxClientContext* context,
 
 typedef UINT(*pcRdpgfxUpdateSurfaces)(RdpgfxClientContext* context);
 
+typedef UINT(*pcRdpgfxUpdateSurfaceArea)(RdpgfxClientContext* context, UINT16 surfaceId,
+                                         UINT32 nrRects, const RECTANGLE_16* rects);
+
 struct _rdpgfx_client_context
 {
        void* handle;
@@ -106,6 +109,7 @@ struct _rdpgfx_client_context
        pcRdpgfxGetCacheSlotData GetCacheSlotData;
 
        pcRdpgfxUpdateSurfaces UpdateSurfaces;
+       pcRdpgfxUpdateSurfaceArea UpdateSurfaceArea;
 
        PROFILER_DEFINE(SurfaceProfiler);
 };
index be30280..3f3d975 100644 (file)
@@ -113,7 +113,7 @@ static UINT gdi_OutputUpdate(rdpGdi* gdi, gdiGfxSurface* surface)
                                &(surface->invalidRegion), &surfaceRect);
 
        if (!(rects = region16_rects(&surface->invalidRegion, &nbRects)) || !nbRects)
-               return CHANNEL_RC_OK;
+                return CHANNEL_RC_OK;
 
        update->BeginPaint(gdi->context);
 
@@ -137,6 +137,7 @@ static UINT gdi_OutputUpdate(rdpGdi* gdi, gdiGfxSurface* surface)
        }
 
        update->EndPaint(gdi->context);
+
        region16_clear(&(surface->invalidRegion));
        return CHANNEL_RC_OK;
 }
@@ -212,12 +213,11 @@ static UINT gdi_SurfaceCommand_Uncompressed(rdpGdi* gdi,
        UINT status = CHANNEL_RC_OK;
        gdiGfxSurface* surface;
        RECTANGLE_16 invalidRect;
-       surface = (gdiGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);
 
+       surface = (gdiGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);
        if (!surface)
        {
-               WLog_ERR(TAG, "%s: unable to retrieve surfaceData for surfaceId=%"PRIu32"", __FUNCTION__,
-                        cmd->surfaceId);
+               WLog_ERR(TAG, "%s: unable to retrieve surfaceData for surfaceId=%"PRIu32"", __FUNCTION__, cmd->surfaceId);
                return ERROR_NOT_FOUND;
        }
 
@@ -253,26 +253,36 @@ static UINT gdi_SurfaceCommand_RemoteFX(rdpGdi* gdi,
 {
        UINT status = CHANNEL_RC_OK;
        gdiGfxSurface* surface;
-       surface = (gdiGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);
+       REGION16 invalidRegion;
+       const RECTANGLE_16* rects;
+       UINT32 nrRects, x;
 
+       surface = (gdiGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);
        if (!surface)
        {
-               WLog_ERR(TAG, "%s: unable to retrieve surfaceData for surfaceId=%"PRIu32"", __FUNCTION__,
-                        cmd->surfaceId);
+               WLog_ERR(TAG, "%s: unable to retrieve surfaceData for surfaceId=%"PRIu32"", __FUNCTION__, cmd->surfaceId);
                return ERROR_NOT_FOUND;
        }
 
        rfx_context_set_pixel_format(surface->codecs->rfx, cmd->format);
 
+       region16_init(&invalidRegion);
        if (!rfx_process_message(surface->codecs->rfx, cmd->data, cmd->length,
                                 cmd->left, cmd->top,
                                 surface->data, surface->format, surface->scanline,
-                                surface->height, &surface->invalidRegion))
+                                surface->height, &invalidRegion))
        {
                WLog_ERR(TAG, "Failed to process RemoteFX message");
+               region16_uninit(&invalidRegion);
                return ERROR_INTERNAL_ERROR;
        }
 
+       rects = region16_rects(&invalidRegion, &nrRects);
+       region16_uninit(&invalidRegion);
+       IFCALL(context->UpdateSurfaceArea, context, surface->surfaceId, nrRects, rects);
+
+       for (x=0; x<nrRects; x++)
+               region16_union_rect(&surface->invalidRegion, &surface->invalidRegion, &rects[x]);
        if (!gdi->inGfxFrame)
        {
                status = CHANNEL_RC_NOT_INITIALIZED;
@@ -295,12 +305,11 @@ static UINT gdi_SurfaceCommand_ClearCodec(rdpGdi* gdi,
        UINT status = CHANNEL_RC_OK;
        gdiGfxSurface* surface;
        RECTANGLE_16 invalidRect;
-       surface = (gdiGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);
 
+       surface = (gdiGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);
        if (!surface)
        {
-               WLog_ERR(TAG, "%s: unable to retrieve surfaceData for surfaceId=%"PRIu32"", __FUNCTION__,
-                        cmd->surfaceId);
+               WLog_ERR(TAG, "%s: unable to retrieve surfaceData for surfaceId=%"PRIu32"", __FUNCTION__, cmd->surfaceId);
                return ERROR_NOT_FOUND;
        }
 
@@ -322,6 +331,7 @@ static UINT gdi_SurfaceCommand_ClearCodec(rdpGdi* gdi,
        invalidRect.bottom = cmd->bottom;
        region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion),
                            &invalidRect);
+       IFCALL(context->UpdateSurfaceArea, context, surface->surfaceId, 1, &invalidRect);
 
        if (!gdi->inGfxFrame)
        {
@@ -344,12 +354,11 @@ static UINT gdi_SurfaceCommand_Planar(rdpGdi* gdi, RdpgfxClientContext* context,
        BYTE* DstData = NULL;
        gdiGfxSurface* surface;
        RECTANGLE_16 invalidRect;
-       surface = (gdiGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);
 
+       surface = (gdiGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);
        if (!surface)
        {
-               WLog_ERR(TAG, "%s: unable to retrieve surfaceData for surfaceId=%"PRIu32"", __FUNCTION__,
-                        cmd->surfaceId);
+               WLog_ERR(TAG, "%s: unable to retrieve surfaceData for surfaceId=%"PRIu32"", __FUNCTION__, cmd->surfaceId);
                return ERROR_NOT_FOUND;
        }
 
@@ -368,6 +377,7 @@ static UINT gdi_SurfaceCommand_Planar(rdpGdi* gdi, RdpgfxClientContext* context,
        invalidRect.bottom = cmd->bottom;
        region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion),
                            &invalidRect);
+       IFCALL(context->UpdateSurfaceArea, context, surface->surfaceId, 1, &invalidRect);
 
        if (!gdi->inGfxFrame)
        {
@@ -393,12 +403,11 @@ static UINT gdi_SurfaceCommand_AVC420(rdpGdi* gdi,
        gdiGfxSurface* surface;
        RDPGFX_H264_METABLOCK* meta;
        RDPGFX_AVC420_BITMAP_STREAM* bs;
-       surface = (gdiGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);
 
+       surface = (gdiGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);
        if (!surface)
        {
-               WLog_ERR(TAG, "%s: unable to retrieve surfaceData for surfaceId=%"PRIu32"", __FUNCTION__,
-                        cmd->surfaceId);
+               WLog_ERR(TAG, "%s: unable to retrieve surfaceData for surfaceId=%"PRIu32"", __FUNCTION__, cmd->surfaceId);
                return ERROR_NOT_FOUND;
        }
 
@@ -425,6 +434,8 @@ static UINT gdi_SurfaceCommand_AVC420(rdpGdi* gdi,
                region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion),
                                    (RECTANGLE_16*) & (meta->regionRects[i]));
        }
+       IFCALL(context->UpdateSurfaceArea, context, surface->surfaceId,
+              meta->numRegionRects, meta->regionRects);
 
        if (!gdi->inGfxFrame)
        {
@@ -453,12 +464,11 @@ static UINT gdi_SurfaceCommand_AVC444(rdpGdi* gdi, RdpgfxClientContext* context,
        RDPGFX_AVC420_BITMAP_STREAM* avc2;
        RDPGFX_H264_METABLOCK* meta2;
        RECTANGLE_16* regionRects = NULL;
-       surface = (gdiGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);
 
+       surface = (gdiGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);
        if (!surface)
        {
-               WLog_ERR(TAG, "%s: unable to retrieve surfaceData for surfaceId=%"PRIu32"", __FUNCTION__,
-                        cmd->surfaceId);
+               WLog_ERR(TAG, "%s: unable to retrieve surfaceData for surfaceId=%"PRIu32"", __FUNCTION__, cmd->surfaceId);
                return ERROR_NOT_FOUND;
        }
 
@@ -492,6 +502,8 @@ static UINT gdi_SurfaceCommand_AVC444(rdpGdi* gdi, RdpgfxClientContext* context,
                                    &(surface->invalidRegion),
                                    &(meta1->regionRects[i]));
        }
+       IFCALL(context->UpdateSurfaceArea, context, surface->surfaceId,
+              meta1->numRegionRects, meta1->regionRects);
 
        for (i = 0; i < meta2->numRegionRects; i++)
        {
@@ -499,6 +511,8 @@ static UINT gdi_SurfaceCommand_AVC444(rdpGdi* gdi, RdpgfxClientContext* context,
                                    &(surface->invalidRegion),
                                    &(meta2->regionRects[i]));
        }
+       IFCALL(context->UpdateSurfaceArea, context, surface->surfaceId,
+              meta2->numRegionRects, meta2->regionRects);
 
        if (!gdi->inGfxFrame)
        {
@@ -522,12 +536,11 @@ static UINT gdi_SurfaceCommand_Alpha(rdpGdi* gdi, RdpgfxClientContext* context,
        UINT32 color;
        gdiGfxSurface* surface;
        RECTANGLE_16 invalidRect;
-       surface = (gdiGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);
 
+       surface = (gdiGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);
        if (!surface)
        {
-               WLog_ERR(TAG, "%s: unable to retrieve surfaceData for surfaceId=%"PRIu32"", __FUNCTION__,
-                        cmd->surfaceId);
+               WLog_ERR(TAG, "%s: unable to retrieve surfaceData for surfaceId=%"PRIu32"", __FUNCTION__, cmd->surfaceId);
                return ERROR_NOT_FOUND;
        }
 
@@ -546,6 +559,7 @@ static UINT gdi_SurfaceCommand_Alpha(rdpGdi* gdi, RdpgfxClientContext* context,
        region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion),
                            &invalidRect);
 
+       IFCALL(context->UpdateSurfaceArea, context, surface->surfaceId, 1, &invalidRect);
        if (!gdi->inGfxFrame)
        {
                status = CHANNEL_RC_NOT_INITIALIZED;
@@ -567,17 +581,20 @@ static UINT gdi_SurfaceCommand_Progressive(rdpGdi* gdi,
        INT32 rc;
        UINT status = CHANNEL_RC_OK;
        gdiGfxSurface* surface;
+       REGION16 invalidRegion;
+       const RECTANGLE_16* rects;
+       UINT32 nrRects, x;
+
        /**
         * Note: Since this comes via a Wire-To-Surface-2 PDU the
         * cmd's top/left/right/bottom/width/height members are always zero!
         * The update region is determined during decompression.
         */
-       surface = (gdiGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);
 
+       surface = (gdiGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);
        if (!surface)
        {
-               WLog_ERR(TAG, "%s: unable to retrieve surfaceData for surfaceId=%"PRIu32"", __FUNCTION__,
-                        cmd->surfaceId);
+               WLog_ERR(TAG, "%s: unable to retrieve surfaceData for surfaceId=%"PRIu32"", __FUNCTION__, cmd->surfaceId);
                return ERROR_NOT_FOUND;
        }
 
@@ -591,16 +608,24 @@ static UINT gdi_SurfaceCommand_Progressive(rdpGdi* gdi,
                return ERROR_INTERNAL_ERROR;
        }
 
+       region16_init(&invalidRegion);
        rc = progressive_decompress(surface->codecs->progressive, cmd->data,
                                    cmd->length, surface->data, surface->format,
                                    surface->scanline, cmd->left, cmd->top,
-                                   &surface->invalidRegion, cmd->surfaceId);
+                                   &invalidRegion, cmd->surfaceId);
 
        if (rc < 0)
        {
                WLog_ERR(TAG, "progressive_decompress failure: %"PRId32"", rc);
+               region16_uninit(&invalidRegion);
                return ERROR_INTERNAL_ERROR;
        }
+       rects = region16_rects(&invalidRegion, &nrRects);
+       region16_uninit(&invalidRegion);
+       IFCALL(context->UpdateSurfaceArea, context, surface->surfaceId, nrRects, rects);
+
+       for (x=0; x<nrRects; x++)
+               region16_union_rect(&surface->invalidRegion, &surface->invalidRegion, &rects[x]);
 
        if (!gdi->inGfxFrame)
        {
@@ -655,7 +680,6 @@ static UINT gdi_SurfaceCommand(RdpgfxClientContext* context,
                        status = gdi_SurfaceCommand_AVC420(gdi, context, cmd);
                        break;
 
-               case RDPGFX_CODECID_AVC444v2:
                case RDPGFX_CODECID_AVC444:
                        status = gdi_SurfaceCommand_AVC444(gdi, context, cmd);
                        break;