From f3e0c95d456508ea6f4ff0b829b0e28ffeffa706 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 19 Apr 2017 13:00:26 +0200 Subject: [PATCH] Added a GFX area update callback. --- include/freerdp/client/rdpgfx.h | 4 +++ libfreerdp/gdi/gfx.c | 80 ++++++++++++++++++++++++++--------------- 2 files changed, 56 insertions(+), 28 deletions(-) diff --git a/include/freerdp/client/rdpgfx.h b/include/freerdp/client/rdpgfx.h index 6fe5dc7..333f30e 100644 --- a/include/freerdp/client/rdpgfx.h +++ b/include/freerdp/client/rdpgfx.h @@ -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); }; diff --git a/libfreerdp/gdi/gfx.c b/libfreerdp/gdi/gfx.c index be30280..3f3d975 100644 --- a/libfreerdp/gdi/gfx.c +++ b/libfreerdp/gdi/gfx.c @@ -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; xinvalidRegion, &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; xinvalidRegion, &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; -- 2.7.4