Hi, I think I've found the cause of the Empire Earth crash. This is not a reference counting problem at all, Empire Earth releases the DirectDraw and Surface objects on purpose. This is what happens:
1) EE creates a DDraw object 2) It attaches a Complex Surface 3) It sets up a D3D device for this Surface 4) EE performs a Flip(NULL, 0x20) on the surface 5) It Releases the DirectDraw object 6) It Releases the surface
Wine releases the surface in 5), Windows doesn't. It appears to me, that Windows doesn't release Surfaces which have a D3D object attached when the DDraw instance they belong to is freed.
I have written a small test app, which reproduces EEs behaviour. It crashes in Wine, but worksin Windows 2000. I'll do some more tests and submit a patch.
Stefan
--- Stefan Dösinger stefandoesinger@gmx.at wrote:
Hi, I think I've found the cause of the Empire Earth crash. This is not a reference counting problem at all, Empire Earth releases the DirectDraw and Surface objects on purpose. This is what happens:
- EE creates a DDraw object
- It attaches a Complex Surface
- It sets up a D3D device for this Surface
- EE performs a Flip(NULL, 0x20) on the surface
- It Releases the DirectDraw object
- It Releases the surface
Wine releases the surface in 5), Windows doesn't. It appears to me, that Windows doesn't release Surfaces which have a D3D object attached when the DDraw instance they belong to is freed.
I have written a small test app, which reproduces EEs behaviour. It crashes in Wine, but worksin Windows 2000. I'll do some more tests and submit a patch.
by the sound of things an internal reference is missing, up until 6 a reference should be kept, preventing the surface from being released at 5.
Oliver.
Stefan
___________________________________________________________ Yahoo! Messenger - NEW crystal clear PC to PC calling worldwide with voicemail http://uk.messenger.yahoo.com
Am Donnerstag, 8. September 2005 18:24 schrieb Oliver Stieber:
--- Stefan Dösinger stefandoesinger@gmx.at wrote:
Hi, I think I've found the cause of the Empire Earth crash. This is not a reference counting problem at all, Empire Earth releases the DirectDraw and Surface objects on purpose. This is what happens:
- EE creates a DDraw object
- It attaches a Complex Surface
- It sets up a D3D device for this Surface
- EE performs a Flip(NULL, 0x20) on the surface
- It Releases the DirectDraw object
- It Releases the surface
Wine releases the surface in 5), Windows doesn't. It appears to me, that Windows doesn't release Surfaces which have a D3D object attached when the DDraw instance they belong to is freed.
I have written a small test app, which reproduces EEs behaviour. It crashes in Wine, but worksin Windows 2000. I'll do some more tests and submit a patch.
by the sound of things an internal reference is missing, up until 6 a reference should be kept, preventing the surface from being released at 5.
No, Wine frees all Surfaces attached to a DDraw object once the DDraw object is freed, no matter how many references the Surface has. Windows does the same for normal surfaces(I checked it), but as it looks not for D3D Surfaces.
If the surface doesn't have a D3D object attached, the above combination leeds to a crash even in Windows.
From the log: 0009:trace:ddraw:Main_DirectDraw_Release (0x7fe00430)->() decrementing from 2. 0009:trace:ddraw:Main_DirectDraw_Release (0x7fe00430)->() decrementing from 1. 0009:warn:ddraw:Main_DirectDrawSurface_ForceDestroy destroying surface 0x5e52f958 with refcnt 2 0009:trace:ddraw:gltex_final_release deleting texture with GL id 0. 0009:warn:ddraw:Main_DirectDrawSurface_ForceDestroy destroying surface 0x5e535ba8 with refcnt 2 0009:trace:ddraw:gltex_final_release deleting texture with GL id 0. 0009:warn:ddraw:Main_DirectDrawSurface_ForceDestroy destroying surface 0x5e535680 with refcnt 2 0009:trace:ddraw:gltex_final_release deleting texture with GL id 0. 0009:warn:ddraw:Main_DirectDrawSurface_ForceDestroy destroying surface 0x5e5352e0 with refcnt 2 0009:trace:ddraw:gltex_final_release deleting texture with GL id 0. 0009:warn:ddraw:Main_DirectDrawSurface_ForceDestroy destroying surface 0x5e54fb00 with refcnt 2 0009:trace:ddraw:gltex_final_release deleting texture with GL id 0. 0009:warn:ddraw:Main_DirectDrawSurface_ForceDestroy destroying surface 0x5e54f5d8 with refcnt 2 0009:trace:ddraw:gltex_final_release deleting texture with GL id 0. 0009:warn:ddraw:Main_DirectDrawSurface_ForceDestroy destroying surface 0x5e5650d8 with refcnt 2 0009:trace:ddraw:gltex_final_release deleting texture with GL id 0. 0009:warn:ddraw:Main_DirectDrawSurface_ForceDestroy destroying surface 0x5e564bb0 with refcnt 1 0009:trace:ddraw:gltex_final_release deleting texture with GL id 0. 0009:warn:ddraw:Main_DirectDrawSurface_ForceDestroy destroying surface 0x7fe04738 with refcnt 2 0009:trace:ddraw:DIB_DirectDrawSurface_free_dc Releasing DC for surface: 0x7fe04738 0009:warn:ddraw:Main_DirectDrawSurface_ForceDestroy destroying surface 0x7fe04398 with refcnt 1 0009:trace:ddraw:User_DirectDrawSurface_final_release waiting for update thread to terminate... 0009:trace:ddraw:User_DirectDrawSurface_final_release update thread terminated 0009:trace:ddraw:DIB_DirectDrawSurface_free_dc Releasing DC for surface: 0x7fe04398 0009:trace:ddraw:Main_DirectDraw_Release (0x7fe000e0)->() decrementing from 1. wine: Unhandled exception (thread 0009), starting debugger... ->Crash due to Releasing a surface attached to DDraw 0x7fe00430
There are a lot of surfaces attached, which are destroyed, and only the Complex surface with the D3D object should survive. Empire Earth also doesn't touch the other surfaces any more.
It's also fine that EE releases the DDraw instance here. It perfoms a lot of checks on a lot of things, and it initialises numerous DDraw objects, Surfaces and D3D objects and Releases them again to check if they are working.
Stefan
Wine releases the surface in 5), Windows doesn't. It appears to me, that Windows doesn't release Surfaces which have a D3D object attached when the DDraw instance they belong to is freed.
Yeah, I suspected that the problem was in the 'force destroy' code. Could you change your test script to get the reference count of the 'complex' object before release of the DDraw object and after ? Could you do the same for the 'normal' objects (mostly before as after it will crash :-) ) ?
After that, it's always a bit tricky to test stuff like this as non-crashing is not a definite proof that the object was not actually destroyed...
Lionel
Hi,
Yeah, I suspected that the problem was in the 'force destroy' code. Could you change your test script to get the reference count of the 'complex' object before release of the DDraw object and after ? Could you do the same for the 'normal' objects (mostly before as after it will crash :-) ) ?
Do you mean on Windows or on Wine? How can I get these members from an external application? I thought that apps can't look inside a COM object, as the structures used by the libs and the structures exported to the app are different.
Well, on the Wine side, I can hack on these thing, but on Windows?
--- Stefan Dösinger stefandoesinger@gmx.at wrote:
Hi,
Yeah, I suspected that the problem was in the 'force destroy' code. Could you change your test script to get the reference count of the 'complex' object before release of the DDraw object and after ? Could you do the same for the 'normal' objects (mostly before as after it will crash :-) ) ?
Do you mean on Windows or on Wine? How can I get these members from an external application? I thought that apps can't look inside a COM object, as the structures used by the libs and the structures exported to the app are different.
Well, on the Wine side, I can hack on these thing, but on Windows?
You should be able to do an AddRef + Release ref.
Oliver.
___________________________________________________________ Yahoo! Messenger - NEW crystal clear PC to PC calling worldwide with voicemail http://uk.messenger.yahoo.com
On Thu, Sep 08, 2005 at 09:20:39PM +0200, Stefan Dösinger wrote:
Do you mean on Windows or on Wine? How can I get these members from an external application? I thought that apps can't look inside a COM object, as the structures used by the libs and the structures exported to the app are different.
Well, just do an 'AddRef' which returns the (now incremented) reference count and then a Release. If you print the returned value minus one, you will get the current reference count at the moment of the call.
Lionel
Am Donnerstag, 8. September 2005 22:03 schrieb Lionel Ulmer:
On Thu, Sep 08, 2005 at 09:20:39PM +0200, Stefan Dösinger wrote:
Do you mean on Windows or on Wine? How can I get these members from an external application? I thought that apps can't look inside a COM object, as the structures used by the libs and the structures exported to the app are different.
Well, just do an 'AddRef' which returns the (now incremented) reference count and then a Release. If you print the returned value minus one, you will get the current reference count at the moment of the call.
I think you're right. After Releasing the DDraw object two times, as EE does, it's far from beeing freed: It has a refcount of 8!! In particular, creating the surface and performing QueryInterface on it increase the refcount by 1, creating a D3D device increases the refcount by 7.
I'll do more tests.
Stefan
On Thu, Sep 08, 2005 at 10:37:56PM +0200, Stefan Dösinger wrote:
I think you're right. After Releasing the DDraw object two times, as EE does, it's far from beeing freed: It has a refcount of 8!! In particular, creating the surface and performing QueryInterface on it increase the refcount by 1, creating a D3D device increases the refcount by 7.
What you could test is artifically increase the refcount of 'normal' surfaces and check if these are deleted or not.
Lionel
Hello,
What you could test is artifically increase the refcount of 'normal' surfaces and check if these are deleted or not.
Sorry for the delay, I was busy over the weekend, but here are some more results. I hope I wasn't misslead by anything again ;-)
*Windows increases the refcount of the DirectDraw7 object by 1 when a surface is created. When the surface is released, the refcount of the DirectDraw7 object is decreased, obviously. Wine doesn't do so(yet), and to my current knowledge, this is what makes Empire Earth crash.
*Windows does free all Surfaces, once their DirectDraw7 parent is freed. So Wine is correct in doing the same. The refcount of the surfaces doesn't matter in this case.
*It's irrelevant if a D3D object is involved or not. Creating a D3D object just increases the refcount of the DirectDraw7 object and the surface, so more releases are neccessary, that's all.
I am looking for a good place to place the AddRef and Release calls to solve the first issue, and I'll send a patch as soon as I have one. I hope that my Cooperative Level patch is applied at this time, this will make creating another patch easier.
Stefan
*Windows increases the refcount of the DirectDraw7 object by 1 when a surface is created. When the surface is released, the refcount of the DirectDraw7 object is decreased, obviously. Wine doesn't do so(yet), and to my current knowledge, this is what makes Empire Earth crash.
Yeah, this is what I suspected: that Wine had some reference counting differences with Windows that provoked this error.
Best would be to write a 'DDraw' test (integrated in the test suite) to be able to check reference counting in some 'standard' cases (surface creation, D3D object creation, ...).
I am looking for a good place to place the AddRef and Release calls to solve the first issue, and I'll send a patch as soon as I have one.
Well, as we call a DDraw 'method' to create the surface, you should add the AddRef call there. For the release, it should be in the 'final_release' call for the surface (AFAIK, each surface already stores a pointer to its parent DDraw object).
Lionel
Best would be to write a 'DDraw' test (integrated in the test suite) to be able to check reference counting in some 'standard' cases (surface creation, D3D object creation, ...).
I am afraid this will have to wait a few days, as I don't have access to any Windows machine the next days.
Well, as we call a DDraw 'method' to create the surface, you should add the AddRef call there. For the release, it should be in the 'final_release' call for the surface (AFAIK, each surface already stores a pointer to its parent DDraw object).
How about this one? It increases the refcount in Main_DirectDraw_AddSurface and decreases it in Main_DirectDraw_RemoveSurface, the places where the surface is attached / removed from the DirectDraw7's surface list.
Hello Lionel, Now that I think that the refcount crash is solved and I'm waiting for the patch I've sent to be reviewed and commited, I've looked into the OpenGL crash: I know the following cases
*Hardware accellerated, with fglrx: Crash in fglrx[1] *Hardware accellerated, other implementation: Crash in some DDraw DIP function *No hardware accelleration: No crash, Main Menu finally starts, but only with a black screen[2]
I've uploaded two logs to my homepage, [1] and [2], if you want to look at them. Well I noticed 2 things:
*Empire Earth starts using a new thread to do ddraw things. *Sigh* *There's some problem due to a missing Z Buffer
Is the first thing likely to cause problems? You told me so some time ago, but it doesn't look like it in the logs. The Z buffer thing is more suspicious to me, but the code path with leads to the crash seems to be prepared for this. Do you have any suggestions?
When I start the game without hw accel, I can take screen shots with the game's screen shot functionality. They show text elements and the mouse pointer. The background and the button decorations are not drawn. See [3]. I can control the menu with the keyboard and start the map editor, which has the in-game graphics. It's basically the same as the menu, text and mouse pointer only, but luckily no further crash :-)
Thanks for taking the time, Stefan
[1] http://doesi.gmxhome.de/ee.fglrx-crash.bz2 [2] http://doesi.gmxhome.de/ee.mesa.bz2 [3] http://doesi.gmxhome.de/EE000.jpg