Refcounting fun
Stefan Dösinger
stefandoesinger at gmx.at
Sun Feb 12 09:50:51 CST 2006
> One way to solve this would be to have wined3d handle the reference
> counting for d3d7/8/9 as well, so that their AddRef/Release calls just
> call AddRef/Release on the wined3d object they wrap. That would also
> mean we need to pass a pointer to the d3d7/8/9 object's cleanup
> function. (Releasing a d3d9 surface to 0 should cause a d3d9 texture
> to be freed). Note that for creating a texture, currently a similair
> construction is used, in that IWineD3DDeviceImpl_CreateTexture gets
> passed a pointer to a d3d9 surface create function, in order to create
> the texture's surfaces.
I have had some reference counting problems with ddraw too, but they were more
simple(Mainly, that needed WineD3D objects had no ddraw counterpart, or that
WineD3D destroys the ddraw parents, although they were still needed).
DDraw doesn't use containers, instead it has surface attachments and complex
surfaces, with some reference counting difficulties. My solution was to
handle that things in ddraw.
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?
> Obviously doing all that would be quite a change in the way d3d is
> setup in wine, and would also have some implications for the d3d7 and
> d3d8 rewrites. I'm wondering if this solution would be acceptable, and
> whether perhaps there are other, better solutions. Anyone care to
> comment?
It might be interesting if there are more such refcount connections. For
textures, my parent/child connections are:
DDraw surface 1 -> WineD3DTexture
IParent -> WineD3DSurface 1
DDraw surface 2 -> WineD3DSurface 2
etc
Directdraw textures are the same objects as directdraw surfaces, so they share
the refcount.
First, I create a ddraw surface, and create a WineD3DTexture for it. The
surface is the child for texture. WineD3D calls my surface creation callback,
which creates a WineD3DSurface for the ddraw surface on the first call, and a
Parent object for the WineD3Dsurface. The IParent objects only purpose is to
release it's child when it's destroyed. For other levels, I create a new
ddraw surface, which is the parent of the new WineD3D surface, and attach it
to the first ddraw surface. The attachment list is managed in ddraw.
When the app releases the compound, it (hopefully) calls the release method of
the first surface. This releases the WineD3D texture, which causes a release
to the IParent object and the further ddraw surfaces. The parent and the
ddraw surfaces release the Wined3d surfaces.
(That code works for 1 level textures, I haven't yet tried an app which uses
multiple levels, or I silently broke that functionality)
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.
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?
Stefan
More information about the wine-devel
mailing list