client-side DIB copy?
Damjan Jovanovic
damjan.jov at gmail.com
Tue Oct 10 12:01:59 CDT 2006
Hi
I'm trying to implement the "client-side DIB copy optimization"
mentioned in dlls/winex11.drv/bitblt.c, but I'm having trouble. The
patch (against wine-0.9.22) is attached.
The one app I know that uses it, Heroes of might and magic 4, runs
much faster with the patch, but the graphics come out wrong: mouse
droppings, black blocks, pictures drawn in wrong places (over panels)
etc.
Is there something else I am supposed to be doing, like holding some
lock, or doing something after I copy the pixels?
I'd really appreciate any help.
Damjan
-------------- next part --------------
--- 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 );
More information about the wine-devel
mailing list