Refcounting fun

H. Verbeet hverbeet at
Sun Feb 12 10:52:25 CST 2006

On 12/02/06, Stefan Dösinger <stefandoesinger 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)
    return IUnknown_Release(object);

More information about the wine-devel mailing list