[PATCH 6/6] d3d9: Decouple d3d9 volumes from wined3d volumes.
Stefan Dösinger
stefan at codeweavers.com
Thu Apr 17 08:47:33 CDT 2014
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;
}
--
1.8.3.2
More information about the wine-patches
mailing list