ddraw: Keep an explicit reference to the wined3d device in surfaces.

Version 1 and version 2 surfaces don't keep references to the ddraw interface
that created them, so such surfaces may get destroyed after the corresponding
ddraw object was destroyed. Wined3d requires that the device is destroyed
after all its resources are destroyed. In principle this issue always existed,
but it was probably made worse by changes in the texture cleanup code.

Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Henri Verbeet 2017-01-04 00:04:47 +01:00 committed by Alexandre Julliard
parent 0190c50a8c
commit c7c0415689
3 changed files with 11 additions and 3 deletions

View File

@ -206,6 +206,7 @@ struct ddraw_texture
DDSURFACEDESC2 surface_desc;
struct ddraw_surface *root;
struct wined3d_device *wined3d_device;
};
HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_desc,

View File

@ -543,6 +543,8 @@ ULONG ddraw_surface_release_iface(struct ddraw_surface *This)
if (iface_count == 0)
{
struct ddraw_texture *texture = wined3d_texture_get_parent(This->wined3d_texture);
struct wined3d_device *wined3d_device = texture->wined3d_device;
IUnknown *release_iface = This->ifaceToRelease;
/* Complex attached surfaces are destroyed implicitly when the root is released */
@ -558,6 +560,9 @@ ULONG ddraw_surface_release_iface(struct ddraw_surface *This)
if (release_iface)
IUnknown_Release(release_iface);
/* Release the device only after anything that may reference it (the
* wined3d texture and rendertarget view in particular) is released. */
wined3d_device_decref(wined3d_device);
}
return iface_count;
@ -6142,6 +6147,7 @@ HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_
wined3d_texture_decref(wined3d_texture);
root->is_complex_root = TRUE;
texture->root = root;
wined3d_device_incref(texture->wined3d_device = ddraw->wined3d_device);
if (desc->dwFlags & DDSD_CKDESTOVERLAY)
wined3d_texture_set_color_key(wined3d_texture, DDCKEY_DESTOVERLAY,
@ -6260,6 +6266,7 @@ HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_
last = wined3d_texture_get_sub_resource_parent(wined3d_texture, 0);
wined3d_texture_decref(wined3d_texture);
texture->root = last;
wined3d_device_incref(texture->wined3d_device = ddraw->wined3d_device);
if (desc->dwFlags & DDSD_CKDESTOVERLAY)
wined3d_texture_set_color_key(wined3d_texture, DDCKEY_DESTOVERLAY,

View File

@ -547,7 +547,7 @@ ULONG CDECL wined3d_device_decref(struct wined3d_device *device)
wined3d_cs_destroy(device->cs);
if (device->recording && wined3d_stateblock_decref(device->recording))
FIXME("Something's still holding the recording stateblock.\n");
ERR("Something's still holding the recording stateblock.\n");
device->recording = NULL;
state_cleanup(&device->state);
@ -562,11 +562,11 @@ ULONG CDECL wined3d_device_decref(struct wined3d_device *device)
{
struct wined3d_resource *resource;
FIXME("Device released with resources still bound, acceptable but unexpected.\n");
ERR("Device released with resources still bound.\n");
LIST_FOR_EACH_ENTRY(resource, &device->resources, struct wined3d_resource, resource_list_entry)
{
FIXME("Leftover resource %p with type %s (%#x).\n",
ERR("Leftover resource %p with type %s (%#x).\n",
resource, debug_d3dresourcetype(resource->type), resource->type);
}
}