I came to the conclusion that the slowness in "Heroes IV" it has to do with
sync'ing lage bitmaps between application DIBs and X Server(see the log: http://bugs.winehq.org/attachment.cgi?id=1470&action=view ).

Also, a complete description of the bug is here: http://bugs.winehq.org/show_bug.cgi?id=3902

So i had this ideea that every GDI function could memorise the rectangle that is modifying, so each time a sync between DIB and X Server is needed, only a small part from the bitmap will get copied! I also made some changes to dib.c, bitblt.c and x11drv.h in "wine-0.9.2\dlls\x11drv" folder to implement my ideea, keeping backwards compatibility (if a DIB function doesn't set a valid rectangle for the bitmap that its modifying, the default values are taken - which is the entire bitmap)

The changes i was talking about are listed below! My free time is very limited and i would strongly appreciate some help, moustly because something is not working ;( and i didn't manage to figure out what...

-added member to X_PHYSBITMAP:

XRectangle modified_rect;

-added 2 functions:

/***********************************************************************
*           X11DRV_SetBoundRect
*/
void X11DRV_SetBoundRect(X_PHYSBITMAP *physBitmap, INT x, INT y, INT width, INT height)
{
        XRectangle *t;
        INT xMin,yMin,xMax,yMax;

        if (!physBitmap) return;

        t = &(physBitmap->modified_rect);

        if ( t->width && t->height && /*already a valid rect inside*/
            width && height ) /*not trying to invalidate rect*/
        {
                //calculate the union of the two rectangles
                xMin = ((t->x < x)?t->x:x);
                yMin = ((t->y < y)?t->y:y);
                xMax = ((t->x + t->width > x + width)?(t->x + t->width):(x + 
width));
                yMax = ((t->y + t->height > y + height)?(t->y + t->height):(y + 
height));

                t->x = xMin;
                t->y = yMin;
                t->width = xMax - xMin;
                t->height = yMax - yMin;

        }
        else
        {
                t->x = x;
                t->y = y;
                t->width = width;
                t->height = height;
        }

TRACE("(%p,%d,%d,%d,%d)\n", physBitmap->hbitmap, t->x, t->y, t->width, t->height);

}

/***********************************************************************
*           X11DRV_GetBoundRect
*/
UINT X11DRV_GetBoundRect(X_PHYSBITMAP *physBitmap, INT *x, INT *y, INT *width, INT *height)
{

        DIBSECTION dib;
        XRectangle *t;


if (!physBitmap || GetObjectW( physBitmap->hbitmap, sizeof(dib), &dib ) != sizeof(dib))
        {
                ERR("called for non-DIBSection!?\n");
                return 1;
        }

        t = &(physBitmap->modified_rect);

        /* we should check for oversize values */
        if ( (t->width > 0) && (t->height > 0) &&
             (t->x < dib.dsBm.bmWidth) && (t->y < dib.dsBm.bmHeight) )
        {
                *x = t->x;
                *y = t->y;

                if (t->x + t->width > dib.dsBm.bmWidth)
                        *width = dib.dsBm.bmWidth - t->x;
                else
                        *width = t->width;

                if (t->y + t->height > dib.dsBm.bmHeight)
                        *height = dib.dsBm.bmHeight - t->y;
                else
                        *height = t->height;
        }
        else
        {
                *x = 0;
                *y = 0;
                *width = dib.dsBm.bmWidth;
                *height = dib.dsBm.bmHeight;
        }

        TRACE("(%p,%d,%d,%d,%d)\n", physBitmap->hbitmap, *x, *y, *width, 
*height);

        return 0;
}

-changed X11DRV_DIB_DoUpdateDIBSection like this:

static void X11DRV_DIB_DoUpdateDIBSection(X_PHYSBITMAP *physBitmap, BOOL toDIB)
{
        INT x,y,width,height;

        if ( X11DRV_GetBoundRect(physBitmap,&x,&y,&width,&height) ) return;

        /*invalidate bound rect*/
        X11DRV_SetBoundRect(physBitmap,0,0,0,0);

   X11DRV_DIB_DoCopyDIBSection(physBitmap, toDIB,
                               physBitmap->colorMap, physBitmap->nColorMap,
physBitmap->pixmap, x, y, x, y, // i think something is wrong here (help?)
                               width, height);

}

- and finally, a GDI function calls it like this (for example bitblt):

   X11DRV_SetBoundRect(physDevDst->bitmap,xDst,yDst,width,height);
   X11DRV_CoerceDIBSection( physDevDst, DIB_Status_GdiMod, FALSE );
   if (physDevDst != physDevSrc)
   {
     X11DRV_SetBoundRect(physDevSrc->bitmap,xSrc,ySrc,width,height);
     X11DRV_CoerceDIBSection( physDevSrc, DIB_Status_GdiMod, FALSE );
   }
result = BITBLT_InternalStretchBlt( physDevDst, xDst, yDst, width, height, physDevSrc, xSrc, ySrc, width, height, rop );

END:
   if (physDevDst != physDevSrc)
     X11DRV_UnlockDIBSection( physDevSrc, FALSE );
   X11DRV_UnlockDIBSection( physDevDst, TRUE );




Reply via email to