On 12/02/06, Stefan Dösinger stefandoesinger@gmx.at wrote:
Could it be that d3d9 surfaces and textures are the same objects on windows? What happens if you QueryInterface the surface for the texture GUID?
It returns 0x80004002 (E_NOINTERFACE). Same thing for the reverse.
When the app releases the compound, it (hopefully) calls the release method of the first surface.
At least for d3d9, it's not guaranteed which surface / texture gets released last. Could be the texture, could be the first surface, could be any of the other surfaces.
My suggestion is to keep d3dX specific refcounting in ddraw / d3d8 / d3d9, and use the WineD3D refcounts for wined3d internal things. A quick guessis to seperate the D3D9 release code from the cleanup code, instead of doing this in WineD3D.
With the solution mentioned in my previous post, d3d7/8/9 objects would essentially not be real COM objects on their own, they would just wrap the relevant wined3d AddRef/Release functions, and not have refcounts of their own. Wined3d would be responsible for it's own refcounting, and cleaning up the d3d7/8/9 "object" as part of it's own cleanup. Separating the d3d9 cleanup and release code would obviously be part of that. Note that if we separate the cleanup and release code we can't just call the cleanup code from wined3d, because we don't know the type of the parent, all we have is an IUnknown pointer. Which is why we would have to pass a pointer to that function to wined3d during object creation.
What happens if a texture has 2 surface levels? A GetSurfaceLevel for the first level AddRefs both the texture and the surface. A GetSurfaceLevel for the secound addrefs the texture and the 2nd surface, but what happens to the first one? A Release() of the first surface Releases() the texture, what happens to the secound surface?
The reference count appears to be shared between the texture and all of its surfaces. This is the output of a small test program I wrote:
texture_refs.c:67:Calling CreateTexture texture_refs.c:69:texture @ 001DB220 texture_refs.c:71:texture refs: 1 texture_refs.c:73:Calling GetSurfaceLevel (0) texture_refs.c:75:surface 0 @ 001DB420 texture_refs.c:78:texture refs: 2 texture_refs.c:79:surface 0 refs: 2 texture_refs.c:82:QueryInterface for surface on texture returned 0x80004002, ptr 00000000 texture_refs.c:84:QueryInterface for texture on surface 0 returned 0x80004002, ptr 00000000 texture_refs.c:86:Calling GetSurfaceLevel (1) texture_refs.c:88:surface 1 @ 001DB540 texture_refs.c:92:texture refs: 3 texture_refs.c:93:surface 0 refs: 3 texture_refs.c:94:surface 1 refs: 3 texture_refs.c:96:Calling Release on texture texture_refs.c:101:texture refs: 2 texture_refs.c:102:surface 0 refs: 2 texture_refs.c:103:surface 1 refs: 2 texture_refs.c:105:Calling Release on surface 1 texture_refs.c:110:texture refs: 1 texture_refs.c:111:surface 0 refs: 1 texture_refs.c:112:surface 1 refs: 1 texture_refs.c:114:Calling AddRef on surface 0 texture_refs.c:119:texture refs: 2 texture_refs.c:120:surface 0 refs: 2 texture_refs.c:121:surface 1 refs: 2
The refcounts in that program are retrieved like this: static int get_refcount(IUnknown *object) { IUnknown_AddRef(object); return IUnknown_Release(object); }