Re: BUG (3920) + sync between DIBs and X Server optimisation. (please help)
Yeah, i also belive putting the modifying rect in Coerce is better, when i first made the changes i just wanted to modify as little as possible and add things without modifying the already existing code too much, keeping it clean. I also belive i am doing something wrong: I noticed that in X11DRV_DIB_CopyDIBSection() function created to optimise bitblt(), the sync is done this way: X11DRV_DIB_DoCopyDIBSection(physBitmap, FALSE, colorMap, nColorMap, physDevDst->drawable, xSrc, ySrc, physDevDst->org.x + xDest, physDevDst->org.y + yDest, width, height); They take in consideration the (org.x,org.y) in the physical device! I don't understand too well what a physical devise exactly is, and i was wondering if i am not mistaking when i sync like this in X11DRV_DIB_DoUpdateDIBSection(): X11DRV_DIB_DoCopyDIBSection(physBitmap, toDIB, physBitmap->colorMap, physBitmap->nColorMap, physBitmap->pixmap, x, y, x, y, width, height); and not taking in consideration the origins of the device? Iulian From: Robert Shearman <[EMAIL PROTECTED]> To: Marinescu-Ghetau Iulian <[EMAIL PROTECTED]> CC: wine-devel@winehq.org Subject: Re: BUG (3920) + sync between DIBs and X Server optimisation. (please help) Date: Mon, 12 Dec 2005 11:07:20 -0600 Marinescu-Ghetau Iulian wrote: 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) - 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 ); } I think it would be better to make X11DRV_CoerceDIBSection take the parameters for a bounding rect, otherwise it is possible to forget a call to SetBoundRect and cause the DIB to not be updated. -- Rob Shearman
BUG (3920) + sync between DIBs and X Server optimisation. (please help)
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 );
Unnormal slowness in Heroes 4 (X11DRV_BitBlt?)
See http://bugs.winehq.org/show_bug.cgi?id=3902 Hey guys, a bit of help here! I did the following changes: -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, 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 ); What am i doing wrong, i mean is my logic correct ?
Re: Please HELP, info required about 'DIB_Status_GdiMod' and 'DIB_Status_AppMod'
Hi there, Thanks alot for all the information, it helped me a great deal in understanding the problem and trying to solve it! I would like to ask you one more thing: if its not too much trouble for you, could you have a look over the few lines i wrote at "http://bugs.winehq.org/show_bug.cgi?id=3902#c4"; and tell me what you think ? I found a way to fix the Bug and improve general bitmaps performance and wanted to know if it could work, before i start coding ! Iulian From: Robert Shearman <[EMAIL PROTECTED]> To: Marinescu-Ghetau Iulian <[EMAIL PROTECTED]> CC: wine-devel@winehq.org Subject: Re: Please HELP, info required about 'DIB_Status_GdiMod' and 'DIB_Status_AppMod' Date: Tue, 29 Nov 2005 11:25:23 -0600 Marinescu-Ghetau Iulian wrote: Hello, Could anyone give me some more info on X11DRV_CoerceDIBSection function and the logic behind using 'DIB_Status_GdiMod' and 'DIB_Status_AppMod' stats? I am trying to repair a bug (3902) that has to do with application waiting exccessivly on some locks and i am kind of lost ;( Any help would be greatly appreciated! That code is designed to keep DIBs sync'ed between applications and the X server. When the application does a Win32 GDI call then the state of the DIB gets set to DIB_Status_GdiMod and the memory that backs the DIB is set to no-access so that a page fault occurs if the application tries to read it. A handler detects this and downloads the DIB from the X server and sets the state to DIB_Status_None. In this state the DIB memory is set to read-only, so that a page fault occurs if the application tries to write it. The same handler also detects this and consequentially sets the DIB state to DIB_Status_AppMod and allows full access to the DIB memory. If this doesn't answer help with your bug then you'll have to be more specific. -- Rob Shearman
Please HELP, info required about 'DIB_Status_GdiMod' and 'DIB_Status_AppMod'
Hello, Could anyone give me some more info on X11DRV_CoerceDIBSection function and the logic behind using 'DIB_Status_GdiMod' and 'DIB_Status_AppMod' stats? I am trying to repair a bug (3902) that has to do with application waiting exccessivly on some locks and i am kind of lost ;( Any help would be greatly appreciated! Iulian