-----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;
}