http://bugs.winehq.org/show_bug.cgi?id=20380
--- Comment #68 from Roderick Colenbrander thunderbird2k@gmail.com 2010-02-08 05:57:19 --- (In reply to comment #67)
Created an attachment (id=26121)
--> (http://bugs.winehq.org/attachment.cgi?id=26121) [details]
patch
I've created a small patch for wine-1.1.38/dlls/winex11.drv/dib.c - see attachment. This patch fixes access flags for DIB image and greatly reduces number of exceptions - so it looks like my HOMM3 works fine.
(In reply to comment #66)
Created an attachment (id=26120)
--> (http://bugs.winehq.org/attachment.cgi?id=26120) [details]
trace with WINEDEBUG=+all
Hello, seems i found where the bug is. Yes, it's access violation when writing to read-only DIB image. (look for the accesses to address 0x1dd0000 in attachment)
in short, the we have:
---> create DIB image to render screen to 0009:trace:bitmap:CreateDIBSection format (800,-600), planes 1, bpp 16, size 960000, RGB ---> then render to our DIB image 0009:trace:bitblt:BitBlt hdcSrc=0x714 0,0 -> hdcDest=0x5cc 0,0 800x600 rop=cc0020 0009:trace:bitblt:X11DRV_StretchBlt vissrc=0,0-800,600 visdst=0,0-800,600 0009:trace:bitmap:X11DRV_DIB_Lock Locking 0x710 from thread 0009 0009:trace:bitmap:X11DRV_DIB_Coerce GdiMod requested in status AppMod 0009:trace:bitmap:X11DRV_DIB_DoProtectDIBSection Changed protection from 4 to 2 ---> DIB image is read-only X11DRV_DIB_DoUpdateDIBSection(); 0009:trace:bitmap:X11DRV_DIB_DoCopyDIBSection Copying from DIB bits to Pixmap 0009:trace:bitmap:X11DRV_DIB_DoProtectDIBSection Changed protection from 2 to 1 ---> and here we have not-accessible DIB image 0009:trace:bitmap:X11DRV_DIB_Unlock Unlocking in status GdiMod 0009:trace:bitmap:X11DRV_DIB_DoProtectDIBSection Changed protection from 1 to 2 ---> but now DIB image only read-only! ---> and when we try to write 0009:trace:ddraw:IDirectDrawSurfaceImpl_Blt (0x1792d8)->(0x339ec4,0x1a71e8,0x339f98,1008000,(nil)) 0009:trace:d3d_surface:IWineD3DBaseSurfaceImpl_LockRect (0x1793d8) : rect@0x339c24 flags(00000000), output lockedRect@0x339c0c, memory@0x1dd0000 ---> we get SIGSEGV (address 01e54fe8 is within range 0x1dd0000-0x1ebb000) 0009:trace:seh:raise_exception code=c0000005 flags=0 addr=0x7ddacaf1 ip=7ddacaf1 tid=0009 0009:trace:seh:raise_exception info[0]=00000001 0009:trace:seh:raise_exception info[1]=01e54fe8 ---> in exception handler we try to restore access flags for read/write 0009:trace:bitmap:X11DRV_DIB_Coerce AppMod requested in status InSync 0009:trace:bitmap:X11DRV_DIB_DoProtectDIBSection Changed protection from 2 to 4 ---> ok, now DIB has r/w-access
This sequence (rw->r->no->r->seh->rw) is repeated again and again generating a log of exceptions and at some moment the program hangs. Disabling audio something helps, maybe because there is no additional threads created for audio processing, but access-violations don't disappear :)
This is the way the DIBSection code is supposed to work. The problem is that the content of a DIBSection needs to be around on the X11 side but programs also have to be able to access the data from a pointer. In order to synchronize both copies there is all this memory protection magic.
In case of a Blt an exception is triggered when the memory copy isn't the latest revision of the image. This is not a problem.
Games which also give issues are ones which use Lock instead of Blt. In such cases we present the DIBSection memory directly to the app. Some programs (at least Populous) directly mess with the stack registers which prevents the memory protection code from recovering from the exception. This is very bad and we consider these apps broken (a DIB engine would fix this OR we shouldn't export the DIBSection memory directly to the app OR prevent the exception from occuring).
The code which I changed in Wine is related to the DIBSection code. Homm3 uses 16-bit and before we had to convert this 16-bit data to 24-bit on each upload (this would likely trigger the memory protection code as well). Due to my xrender work this conversion is not needed. Some code is different now (so perhaps somewhere I forgot to call some dib memory protection related code) or my code was fully correct but uncovered a new bug (I mean that when using the depth conversion, some code 'by accident' disarms the memory protections before they are presented to the app).
Based on what I described above, you might understand that the patch which you proposed is not a correct solution since this is how the DIBSection code should behave. The huge amount of exceptions which occurs is what makes the issue very hard to debug in combination with the fact that for some apps the stack gets corrupted which makes it very hard to find what code triggered the bug.
In case of Homm3 I would recommend to figure out first if the bug is not a result of Homm3 calling Lock/Unlock directly.
Roderick