[codec,color] expose freerdp_image_copy (no)overlap

expose functions for overlapping and non overlapping images to use
directly
This commit is contained in:
akallabeth 2024-05-23 10:07:14 +02:00
parent 1a58e74c17
commit 1b3f3a0408
No known key found for this signature in database
GPG Key ID: A49454A3FC909FD5
15 changed files with 114 additions and 77 deletions

View File

@ -352,7 +352,8 @@ typedef struct gdi_palette gdiPalette;
UINT32 xorMaskLength, const BYTE* WINPR_RESTRICT andMask, UINT32 andMaskLength,
UINT32 xorBpp, const gdiPalette* WINPR_RESTRICT palette);
/***
/*** Copies an image from source to destination, converting if necessary.
* Source and destination may overlap.
*
* @param pDstData destination buffer
* @param DstFormat destination buffer format
@ -377,6 +378,21 @@ typedef struct gdi_palette gdiPalette;
UINT32 nXSrc, UINT32 nYSrc, const gdiPalette* palette,
UINT32 flags);
/*** Same as freerdp_image_copy() but only for overlapping source and destination
*/
FREERDP_API BOOL freerdp_image_copy_overlap(
BYTE* WINPR_RESTRICT pDstData, DWORD DstFormat, UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,
UINT32 nWidth, UINT32 nHeight, const BYTE* WINPR_RESTRICT pSrcData, DWORD SrcFormat,
UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc, const gdiPalette* WINPR_RESTRICT palette,
UINT32 flags);
/*** Same as freerdp_image_copy() but only for non overlapping source and destination
*/
FREERDP_API BOOL freerdp_image_copy_no_overlap(
BYTE* WINPR_RESTRICT pDstData, DWORD DstFormat, UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,
UINT32 nWidth, UINT32 nHeight, const BYTE* WINPR_RESTRICT pSrcData, DWORD SrcFormat,
UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc, const gdiPalette* WINPR_RESTRICT palette,
UINT32 flags);
/***
*
* @param pDstData destination buffer

View File

@ -124,8 +124,9 @@ static BOOL convert_color(BYTE* dst, UINT32 nDstStep, UINT32 DstFormat, UINT32 n
if (nHeight + nYDst > nDstHeight)
nHeight = nDstHeight - nYDst;
return freerdp_image_copy(dst, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight, src,
SrcFormat, nSrcStep, 0, 0, palette, FREERDP_KEEP_DST_ALPHA);
return freerdp_image_copy_no_overlap(dst, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight,
src, SrcFormat, nSrcStep, 0, 0, palette,
FREERDP_KEEP_DST_ALPHA);
}
static BOOL clear_decompress_nscodec(NSC_CONTEXT* nsc, UINT32 width, UINT32 height, wStream* s,
@ -1118,8 +1119,9 @@ INT32 clear_decompress(CLEAR_CONTEXT* clear, const BYTE* pSrcData, UINT32 SrcSiz
if (glyphData)
{
if (!freerdp_image_copy(glyphData, clear->format, 0, 0, 0, nWidth, nHeight, pDstData,
DstFormat, nDstStep, nXDst, nYDst, palette, FREERDP_KEEP_DST_ALPHA))
if (!freerdp_image_copy_no_overlap(glyphData, clear->format, 0, 0, 0, nWidth, nHeight,
pDstData, DstFormat, nDstStep, nXDst, nYDst, palette,
FREERDP_KEEP_DST_ALPHA))
goto fail;
}

View File

@ -241,8 +241,8 @@ BOOL freerdp_image_copy_from_icon_data(BYTE* WINPR_RESTRICT pDstData, UINT32 Dst
return FALSE;
fill_gdi_palette_for_icon(colorTable, cbColorTable, &palette);
if (!freerdp_image_copy(pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight, bitsColor,
format, 0, 0, 0, &palette, FREERDP_FLIP_VERTICAL))
if (!freerdp_image_copy_no_overlap(pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight,
bitsColor, format, 0, 0, 0, &palette, FREERDP_FLIP_VERTICAL))
return FALSE;
/* apply alpha mask */
@ -576,12 +576,11 @@ static INLINE BOOL overlapping(const BYTE* pDstData, UINT32 nXDst, UINT32 nYDst,
return FALSE;
}
static BOOL freerdp_image_copy_no_overlap(BYTE* WINPR_RESTRICT pDstData, DWORD DstFormat,
UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,
UINT32 nWidth, UINT32 nHeight,
const BYTE* WINPR_RESTRICT pSrcData, DWORD SrcFormat,
UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc,
const gdiPalette* WINPR_RESTRICT palette, UINT32 flags)
BOOL freerdp_image_copy_no_overlap(BYTE* WINPR_RESTRICT pDstData, DWORD DstFormat, UINT32 nDstStep,
UINT32 nXDst, UINT32 nYDst, UINT32 nWidth, UINT32 nHeight,
const BYTE* WINPR_RESTRICT pSrcData, DWORD SrcFormat,
UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc,
const gdiPalette* WINPR_RESTRICT palette, UINT32 flags)
{
const SSIZE_T dstByte = FreeRDPGetBytesPerPixel(DstFormat);
const SSIZE_T srcByte = FreeRDPGetBytesPerPixel(SrcFormat);
@ -696,11 +695,10 @@ static BOOL freerdp_image_copy_no_overlap(BYTE* WINPR_RESTRICT pDstData, DWORD D
return TRUE;
}
static BOOL freerdp_image_copy_overlap(BYTE* pDstData, DWORD DstFormat, UINT32 nDstStep,
UINT32 nXDst, UINT32 nYDst, UINT32 nWidth, UINT32 nHeight,
const BYTE* pSrcData, DWORD SrcFormat, UINT32 nSrcStep,
UINT32 nXSrc, UINT32 nYSrc, const gdiPalette* palette,
UINT32 flags)
BOOL freerdp_image_copy_overlap(BYTE* pDstData, DWORD DstFormat, UINT32 nDstStep, UINT32 nXDst,
UINT32 nYDst, UINT32 nWidth, UINT32 nHeight, const BYTE* pSrcData,
DWORD SrcFormat, UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc,
const gdiPalette* palette, UINT32 flags)
{
const UINT32 dstByte = FreeRDPGetBytesPerPixel(DstFormat);
const UINT32 srcByte = FreeRDPGetBytesPerPixel(SrcFormat);

View File

@ -622,9 +622,9 @@ BOOL interleaved_decompress(BITMAP_INTERLEAVED_CONTEXT* interleaved, const BYTE*
return FALSE;
}
if (!freerdp_image_copy(pDstData, DstFormat, nDstStep, nXDst, nYDst, nDstWidth, nDstHeight,
interleaved->TempBuffer, SrcFormat, scanline, 0, 0, palette,
FREERDP_FLIP_VERTICAL | FREERDP_KEEP_DST_ALPHA))
if (!freerdp_image_copy_no_overlap(pDstData, DstFormat, nDstStep, nXDst, nYDst, nDstWidth,
nDstHeight, interleaved->TempBuffer, SrcFormat, scanline, 0,
0, palette, FREERDP_FLIP_VERTICAL | FREERDP_KEEP_DST_ALPHA))
{
WLog_ERR(TAG, "freerdp_image_copy failed");
return FALSE;
@ -681,8 +681,9 @@ BOOL interleaved_compress(BITMAP_INTERLEAVED_CONTEXT* interleaved, BYTE* pDstDat
return FALSE;
}
if (!freerdp_image_copy(interleaved->TempBuffer, DstFormat, 0, 0, 0, nWidth, nHeight, pSrcData,
SrcFormat, nSrcStep, nXSrc, nYSrc, palette, FREERDP_KEEP_DST_ALPHA))
if (!freerdp_image_copy_no_overlap(interleaved->TempBuffer, DstFormat, 0, 0, 0, nWidth, nHeight,
pSrcData, SrcFormat, nSrcStep, nXSrc, nYSrc, palette,
FREERDP_KEEP_DST_ALPHA))
return FALSE;
s = Stream_New(pDstData, *pDstSize);

View File

@ -505,8 +505,9 @@ BOOL nsc_process_message(NSC_CONTEXT* context, UINT16 bpp, UINT32 width, UINT32
return FALSE;
}
if (!freerdp_image_copy(pDstData, DstFormat, nDstStride, nXDst, nYDst, width, height,
context->BitmapData, PIXEL_FORMAT_BGRA32, 0, 0, 0, NULL, flip))
if (!freerdp_image_copy_no_overlap(pDstData, DstFormat, nDstStride, nXDst, nYDst, width, height,
context->BitmapData, PIXEL_FORMAT_BGRA32, 0, 0, 0, NULL,
flip))
return FALSE;
return TRUE;

View File

@ -978,8 +978,9 @@ BOOL planar_decompress(BITMAP_PLANAR_CONTEXT* planar, const BYTE* pSrcData, UINT
if (pTempData != pDstData)
{
if (!freerdp_image_copy(pDstData, DstFormat, nDstStep, nXDst, nYDst, w, h, pTempData,
TempFormat, nTempStep, nXDst, nYDst, NULL, FREERDP_FLIP_NONE))
if (!freerdp_image_copy_no_overlap(pDstData, DstFormat, nDstStep, nXDst, nYDst, w, h,
pTempData, TempFormat, nTempStep, nXDst, nYDst, NULL,
FREERDP_FLIP_NONE))
{
WLog_ERR(TAG, "planar image copy failed");
return FALSE;

View File

@ -2365,9 +2365,9 @@ static BOOL update_tiles(PROGRESSIVE_CONTEXT* progressive, PROGRESSIVE_SURFACE_C
goto fail;
if (rect->top + height > surface->height)
goto fail;
rc = freerdp_image_copy(pDstData, DstFormat, nDstStep, rect->left, rect->top, width,
height, tile->data, progressive->format, tile->stride, nXSrc,
nYSrc, NULL, FREERDP_KEEP_DST_ALPHA);
rc = freerdp_image_copy_no_overlap(
pDstData, DstFormat, nDstStep, rect->left, rect->top, width, height, tile->data,
progressive->format, tile->stride, nXSrc, nYSrc, NULL, FREERDP_KEEP_DST_ALPHA);
if (!rc)
break;

View File

@ -1327,9 +1327,9 @@ BOOL rfx_process_message(RFX_CONTEXT* context, const BYTE* data, UINT32 length,
const UINT32 nWidth = updateRects[j].right - updateRects[j].left;
const UINT32 nHeight = updateRects[j].bottom - updateRects[j].top;
if (!freerdp_image_copy(dst, dstFormat, dstStride, nXDst, nYDst, nWidth, nHeight,
tile->data, context->pixel_format, stride, nXSrc, nYSrc,
NULL, FREERDP_FLIP_NONE))
if (!freerdp_image_copy_no_overlap(dst, dstFormat, dstStride, nXDst, nYDst, nWidth,
nHeight, tile->data, context->pixel_format,
stride, nXSrc, nYSrc, NULL, FREERDP_FLIP_NONE))
{
region16_uninit(&updateRegion);
WLog_Print(context->priv->log, WLOG_ERROR,

View File

@ -637,8 +637,9 @@ static BOOL gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt)
brushFormat = gdi_get_pixel_format(bpp);
if (!freerdp_image_copy(data, gdi->drawing->hdc->format, 0, 0, 0, 8, 8, brush->data,
brushFormat, 0, 0, 0, &gdi->palette, FREERDP_FLIP_NONE))
if (!freerdp_image_copy_no_overlap(data, gdi->drawing->hdc->format, 0, 0, 0, 8, 8,
brush->data, brushFormat, 0, 0, 0, &gdi->palette,
FREERDP_FLIP_NONE))
goto out_error;
}
else
@ -898,8 +899,9 @@ static BOOL gdi_mem3blt(rdpContext* context, MEM3BLT_ORDER* mem3blt)
brushFormat = gdi_get_pixel_format(bpp);
if (!freerdp_image_copy(data, gdi->drawing->hdc->format, 0, 0, 0, 8, 8, brush->data,
brushFormat, 0, 0, 0, &gdi->palette, FREERDP_FLIP_NONE))
if (!freerdp_image_copy_no_overlap(data, gdi->drawing->hdc->format, 0, 0, 0, 8, 8,
brush->data, brushFormat, 0, 0, 0, &gdi->palette,
FREERDP_FLIP_NONE))
{
ret = FALSE;
winpr_aligned_free(data);
@ -1108,10 +1110,10 @@ static BOOL gdi_surface_bits(rdpContext* context, const SURFACE_BITS_COMMAND* cm
goto out;
}
if (!freerdp_image_copy(gdi->primary_buffer, gdi->dstFormat, gdi->stride, cmdRect.left,
cmdRect.top, cmdRect.right - cmdRect.left,
cmdRect.bottom - cmdRect.top, cmd->bmp.bitmapData, format, 0, 0,
0, &gdi->palette, FREERDP_FLIP_VERTICAL))
if (!freerdp_image_copy_no_overlap(
gdi->primary_buffer, gdi->dstFormat, gdi->stride, cmdRect.left, cmdRect.top,
cmdRect.right - cmdRect.left, cmdRect.bottom - cmdRect.top, cmd->bmp.bitmapData,
format, 0, 0, 0, &gdi->palette, FREERDP_FLIP_VERTICAL))
{
WLog_ERR(TAG, "Failed to process nocodec message");
goto out;

View File

@ -375,9 +375,9 @@ static UINT gdi_SurfaceCommand_Uncompressed(rdpGdi* gdi, RdpgfxClientContext* co
return ERROR_INVALID_DATA;
}
if (!freerdp_image_copy(surface->data, surface->format, surface->scanline, cmd->left, cmd->top,
cmd->width, cmd->height, cmd->data, cmd->format, 0, 0, 0, NULL,
FREERDP_FLIP_NONE))
if (!freerdp_image_copy_no_overlap(surface->data, surface->format, surface->scanline, cmd->left,
cmd->top, cmd->width, cmd->height, cmd->data, cmd->format, 0,
0, 0, NULL, FREERDP_FLIP_NONE))
return ERROR_INTERNAL_ERROR;
invalidRect.left = (UINT16)MIN(UINT16_MAX, cmd->left);
@ -1332,11 +1332,22 @@ static UINT gdi_SurfaceToSurface(RdpgfxClientContext* context,
if (!is_rect_valid(&rect, surfaceDst->width, surfaceDst->height))
goto fail;
if (!freerdp_image_copy(surfaceDst->data, surfaceDst->format, surfaceDst->scanline,
destPt->x, destPt->y, nWidth, nHeight, surfaceSrc->data,
surfaceSrc->format, surfaceSrc->scanline, rectSrc->left,
rectSrc->top, NULL, FREERDP_FLIP_NONE))
goto fail;
if (surfaceDst == surfaceSrc)
{
if (!freerdp_image_copy_overlap(
surfaceDst->data, surfaceDst->format, surfaceDst->scanline, destPt->x,
destPt->y, nWidth, nHeight, surfaceSrc->data, surfaceSrc->format,
surfaceSrc->scanline, rectSrc->left, rectSrc->top, NULL, FREERDP_FLIP_NONE))
goto fail;
}
else
{
if (!freerdp_image_copy_no_overlap(
surfaceDst->data, surfaceDst->format, surfaceDst->scanline, destPt->x,
destPt->y, nWidth, nHeight, surfaceSrc->data, surfaceSrc->format,
surfaceSrc->scanline, rectSrc->left, rectSrc->top, NULL, FREERDP_FLIP_NONE))
goto fail;
}
invalidRect = rect;
region16_union_rect(&surfaceDst->invalidRegion, &surfaceDst->invalidRegion, &invalidRect);
@ -1422,9 +1433,10 @@ static UINT gdi_SurfaceToCache(RdpgfxClientContext* context,
if (!cacheEntry->data)
goto fail;
if (!freerdp_image_copy(cacheEntry->data, cacheEntry->format, cacheEntry->scanline, 0, 0,
cacheEntry->width, cacheEntry->height, surface->data, surface->format,
surface->scanline, rect->left, rect->top, NULL, FREERDP_FLIP_NONE))
if (!freerdp_image_copy_no_overlap(cacheEntry->data, cacheEntry->format, cacheEntry->scanline,
0, 0, cacheEntry->width, cacheEntry->height, surface->data,
surface->format, surface->scanline, rect->left, rect->top,
NULL, FREERDP_FLIP_NONE))
goto fail;
RDPGFX_EVICT_CACHE_ENTRY_PDU evict = { surfaceToCache->cacheSlot };
@ -1478,10 +1490,10 @@ static UINT gdi_CacheToSurface(RdpgfxClientContext* context,
if (!is_rect_valid(&rect, surface->width, surface->height))
goto fail;
if (!freerdp_image_copy(surface->data, surface->format, surface->scanline, destPt->x,
destPt->y, cacheEntry->width, cacheEntry->height, cacheEntry->data,
cacheEntry->format, cacheEntry->scanline, 0, 0, NULL,
FREERDP_FLIP_NONE))
if (!freerdp_image_copy_no_overlap(surface->data, surface->format, surface->scanline,
destPt->x, destPt->y, cacheEntry->width,
cacheEntry->height, cacheEntry->data, cacheEntry->format,
cacheEntry->scanline, 0, 0, NULL, FREERDP_FLIP_NONE))
goto fail;
invalidRect = rect;
@ -1566,9 +1578,10 @@ static UINT gdi_ImportCacheEntry(RdpgfxClientContext* context, UINT16 cacheSlot,
if (!cacheEntry)
goto fail;
if (!freerdp_image_copy(cacheEntry->data, cacheEntry->format, cacheEntry->scanline, 0, 0,
cacheEntry->width, cacheEntry->height, importCacheEntry->data,
PIXEL_FORMAT_BGRX32, 0, 0, 0, NULL, FREERDP_FLIP_NONE))
if (!freerdp_image_copy_no_overlap(cacheEntry->data, cacheEntry->format, cacheEntry->scanline,
0, 0, cacheEntry->width, cacheEntry->height,
importCacheEntry->data, PIXEL_FORMAT_BGRX32, 0, 0, 0, NULL,
FREERDP_FLIP_NONE))
goto fail;
RDPGFX_EVICT_CACHE_ENTRY_PDU evict = { cacheSlot };

View File

@ -59,8 +59,9 @@ HGDI_BITMAP gdi_create_bitmap(rdpGdi* gdi, UINT32 nWidth, UINT32 nHeight, UINT32
pSrcData = data;
nSrcStep = nWidth * FreeRDPGetBytesPerPixel(SrcFormat);
if (!freerdp_image_copy(pDstData, gdi->dstFormat, nDstStep, 0, 0, nWidth, nHeight, pSrcData,
SrcFormat, nSrcStep, 0, 0, &gdi->palette, FREERDP_FLIP_NONE))
if (!freerdp_image_copy_no_overlap(pDstData, gdi->dstFormat, nDstStep, 0, 0, nWidth, nHeight,
pSrcData, SrcFormat, nSrcStep, 0, 0, &gdi->palette,
FREERDP_FLIP_NONE))
{
winpr_aligned_free(pDstData);
return NULL;
@ -183,9 +184,9 @@ static BOOL gdi_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap, const
return FALSE;
}
return freerdp_image_copy(bitmap->data, bitmap->format, 0, 0, 0, DstWidth, DstHeight,
pSrcData, PIXEL_FORMAT_XRGB32, 0, 0, 0, &gdi->palette,
FREERDP_FLIP_VERTICAL);
return freerdp_image_copy_no_overlap(bitmap->data, bitmap->format, 0, 0, 0, DstWidth,
DstHeight, pSrcData, PIXEL_FORMAT_XRGB32, 0, 0, 0,
&gdi->palette, FREERDP_FLIP_VERTICAL);
}
else if (bpp < 32)
{
@ -231,8 +232,9 @@ static BOOL gdi_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap, const
}
}
if (!freerdp_image_copy(bitmap->data, bitmap->format, 0, 0, 0, DstWidth, DstHeight,
pSrcData, SrcFormat, 0, 0, 0, &gdi->palette, FREERDP_FLIP_VERTICAL))
if (!freerdp_image_copy_no_overlap(bitmap->data, bitmap->format, 0, 0, 0, DstWidth,
DstHeight, pSrcData, SrcFormat, 0, 0, 0, &gdi->palette,
FREERDP_FLIP_VERTICAL))
{
WLog_ERR(TAG, "freerdp_image_copy failed");
return FALSE;

View File

@ -405,9 +405,9 @@ static void (^mac_capture_stream_handler)(
}
else
{
freerdp_image_copy(surface->data, surface->format, surface->scanline, x, y, width, height,
pSrcData, PIXEL_FORMAT_BGRX32, nSrcStep, x, y, NULL,
FREERDP_FLIP_NONE);
freerdp_image_copy_no_overlap(surface->data, surface->format, surface->scanline, x, y,
width, height, pSrcData, PIXEL_FORMAT_BGRX32, nSrcStep, x,
y, NULL, FREERDP_FLIP_NONE);
}
LeaveCriticalSection(&(surface->lock));

View File

@ -314,8 +314,9 @@ static int win_shadow_surface_copy(winShadowSubsystem* subsystem)
if (status <= 0)
return status;
if (!freerdp_image_copy(surface->data, surface->format, surface->scanline, x, y, width, height,
pDstData, DstFormat, nDstStep, x, y, NULL, FREERDP_FLIP_NONE))
if (!freerdp_image_copy_no_overlap(surface->data, surface->format, surface->scanline, x, y,
width, height, pDstData, DstFormat, nDstStep, x, y, NULL,
FREERDP_FLIP_NONE))
return ERROR_INTERNAL_ERROR;
ArrayList_Lock(server->clients);

View File

@ -853,10 +853,10 @@ static int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem)
WINPR_ASSERT(image->bytes_per_line >= 0);
WINPR_ASSERT(width >= 0);
WINPR_ASSERT(height >= 0);
success = freerdp_image_copy(surface->data, surface->format, surface->scanline, x, y,
(UINT32)width, (UINT32)height, (BYTE*)image->data,
subsystem->format, (UINT32)image->bytes_per_line, x, y,
NULL, FREERDP_FLIP_NONE);
success = freerdp_image_copy_no_overlap(
surface->data, surface->format, surface->scanline, x, y, (UINT32)width,
(UINT32)height, (BYTE*)image->data, subsystem->format,
(UINT32)image->bytes_per_line, x, y, NULL, FREERDP_FLIP_NONE);
LeaveCriticalSection(&surface->lock);
if (!success)
goto fail_capture;

View File

@ -1335,8 +1335,8 @@ static BOOL shadow_client_send_surface_gfx(rdpShadowClient* client, const BYTE*
WINPR_ASSERT(data);
rc = freerdp_image_copy(data, PIXEL_FORMAT_BGRA32, 0, 0, 0, w, h, pSrcData, SrcFormat,
nSrcStep, cmd.left, cmd.top, NULL, 0);
rc = freerdp_image_copy_no_overlap(data, PIXEL_FORMAT_BGRA32, 0, 0, 0, w, h, pSrcData,
SrcFormat, nSrcStep, cmd.left, cmd.top, NULL, 0);
WINPR_ASSERT(rc);
cmd.data = data;