--- a/dlls/winex11.drv/bitblt.c 2006-07-10 18:01:09.000000000 +0200 +++ b/dlls/winex11.drv/bitblt.c 2006-10-10 18:22:21.000000000 +0200 @@ -1526,6 +1526,75 @@ /*********************************************************************** + * X11DRV_ClientSideDIBCopy + */ +static BOOL X11DRV_ClientSideDIBCopy( X11DRV_PDEVICE *physDevSrc, INT xSrc, INT ySrc, + X11DRV_PDEVICE *physDevDst, INT xDst, INT yDst, + INT width, INT height ) +{ + DIBSECTION srcDib, dstDib; + BYTE *srcPtr, *dstPtr; + INT widthBytes, srcOffsetBytes, dstOffsetBytes; + INT i; + + switch (physDevSrc->depth) + { + case 1: + widthBytes = (width / 8) + (((width % 8) > 0) ? 1 : 0); + srcOffsetBytes = (xSrc / 8) + (((xSrc % 8) > 0) ? 1 : 0); + dstOffsetBytes = (xDst / 8) + (((xDst % 8) > 0) ? 1 : 0); + break; + case 4: + widthBytes = (width / 2) + (((width % 2) > 0) ? 1 : 0); + srcOffsetBytes = (xSrc / 2) + (((xSrc % 2) > 0) ? 1 : 0); + dstOffsetBytes = (xDst / 2) + (((xDst % 2) > 0) ? 1 : 0); + break; + case 8: + widthBytes = width; + srcOffsetBytes = xSrc; + dstOffsetBytes = xDst; + break; + case 15: + case 16: + widthBytes = width * 2; + srcOffsetBytes = xSrc * 2; + dstOffsetBytes = xDst * 2; + break; + case 24: + widthBytes = width * 3; + srcOffsetBytes = xSrc * 3; + dstOffsetBytes = xDst * 3; + break; + case 32: + widthBytes = width * 4; + srcOffsetBytes = xSrc * 4; + dstOffsetBytes = xDst * 4; + break; + default: + FIXME("don't know how to work with a depth of %d\n", physDevSrc->depth); + return FALSE; + } + + if (GetObjectW(physDevSrc->bitmap->hbitmap, sizeof(srcDib), &srcDib) != sizeof(srcDib)) + return FALSE; + if (GetObjectW(physDevDst->bitmap->hbitmap, sizeof(dstDib), &dstDib) != sizeof(dstDib)) + return FALSE; + + srcPtr = &physDevSrc->bitmap->base[ySrc*srcDib.dsBm.bmWidthBytes + srcOffsetBytes]; + dstPtr = &physDevDst->bitmap->base[yDst*dstDib.dsBm.bmWidthBytes + dstOffsetBytes]; + + for (i = 0; i < height; ++i) + { + memcpy(dstPtr, srcPtr, widthBytes); + srcPtr += srcDib.dsBm.bmWidthBytes; + dstPtr += dstDib.dsBm.bmWidthBytes; + } + + return TRUE; +} + + +/*********************************************************************** * X11DRV_BitBlt */ BOOL X11DRV_BitBlt( X11DRV_PDEVICE *physDevDst, INT xDst, INT yDst, @@ -1587,6 +1656,12 @@ height = visRectDst.bottom - visRectDst.top; if (sDst == DIB_Status_AppMod) { + result = X11DRV_ClientSideDIBCopy( physDevSrc, xSrc, ySrc, + physDevDst, xDst, yDst, + width, height ); + if (result) + goto END; + /* fall-back */ FIXME("potential optimization - client-side DIB copy\n"); } X11DRV_CoerceDIBSection( physDevDst, DIB_Status_GdiMod, FALSE );