[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