[PATCH 6/6] d3d9: Decouple d3d9 volumes from wined3d volumes.

Stefan Dösinger stefandoesinger at gmail.com
Thu Apr 17 08:56:33 CDT 2014


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Fyi, doing the same for surfaces will take a while because a number of
surface-related functions have to be moved out of the way first. If
having a difference between volumes and surfaces is an issue skip this
patch for now.

Am 2014-04-17 15:47, schrieb Stefan Dösinger:
> Releasing the partially created texture in case of an out of memory
> error is a problem, see volumetexture_init.
> 
> My choice to handle this would be to move the memory allocation into the
> init function (and rename it), but a few years ago Henri has changed it
> into the opposite direction everywhere. I'm open to other suggestions.
> (And no, I don't like the idea of calculating the mipmap levels before
> calling wined3d_texture_create.)
> ---
>  dlls/d3d9/d3d9_private.h |  10 +++--
>  dlls/d3d9/device.c       |  15 +------
>  dlls/d3d9/texture.c      | 108 ++++++++++++++++++++++++++++++++---------------
>  dlls/d3d9/volume.c       |  30 ++-----------
>  4 files changed, 85 insertions(+), 78 deletions(-)
> 
> diff --git a/dlls/d3d9/d3d9_private.h b/dlls/d3d9/d3d9_private.h
> index 389cc95..2f59a2f 100644
> --- a/dlls/d3d9/d3d9_private.h
> +++ b/dlls/d3d9/d3d9_private.h
> @@ -184,14 +184,13 @@ struct d3d9_volume
>  {
>      IDirect3DVolume9 IDirect3DVolume9_iface;
>      struct d3d9_resource resource;
> -    struct wined3d_volume *wined3d_volume;
>      IUnknown *container;
>      IUnknown *forwardReference;
>      UINT level;
>  };
>  
> -void volume_init(struct d3d9_volume *volume, struct wined3d_volume *wined3d_volume,
> -        UINT level, const struct wined3d_parent_ops **parent_ops) DECLSPEC_HIDDEN;
> +void d3d9_volume_init(struct d3d9_volume *volume, UINT level) DECLSPEC_HIDDEN;
> +void d3d9_volume_destroy(void *sub_resource) DECLSPEC_HIDDEN;
>  
>  struct d3d9_swapchain
>  {
> @@ -251,6 +250,11 @@ struct d3d9_texture
>      struct d3d9_resource resource;
>      struct wined3d_texture *wined3d_texture;
>      IDirect3DDevice9Ex *parent_device;
> +
> +    void **sub_resource;
> +    void (*sub_resource_destroy)(void *sub_resource);
> +    UINT level_count, sub_resource_count;
> +    BOOL error_cleanup;
>  };
>  
>  HRESULT cubetexture_init(struct d3d9_texture *texture, struct d3d9_device *device,
> diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c
> index 84184ec..11e13c5 100644
> --- a/dlls/d3d9/device.c
> +++ b/dlls/d3d9/device.c
> @@ -3448,22 +3448,11 @@ static HRESULT CDECL device_parent_volume_created(struct wined3d_device_parent *
>          void *container_parent, struct wined3d_volume *volume, UINT level, void **parent,
>          const struct wined3d_parent_ops **parent_ops)
>  {
> -    struct d3d9_volume *d3d_volume;
> -
>      TRACE("device_parent %p, container_parent %p, volume %p, parent %p, parent_ops %p.\n",
>              device_parent, container_parent, volume, parent, parent_ops);
>  
> -    if (!(d3d_volume = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*d3d_volume))))
> -        return E_OUTOFMEMORY;
> -
> -    volume_init(d3d_volume, volume, level, parent_ops);
> -    *parent = d3d_volume;
> -    TRACE("Created volume %p.\n", d3d_volume);
> -
> -    d3d_volume->container = container_parent;
> -
> -    IDirect3DVolume9_Release(&d3d_volume->IDirect3DVolume9_iface);
> -    d3d_volume->forwardReference = container_parent;
> +    *parent_ops = &d3d9_null_wined3d_parent_ops;
> +    *parent = container_parent;
>  
>      return D3D_OK;
>  }
> diff --git a/dlls/d3d9/texture.c b/dlls/d3d9/texture.c
> index 7e8dd68..03c75fa 100644
> --- a/dlls/d3d9/texture.c
> +++ b/dlls/d3d9/texture.c
> @@ -1018,15 +1018,9 @@ static DWORD WINAPI d3d9_texture_3d_GetLOD(IDirect3DVolumeTexture9 *iface)
>  static DWORD WINAPI d3d9_texture_3d_GetLevelCount(IDirect3DVolumeTexture9 *iface)
>  {
>      struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
> -    DWORD ret;
>  
>      TRACE("iface %p.\n", iface);
> -
> -    wined3d_mutex_lock();
> -    ret = wined3d_texture_get_level_count(texture->wined3d_texture);
> -    wined3d_mutex_unlock();
> -
> -    return ret;
> +    return texture->level_count;
>  }
>  
>  static HRESULT WINAPI d3d9_texture_3d_SetAutoGenFilterType(IDirect3DVolumeTexture9 *iface,
> @@ -1073,55 +1067,48 @@ static void WINAPI d3d9_texture_3d_GenerateMipSubLevels(IDirect3DVolumeTexture9
>  static HRESULT WINAPI d3d9_texture_3d_GetLevelDesc(IDirect3DVolumeTexture9 *iface, UINT level, D3DVOLUME_DESC *desc)
>  {
>      struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
> -    HRESULT hr = D3D_OK;
> -    DWORD level_count;
> +    struct wined3d_resource *resource = wined3d_texture_get_resource(texture->wined3d_texture);
> +    struct wined3d_resource_desc wined3d_desc;
>  
>      TRACE("iface %p, level %u, desc %p.\n", iface, level, desc);
>  
> -    wined3d_mutex_lock();
> -    level_count = wined3d_texture_get_level_count(texture->wined3d_texture);
> -    if (level >= level_count)
> +    if (level >= texture->level_count)
>      {
>          WARN("Invalid mipmap level specified, returning D3DERR_INVALIDCALL.\n");
> -        hr = D3DERR_INVALIDCALL;
> +        return D3DERR_INVALIDCALL;
>      }
> -    else
> -    {
> -        struct wined3d_resource *resource = wined3d_texture_get_resource(texture->wined3d_texture);
> -        struct wined3d_resource_desc wined3d_desc;
>  
> -        wined3d_resource_get_desc(resource, &wined3d_desc);
> -        desc->Format = d3dformat_from_wined3dformat(wined3d_desc.format);
> -        desc->Type = D3DRTYPE_VOLUME;
> -        desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK;
> -        desc->Pool = wined3d_desc.pool;
> -        desc->Width = max(wined3d_desc.width >> level, 1);
> -        desc->Height = max(wined3d_desc.height >> level, 1);
> -        desc->Depth = max(wined3d_desc.depth >> level, 1);
> -        hr = D3D_OK;
> -    }
> +    wined3d_mutex_lock();
> +    wined3d_resource_get_desc(resource, &wined3d_desc);
> +    desc->Format = d3dformat_from_wined3dformat(wined3d_desc.format);
> +    desc->Type = D3DRTYPE_VOLUME;
> +    desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK;
> +    desc->Pool = wined3d_desc.pool;
> +    desc->Width = max(wined3d_desc.width >> level, 1);
> +    desc->Height = max(wined3d_desc.height >> level, 1);
> +    desc->Depth = max(wined3d_desc.depth >> level, 1);
>      wined3d_mutex_unlock();
>  
> -    return hr;
> +    return D3D_OK;
>  }
>  
>  static HRESULT WINAPI d3d9_texture_3d_GetVolumeLevel(IDirect3DVolumeTexture9 *iface,
>          UINT level, IDirect3DVolume9 **volume)
>  {
>      struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
> -    struct wined3d_resource *sub_resource;
>      struct d3d9_volume *volume_impl;
>  
>      TRACE("iface %p, level %u, volume %p.\n", iface, level, volume);
>  
>      wined3d_mutex_lock();
> -    if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level)))
> +    if (level >= texture->level_count)
>      {
> +        WARN("Invalid mipmap level specified, returning D3DERR_INVALIDCALL.\n");
>          wined3d_mutex_unlock();
>          return D3DERR_INVALIDCALL;
>      }
>  
> -    volume_impl = wined3d_resource_get_parent(sub_resource);
> +    volume_impl = texture->sub_resource[level];
>      *volume = &volume_impl->IDirect3DVolume9_iface;
>      IDirect3DVolume9_AddRef(*volume);
>      wined3d_mutex_unlock();
> @@ -1234,9 +1221,18 @@ struct d3d9_texture *unsafe_impl_from_IDirect3DBaseTexture9(IDirect3DBaseTexture
>  
>  static void STDMETHODCALLTYPE d3d9_texture_wined3d_object_destroyed(void *parent)
>  {
> +    UINT i;
>      struct d3d9_texture *texture = parent;
>      d3d9_resource_cleanup(&texture->resource);
> -    HeapFree(GetProcessHeap(), 0, texture);
> +
> +    if (texture->sub_resource)
> +    {
> +        for (i = 0; i < texture->sub_resource_count && texture->sub_resource[i]; i++)
> +            texture->sub_resource_destroy(texture->sub_resource[i]);
> +        HeapFree(GetProcessHeap(), 0, texture->sub_resource);
> +    }
> +    if (!texture->error_cleanup)
> +        HeapFree(GetProcessHeap(), 0, texture);
>  }
>  
>  static const struct wined3d_parent_ops d3d9_texture_wined3d_parent_ops =
> @@ -1331,6 +1327,7 @@ HRESULT volumetexture_init(struct d3d9_texture *texture, struct d3d9_device *dev
>  {
>      struct wined3d_resource_desc desc;
>      HRESULT hr;
> +    DWORD i;
>  
>      texture->IDirect3DBaseTexture9_iface.lpVtbl = (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_3d_vtbl;
>      d3d9_resource_init(&texture->resource);
> @@ -1350,15 +1347,56 @@ HRESULT volumetexture_init(struct d3d9_texture *texture, struct d3d9_device *dev
>      wined3d_mutex_lock();
>      hr = wined3d_texture_create(device->wined3d_device, &desc, levels, 0,
>              texture, &d3d9_texture_wined3d_parent_ops, &texture->wined3d_texture);
> -    wined3d_mutex_unlock();
>      if (FAILED(hr))
>      {
>          WARN("Failed to create wined3d volume texture, hr %#x.\n", hr);
> -        return hr;
> +        goto error;
> +    }
> +
> +    texture->level_count = wined3d_texture_get_level_count(texture->wined3d_texture);
> +    texture->sub_resource_count = texture->level_count;
> +
> +    texture->sub_resource_destroy = d3d9_volume_destroy;
> +    texture->sub_resource = HeapAlloc(GetProcessHeap(), 0,
> +            sizeof(*texture->sub_resource) * texture->sub_resource_count);
> +    if (!texture->sub_resource)
> +    {
> +        hr = E_OUTOFMEMORY;
> +        goto error;
> +    }
> +
> +    for (i = 0; i < texture->level_count; i++)
> +    {
> +        struct d3d9_volume *d3d9_volume;
> +
> +        if (!(d3d9_volume = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*d3d9_volume))))
> +        {
> +            hr = E_OUTOFMEMORY;
> +            goto error;
> +        }
> +        d3d9_volume_init(d3d9_volume, i);
> +        TRACE("Created volume %p.\n", d3d9_volume);
> +
> +        d3d9_volume->container = (IUnknown *)&texture->IDirect3DBaseTexture9_iface;
> +        IDirect3DVolume9_Release(&d3d9_volume->IDirect3DVolume9_iface);
> +        d3d9_volume->forwardReference = d3d9_volume->container;
> +        texture->sub_resource[i] = d3d9_volume;
>      }
>  
>      texture->parent_device = &device->IDirect3DDevice9Ex_iface;
>      IDirect3DDevice9Ex_AddRef(texture->parent_device);
> -
> +    wined3d_mutex_unlock();
>      return D3D_OK;
> +
> +error:
> +    /* Once the wined3d texture is created there is no way to destroy it without running
> +     * d3d9_texture_wined3d_object_destroyed. The caller expects volumetexture_init not
> +     * to free texture in case of an error. */
> +    if (texture->wined3d_texture)
> +    {
> +        texture->error_cleanup = TRUE;
> +        wined3d_texture_decref(texture->wined3d_texture);
> +    }
> +    wined3d_mutex_unlock();
> +    return hr;
>  }
> diff --git a/dlls/d3d9/volume.c b/dlls/d3d9/volume.c
> index 07f15ca..916a949 100644
> --- a/dlls/d3d9/volume.c
> +++ b/dlls/d3d9/volume.c
> @@ -63,13 +63,6 @@ static ULONG WINAPI d3d9_volume_AddRef(IDirect3DVolume9 *iface)
>      refcount = InterlockedIncrement(&volume->resource.refcount);
>      TRACE("%p increasing refcount to %u.\n", iface, refcount);
>  
> -    if (refcount == 1)
> -    {
> -        wined3d_mutex_lock();
> -        wined3d_volume_incref(volume->wined3d_volume);
> -        wined3d_mutex_unlock();
> -    }
> -
>      return refcount;
>  }
>  
> @@ -89,13 +82,6 @@ static ULONG WINAPI d3d9_volume_Release(IDirect3DVolume9 *iface)
>      refcount = InterlockedDecrement(&volume->resource.refcount);
>      TRACE("%p decreasing refcount to %u.\n", iface, refcount);
>  
> -    if (!refcount)
> -    {
> -        wined3d_mutex_lock();
> -        wined3d_volume_decref(volume->wined3d_volume);
> -        wined3d_mutex_unlock();
> -    }
> -
>      return refcount;
>  }
>  
> @@ -213,26 +199,16 @@ static const struct IDirect3DVolume9Vtbl d3d9_volume_vtbl =
>      d3d9_volume_UnlockBox,
>  };
>  
> -static void STDMETHODCALLTYPE volume_wined3d_object_destroyed(void *parent)
> +void d3d9_volume_destroy(void *sub_resource)
>  {
> -    struct d3d9_volume *volume = parent;
> +    struct d3d9_volume *volume = sub_resource;
>      d3d9_resource_cleanup(&volume->resource);
>      HeapFree(GetProcessHeap(), 0, volume);
>  }
>  
> -static const struct wined3d_parent_ops d3d9_volume_wined3d_parent_ops =
> -{
> -    volume_wined3d_object_destroyed,
> -};
> -
> -void volume_init(struct d3d9_volume *volume, struct wined3d_volume *wined3d_volume,
> -        UINT level, const struct wined3d_parent_ops **parent_ops)
> +void d3d9_volume_init(struct d3d9_volume *volume, UINT level)
>  {
>      volume->IDirect3DVolume9_iface.lpVtbl = &d3d9_volume_vtbl;
>      d3d9_resource_init(&volume->resource);
> -    wined3d_volume_incref(wined3d_volume);
> -    volume->wined3d_volume = wined3d_volume;
>      volume->level = level;
> -
> -    *parent_ops = &d3d9_volume_wined3d_parent_ops;
>  }
> 

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.22 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iQIcBAEBAgAGBQJTT92RAAoJEN0/YqbEcdMwAe0P/2Nt/ZATqANNkVaY6o6BdknG
qfw6wSQemhF3OvKX84aKSqdEdjOkHNqtQb9wHE1jEoGufkSO9VLINIOJRqa8M962
8cwg2fceNVlU148pwvdCYbkbvJofN0zqDT91IRTBfkKsoAo4Fcwo9fSzKp28gQQv
KLBvcJksQ0DZNZAxHrjbGpu16xVinfTypVIa8KLrar4Ns+XPoYDikghKh7s+kSb6
Mvo5ZwmNTLYi6dLFblzjRV8ftLriN8gI6r4BxYoAotVTuN70FRG4ce+qs97Nwwe9
nAEfcSp752N5DQ2qLWiBZdaa/ZjX3y389hkaHB2uYz8RZH91hEecMgIV+6SzF4el
SU5apNTF214x2SBKvGwL0jLRQ0J1QoEVbw2siwwyIS02id3yp19yekiEdOsfmq+4
CMaYdZSHHOBntcFNwz/TMli1y46ugTHWVPimVz1WGqNfWdxN1xyJX5YdIyRpIPC8
lzuzsobX9DyULFHAtrDz3RrBCMsztTFbag7bIAZ3ZbLLxEEMm0926eEQVBsGY1fZ
uS5V6AKA8JLQ+OZfNCoZeiMASR70PfICoBpahld1rNo5NfjsB56P+h+kWWkP8l6q
OOeXJgYYn3n40LndHl0EPk6EjXUqyUkZ9s1sPxcdgL6GD1iE9oRPHBmm2OC19+tF
rswC/IHRuFD+4KHlR5OR
=dY9X
-----END PGP SIGNATURE-----



More information about the wine-devel mailing list