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