Refcounting fun

H. Verbeet hverbeet at gmail.com
Sun Feb 12 14:41:12 CST 2006


On 12/02/06, Stefan Dösinger <stefandoesinger at gmx.at> wrote:
> Hi,
> I've thought over this: If you want to connect the IWineD3DTexture and
> IWineD3DSurface refcounts only, then there's no problem for me. If you want
> to connect the Texture's and Surface's Parents refcount,
Are you talking about IDirect3DSurface9 <=> IDirect3DTexture9 or do
you mean IDirect3DSurface9 <=> IWineD3DSurface?

> then you have do the
> same for the rendertargets and the swapchain(I guess that Windows does that
> too), and I can use that connection to manage complex ddraw surfaces.
I haven't verified it, but the MSDN documentation for GetContainer
appears to imply that it does.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3DSurface9__GetContainer.asp
Unfortunately my knowledge of ddraw and d3d7 is somewhat limited, so
it's a bit hard for me to oversee all the implications those changes
would have for ddraw / d3d7. The choice for Surface and Texture as an
example is somewhat arbitrary I guess, but probably the one for which
it matters the most. (As in, is most likely to break stuff if it isn't
implemented correctly). In principle it would change for any object
that has a container or uses similar construction. Perhaps it would
even make sense to forward AddRef and Release calls for all d3d7/8/9
objects that directly wrap a wined3d object.

For reference, the code for Release & CleanUp would look something
like this for the different objects:

/* WineD3D Surface */
ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface) {
    IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
    if (This->container) {
        return IWineD3DBase_Release(This->container);
    } else {
        /* Handle our own refcounting */
    }
}

void WINAPI IWineD3DSurfaceImpl_CleanUp(IWineD3DSurface *iface) {
    IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;

    /* Do some cleaning for ourselves */

    This->parentCleanUp(This->parent);
}

/* WineD3D Texture */
ULONG WINAPI IWineD3DTextureImpl_Release(IWineD3DTexture *iface) {
    IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface;
    ULONG ref = InterlockedDecrement(&This->resource.ref);
    if (!ref) {
        IWineD3DTexture_CleanUp(iface);
    }

    return ref;
}

void WINAPI IWineD3DTextureImpl_CleanUp(IWineD3DTexture *iface) {
    IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface;
    int i;
    for (i = 0; i < This->baseTexture.levels; ++i) {
        IWineD3DSurface_Cleanup(This->surfaces[i]);
    }

    /* Do some cleaning for ourselves */

    This->parentCleanUp(This->parent);
}

/* IDirect3DSurface9 */
ULONG WINAPI IDirect3DSurface9Impl_Release(IDirect3DSurface9 *iface) {
    IDirect3DSurface9Impl *This = (IDirect3DSurface9Impl *)iface;
    return IWineD3DSurface_Release(This->wineD3DSurface);
}

void WINAPI IDirect3DSurface9Impl_CleanUp(IDirect3DSurface9 *iface) {
    IDirect3DSurface9Impl *This = (IDirect3DSurface9Impl *)iface;
    /* Cleanup Some stuff */
}

/* IDirect3DTexture9 */
ULONG WINAPI IDirect3DTexture9Impl_Release(IDirect3DTexture9 *iface) {
    IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface;
    return IWineD3DTexture_Release(This->wineD3DTexture);
}

void WINAPI IDirect3DTexture9Impl_CleanUp(IDirect3DTexture9 *iface) {
    IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface;
    /* Cleanup Some stuff */
}


AddRef would follow a similar pattern, although somewhat simpler since
it doesn't have to handle cleaning up the object.



More information about the wine-devel mailing list