Am Donnerstag 29 Juni 2006 16:43 schrieb Krzysztof Benkowski:
Hello,
In the latest version of wine (0.9.16) there is a regression which makes
Dune 2000 crash.
After some debugging i found that the problem lays in
IDirectDrawSurfaceImpl_Release method.
The game (Dune 2000) shows that the assumption that all attached
surfaces should be destroyed
regardless of their refcount is wrong.
According to the msdn this should happen,
and it sounds logical to me. All
complex surfaces are created with one call, so they should be destroyed with
one call too.
I haven't seen a single app explicitly releasing the back buffer, even the sdk
demos don't do that. Ideally a test case could be of help, but I don't know
how to test if a surface is actually destroyed.
What causes the crash in few words:
- first Dune 2000 creates a surface with a backbuffer
- then it gets the backbuffer interface by GetAttachedSurface method
(refcount for the backbuffer is incremented)
- it releases the frontbuffer (the backbuffer is destroyed even though
its refcount is higher than frontbuffer's)
Are you sure that the front buffer
is meant to be destroyed? Maybe the front
buffer's refcount is meant to be increased somewhere, so it isn't destroyed?
- creates new frontbuffer and an offscreen plain
Does it attach the front buffer to the back buffer, or vice versa?
So my fix is rather quick and thus i'm not quite
sure if it's correct.
That's because the game works with it
but when it quits it leaves the backbuffer not released. I don't know if
it's the game's fault or the fix has to be
done some other way. I've done it this way:
--- surface.c 26 Jun 2006 12:15:20 -0000 1.6
+++ surface.c 29 Jun 2006 14:09:59 -0000
@@ -377,7 +377,7 @@ IDirectDrawSurfaceImpl_Release(IDirectDr
while( (surf = This->next_complex) )
{
This->next_complex = surf->next_complex; /* Unchain it
from the complex listing */
- IDirectDrawSurfaceImpl_Destroy(surf); /* Destroy it */
+ IDirectDrawSurfaceImpl_Release(surf); /* Release it */
}
This was my original way of handling this, and it lead to huge memory
leaks in
3D games which create mipmap textures. Usually they call getAttachedSurface
for the sublevels and didn't care to release the surfaces.
If someone can think of a way to prove that a COM object is actually destroyed
then a test case might clear up this issue.
Stefan