22#include <freerdp/config.h> 
   24#include "../core/update.h" 
   26#include <winpr/assert.h> 
   27#include <winpr/cast.h> 
   29#include <freerdp/api.h> 
   30#include <freerdp/log.h> 
   31#include <freerdp/gdi/gfx.h> 
   32#include <freerdp/gdi/region.h> 
   33#include <freerdp/utils/gfx.h> 
   36#define TAG FREERDP_TAG("gdi") 
   38static BOOL is_rect_valid(
const RECTANGLE_16* rect, 
size_t width, 
size_t height)
 
   42  if ((rect->left > rect->right) || (rect->right > width))
 
   44  if ((rect->top > rect->bottom) || (rect->bottom > height))
 
   54  rect.left = (UINT16)MIN(UINT16_MAX, cmd->left);
 
   55  rect.top = (UINT16)MIN(UINT16_MAX, cmd->top);
 
   56  rect.right = (UINT16)MIN(UINT16_MAX, cmd->right);
 
   57  rect.bottom = (UINT16)MIN(UINT16_MAX, cmd->bottom);
 
   58  if (!is_rect_valid(&rect, surface->width, surface->height))
 
   61             "Command rect %" PRIu32 
"x%" PRIu32 
"-%" PRIu32 
"x%" PRIu32
 
   62             " not within bounds of %" PRIu32 
"x%" PRIu32,
 
   63             rect.left, rect.top, cmd->width, cmd->height, surface->width, surface->height);
 
   70static DWORD gfx_align_scanline(DWORD widthInBytes, DWORD alignment)
 
   72  const UINT32 align = alignment;
 
   73  const UINT32 pad = align - (widthInBytes % alignment);
 
   74  UINT32 scanline = widthInBytes;
 
   87static UINT gdi_ResetGraphics(RdpgfxClientContext* context,
 
   90  UINT rc = ERROR_INTERNAL_ERROR;
 
   92  UINT32 DesktopWidth = 0;
 
   93  UINT32 DesktopHeight = 0;
 
   94  UINT16* pSurfaceIds = NULL;
 
   96  rdpUpdate* update = NULL;
 
   97  rdpSettings* settings = NULL;
 
   99  WINPR_ASSERT(context);
 
  100  WINPR_ASSERT(resetGraphics);
 
  102  gdi = (rdpGdi*)context->custom;
 
  105  update = gdi->context->update;
 
  106  WINPR_ASSERT(update);
 
  108  settings = gdi->context->settings;
 
  109  WINPR_ASSERT(settings);
 
  110  EnterCriticalSection(&context->mux);
 
  111  DesktopWidth = resetGraphics->width;
 
  112  DesktopHeight = resetGraphics->height;
 
  121    WINPR_ASSERT(update->DesktopResize);
 
  122    update->DesktopResize(gdi->context);
 
  125  WINPR_ASSERT(context->GetSurfaceIds);
 
  126  context->GetSurfaceIds(context, &pSurfaceIds, &count);
 
  128  for (UINT32 index = 0; index < count; index++)
 
  130    WINPR_ASSERT(context->GetSurfaceData);
 
  131    gdiGfxSurface* surface =
 
  132        (gdiGfxSurface*)context->GetSurfaceData(context, pSurfaceIds[index]);
 
  137    memset(surface->data, 0xFF, (
size_t)surface->scanline * surface->height);
 
  138    region16_clear(&surface->invalidRegion);
 
  145    const UINT32 width = (UINT32)MAX(0, gdi->width);
 
  146    const UINT32 height = (UINT32)MAX(0, gdi->height);
 
  148    if (!freerdp_client_codecs_reset(
 
  153    if (!freerdp_client_codecs_reset(
 
  162  LeaveCriticalSection(&context->mux);
 
  166static UINT gdi_OutputUpdate(rdpGdi* gdi, gdiGfxSurface* surface)
 
  168  UINT rc = ERROR_INTERNAL_ERROR;
 
  174  rdpUpdate* update = NULL;
 
  177  WINPR_ASSERT(gdi->context);
 
  178  WINPR_ASSERT(surface);
 
  180  update = gdi->context->update;
 
  181  WINPR_ASSERT(update);
 
  183  if (gdi->suppressOutput)
 
  184    return CHANNEL_RC_OK;
 
  186  surfaceX = surface->outputOriginX;
 
  187  surfaceY = surface->outputOriginY;
 
  188  surfaceRect.left = 0;
 
  190  surfaceRect.right = (UINT16)MIN(UINT16_MAX, surface->mappedWidth);
 
  191  surfaceRect.bottom = (UINT16)MIN(UINT16_MAX, surface->mappedHeight);
 
  192  region16_intersect_rect(&(surface->invalidRegion), &(surface->invalidRegion), &surfaceRect);
 
  193  const double sx = surface->outputTargetWidth / (double)surface->mappedWidth;
 
  194  const double sy = surface->outputTargetHeight / (double)surface->mappedHeight;
 
  196  if (!(rects = region16_rects(&surface->invalidRegion, &nbRects)) || !nbRects)
 
  197    return CHANNEL_RC_OK;
 
  199  if (!update_begin_paint(update))
 
  202  for (UINT32 i = 0; i < nbRects; i++)
 
  204    const UINT32 nXSrc = rects[i].left;
 
  205    const UINT32 nYSrc = rects[i].top;
 
  206    const UINT32 nXDst = (UINT32)MIN(surfaceX + nXSrc * sx, gdi->width - 1);
 
  207    const UINT32 nYDst = (UINT32)MIN(surfaceY + nYSrc * sy, gdi->height - 1);
 
  208    const UINT32 swidth = rects[i].right - rects[i].left;
 
  209    const UINT32 sheight = rects[i].bottom - rects[i].top;
 
  210    const UINT32 dwidth = MIN((UINT32)(swidth * sx), (UINT32)gdi->width - nXDst);
 
  211    const UINT32 dheight = MIN((UINT32)(sheight * sy), (UINT32)gdi->height - nYDst);
 
  213    if (!freerdp_image_scale(gdi->primary_buffer, gdi->dstFormat, gdi->stride, nXDst, nYDst,
 
  214                             dwidth, dheight, surface->data, surface->format, surface->scanline,
 
  215                             nXSrc, nYSrc, swidth, sheight))
 
  217      rc = CHANNEL_RC_NULL_DATA;
 
  221    gdi_InvalidateRegion(gdi->primary->hdc, (INT32)nXDst, (INT32)nYDst, (INT32)dwidth,
 
  228  if (!update_end_paint(update))
 
  229    rc = ERROR_INTERNAL_ERROR;
 
  231  region16_clear(&(surface->invalidRegion));
 
  235static UINT gdi_WindowUpdate(RdpgfxClientContext* context, gdiGfxSurface* surface)
 
  237  WINPR_ASSERT(context);
 
  238  WINPR_ASSERT(surface);
 
  239  return IFCALLRESULT(CHANNEL_RC_OK, context->UpdateWindowFromSurface, context, surface);
 
  242static UINT gdi_UpdateSurfaces(RdpgfxClientContext* context)
 
  245  UINT status = ERROR_INTERNAL_ERROR;
 
  246  UINT16* pSurfaceIds = NULL;
 
  249  WINPR_ASSERT(context);
 
  251  gdi = (rdpGdi*)context->custom;
 
  254  EnterCriticalSection(&context->mux);
 
  256  WINPR_ASSERT(context->GetSurfaceIds);
 
  257  context->GetSurfaceIds(context, &pSurfaceIds, &count);
 
  258  status = CHANNEL_RC_OK;
 
  260  for (UINT32 index = 0; index < count; index++)
 
  262    WINPR_ASSERT(context->GetSurfaceData);
 
  263    gdiGfxSurface* surface =
 
  264        (gdiGfxSurface*)context->GetSurfaceData(context, pSurfaceIds[index]);
 
  270    if (context->UpdateSurfaceArea)
 
  272      if (surface->handleInUpdateSurfaceArea)
 
  276    if (surface->outputMapped)
 
  277      status = gdi_OutputUpdate(gdi, surface);
 
  278    else if (surface->windowMapped)
 
  279      status = gdi_WindowUpdate(context, surface);
 
  281    if (status != CHANNEL_RC_OK)
 
  286  LeaveCriticalSection(&context->mux);
 
  299  WINPR_ASSERT(context);
 
  300  WINPR_ASSERT(startFrame);
 
  302  gdi = (rdpGdi*)context->custom;
 
  304  gdi->inGfxFrame = TRUE;
 
  305  gdi->frameId = startFrame->frameId;
 
  306  return CHANNEL_RC_OK;
 
  309static UINT gdi_call_update_surfaces(RdpgfxClientContext* context)
 
  311  WINPR_ASSERT(context);
 
  312  return IFCALLRESULT(CHANNEL_RC_OK, context->UpdateSurfaces, context);
 
  320static UINT gdi_EndFrame(RdpgfxClientContext* context,
 
  323  WINPR_ASSERT(context);
 
  324  WINPR_ASSERT(endFrame);
 
  326  rdpGdi* gdi = (rdpGdi*)context->custom;
 
  328  const UINT status = gdi_call_update_surfaces(context);
 
  329  gdi->inGfxFrame = FALSE;
 
  333static UINT gdi_interFrameUpdate(rdpGdi* gdi, RdpgfxClientContext* context)
 
  336  UINT status = CHANNEL_RC_OK;
 
  337  if (!gdi->inGfxFrame)
 
  338    status = gdi_call_update_surfaces(context);
 
  347static UINT gdi_SurfaceCommand_Uncompressed(rdpGdi* gdi, RdpgfxClientContext* context,
 
  350  UINT status = CHANNEL_RC_OK;
 
  351  gdiGfxSurface* surface = NULL;
 
  356  WINPR_ASSERT(context);
 
  359  WINPR_ASSERT(context->GetSurfaceData);
 
  361      (gdiGfxSurface*)context->GetSurfaceData(context, (UINT16)MIN(UINT16_MAX, cmd->surfaceId));
 
  365    WLog_ERR(TAG, 
"unable to retrieve surfaceData for surfaceId=%" PRIu32 
"", cmd->surfaceId);
 
  366    return ERROR_NOT_FOUND;
 
  369  if (!is_within_surface(surface, cmd))
 
  370    return ERROR_INVALID_DATA;
 
  372  bpp = FreeRDPGetBytesPerPixel(cmd->format);
 
  373  size = 1ull * bpp * cmd->width * cmd->height;
 
  374  if (cmd->length < size)
 
  376    WLog_ERR(TAG, 
"Not enough data, got %" PRIu32 
", expected %" PRIuz, cmd->length, size);
 
  377    return ERROR_INVALID_DATA;
 
  380  if (!freerdp_image_copy_no_overlap(surface->data, surface->format, surface->scanline, cmd->left,
 
  381                                     cmd->top, cmd->width, cmd->height, cmd->data, cmd->format, 0,
 
  382                                     0, 0, NULL, FREERDP_FLIP_NONE))
 
  383    return ERROR_INTERNAL_ERROR;
 
  385  invalidRect.left = (UINT16)MIN(UINT16_MAX, cmd->left);
 
  386  invalidRect.top = (UINT16)MIN(UINT16_MAX, cmd->top);
 
  387  invalidRect.right = (UINT16)MIN(UINT16_MAX, cmd->right);
 
  388  invalidRect.bottom = (UINT16)MIN(UINT16_MAX, cmd->bottom);
 
  389  region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion), &invalidRect);
 
  390  status = IFCALLRESULT(CHANNEL_RC_OK, context->UpdateSurfaceArea, context, surface->surfaceId, 1,
 
  393  if (status != CHANNEL_RC_OK)
 
  396  status = gdi_interFrameUpdate(gdi, context);
 
  407static UINT gdi_SurfaceCommand_RemoteFX(rdpGdi* gdi, RdpgfxClientContext* context,
 
  410  UINT status = ERROR_INTERNAL_ERROR;
 
  411  gdiGfxSurface* surface = NULL;
 
  416  WINPR_ASSERT(context);
 
  419  WINPR_ASSERT(context->GetSurfaceData);
 
  421      (gdiGfxSurface*)context->GetSurfaceData(context, (UINT16)MIN(UINT16_MAX, cmd->surfaceId));
 
  425    WLog_ERR(TAG, 
"unable to retrieve surfaceData for surfaceId=%" PRIu32 
"", cmd->surfaceId);
 
  426    return ERROR_NOT_FOUND;
 
  429  WINPR_ASSERT(surface->codecs);
 
  430  rfx_context_set_pixel_format(surface->codecs->rfx, cmd->format);
 
  431  region16_init(&invalidRegion);
 
  433  if (!rfx_process_message(surface->codecs->rfx, cmd->data, cmd->length, cmd->left, cmd->top,
 
  434                           surface->data, surface->format, surface->scanline, surface->height,
 
  437    WLog_ERR(TAG, 
"Failed to process RemoteFX message");
 
  441  rects = region16_rects(&invalidRegion, &nrRects);
 
  442  status = IFCALLRESULT(CHANNEL_RC_OK, context->UpdateSurfaceArea, context, surface->surfaceId,
 
  445  if (status != CHANNEL_RC_OK)
 
  448  for (UINT32 x = 0; x < nrRects; x++)
 
  449    region16_union_rect(&surface->invalidRegion, &surface->invalidRegion, &rects[x]);
 
  451  status = gdi_interFrameUpdate(gdi, context);
 
  454  region16_uninit(&invalidRegion);
 
  463static UINT gdi_SurfaceCommand_ClearCodec(rdpGdi* gdi, RdpgfxClientContext* context,
 
  467  UINT status = CHANNEL_RC_OK;
 
  468  gdiGfxSurface* surface = NULL;
 
  471  WINPR_ASSERT(context);
 
  474  WINPR_ASSERT(context->GetSurfaceData);
 
  476      (gdiGfxSurface*)context->GetSurfaceData(context, (UINT16)MIN(UINT16_MAX, cmd->surfaceId));
 
  480    WLog_ERR(TAG, 
"unable to retrieve surfaceData for surfaceId=%" PRIu32 
"", cmd->surfaceId);
 
  481    return ERROR_NOT_FOUND;
 
  484  WINPR_ASSERT(surface->codecs);
 
  485  rc = clear_decompress(surface->codecs->clear, cmd->data, cmd->length, cmd->width, cmd->height,
 
  486                        surface->data, surface->format, surface->scanline, cmd->left, cmd->top,
 
  487                        surface->width, surface->height, &gdi->palette);
 
  491    WLog_ERR(TAG, 
"clear_decompress failure: %" PRId32 
"", rc);
 
  492    return ERROR_INTERNAL_ERROR;
 
  495  invalidRect.left = (UINT16)MIN(UINT16_MAX, cmd->left);
 
  496  invalidRect.top = (UINT16)MIN(UINT16_MAX, cmd->top);
 
  497  invalidRect.right = (UINT16)MIN(UINT16_MAX, cmd->right);
 
  498  invalidRect.bottom = (UINT16)MIN(UINT16_MAX, cmd->bottom);
 
  499  region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion), &invalidRect);
 
  500  status = IFCALLRESULT(CHANNEL_RC_OK, context->UpdateSurfaceArea, context, surface->surfaceId, 1,
 
  503  if (status != CHANNEL_RC_OK)
 
  506  status = gdi_interFrameUpdate(gdi, context);
 
  517static UINT gdi_SurfaceCommand_Planar(rdpGdi* gdi, RdpgfxClientContext* context,
 
  520  UINT status = CHANNEL_RC_OK;
 
  521  BYTE* DstData = NULL;
 
  522  gdiGfxSurface* surface = NULL;
 
  525  WINPR_ASSERT(context);
 
  528  WINPR_ASSERT(context->GetSurfaceData);
 
  530      (gdiGfxSurface*)context->GetSurfaceData(context, (UINT16)MIN(UINT16_MAX, cmd->surfaceId));
 
  534    WLog_ERR(TAG, 
"unable to retrieve surfaceData for surfaceId=%" PRIu32 
"", cmd->surfaceId);
 
  535    return ERROR_NOT_FOUND;
 
  538  DstData = surface->data;
 
  540  if (!is_within_surface(surface, cmd))
 
  541    return ERROR_INVALID_DATA;
 
  543  if (!freerdp_bitmap_decompress_planar(surface->codecs->planar, cmd->data, cmd->length,
 
  544                                        cmd->width, cmd->height, DstData, surface->format,
 
  545                                        surface->scanline, cmd->left, cmd->top, cmd->width,
 
  547    return ERROR_INTERNAL_ERROR;
 
  549  invalidRect.left = (UINT16)MIN(UINT16_MAX, cmd->left);
 
  550  invalidRect.top = (UINT16)MIN(UINT16_MAX, cmd->top);
 
  551  invalidRect.right = (UINT16)MIN(UINT16_MAX, cmd->right);
 
  552  invalidRect.bottom = (UINT16)MIN(UINT16_MAX, cmd->bottom);
 
  553  region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion), &invalidRect);
 
  554  status = IFCALLRESULT(CHANNEL_RC_OK, context->UpdateSurfaceArea, context, surface->surfaceId, 1,
 
  557  if (status != CHANNEL_RC_OK)
 
  560  status = gdi_interFrameUpdate(gdi, context);
 
  571static UINT gdi_SurfaceCommand_AVC420(rdpGdi* gdi, RdpgfxClientContext* context,
 
  576  UINT status = CHANNEL_RC_OK;
 
  577  gdiGfxSurface* surface = NULL;
 
  581  WINPR_ASSERT(context);
 
  584  WINPR_ASSERT(context->GetSurfaceData);
 
  586      (gdiGfxSurface*)context->GetSurfaceData(context, (UINT16)MIN(UINT16_MAX, cmd->surfaceId));
 
  590    WLog_ERR(TAG, 
"unable to retrieve surfaceData for surfaceId=%" PRIu32 
"", cmd->surfaceId);
 
  591    return ERROR_NOT_FOUND;
 
  596    surface->h264 = h264_context_new(FALSE);
 
  600      WLog_ERR(TAG, 
"unable to create h264 context");
 
  601      return ERROR_NOT_ENOUGH_MEMORY;
 
  604    if (!h264_context_reset(surface->h264, surface->width, surface->height))
 
  605      return ERROR_INTERNAL_ERROR;
 
  609    return ERROR_NOT_SUPPORTED;
 
  614    return ERROR_INTERNAL_ERROR;
 
  617  rc = avc420_decompress(surface->h264, bs->data, bs->length, surface->data, surface->format,
 
  618                         surface->scanline, surface->width, surface->height, meta->regionRects,
 
  619                         meta->numRegionRects);
 
  623    WLog_WARN(TAG, 
"avc420_decompress failure: %" PRId32 
", ignoring update.", rc);
 
  624    return CHANNEL_RC_OK;
 
  627  for (UINT32 i = 0; i < meta->numRegionRects; i++)
 
  629    region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion),
 
  630                        &(meta->regionRects[i]));
 
  633  status = IFCALLRESULT(CHANNEL_RC_OK, context->UpdateSurfaceArea, context, surface->surfaceId,
 
  634                        meta->numRegionRects, meta->regionRects);
 
  636  if (status != CHANNEL_RC_OK)
 
  639  status = gdi_interFrameUpdate(gdi, context);
 
  644  return ERROR_NOT_SUPPORTED;
 
  653static UINT gdi_SurfaceCommand_AVC444(rdpGdi* gdi, RdpgfxClientContext* context,
 
  658  UINT status = CHANNEL_RC_OK;
 
  659  gdiGfxSurface* surface = NULL;
 
  666  WINPR_ASSERT(context);
 
  669  WINPR_ASSERT(context->GetSurfaceData);
 
  671      (gdiGfxSurface*)context->GetSurfaceData(context, (UINT16)MIN(UINT16_MAX, cmd->surfaceId));
 
  675    WLog_ERR(TAG, 
"unable to retrieve surfaceData for surfaceId=%" PRIu32 
"", cmd->surfaceId);
 
  676    return ERROR_NOT_FOUND;
 
  681    surface->h264 = h264_context_new(FALSE);
 
  685      WLog_ERR(TAG, 
"unable to create h264 context");
 
  686      return ERROR_NOT_ENOUGH_MEMORY;
 
  689    if (!h264_context_reset(surface->h264, surface->width, surface->height))
 
  690      return ERROR_INTERNAL_ERROR;
 
  694    return ERROR_NOT_SUPPORTED;
 
  699    return ERROR_INTERNAL_ERROR;
 
  701  avc1 = &bs->bitstream[0];
 
  702  avc2 = &bs->bitstream[1];
 
  705  rc = avc444_decompress(surface->h264, bs->LC, meta1->regionRects, meta1->numRegionRects,
 
  706                         avc1->data, avc1->length, meta2->regionRects, meta2->numRegionRects,
 
  707                         avc2->data, avc2->length, surface->data, surface->format,
 
  708                         surface->scanline, surface->width, surface->height, cmd->codecId);
 
  712    WLog_WARN(TAG, 
"avc444_decompress failure: %" PRIu32 
", ignoring update.", status);
 
  713    return CHANNEL_RC_OK;
 
  716  for (UINT32 i = 0; i < meta1->numRegionRects; i++)
 
  718    region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion),
 
  719                        &(meta1->regionRects[i]));
 
  722  status = IFCALLRESULT(CHANNEL_RC_OK, context->UpdateSurfaceArea, context, surface->surfaceId,
 
  723                        meta1->numRegionRects, meta1->regionRects);
 
  725  if (status != CHANNEL_RC_OK)
 
  728  for (UINT32 i = 0; i < meta2->numRegionRects; i++)
 
  730    region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion),
 
  731                        &(meta2->regionRects[i]));
 
  734  status = IFCALLRESULT(CHANNEL_RC_OK, context->UpdateSurfaceArea, context, surface->surfaceId,
 
  735                        meta2->numRegionRects, meta2->regionRects);
 
  737  if (status != CHANNEL_RC_OK)
 
  740  status = gdi_interFrameUpdate(gdi, context);
 
  745  return ERROR_NOT_SUPPORTED;
 
  749static BOOL gdi_apply_alpha(BYTE* data, UINT32 format, UINT32 stride, 
RECTANGLE_16* rect,
 
  750                            UINT32 startOffsetX, UINT32 count, BYTE a)
 
  754  const UINT32 bpp = FreeRDPGetBytesPerPixel(format);
 
  757  for (
size_t y = rect->top; y < rect->bottom; y++)
 
  759    BYTE* line = &data[y * stride];
 
  761    for (
size_t x = first ? rect->left + startOffsetX : rect->left; x < rect->right; x++)
 
  767      if (written == count)
 
  770      BYTE* src = &line[x * bpp];
 
  771      UINT32 color = FreeRDPReadColor(src, format);
 
  772      FreeRDPSplitColor(color, format, &r, &g, &b, NULL, NULL);
 
  773      color = FreeRDPGetColor(format, r, g, b, a);
 
  774      FreeRDPWriteColor(src, format, color);
 
  788static UINT gdi_SurfaceCommand_Alpha(rdpGdi* gdi, RdpgfxClientContext* context,
 
  791  UINT status = CHANNEL_RC_OK;
 
  793  UINT16 compressed = 0;
 
  794  gdiGfxSurface* surface = NULL;
 
  799  WINPR_ASSERT(context);
 
  802  s = Stream_StaticConstInit(&buffer, cmd->data, cmd->length);
 
  804  if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
 
  805    return ERROR_INVALID_DATA;
 
  807  WINPR_ASSERT(context->GetSurfaceData);
 
  809      (gdiGfxSurface*)context->GetSurfaceData(context, (UINT16)MIN(UINT16_MAX, cmd->surfaceId));
 
  813    WLog_ERR(TAG, 
"unable to retrieve surfaceData for surfaceId=%" PRIu32 
"", cmd->surfaceId);
 
  814    return ERROR_NOT_FOUND;
 
  817  if (!is_within_surface(surface, cmd))
 
  818    return ERROR_INVALID_DATA;
 
  820  Stream_Read_UINT16(s, alphaSig);
 
  821  Stream_Read_UINT16(s, compressed);
 
  823  if (alphaSig != 0x414C)
 
  824    return ERROR_INVALID_DATA;
 
  828    if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, cmd->height, cmd->width))
 
  829      return ERROR_INVALID_DATA;
 
  831    for (
size_t y = cmd->top; y < cmd->top + cmd->height; y++)
 
  833      BYTE* line = &surface->data[y * surface->scanline];
 
  835      for (
size_t x = cmd->left; x < cmd->left + cmd->width; x++)
 
  842        BYTE* src = &line[x * FreeRDPGetBytesPerPixel(surface->format)];
 
  843        Stream_Read_UINT8(s, a);
 
  844        color = FreeRDPReadColor(src, surface->format);
 
  845        FreeRDPSplitColor(color, surface->format, &r, &g, &b, NULL, NULL);
 
  846        color = FreeRDPGetColor(surface->format, r, g, b, a);
 
  847        FreeRDPWriteColor(src, surface->format, color);
 
  853    UINT32 startOffsetX = 0;
 
  855    rect.left = (UINT16)MIN(UINT16_MAX, cmd->left);
 
  856    rect.top = (UINT16)MIN(UINT16_MAX, cmd->top);
 
  857    rect.right = (UINT16)MIN(UINT16_MAX, cmd->left + cmd->width);
 
  858    rect.bottom = (UINT16)MIN(UINT16_MAX, cmd->top + cmd->height);
 
  860    while (rect.top < rect.bottom)
 
  865      if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
 
  866        return ERROR_INVALID_DATA;
 
  868      Stream_Read_UINT8(s, a);
 
  869      Stream_Read_UINT8(s, count);
 
  873        if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
 
  874          return ERROR_INVALID_DATA;
 
  876        Stream_Read_UINT16(s, count);
 
  880          if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
 
  881            return ERROR_INVALID_DATA;
 
  883          Stream_Read_UINT32(s, count);
 
  887      if (!gdi_apply_alpha(surface->data, surface->format, surface->scanline, &rect,
 
  888                           startOffsetX, count, a))
 
  889        return ERROR_INTERNAL_ERROR;
 
  891      startOffsetX += count;
 
  893      while (startOffsetX >= cmd->width)
 
  895        startOffsetX -= cmd->width;
 
  901  invalidRect.left = (UINT16)MIN(UINT16_MAX, cmd->left);
 
  902  invalidRect.top = (UINT16)MIN(UINT16_MAX, cmd->top);
 
  903  invalidRect.right = (UINT16)MIN(UINT16_MAX, cmd->right);
 
  904  invalidRect.bottom = (UINT16)MIN(UINT16_MAX, cmd->bottom);
 
  905  region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion), &invalidRect);
 
  906  status = IFCALLRESULT(CHANNEL_RC_OK, context->UpdateSurfaceArea, context, surface->surfaceId, 1,
 
  909  if (status != CHANNEL_RC_OK)
 
  912  status = gdi_interFrameUpdate(gdi, context);
 
  918#if defined(WITH_GFX_FRAME_DUMP) 
  921  static UINT64 xxx = 0;
 
  922  const char* path = 
"/tmp/dump/";
 
  924  char fname[1024] = { 0 };
 
  926  snprintf(fname, 
sizeof(fname), 
"%s/%08" PRIx64 
".raw", path, xxx++);
 
  927  FILE* fp = fopen(fname, 
"w");
 
  930  (void)fprintf(fp, 
"frameid: %" PRIu32 
"\n", frameId);
 
  931  (void)fprintf(fp, 
"surfaceId: %" PRIu32 
"\n", cmd->surfaceId);
 
  932  (void)fprintf(fp, 
"codecId: %" PRIu32 
"\n", cmd->codecId);
 
  933  (void)fprintf(fp, 
"contextId: %" PRIu32 
"\n", cmd->contextId);
 
  934  (void)fprintf(fp, 
"format: %" PRIu32 
"\n", cmd->format);
 
  935  (void)fprintf(fp, 
"left: %" PRIu32 
"\n", cmd->left);
 
  936  (void)fprintf(fp, 
"top: %" PRIu32 
"\n", cmd->top);
 
  937  (void)fprintf(fp, 
"right: %" PRIu32 
"\n", cmd->right);
 
  938  (void)fprintf(fp, 
"bottom: %" PRIu32 
"\n", cmd->bottom);
 
  939  (void)fprintf(fp, 
"width: %" PRIu32 
"\n", cmd->width);
 
  940  (void)fprintf(fp, 
"height: %" PRIu32 
"\n", cmd->height);
 
  941  (void)fprintf(fp, 
"length: %" PRIu32 
"\n", cmd->length);
 
  943  char* bdata = crypto_base64_encode_ex(cmd->data, cmd->length, FALSE);
 
  944  (void)fprintf(fp, 
"data: %s\n", bdata);
 
  955static UINT gdi_SurfaceCommand_Progressive(rdpGdi* gdi, RdpgfxClientContext* context,
 
  959  UINT status = CHANNEL_RC_OK;
 
  960  gdiGfxSurface* surface = NULL;
 
  970  WINPR_ASSERT(context);
 
  972  const UINT16 surfaceId = (UINT16)MIN(UINT16_MAX, cmd->surfaceId);
 
  974  WINPR_ASSERT(context->GetSurfaceData);
 
  975  surface = (gdiGfxSurface*)context->GetSurfaceData(context, surfaceId);
 
  979    WLog_ERR(TAG, 
"unable to retrieve surfaceData for surfaceId=%" PRIu32 
"", cmd->surfaceId);
 
  980    return ERROR_NOT_FOUND;
 
  983  if (!is_within_surface(surface, cmd))
 
  984    return ERROR_INVALID_DATA;
 
  986  WINPR_ASSERT(surface->codecs);
 
  987  rc = progressive_create_surface_context(surface->codecs->progressive, surfaceId, surface->width,
 
  992    WLog_ERR(TAG, 
"progressive_create_surface_context failure: %" PRId32 
"", rc);
 
  993    return ERROR_INTERNAL_ERROR;
 
  996  region16_init(&invalidRegion);
 
  998  rc = progressive_decompress(surface->codecs->progressive, cmd->data, cmd->length, surface->data,
 
  999                              surface->format, surface->scanline, cmd->left, cmd->top,
 
 1000                              &invalidRegion, surfaceId, gdi->frameId);
 
 1004    WLog_ERR(TAG, 
"progressive_decompress failure: %" PRId32 
"", rc);
 
 1005    region16_uninit(&invalidRegion);
 
 1006    return ERROR_INTERNAL_ERROR;
 
 1009  rects = region16_rects(&invalidRegion, &nrRects);
 
 1010  status = IFCALLRESULT(CHANNEL_RC_OK, context->UpdateSurfaceArea, context, surface->surfaceId,
 
 1013  if (status != CHANNEL_RC_OK)
 
 1016  for (UINT32 x = 0; x < nrRects; x++)
 
 1017    region16_union_rect(&surface->invalidRegion, &surface->invalidRegion, &rects[x]);
 
 1019  region16_uninit(&invalidRegion);
 
 1021  status = gdi_interFrameUpdate(gdi, context);
 
 1034  UINT status = CHANNEL_RC_OK;
 
 1037  if (!context || !cmd)
 
 1038    return ERROR_INVALID_PARAMETER;
 
 1040  gdi = (rdpGdi*)context->custom;
 
 1042  EnterCriticalSection(&context->mux);
 
 1043  const UINT16 codecId = WINPR_ASSERTING_INT_CAST(UINT16, cmd->codecId);
 
 1044  WLog_Print(gdi->log, WLOG_TRACE,
 
 1045             "surfaceId=%" PRIu32 
", codec=%s [%" PRIu32 
"], contextId=%" PRIu32 
", format=%s, " 
 1046             "left=%" PRIu32 
", top=%" PRIu32 
", right=%" PRIu32 
", bottom=%" PRIu32
 
 1047             ", width=%" PRIu32 
", height=%" PRIu32 
" " 
 1048             "length=%" PRIu32 
", data=%p, extra=%p",
 
 1049             cmd->surfaceId, rdpgfx_get_codec_id_string(codecId), cmd->codecId, cmd->contextId,
 
 1050             FreeRDPGetColorFormatName(cmd->format), cmd->left, cmd->top, cmd->right, cmd->bottom,
 
 1051             cmd->width, cmd->height, cmd->length, (
void*)cmd->data, (
void*)cmd->extra);
 
 1052#if defined(WITH_GFX_FRAME_DUMP) 
 1053  dump_cmd(cmd, gdi->frameId);
 
 1058    case RDPGFX_CODECID_UNCOMPRESSED:
 
 1059      status = gdi_SurfaceCommand_Uncompressed(gdi, context, cmd);
 
 1062    case RDPGFX_CODECID_CAVIDEO:
 
 1063      status = gdi_SurfaceCommand_RemoteFX(gdi, context, cmd);
 
 1066    case RDPGFX_CODECID_CLEARCODEC:
 
 1067      status = gdi_SurfaceCommand_ClearCodec(gdi, context, cmd);
 
 1070    case RDPGFX_CODECID_PLANAR:
 
 1071      status = gdi_SurfaceCommand_Planar(gdi, context, cmd);
 
 1074    case RDPGFX_CODECID_AVC420:
 
 1075      status = gdi_SurfaceCommand_AVC420(gdi, context, cmd);
 
 1078    case RDPGFX_CODECID_AVC444v2:
 
 1079    case RDPGFX_CODECID_AVC444:
 
 1080      status = gdi_SurfaceCommand_AVC444(gdi, context, cmd);
 
 1083    case RDPGFX_CODECID_ALPHA:
 
 1084      status = gdi_SurfaceCommand_Alpha(gdi, context, cmd);
 
 1087    case RDPGFX_CODECID_CAPROGRESSIVE:
 
 1088      status = gdi_SurfaceCommand_Progressive(gdi, context, cmd);
 
 1091    case RDPGFX_CODECID_CAPROGRESSIVE_V2:
 
 1092      WLog_WARN(TAG, 
"SurfaceCommand %s [0x%08" PRIX16 
"] not implemented",
 
 1093                rdpgfx_get_codec_id_string(codecId), codecId);
 
 1097      WLog_WARN(TAG, 
"Invalid SurfaceCommand %s [0x%08" PRIX16 
"]",
 
 1098                rdpgfx_get_codec_id_string(codecId), codecId);
 
 1102  LeaveCriticalSection(&context->mux);
 
 1112gdi_DeleteEncodingContext(RdpgfxClientContext* context,
 
 1115  WINPR_ASSERT(context);
 
 1116  WINPR_ASSERT(deleteEncodingContext);
 
 1117  WINPR_UNUSED(context);
 
 1118  WINPR_UNUSED(deleteEncodingContext);
 
 1119  return CHANNEL_RC_OK;
 
 1127static UINT gdi_CreateSurface(RdpgfxClientContext* context,
 
 1130  UINT rc = ERROR_INTERNAL_ERROR;
 
 1131  gdiGfxSurface* surface = NULL;
 
 1133  WINPR_ASSERT(context);
 
 1134  WINPR_ASSERT(createSurface);
 
 1135  gdi = (rdpGdi*)context->custom;
 
 1137  WINPR_ASSERT(gdi->context);
 
 1138  EnterCriticalSection(&context->mux);
 
 1139  surface = (gdiGfxSurface*)calloc(1, 
sizeof(gdiGfxSurface));
 
 1146    WINPR_ASSERT(context->codecs);
 
 1147    surface->codecs = context->codecs;
 
 1149    if (!surface->codecs)
 
 1156  surface->surfaceId = createSurface->surfaceId;
 
 1157  surface->width = gfx_align_scanline(createSurface->width, 16);
 
 1158  surface->height = gfx_align_scanline(createSurface->height, 16);
 
 1159  surface->mappedWidth = createSurface->width;
 
 1160  surface->mappedHeight = createSurface->height;
 
 1161  surface->outputTargetWidth = createSurface->width;
 
 1162  surface->outputTargetHeight = createSurface->height;
 
 1164  switch (createSurface->pixelFormat)
 
 1166    case GFX_PIXEL_FORMAT_ARGB_8888:
 
 1167      surface->format = PIXEL_FORMAT_BGRA32;
 
 1170    case GFX_PIXEL_FORMAT_XRGB_8888:
 
 1171      surface->format = PIXEL_FORMAT_BGRX32;
 
 1179  surface->scanline = gfx_align_scanline(surface->width * 4UL, 16);
 
 1180  surface->data = (BYTE*)winpr_aligned_malloc(1ull * surface->scanline * surface->height, 16);
 
 1188  memset(surface->data, 0xFF, (
size_t)surface->scanline * surface->height);
 
 1189  region16_init(&surface->invalidRegion);
 
 1191  WINPR_ASSERT(context->SetSurfaceData);
 
 1192  rc = context->SetSurfaceData(context, surface->surfaceId, (
void*)surface);
 
 1194  LeaveCriticalSection(&context->mux);
 
 1203static UINT gdi_DeleteSurface(RdpgfxClientContext* context,
 
 1206  UINT rc = CHANNEL_RC_OK;
 
 1207  UINT res = ERROR_INTERNAL_ERROR;
 
 1208  rdpCodecs* codecs = NULL;
 
 1209  gdiGfxSurface* surface = NULL;
 
 1210  EnterCriticalSection(&context->mux);
 
 1212  WINPR_ASSERT(context->GetSurfaceData);
 
 1213  surface = (gdiGfxSurface*)context->GetSurfaceData(context, deleteSurface->surfaceId);
 
 1217    if (surface->windowMapped)
 
 1218      rc = IFCALLRESULT(CHANNEL_RC_OK, context->UnmapWindowForSurface, context,
 
 1222    h264_context_free(surface->h264);
 
 1224    region16_uninit(&surface->invalidRegion);
 
 1225    codecs = surface->codecs;
 
 1226    winpr_aligned_free(surface->data);
 
 1230  WINPR_ASSERT(context->SetSurfaceData);
 
 1231  res = context->SetSurfaceData(context, deleteSurface->surfaceId, NULL);
 
 1235  if (codecs && codecs->progressive)
 
 1236    progressive_delete_surface_context(codecs->progressive, deleteSurface->surfaceId);
 
 1238  LeaveCriticalSection(&context->mux);
 
 1242static BOOL intersect_rect(
const RECTANGLE_16* rect, 
const gdiGfxSurface* surface,
 
 1246  WINPR_ASSERT(surface);
 
 1247  WINPR_ASSERT(prect);
 
 1249  if (rect->left > rect->right)
 
 1251  if (rect->left > surface->width)
 
 1253  if (rect->top > rect->bottom)
 
 1255  if (rect->top > surface->height)
 
 1257  prect->left = rect->left;
 
 1258  prect->top = rect->top;
 
 1260  prect->right = MIN(rect->right, WINPR_ASSERTING_INT_CAST(UINT16, surface->width));
 
 1261  prect->bottom = MIN(rect->bottom, WINPR_ASSERTING_INT_CAST(UINT16, surface->height));
 
 1272  UINT status = ERROR_INTERNAL_ERROR;
 
 1275  rdpGdi* gdi = (rdpGdi*)context->custom;
 
 1277  EnterCriticalSection(&context->mux);
 
 1279  WINPR_ASSERT(context->GetSurfaceData);
 
 1280  gdiGfxSurface* surface = (gdiGfxSurface*)context->GetSurfaceData(context, solidFill->surfaceId);
 
 1285  const BYTE b = solidFill->fillPixel.B;
 
 1286  const BYTE g = solidFill->fillPixel.G;
 
 1287  const BYTE r = solidFill->fillPixel.R;
 
 1295  const UINT32 color = FreeRDPGetColor(surface->format, r, g, b, a);
 
 1297  for (UINT16 index = 0; index < solidFill->fillRectCount; index++)
 
 1299    const RECTANGLE_16* rect = &(solidFill->fillRects[index]);
 
 1301    if (!intersect_rect(rect, surface, &invalidRect))
 
 1304    const UINT32 nWidth = invalidRect.right - invalidRect.left;
 
 1305    const UINT32 nHeight = invalidRect.bottom - invalidRect.top;
 
 1307    if (!freerdp_image_fill(surface->data, surface->format, surface->scanline, invalidRect.left,
 
 1308                            invalidRect.top, nWidth, nHeight, color))
 
 1311    region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion), &invalidRect);
 
 1314  status = IFCALLRESULT(CHANNEL_RC_OK, context->UpdateSurfaceArea, context, surface->surfaceId,
 
 1315                        solidFill->fillRectCount, solidFill->fillRects);
 
 1317  if (status != CHANNEL_RC_OK)
 
 1320  LeaveCriticalSection(&context->mux);
 
 1322  return gdi_interFrameUpdate(gdi, context);
 
 1324  LeaveCriticalSection(&context->mux);
 
 1333static UINT gdi_SurfaceToSurface(RdpgfxClientContext* context,
 
 1336  UINT status = ERROR_INTERNAL_ERROR;
 
 1337  BOOL sameSurface = 0;
 
 1342  gdiGfxSurface* surfaceSrc = NULL;
 
 1343  gdiGfxSurface* surfaceDst = NULL;
 
 1344  rdpGdi* gdi = (rdpGdi*)context->custom;
 
 1345  EnterCriticalSection(&context->mux);
 
 1346  rectSrc = &(surfaceToSurface->rectSrc);
 
 1348  WINPR_ASSERT(context->GetSurfaceData);
 
 1349  surfaceSrc = (gdiGfxSurface*)context->GetSurfaceData(context, surfaceToSurface->surfaceIdSrc);
 
 1351      (surfaceToSurface->surfaceIdSrc == surfaceToSurface->surfaceIdDest) ? TRUE : FALSE;
 
 1355        (gdiGfxSurface*)context->GetSurfaceData(context, surfaceToSurface->surfaceIdDest);
 
 1357    surfaceDst = surfaceSrc;
 
 1359  if (!surfaceSrc || !surfaceDst)
 
 1362  if (!is_rect_valid(rectSrc, surfaceSrc->width, surfaceSrc->height))
 
 1365  nWidth = rectSrc->right - rectSrc->left;
 
 1366  nHeight = rectSrc->bottom - rectSrc->top;
 
 1368  for (UINT16 index = 0; index < surfaceToSurface->destPtsCount; index++)
 
 1370    const RDPGFX_POINT16* destPt = &surfaceToSurface->destPts[index];
 
 1372                              (UINT16)MIN(UINT16_MAX, destPt->x + nWidth),
 
 1373                              (UINT16)MIN(UINT16_MAX, destPt->y + nHeight) };
 
 1374    if (!is_rect_valid(&rect, surfaceDst->width, surfaceDst->height))
 
 1377    if (!freerdp_image_copy(surfaceDst->data, surfaceDst->format, surfaceDst->scanline,
 
 1378                            destPt->x, destPt->y, nWidth, nHeight, surfaceSrc->data,
 
 1379                            surfaceSrc->format, surfaceSrc->scanline, rectSrc->left,
 
 1380                            rectSrc->top, NULL, FREERDP_FLIP_NONE))
 
 1384    region16_union_rect(&surfaceDst->invalidRegion, &surfaceDst->invalidRegion, &invalidRect);
 
 1385    status = IFCALLRESULT(CHANNEL_RC_OK, context->UpdateSurfaceArea, context,
 
 1386                          surfaceDst->surfaceId, 1, &invalidRect);
 
 1388    if (status != CHANNEL_RC_OK)
 
 1392  LeaveCriticalSection(&context->mux);
 
 1394  return gdi_interFrameUpdate(gdi, context);
 
 1396  LeaveCriticalSection(&context->mux);
 
 1400static void gdi_GfxCacheEntryFree(gdiGfxCacheEntry* entry)
 
 1408static gdiGfxCacheEntry* gdi_GfxCacheEntryNew(UINT64 cacheKey, UINT32 width, UINT32 height,
 
 1411  gdiGfxCacheEntry* cacheEntry = (gdiGfxCacheEntry*)calloc(1, 
sizeof(gdiGfxCacheEntry));
 
 1415  cacheEntry->cacheKey = cacheKey;
 
 1416  cacheEntry->width = width;
 
 1417  cacheEntry->height = height;
 
 1418  cacheEntry->format = format;
 
 1419  cacheEntry->scanline = gfx_align_scanline(cacheEntry->width * 4, 16);
 
 1421  if ((cacheEntry->width > 0) && (cacheEntry->height > 0))
 
 1423    cacheEntry->data = (BYTE*)calloc(cacheEntry->height, cacheEntry->scanline);
 
 1425    if (!cacheEntry->data)
 
 1430  gdi_GfxCacheEntryFree(cacheEntry);
 
 1439static UINT gdi_SurfaceToCache(RdpgfxClientContext* context,
 
 1443  gdiGfxSurface* surface = NULL;
 
 1444  gdiGfxCacheEntry* cacheEntry = NULL;
 
 1445  UINT rc = ERROR_INTERNAL_ERROR;
 
 1446  EnterCriticalSection(&context->mux);
 
 1447  rect = &(surfaceToCache->rectSrc);
 
 1449  WINPR_ASSERT(context->GetSurfaceData);
 
 1450  surface = (gdiGfxSurface*)context->GetSurfaceData(context, surfaceToCache->surfaceId);
 
 1455  if (!is_rect_valid(rect, surface->width, surface->height))
 
 1458  cacheEntry = gdi_GfxCacheEntryNew(surfaceToCache->cacheKey, (UINT32)(rect->right - rect->left),
 
 1459                                    (UINT32)(rect->bottom - rect->top), surface->format);
 
 1464  if (!cacheEntry->data)
 
 1467  if (!freerdp_image_copy_no_overlap(cacheEntry->data, cacheEntry->format, cacheEntry->scanline,
 
 1468                                     0, 0, cacheEntry->width, cacheEntry->height, surface->data,
 
 1469                                     surface->format, surface->scanline, rect->left, rect->top,
 
 1470                                     NULL, FREERDP_FLIP_NONE))
 
 1474  WINPR_ASSERT(context->EvictCacheEntry);
 
 1475  context->EvictCacheEntry(context, &evict);
 
 1477  WINPR_ASSERT(context->SetCacheSlotData);
 
 1478  rc = context->SetCacheSlotData(context, surfaceToCache->cacheSlot, (
void*)cacheEntry);
 
 1480  if (rc != CHANNEL_RC_OK)
 
 1481    gdi_GfxCacheEntryFree(cacheEntry);
 
 1482  LeaveCriticalSection(&context->mux);
 
 1491static UINT gdi_CacheToSurface(RdpgfxClientContext* context,
 
 1494  UINT status = ERROR_INTERNAL_ERROR;
 
 1495  gdiGfxSurface* surface = NULL;
 
 1496  gdiGfxCacheEntry* cacheEntry = NULL;
 
 1498  rdpGdi* gdi = (rdpGdi*)context->custom;
 
 1500  EnterCriticalSection(&context->mux);
 
 1502  WINPR_ASSERT(context->GetSurfaceData);
 
 1503  surface = (gdiGfxSurface*)context->GetSurfaceData(context, cacheToSurface->surfaceId);
 
 1505  WINPR_ASSERT(context->GetCacheSlotData);
 
 1506  cacheEntry = (gdiGfxCacheEntry*)context->GetCacheSlotData(context, cacheToSurface->cacheSlot);
 
 1508  if (!surface || !cacheEntry)
 
 1511  for (UINT16 index = 0; index < cacheToSurface->destPtsCount; index++)
 
 1515                              (UINT16)MIN(UINT16_MAX, destPt->x + cacheEntry->width),
 
 1516                              (UINT16)MIN(UINT16_MAX, destPt->y + cacheEntry->height) };
 
 1518    if (rectangle_is_empty(&rect))
 
 1521    if (!is_rect_valid(&rect, surface->width, surface->height))
 
 1524    if (!freerdp_image_copy_no_overlap(surface->data, surface->format, surface->scanline,
 
 1525                                       destPt->x, destPt->y, cacheEntry->width,
 
 1526                                       cacheEntry->height, cacheEntry->data, cacheEntry->format,
 
 1527                                       cacheEntry->scanline, 0, 0, NULL, FREERDP_FLIP_NONE))
 
 1531    region16_union_rect(&surface->invalidRegion, &surface->invalidRegion, &invalidRect);
 
 1532    status = IFCALLRESULT(CHANNEL_RC_OK, context->UpdateSurfaceArea, context,
 
 1533                          surface->surfaceId, 1, &invalidRect);
 
 1535    if (status != CHANNEL_RC_OK)
 
 1539  LeaveCriticalSection(&context->mux);
 
 1541  return gdi_interFrameUpdate(gdi, context);
 
 1544  LeaveCriticalSection(&context->mux);
 
 1553static UINT gdi_CacheImportReply(RdpgfxClientContext* context,
 
 1557  const UINT16* slots = NULL;
 
 1558  UINT error = CHANNEL_RC_OK;
 
 1560  slots = cacheImportReply->cacheSlots;
 
 1561  count = cacheImportReply->importedEntriesCount;
 
 1563  for (UINT16 index = 0; index < count; index++)
 
 1565    UINT16 cacheSlot = slots[index];
 
 1570    WINPR_ASSERT(context->GetCacheSlotData);
 
 1571    gdiGfxCacheEntry* cacheEntry =
 
 1572        (gdiGfxCacheEntry*)context->GetCacheSlotData(context, cacheSlot);
 
 1577    cacheEntry = gdi_GfxCacheEntryNew(cacheSlot, 0, 0, PIXEL_FORMAT_BGRX32);
 
 1580      return ERROR_INTERNAL_ERROR;
 
 1582    WINPR_ASSERT(context->SetCacheSlotData);
 
 1583    error = context->SetCacheSlotData(context, cacheSlot, (
void*)cacheEntry);
 
 1587      WLog_ERR(TAG, 
"CacheImportReply: SetCacheSlotData failed with error %" PRIu32 
"",
 
 1589      gdi_GfxCacheEntryFree(cacheEntry);
 
 1597static UINT gdi_ImportCacheEntry(RdpgfxClientContext* context, UINT16 cacheSlot,
 
 1600  UINT error = ERROR_INTERNAL_ERROR;
 
 1601  gdiGfxCacheEntry* cacheEntry = NULL;
 
 1604    return CHANNEL_RC_OK;
 
 1606  cacheEntry = gdi_GfxCacheEntryNew(importCacheEntry->key64, importCacheEntry->width,
 
 1607                                    importCacheEntry->height, PIXEL_FORMAT_BGRX32);
 
 1612  if (!freerdp_image_copy_no_overlap(cacheEntry->data, cacheEntry->format, cacheEntry->scanline,
 
 1613                                     0, 0, cacheEntry->width, cacheEntry->height,
 
 1614                                     importCacheEntry->data, PIXEL_FORMAT_BGRX32, 0, 0, 0, NULL,
 
 1619  WINPR_ASSERT(context->EvictCacheEntry);
 
 1620  error = context->EvictCacheEntry(context, &evict);
 
 1621  if (error != CHANNEL_RC_OK)
 
 1624  WINPR_ASSERT(context->SetCacheSlotData);
 
 1625  error = context->SetCacheSlotData(context, cacheSlot, (
void*)cacheEntry);
 
 1630    gdi_GfxCacheEntryFree(cacheEntry);
 
 1631    WLog_ERR(TAG, 
"ImportCacheEntry: SetCacheSlotData failed with error %" PRIu32 
"", error);
 
 1637static UINT gdi_ExportCacheEntry(RdpgfxClientContext* context, UINT16 cacheSlot,
 
 1640  gdiGfxCacheEntry* cacheEntry = NULL;
 
 1642  WINPR_ASSERT(context->GetCacheSlotData);
 
 1643  cacheEntry = (gdiGfxCacheEntry*)context->GetCacheSlotData(context, cacheSlot);
 
 1647    exportCacheEntry->key64 = cacheEntry->cacheKey;
 
 1648    exportCacheEntry->width = (UINT16)MIN(UINT16_MAX, cacheEntry->width);
 
 1649    exportCacheEntry->height = (UINT16)MIN(UINT16_MAX, cacheEntry->height);
 
 1650    exportCacheEntry->size = cacheEntry->width * cacheEntry->height * 4;
 
 1651    exportCacheEntry->flags = 0;
 
 1652    exportCacheEntry->data = cacheEntry->data;
 
 1653    return CHANNEL_RC_OK;
 
 1656  return ERROR_NOT_FOUND;
 
 1664static UINT gdi_EvictCacheEntry(RdpgfxClientContext* context,
 
 1667  gdiGfxCacheEntry* cacheEntry = NULL;
 
 1668  UINT rc = ERROR_NOT_FOUND;
 
 1670  WINPR_ASSERT(context);
 
 1671  WINPR_ASSERT(evictCacheEntry);
 
 1673  EnterCriticalSection(&context->mux);
 
 1675  WINPR_ASSERT(context->GetCacheSlotData);
 
 1676  cacheEntry = (gdiGfxCacheEntry*)context->GetCacheSlotData(context, evictCacheEntry->cacheSlot);
 
 1678  gdi_GfxCacheEntryFree(cacheEntry);
 
 1680  WINPR_ASSERT(context->SetCacheSlotData);
 
 1681  rc = context->SetCacheSlotData(context, evictCacheEntry->cacheSlot, NULL);
 
 1682  LeaveCriticalSection(&context->mux);
 
 1691static UINT gdi_MapSurfaceToOutput(RdpgfxClientContext* context,
 
 1694  UINT rc = ERROR_INTERNAL_ERROR;
 
 1695  gdiGfxSurface* surface = NULL;
 
 1696  EnterCriticalSection(&context->mux);
 
 1698  WINPR_ASSERT(context->GetSurfaceData);
 
 1699  surface = (gdiGfxSurface*)context->GetSurfaceData(context, surfaceToOutput->surfaceId);
 
 1704  if (surface->windowMapped)
 
 1706    WLog_WARN(TAG, 
"surface already windowMapped when trying to set outputMapped");
 
 1710  surface->outputMapped = TRUE;
 
 1711  surface->outputOriginX = surfaceToOutput->outputOriginX;
 
 1712  surface->outputOriginY = surfaceToOutput->outputOriginY;
 
 1713  surface->outputTargetWidth = surface->mappedWidth;
 
 1714  surface->outputTargetHeight = surface->mappedHeight;
 
 1715  region16_clear(&surface->invalidRegion);
 
 1718  LeaveCriticalSection(&context->mux);
 
 1723gdi_MapSurfaceToScaledOutput(RdpgfxClientContext* context,
 
 1726  UINT rc = ERROR_INTERNAL_ERROR;
 
 1727  gdiGfxSurface* surface = NULL;
 
 1728  EnterCriticalSection(&context->mux);
 
 1730  WINPR_ASSERT(context->GetSurfaceData);
 
 1731  surface = (gdiGfxSurface*)context->GetSurfaceData(context, surfaceToOutput->surfaceId);
 
 1736  if (surface->windowMapped)
 
 1738    WLog_WARN(TAG, 
"surface already windowMapped when trying to set outputMapped");
 
 1742  surface->outputMapped = TRUE;
 
 1743  surface->outputOriginX = surfaceToOutput->outputOriginX;
 
 1744  surface->outputOriginY = surfaceToOutput->outputOriginY;
 
 1745  surface->outputTargetWidth = surfaceToOutput->targetWidth;
 
 1746  surface->outputTargetHeight = surfaceToOutput->targetHeight;
 
 1747  region16_clear(&surface->invalidRegion);
 
 1750  LeaveCriticalSection(&context->mux);
 
 1759static UINT gdi_MapSurfaceToWindow(RdpgfxClientContext* context,
 
 1762  UINT rc = ERROR_INTERNAL_ERROR;
 
 1763  gdiGfxSurface* surface = NULL;
 
 1764  EnterCriticalSection(&context->mux);
 
 1766  WINPR_ASSERT(context->GetSurfaceData);
 
 1767  surface = (gdiGfxSurface*)context->GetSurfaceData(context, surfaceToWindow->surfaceId);
 
 1772  if (surface->outputMapped)
 
 1774    WLog_WARN(TAG, 
"surface already outputMapped when trying to set windowMapped");
 
 1778  if (surface->windowMapped)
 
 1780    if (surface->windowId != surfaceToWindow->windowId)
 
 1782      WLog_WARN(TAG, 
"surface windowId mismatch, has %" PRIu64 
", expected %" PRIu64,
 
 1783                surface->windowId, surfaceToWindow->windowId);
 
 1787  surface->windowMapped = TRUE;
 
 1789  surface->windowId = surfaceToWindow->windowId;
 
 1790  surface->mappedWidth = surfaceToWindow->mappedWidth;
 
 1791  surface->mappedHeight = surfaceToWindow->mappedHeight;
 
 1792  surface->outputTargetWidth = surfaceToWindow->mappedWidth;
 
 1793  surface->outputTargetHeight = surfaceToWindow->mappedHeight;
 
 1794  rc = IFCALLRESULT(CHANNEL_RC_OK, context->MapWindowForSurface, context,
 
 1795                    surfaceToWindow->surfaceId, surfaceToWindow->windowId);
 
 1797  LeaveCriticalSection(&context->mux);
 
 1802gdi_MapSurfaceToScaledWindow(RdpgfxClientContext* context,
 
 1805  UINT rc = ERROR_INTERNAL_ERROR;
 
 1806  gdiGfxSurface* surface = NULL;
 
 1807  EnterCriticalSection(&context->mux);
 
 1809  WINPR_ASSERT(context->GetSurfaceData);
 
 1810  surface = (gdiGfxSurface*)context->GetSurfaceData(context, surfaceToWindow->surfaceId);
 
 1815  if (surface->outputMapped)
 
 1817    WLog_WARN(TAG, 
"surface already outputMapped when trying to set windowMapped");
 
 1821  if (surface->windowMapped)
 
 1823    if (surface->windowId != surfaceToWindow->windowId)
 
 1825      WLog_WARN(TAG, 
"surface windowId mismatch, has %" PRIu64 
", expected %" PRIu64,
 
 1826                surface->windowId, surfaceToWindow->windowId);
 
 1830  surface->windowMapped = TRUE;
 
 1832  surface->windowId = surfaceToWindow->windowId;
 
 1833  surface->mappedWidth = surfaceToWindow->mappedWidth;
 
 1834  surface->mappedHeight = surfaceToWindow->mappedHeight;
 
 1835  surface->outputTargetWidth = surfaceToWindow->targetWidth;
 
 1836  surface->outputTargetHeight = surfaceToWindow->targetHeight;
 
 1837  rc = IFCALLRESULT(CHANNEL_RC_OK, context->MapWindowForSurface, context,
 
 1838                    surfaceToWindow->surfaceId, surfaceToWindow->windowId);
 
 1840  LeaveCriticalSection(&context->mux);
 
 1844BOOL gdi_graphics_pipeline_init(rdpGdi* gdi, RdpgfxClientContext* gfx)
 
 1846  return gdi_graphics_pipeline_init_ex(gdi, gfx, NULL, NULL, NULL);
 
 1849BOOL gdi_graphics_pipeline_init_ex(rdpGdi* gdi, RdpgfxClientContext* gfx,
 
 1850                                   pcRdpgfxMapWindowForSurface map,
 
 1851                                   pcRdpgfxUnmapWindowForSurface unmap,
 
 1852                                   pcRdpgfxUpdateSurfaceArea update)
 
 1854  if (!gdi || !gfx || !gdi->context || !gdi->context->settings)
 
 1857  rdpContext* context = gdi->context;
 
 1858  rdpSettings* settings = context->settings;
 
 1861  gfx->custom = (
void*)gdi;
 
 1862  gfx->ResetGraphics = gdi_ResetGraphics;
 
 1863  gfx->StartFrame = gdi_StartFrame;
 
 1864  gfx->EndFrame = gdi_EndFrame;
 
 1865  gfx->SurfaceCommand = gdi_SurfaceCommand;
 
 1866  gfx->DeleteEncodingContext = gdi_DeleteEncodingContext;
 
 1867  gfx->CreateSurface = gdi_CreateSurface;
 
 1868  gfx->DeleteSurface = gdi_DeleteSurface;
 
 1869  gfx->SolidFill = gdi_SolidFill;
 
 1870  gfx->SurfaceToSurface = gdi_SurfaceToSurface;
 
 1871  gfx->SurfaceToCache = gdi_SurfaceToCache;
 
 1872  gfx->CacheToSurface = gdi_CacheToSurface;
 
 1873  gfx->CacheImportReply = gdi_CacheImportReply;
 
 1874  gfx->ImportCacheEntry = gdi_ImportCacheEntry;
 
 1875  gfx->ExportCacheEntry = gdi_ExportCacheEntry;
 
 1876  gfx->EvictCacheEntry = gdi_EvictCacheEntry;
 
 1877  gfx->MapSurfaceToOutput = gdi_MapSurfaceToOutput;
 
 1878  gfx->MapSurfaceToWindow = gdi_MapSurfaceToWindow;
 
 1879  gfx->MapSurfaceToScaledOutput = gdi_MapSurfaceToScaledOutput;
 
 1880  gfx->MapSurfaceToScaledWindow = gdi_MapSurfaceToScaledWindow;
 
 1881  gfx->UpdateSurfaces = gdi_UpdateSurfaces;
 
 1882  gfx->MapWindowForSurface = map;
 
 1883  gfx->UnmapWindowForSurface = unmap;
 
 1884  gfx->UpdateSurfaceArea = update;
 
 1892    gfx->codecs = freerdp_client_codecs_new(flags);
 
 1895    if (!freerdp_client_codecs_prepare(gfx->codecs, FREERDP_CODEC_ALL, w, h))
 
 1898  InitializeCriticalSection(&gfx->mux);
 
 1899  PROFILER_CREATE(gfx->SurfaceProfiler, 
"GFX-PROFILER")
 
 1907  gdi->graphicsReset = TRUE;
 
 1910    gfx->UpdateSurfaceArea = NULL;
 
 1911    gfx->UpdateSurfaces = NULL;
 
 1912    gfx->SurfaceCommand = NULL;
 
 1918void gdi_graphics_pipeline_uninit(rdpGdi* gdi, RdpgfxClientContext* gfx)
 
 1927  freerdp_client_codecs_free(gfx->codecs);
 
 1929  DeleteCriticalSection(&gfx->mux);
 
 1930  PROFILER_PRINT_HEADER
 
 1931  PROFILER_PRINT(gfx->SurfaceProfiler)
 
 1932  PROFILER_PRINT_FOOTER
 
 1933  PROFILER_FREE(gfx->SurfaceProfiler)
 
 1936const 
char* rdpgfx_caps_version_str(UINT32 capsVersion)
 
 1938  switch (capsVersion)
 
 1940    case RDPGFX_CAPVERSION_8:
 
 1941      return "RDPGFX_CAPVERSION_8";
 
 1942    case RDPGFX_CAPVERSION_81:
 
 1943      return "RDPGFX_CAPVERSION_81";
 
 1944    case RDPGFX_CAPVERSION_10:
 
 1945      return "RDPGFX_CAPVERSION_10";
 
 1946    case RDPGFX_CAPVERSION_101:
 
 1947      return "RDPGFX_CAPVERSION_101";
 
 1948    case RDPGFX_CAPVERSION_102:
 
 1949      return "RDPGFX_CAPVERSION_102";
 
 1950    case RDPGFX_CAPVERSION_103:
 
 1951      return "RDPGFX_CAPVERSION_103";
 
 1952    case RDPGFX_CAPVERSION_104:
 
 1953      return "RDPGFX_CAPVERSION_104";
 
 1954    case RDPGFX_CAPVERSION_105:
 
 1955      return "RDPGFX_CAPVERSION_105";
 
 1956    case RDPGFX_CAPVERSION_106:
 
 1957      return "RDPGFX_CAPVERSION_106";
 
 1958    case RDPGFX_CAPVERSION_106_ERR:
 
 1959      return "RDPGFX_CAPVERSION_106_ERR";
 
 1960    case RDPGFX_CAPVERSION_107:
 
 1961      return "RDPGFX_CAPVERSION_107";
 
 1963      return "RDPGFX_CAPVERSION_UNKNOWN";
 
FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
 
FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.
 
FREERDP_API UINT32 freerdp_settings_get_codecs_flags(const rdpSettings *settings)
helper function to get a mask of supported codec flags.
 
FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 param)
Sets a UINT32 settings value.