libfreerdp-gdi: fix SurfaceToSurface overlapping copies

This commit is contained in:
Marc-André Moreau 2014-09-16 17:41:24 -04:00
parent 1837c34e6e
commit c40d8155a6
4 changed files with 117 additions and 11 deletions

View File

@ -628,6 +628,7 @@ int xf_SolidFill(RdpgfxClientContext* context, RDPGFX_SOLID_FILL_PDU* solidFill)
int xf_SurfaceToSurface(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_SURFACE_PDU* surfaceToSurface) int xf_SurfaceToSurface(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_SURFACE_PDU* surfaceToSurface)
{ {
UINT16 index; UINT16 index;
BOOL sameSurface;
int nWidth, nHeight; int nWidth, nHeight;
RDPGFX_RECT16* rectSrc; RDPGFX_RECT16* rectSrc;
RDPGFX_POINT16* destPt; RDPGFX_POINT16* destPt;
@ -638,11 +639,12 @@ int xf_SurfaceToSurface(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_SURFACE_
rectSrc = &(surfaceToSurface->rectSrc); rectSrc = &(surfaceToSurface->rectSrc);
destPt = &surfaceToSurface->destPts[0]; destPt = &surfaceToSurface->destPts[0];
/**not needed?*/
surfaceSrc = (xfGfxSurface*) context->GetSurfaceData(context, surfaceToSurface->surfaceIdSrc); surfaceSrc = (xfGfxSurface*) context->GetSurfaceData(context, surfaceToSurface->surfaceIdSrc);
if (surfaceToSurface->surfaceIdSrc != surfaceToSurface->surfaceIdDest) sameSurface = (surfaceToSurface->surfaceIdSrc == surfaceToSurface->surfaceIdDest) ? TRUE : FALSE;
if (!sameSurface)
surfaceDst = (xfGfxSurface*) context->GetSurfaceData(context, surfaceToSurface->surfaceIdDest); surfaceDst = (xfGfxSurface*) context->GetSurfaceData(context, surfaceToSurface->surfaceIdDest);
else else
surfaceDst = surfaceSrc; surfaceDst = surfaceSrc;
@ -657,16 +659,22 @@ int xf_SurfaceToSurface(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_SURFACE_
{ {
destPt = &surfaceToSurface->destPts[index]; destPt = &surfaceToSurface->destPts[index];
freerdp_image_copy(surfaceDst->data, PIXEL_FORMAT_XRGB32, surfaceDst->scanline, if (sameSurface)
destPt->x, destPt->y, nWidth, nHeight, surfaceSrc->data, PIXEL_FORMAT_XRGB32, {
surfaceSrc->scanline, rectSrc->left, rectSrc->top); freerdp_image_move(surfaceDst->data, PIXEL_FORMAT_XRGB32, surfaceDst->scanline,
destPt->x, destPt->y, nWidth, nHeight, rectSrc->left, rectSrc->top);
}
else
{
freerdp_image_copy(surfaceDst->data, PIXEL_FORMAT_XRGB32, surfaceDst->scanline,
destPt->x, destPt->y, nWidth, nHeight, surfaceSrc->data, PIXEL_FORMAT_XRGB32,
surfaceSrc->scanline, rectSrc->left, rectSrc->top);
}
invalidRect.left = destPt->x; invalidRect.left = destPt->x;
invalidRect.top = destPt->y; invalidRect.top = destPt->y;
invalidRect.right = destPt->x + rectSrc->right; invalidRect.right = destPt->x + rectSrc->right;
invalidRect.bottom = destPt->y + rectSrc->bottom; invalidRect.bottom = destPt->y + rectSrc->bottom;
/**width,height?*/
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect); region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect);
} }

View File

@ -454,6 +454,8 @@ FREERDP_API void freerdp_clrconv_free(HCLRCONV clrconv);
FREERDP_API int freerdp_image_copy(BYTE* pDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, FREERDP_API int freerdp_image_copy(BYTE* pDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst,
int nWidth, int nHeight, BYTE* pSrcData, DWORD SrcFormat, int nSrcStep, int nXSrc, int nYSrc); int nWidth, int nHeight, BYTE* pSrcData, DWORD SrcFormat, int nSrcStep, int nXSrc, int nYSrc);
FREERDP_API int freerdp_image_move(BYTE* pData, DWORD Format, int nStep, int nXDst, int nYDst,
int nWidth, int nHeight, int nXSrc, int nYSrc);
FREERDP_API int freerdp_image_fill(BYTE* pDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, FREERDP_API int freerdp_image_fill(BYTE* pDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst,
int nWidth, int nHeight, UINT32 color); int nWidth, int nHeight, UINT32 color);

View File

@ -1878,6 +1878,91 @@ int freerdp_image_copy(BYTE* pDstData, DWORD DstFormat, int nDstStep, int nXDst,
return -1; return -1;
} }
int freerdp_image_move(BYTE* pData, DWORD Format, int nStep, int nXDst, int nYDst, int nWidth, int nHeight, int nXSrc, int nYSrc)
{
int y;
BOOL overlap;
BYTE* pSrcPixel;
BYTE* pDstPixel;
overlap = (((nXDst + nWidth) > nXSrc) && (nXDst < (nXSrc + nWidth)) &&
((nYDst + nHeight) > nYSrc) && (nYDst < (nYSrc + nHeight))) ? TRUE : FALSE;
if (!overlap)
{
pSrcPixel = &pData[(nYSrc * nStep) + (nXSrc * 4)];
pDstPixel = &pData[(nYDst * nStep) + (nXDst * 4)];
for (y = 0; y < nHeight; y++)
{
CopyMemory(pDstPixel, pSrcPixel, nWidth * 4);
pSrcPixel += nStep;
pDstPixel += nStep;
}
return 1;
}
if (nYSrc < nYDst)
{
/* copy down */
pSrcPixel = &pData[((nYSrc + nHeight - 1) * nStep) + (nXSrc * 4)];
pDstPixel = &pData[((nYDst + nHeight - 1) * nStep) + (nXDst * 4)];
for (y = 0; y < nHeight; y++)
{
CopyMemory(pDstPixel, pSrcPixel, nWidth * 4);
pSrcPixel -= nStep;
pDstPixel -= nStep;
}
}
else if (nYSrc > nYDst)
{
/* copy up */
pSrcPixel = &pData[(nYSrc * nStep) + (nXSrc * 4)];
pDstPixel = &pData[(nYDst * nStep) + (nXDst * 4)];
for (y = 0; y < nHeight; y++)
{
CopyMemory(pDstPixel, pSrcPixel, nWidth * 4);
pSrcPixel += nStep;
pDstPixel += nStep;
}
}
else if (nXSrc > nXDst)
{
/* copy left */
pSrcPixel = &pData[(nYSrc * nStep) + (nXSrc * 4)];
pDstPixel = &pData[(nYDst * nStep) + (nXDst * 4)];
for (y = 0; y < nHeight; y++)
{
MoveMemory(pDstPixel, pSrcPixel, nWidth * 4);
pSrcPixel += nStep;
pDstPixel += nStep;
}
}
else
{
/* copy right */
pSrcPixel = &pData[(nYSrc * nStep) + (nXSrc * 4)];
pDstPixel = &pData[(nYDst * nStep) + (nXDst * 4)];
for (y = 0; y < nHeight; y++)
{
MoveMemory(pDstPixel, pSrcPixel, nWidth * 4);
pSrcPixel += nStep;
pDstPixel += nStep;
}
}
return 1;
}
void* freerdp_image_memset32(UINT32* ptr, UINT32 fill, size_t length) void* freerdp_image_memset32(UINT32* ptr, UINT32 fill, size_t length)
{ {
while (length--) while (length--)

View File

@ -633,6 +633,7 @@ int gdi_SolidFill(RdpgfxClientContext* context, RDPGFX_SOLID_FILL_PDU* solidFill
int gdi_SurfaceToSurface(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_SURFACE_PDU* surfaceToSurface) int gdi_SurfaceToSurface(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_SURFACE_PDU* surfaceToSurface)
{ {
UINT16 index; UINT16 index;
BOOL sameSurface;
int nWidth, nHeight; int nWidth, nHeight;
RDPGFX_RECT16* rectSrc; RDPGFX_RECT16* rectSrc;
RDPGFX_POINT16* destPt; RDPGFX_POINT16* destPt;
@ -646,7 +647,9 @@ int gdi_SurfaceToSurface(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_SURFACE
surfaceSrc = (gdiGfxSurface*) context->GetSurfaceData(context, surfaceToSurface->surfaceIdSrc); surfaceSrc = (gdiGfxSurface*) context->GetSurfaceData(context, surfaceToSurface->surfaceIdSrc);
if (surfaceToSurface->surfaceIdSrc != surfaceToSurface->surfaceIdDest) sameSurface = (surfaceToSurface->surfaceIdSrc == surfaceToSurface->surfaceIdDest) ? TRUE : FALSE;
if (!sameSurface)
surfaceDst = (gdiGfxSurface*) context->GetSurfaceData(context, surfaceToSurface->surfaceIdDest); surfaceDst = (gdiGfxSurface*) context->GetSurfaceData(context, surfaceToSurface->surfaceIdDest);
else else
surfaceDst = surfaceSrc; surfaceDst = surfaceSrc;
@ -661,9 +664,17 @@ int gdi_SurfaceToSurface(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_SURFACE
{ {
destPt = &surfaceToSurface->destPts[index]; destPt = &surfaceToSurface->destPts[index];
freerdp_image_copy(surfaceDst->data, surfaceDst->format, surfaceDst->scanline, if (sameSurface)
destPt->x, destPt->y, nWidth, nHeight, surfaceSrc->data, surfaceSrc->format, {
surfaceSrc->scanline, rectSrc->left, rectSrc->top); freerdp_image_move(surfaceDst->data, surfaceDst->format, surfaceDst->scanline,
destPt->x, destPt->y, nWidth, nHeight, rectSrc->left, rectSrc->top);
}
else
{
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);
}
invalidRect.left = destPt->x; invalidRect.left = destPt->x;
invalidRect.top = destPt->y; invalidRect.top = destPt->y;