-- v2: d3d9: Use a separate draw texture for managed resources. d3d9: Add reference counting helpers for textures.
From: Zebediah Figura zfigura@codeweavers.com
--- dlls/d3d9/d3d9_private.h | 13 +-- dlls/d3d9/device.c | 6 +- dlls/d3d9/texture.c | 185 +++++++++++---------------------------- 3 files changed, 61 insertions(+), 143 deletions(-)
diff --git a/dlls/d3d9/d3d9_private.h b/dlls/d3d9/d3d9_private.h index 858568f5e1c..4169ab74973 100644 --- a/dlls/d3d9/d3d9_private.h +++ b/dlls/d3d9/d3d9_private.h @@ -228,12 +228,13 @@ struct d3d9_texture D3DTEXTUREFILTERTYPE autogen_filter_type; };
-HRESULT cubetexture_init(struct d3d9_texture *texture, struct d3d9_device *device, - UINT edge_length, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool) DECLSPEC_HIDDEN; -HRESULT texture_init(struct d3d9_texture *texture, struct d3d9_device *device, - UINT width, UINT height, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool) DECLSPEC_HIDDEN; -HRESULT volumetexture_init(struct d3d9_texture *texture, struct d3d9_device *device, - UINT width, UINT height, UINT depth, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool) DECLSPEC_HIDDEN; +HRESULT d3d9_texture_2d_init(struct d3d9_texture *texture, struct d3d9_device *device, unsigned int width, + unsigned int height, unsigned int level_count, DWORD usage, D3DFORMAT format, D3DPOOL pool); +HRESULT d3d9_texture_3d_init(struct d3d9_texture *texture, struct d3d9_device *device, unsigned int width, + unsigned int height, unsigned int depth, unsigned int level_count, DWORD usage, D3DFORMAT format, D3DPOOL pool); +HRESULT d3d9_texture_cube_init(struct d3d9_texture *texture, struct d3d9_device *device, + unsigned int edge_length, unsigned int level_count, DWORD usage, D3DFORMAT format, D3DPOOL pool); + struct d3d9_texture *unsafe_impl_from_IDirect3DBaseTexture9(IDirect3DBaseTexture9 *iface) DECLSPEC_HIDDEN; void d3d9_texture_flag_auto_gen_mipmap(struct d3d9_texture *texture) DECLSPEC_HIDDEN; void d3d9_texture_gen_auto_mipmap(struct d3d9_texture *texture) DECLSPEC_HIDDEN; diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c index 9b8e44f6891..5f7b3f03ae3 100644 --- a/dlls/d3d9/device.c +++ b/dlls/d3d9/device.c @@ -1323,7 +1323,7 @@ static HRESULT WINAPI d3d9_device_CreateTexture(IDirect3DDevice9Ex *iface, if (!(object = heap_alloc_zero(sizeof(*object)))) return D3DERR_OUTOFVIDEOMEMORY;
- hr = texture_init(object, device, width, height, levels, usage, format, pool); + hr = d3d9_texture_2d_init(object, device, width, height, levels, usage, format, pool); if (FAILED(hr)) { WARN("Failed to initialize texture, hr %#x.\n", hr); @@ -1379,7 +1379,7 @@ static HRESULT WINAPI d3d9_device_CreateVolumeTexture(IDirect3DDevice9Ex *iface, if (!(object = heap_alloc_zero(sizeof(*object)))) return D3DERR_OUTOFVIDEOMEMORY;
- hr = volumetexture_init(object, device, width, height, depth, levels, usage, format, pool); + hr = d3d9_texture_3d_init(object, device, width, height, depth, levels, usage, format, pool); if (FAILED(hr)) { WARN("Failed to initialize volume texture, hr %#x.\n", hr); @@ -1424,7 +1424,7 @@ static HRESULT WINAPI d3d9_device_CreateCubeTexture(IDirect3DDevice9Ex *iface, if (!(object = heap_alloc_zero(sizeof(*object)))) return D3DERR_OUTOFVIDEOMEMORY;
- hr = cubetexture_init(object, device, edge_length, levels, usage, format, pool); + hr = d3d9_texture_cube_init(object, device, edge_length, levels, usage, format, pool); if (FAILED(hr)) { WARN("Failed to initialize cube texture, hr %#x.\n", hr); diff --git a/dlls/d3d9/texture.c b/dlls/d3d9/texture.c index 31bf95834b8..8f4798fa81c 100644 --- a/dlls/d3d9/texture.c +++ b/dlls/d3d9/texture.c @@ -1293,13 +1293,13 @@ static const struct wined3d_parent_ops d3d9_texture_wined3d_parent_ops = d3d9_texture_wined3d_object_destroyed, };
-HRESULT texture_init(struct d3d9_texture *texture, struct d3d9_device *device, - UINT width, UINT height, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool) +static HRESULT d3d9_texture_init(struct d3d9_texture *texture, struct d3d9_device *device, + const struct wined3d_resource_desc *desc, D3DPOOL pool, DWORD usage, + unsigned int layer_count, unsigned int level_count) { struct wined3d_adapter *wined3d_adapter; - struct wined3d_resource_desc desc; unsigned int output_idx; - DWORD flags = 0; + unsigned int flags = 0; HRESULT hr;
if (pool == D3DPOOL_MANAGED && device->d3d_parent->extended) @@ -1308,25 +1308,14 @@ HRESULT texture_init(struct d3d9_texture *texture, struct d3d9_device *device, return D3DERR_INVALIDCALL; }
- texture->IDirect3DBaseTexture9_iface.lpVtbl = (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_2d_vtbl; d3d9_resource_init(&texture->resource); list_init(&texture->rtv_list); texture->usage = usage;
- desc.resource_type = WINED3D_RTYPE_TEXTURE_2D; - desc.format = wined3dformat_from_d3dformat(format); - desc.multisample_type = WINED3D_MULTISAMPLE_NONE; - desc.multisample_quality = 0; - desc.usage = wined3d_usage_from_d3d(pool, usage); - desc.bind_flags = wined3d_bind_flags_from_d3d9_usage(usage) | WINED3D_BIND_SHADER_RESOURCE; - desc.access = wined3daccess_from_d3dpool(pool, usage); - desc.width = width; - desc.height = height; - desc.depth = 1; - desc.size = 0; - - if (is_gdi_compat_wined3dformat(desc.format)) + if (desc->resource_type == WINED3D_RTYPE_TEXTURE_2D && is_gdi_compat_wined3dformat(desc->format)) flags |= WINED3D_TEXTURE_CREATE_GET_DC; + if (pool == D3DPOOL_SYSTEMMEM) + flags |= WINED3D_TEXTURE_CREATE_RECORD_DIRTY_REGIONS;
if (usage & D3DUSAGE_WRITEONLY) { @@ -1335,14 +1324,21 @@ HRESULT texture_init(struct d3d9_texture *texture, struct d3d9_device *device, } if (usage & D3DUSAGE_AUTOGENMIPMAP) { + if (desc->resource_type == WINED3D_RTYPE_TEXTURE_3D) + { + WARN("Texture can't be created with the D3DUSAGE_WRITEONLY flags, returning D3DERR_INVALIDCALL.\n"); + return D3DERR_INVALIDCALL; + } + if (pool == D3DPOOL_SYSTEMMEM) { WARN("D3DUSAGE_AUTOGENMIPMAP texture can't be in D3DPOOL_SYSTEMMEM, returning D3DERR_INVALIDCALL.\n"); return D3DERR_INVALIDCALL; } - if (levels && levels != 1) + + if (level_count && level_count != 1) { - WARN("D3DUSAGE_AUTOGENMIPMAP texture with %u levels, returning D3DERR_INVALIDCALL.\n", levels); + WARN("D3DUSAGE_AUTOGENMIPMAP texture with %u level_count, returning D3DERR_INVALIDCALL.\n", level_count); return D3DERR_INVALIDCALL; } wined3d_mutex_lock(); @@ -1350,18 +1346,18 @@ HRESULT texture_init(struct d3d9_texture *texture, struct d3d9_device *device, wined3d_adapter = wined3d_output_get_adapter(device->d3d_parent->wined3d_outputs[output_idx]); hr = wined3d_check_device_format(device->d3d_parent->wined3d, wined3d_adapter, WINED3D_DEVICE_TYPE_HAL, WINED3DFMT_B8G8R8A8_UNORM, WINED3DUSAGE_QUERY_GENMIPMAP, - WINED3D_BIND_SHADER_RESOURCE, WINED3D_RTYPE_TEXTURE_2D, wined3dformat_from_d3dformat(format)); + WINED3D_BIND_SHADER_RESOURCE, WINED3D_RTYPE_TEXTURE_2D, desc->format); wined3d_mutex_unlock(); if (hr == D3D_OK) { flags |= WINED3D_TEXTURE_CREATE_GENERATE_MIPMAPS; - levels = 0; + level_count = 0; } else { - WARN("D3DUSAGE_AUTOGENMIPMAP not supported on D3DFORMAT %#x, creating a texture " - "with a single level.\n", format); - levels = 1; + WARN("Mipmap autogeneration is not supported on wined3d format %#x, " + "creating a texture with a single level.\n", desc->format); + level_count = 1; } texture->autogen_filter_type = D3DTEXF_LINEAR; } @@ -1369,13 +1365,11 @@ HRESULT texture_init(struct d3d9_texture *texture, struct d3d9_device *device, { texture->autogen_filter_type = D3DTEXF_NONE; } - if (!levels) - levels = wined3d_log2i(max(width, height)) + 1; - if (pool == D3DPOOL_SYSTEMMEM) - flags |= WINED3D_TEXTURE_CREATE_RECORD_DIRTY_REGIONS; + if (!level_count) + level_count = wined3d_log2i(max(max(desc->width, desc->height), desc->depth)) + 1;
wined3d_mutex_lock(); - hr = wined3d_texture_create(device->wined3d_device, &desc, 1, levels, flags, + hr = wined3d_texture_create(device->wined3d_device, desc, layer_count, level_count, flags, NULL, texture, &d3d9_texture_wined3d_parent_ops, &texture->wined3d_texture); wined3d_mutex_unlock(); if (FAILED(hr)) @@ -1390,23 +1384,31 @@ HRESULT texture_init(struct d3d9_texture *texture, struct d3d9_device *device, return D3D_OK; }
-HRESULT cubetexture_init(struct d3d9_texture *texture, struct d3d9_device *device, - UINT edge_length, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool) +HRESULT d3d9_texture_2d_init(struct d3d9_texture *texture, struct d3d9_device *device, unsigned int width, + unsigned int height, unsigned int level_count, DWORD usage, D3DFORMAT format, D3DPOOL pool) { struct wined3d_resource_desc desc; - DWORD flags = 0; - HRESULT hr;
- if (pool == D3DPOOL_MANAGED && device->d3d_parent->extended) - { - WARN("Managed resources are not supported by d3d9ex devices.\n"); - return D3DERR_INVALIDCALL; - } + desc.resource_type = WINED3D_RTYPE_TEXTURE_2D; + desc.format = wined3dformat_from_d3dformat(format); + desc.multisample_type = WINED3D_MULTISAMPLE_NONE; + desc.multisample_quality = 0; + desc.usage = wined3d_usage_from_d3d(pool, usage); + desc.bind_flags = wined3d_bind_flags_from_d3d9_usage(usage) | WINED3D_BIND_SHADER_RESOURCE; + desc.access = wined3daccess_from_d3dpool(pool, usage); + desc.width = width; + desc.height = height; + desc.depth = 1; + desc.size = 0;
- texture->IDirect3DBaseTexture9_iface.lpVtbl = (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_cube_vtbl; - d3d9_resource_init(&texture->resource); - list_init(&texture->rtv_list); - texture->usage = usage; + texture->IDirect3DBaseTexture9_iface.lpVtbl = (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_2d_vtbl; + return d3d9_texture_init(texture, device, &desc, pool, usage, 1, level_count); +} + +HRESULT d3d9_texture_cube_init(struct d3d9_texture *texture, struct d3d9_device *device, + unsigned int edge_length, unsigned int level_count, DWORD usage, D3DFORMAT format, D3DPOOL pool) +{ + struct wined3d_resource_desc desc;
desc.resource_type = WINED3D_RTYPE_TEXTURE_2D; desc.format = wined3dformat_from_d3dformat(format); @@ -1420,77 +1422,19 @@ HRESULT cubetexture_init(struct d3d9_texture *texture, struct d3d9_device *devic desc.depth = 1; desc.size = 0;
- if (is_gdi_compat_wined3dformat(desc.format)) - flags |= WINED3D_TEXTURE_CREATE_GET_DC; - - if (usage & D3DUSAGE_WRITEONLY) - { - WARN("Texture can't be created with the D3DUSAGE_WRITEONLY flags, returning D3DERR_INVALIDCALL.\n"); - return D3DERR_INVALIDCALL; - } - if (usage & D3DUSAGE_AUTOGENMIPMAP) - { - if (pool == D3DPOOL_SYSTEMMEM) - { - WARN("D3DUSAGE_AUTOGENMIPMAP texture can't be in D3DPOOL_SYSTEMMEM, returning D3DERR_INVALIDCALL.\n"); - return D3DERR_INVALIDCALL; - } - if (levels && levels != 1) - { - WARN("D3DUSAGE_AUTOGENMIPMAP texture with %u levels, returning D3DERR_INVALIDCALL.\n", levels); - return D3DERR_INVALIDCALL; - } - flags |= WINED3D_TEXTURE_CREATE_GENERATE_MIPMAPS; - texture->autogen_filter_type = D3DTEXF_LINEAR; - levels = 0; - } - else - { - texture->autogen_filter_type = D3DTEXF_NONE; - } - if (!levels) - levels = wined3d_log2i(edge_length) + 1; - if (pool == D3DPOOL_SYSTEMMEM) - flags |= WINED3D_TEXTURE_CREATE_RECORD_DIRTY_REGIONS; - - wined3d_mutex_lock(); - hr = wined3d_texture_create(device->wined3d_device, &desc, 6, levels, flags, - NULL, texture, &d3d9_texture_wined3d_parent_ops, &texture->wined3d_texture); - wined3d_mutex_unlock(); - if (FAILED(hr)) - { - WARN("Failed to create wined3d cube texture, hr %#x.\n", hr); - return hr; - } - - texture->parent_device = device; - IDirect3DDevice9Ex_AddRef(&texture->parent_device->IDirect3DDevice9Ex_iface); - - return D3D_OK; + texture->IDirect3DBaseTexture9_iface.lpVtbl = (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_cube_vtbl; + return d3d9_texture_init(texture, device, &desc, pool, usage, 6, level_count); }
-HRESULT volumetexture_init(struct d3d9_texture *texture, struct d3d9_device *device, - UINT width, UINT height, UINT depth, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool) +HRESULT d3d9_texture_3d_init(struct d3d9_texture *texture, struct d3d9_device *device, unsigned int width, + unsigned int height, unsigned int depth, unsigned int level_count, DWORD usage, D3DFORMAT format, D3DPOOL pool) { struct wined3d_resource_desc desc; - DWORD flags = 0; - HRESULT hr; - - if (pool == D3DPOOL_MANAGED && device->d3d_parent->extended) - { - WARN("Managed resources are not supported by d3d9ex devices.\n"); - return D3DERR_INVALIDCALL; - }
/* In d3d9, 3D textures can't be used as rendertarget or depth/stencil buffer. */ if (usage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL)) return D3DERR_INVALIDCALL;
- texture->IDirect3DBaseTexture9_iface.lpVtbl = (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_3d_vtbl; - d3d9_resource_init(&texture->resource); - list_init(&texture->rtv_list); - texture->usage = usage; - desc.resource_type = WINED3D_RTYPE_TEXTURE_3D; desc.format = wined3dformat_from_d3dformat(format); desc.multisample_type = WINED3D_MULTISAMPLE_NONE; @@ -1503,33 +1447,6 @@ HRESULT volumetexture_init(struct d3d9_texture *texture, struct d3d9_device *dev desc.depth = depth; desc.size = 0;
- if (usage & D3DUSAGE_WRITEONLY) - { - WARN("Texture can't be created with the D3DUSAGE_WRITEONLY flags, returning D3DERR_INVALIDCALL.\n"); - return D3DERR_INVALIDCALL; - } - if (usage & D3DUSAGE_AUTOGENMIPMAP) - { - WARN("D3DUSAGE_AUTOGENMIPMAP volume texture is not supported, returning D3DERR_INVALIDCALL.\n"); - return D3DERR_INVALIDCALL; - } - if (!levels) - levels = wined3d_log2i(max(max(width, height), depth)) + 1; - if (pool == D3DPOOL_SYSTEMMEM) - flags |= WINED3D_TEXTURE_CREATE_RECORD_DIRTY_REGIONS; - - wined3d_mutex_lock(); - hr = wined3d_texture_create(device->wined3d_device, &desc, 1, levels, flags, - NULL, 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; - } - - texture->parent_device = device; - IDirect3DDevice9Ex_AddRef(&texture->parent_device->IDirect3DDevice9Ex_iface); - - return D3D_OK; + texture->IDirect3DBaseTexture9_iface.lpVtbl = (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_3d_vtbl; + return d3d9_texture_init(texture, device, &desc, pool, usage, 1, level_count); }
From: Zebediah Figura zfigura@codeweavers.com
--- dlls/d3d9/texture.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-)
diff --git a/dlls/d3d9/texture.c b/dlls/d3d9/texture.c index 8f4798fa81c..48722c64348 100644 --- a/dlls/d3d9/texture.c +++ b/dlls/d3d9/texture.c @@ -22,6 +22,13 @@
WINE_DEFAULT_DEBUG_CHANNEL(d3d9);
+static void d3d9_texture_preload(struct d3d9_texture *texture) +{ + wined3d_mutex_lock(); + wined3d_resource_preload(wined3d_texture_get_resource(texture->wined3d_texture)); + wined3d_mutex_unlock(); +} + static inline struct d3d9_texture *impl_from_IDirect3DTexture9(IDirect3DTexture9 *iface) { return CONTAINING_RECORD(iface, struct d3d9_texture, IDirect3DBaseTexture9_iface); @@ -246,9 +253,7 @@ static void WINAPI d3d9_texture_2d_PreLoad(IDirect3DTexture9 *iface)
TRACE("iface %p.\n", iface);
- wined3d_mutex_lock(); - wined3d_resource_preload(wined3d_texture_get_resource(texture->wined3d_texture)); - wined3d_mutex_unlock(); + d3d9_texture_preload(texture); }
static D3DRESOURCETYPE WINAPI d3d9_texture_2d_GetType(IDirect3DTexture9 *iface) @@ -644,9 +649,7 @@ static void WINAPI d3d9_texture_cube_PreLoad(IDirect3DCubeTexture9 *iface)
TRACE("iface %p.\n", iface);
- wined3d_mutex_lock(); - wined3d_resource_preload(wined3d_texture_get_resource(texture->wined3d_texture)); - wined3d_mutex_unlock(); + d3d9_texture_preload(texture); }
static D3DRESOURCETYPE WINAPI d3d9_texture_cube_GetType(IDirect3DCubeTexture9 *iface) @@ -1062,9 +1065,7 @@ static void WINAPI d3d9_texture_3d_PreLoad(IDirect3DVolumeTexture9 *iface)
TRACE("iface %p.\n", iface);
- wined3d_mutex_lock(); - wined3d_resource_preload(wined3d_texture_get_resource(texture->wined3d_texture)); - wined3d_mutex_unlock(); + d3d9_texture_preload(texture); }
static D3DRESOURCETYPE WINAPI d3d9_texture_3d_GetType(IDirect3DVolumeTexture9 *iface)
From: Zebediah Figura zfigura@codeweavers.com
--- dlls/d3d9/texture.c | 137 +++++++++++++++++--------------------------- 1 file changed, 54 insertions(+), 83 deletions(-)
diff --git a/dlls/d3d9/texture.c b/dlls/d3d9/texture.c index 48722c64348..5308a7da08f 100644 --- a/dlls/d3d9/texture.c +++ b/dlls/d3d9/texture.c @@ -22,6 +22,54 @@
WINE_DEFAULT_DEBUG_CHANNEL(d3d9);
+static ULONG d3d9_texture_incref(struct d3d9_texture *texture) +{ + ULONG ref = InterlockedIncrement(&texture->resource.refcount); + + TRACE("%p increasing refcount to %u.\n", texture, ref); + + if (ref == 1) + { + struct d3d9_surface *surface; + + IDirect3DDevice9Ex_AddRef(&texture->parent_device->IDirect3DDevice9Ex_iface); + wined3d_mutex_lock(); + LIST_FOR_EACH_ENTRY(surface, &texture->rtv_list, struct d3d9_surface, rtv_entry) + { + wined3d_rendertarget_view_incref(surface->wined3d_rtv); + } + wined3d_texture_incref(texture->wined3d_texture); + wined3d_mutex_unlock(); + } + + return ref; +} + +static ULONG d3d9_texture_decref(struct d3d9_texture *texture) +{ + ULONG ref = InterlockedDecrement(&texture->resource.refcount); + + TRACE("%p decreasing refcount to %u.\n", texture, ref); + + if (!ref) + { + IDirect3DDevice9Ex *parent_device = &texture->parent_device->IDirect3DDevice9Ex_iface; + struct d3d9_surface *surface; + + wined3d_mutex_lock(); + if (texture->wined3d_srv) + wined3d_shader_resource_view_decref(texture->wined3d_srv); + LIST_FOR_EACH_ENTRY(surface, &texture->rtv_list, struct d3d9_surface, rtv_entry) + wined3d_rendertarget_view_decref(surface->wined3d_rtv); + wined3d_texture_decref(texture->wined3d_texture); + wined3d_mutex_unlock(); + + /* Release the device last, as it may cause the device to be destroyed. */ + IDirect3DDevice9Ex_Release(parent_device); + } + return ref; +} + static void d3d9_texture_preload(struct d3d9_texture *texture) { wined3d_mutex_lock(); @@ -84,23 +132,6 @@ static struct wined3d_shader_resource_view *d3d9_texture_acquire_shader_resource return texture->wined3d_srv; }
-static void d3d9_texture_cleanup(struct d3d9_texture *texture) -{ - IDirect3DDevice9Ex *parent_device = &texture->parent_device->IDirect3DDevice9Ex_iface; - struct d3d9_surface *surface; - - wined3d_mutex_lock(); - if (texture->wined3d_srv) - wined3d_shader_resource_view_decref(texture->wined3d_srv); - LIST_FOR_EACH_ENTRY(surface, &texture->rtv_list, struct d3d9_surface, rtv_entry) - wined3d_rendertarget_view_decref(surface->wined3d_rtv); - wined3d_texture_decref(texture->wined3d_texture); - wined3d_mutex_unlock(); - - /* Release the device last, as it may cause the device to be destroyed. */ - IDirect3DDevice9Ex_Release(parent_device); -} - /* wined3d critical section must be taken by the caller. */ void d3d9_texture_gen_auto_mipmap(struct d3d9_texture *texture) { @@ -140,37 +171,15 @@ static HRESULT WINAPI d3d9_texture_2d_QueryInterface(IDirect3DTexture9 *iface, R static ULONG WINAPI d3d9_texture_2d_AddRef(IDirect3DTexture9 *iface) { struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface); - ULONG ref = InterlockedIncrement(&texture->resource.refcount); - - TRACE("%p increasing refcount to %u.\n", iface, ref); - - if (ref == 1) - { - struct d3d9_surface *surface;
- IDirect3DDevice9Ex_AddRef(&texture->parent_device->IDirect3DDevice9Ex_iface); - wined3d_mutex_lock(); - LIST_FOR_EACH_ENTRY(surface, &texture->rtv_list, struct d3d9_surface, rtv_entry) - { - wined3d_rendertarget_view_incref(surface->wined3d_rtv); - } - wined3d_texture_incref(texture->wined3d_texture); - wined3d_mutex_unlock(); - } - - return ref; + return d3d9_texture_incref(texture); }
static ULONG WINAPI d3d9_texture_2d_Release(IDirect3DTexture9 *iface) { struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface); - ULONG ref = InterlockedDecrement(&texture->resource.refcount); - - TRACE("%p decreasing refcount to %u.\n", iface, ref);
- if (!ref) - d3d9_texture_cleanup(texture); - return ref; + return d3d9_texture_decref(texture); }
static HRESULT WINAPI d3d9_texture_2d_GetDevice(IDirect3DTexture9 *iface, IDirect3DDevice9 **device) @@ -536,37 +545,15 @@ static HRESULT WINAPI d3d9_texture_cube_QueryInterface(IDirect3DCubeTexture9 *if static ULONG WINAPI d3d9_texture_cube_AddRef(IDirect3DCubeTexture9 *iface) { struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface); - ULONG ref = InterlockedIncrement(&texture->resource.refcount); - - TRACE("%p increasing refcount to %u.\n", iface, ref);
- if (ref == 1) - { - struct d3d9_surface *surface; - - IDirect3DDevice9Ex_AddRef(&texture->parent_device->IDirect3DDevice9Ex_iface); - wined3d_mutex_lock(); - LIST_FOR_EACH_ENTRY(surface, &texture->rtv_list, struct d3d9_surface, rtv_entry) - { - wined3d_rendertarget_view_incref(surface->wined3d_rtv); - } - wined3d_texture_incref(texture->wined3d_texture); - wined3d_mutex_unlock(); - } - - return ref; + return d3d9_texture_incref(texture); }
static ULONG WINAPI d3d9_texture_cube_Release(IDirect3DCubeTexture9 *iface) { struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface); - ULONG ref = InterlockedDecrement(&texture->resource.refcount);
- TRACE("%p decreasing refcount to %u.\n", iface, ref); - - if (!ref) - d3d9_texture_cleanup(texture); - return ref; + return d3d9_texture_decref(texture); }
static HRESULT WINAPI d3d9_texture_cube_GetDevice(IDirect3DCubeTexture9 *iface, IDirect3DDevice9 **device) @@ -958,31 +945,15 @@ static HRESULT WINAPI d3d9_texture_3d_QueryInterface(IDirect3DVolumeTexture9 *if static ULONG WINAPI d3d9_texture_3d_AddRef(IDirect3DVolumeTexture9 *iface) { struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface); - ULONG ref = InterlockedIncrement(&texture->resource.refcount); - - TRACE("%p increasing refcount to %u.\n", iface, ref);
- if (ref == 1) - { - IDirect3DDevice9Ex_AddRef(&texture->parent_device->IDirect3DDevice9Ex_iface); - wined3d_mutex_lock(); - wined3d_texture_incref(texture->wined3d_texture); - wined3d_mutex_unlock(); - } - - return ref; + return d3d9_texture_incref(texture); }
static ULONG WINAPI d3d9_texture_3d_Release(IDirect3DVolumeTexture9 *iface) { struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface); - ULONG ref = InterlockedDecrement(&texture->resource.refcount);
- TRACE("%p decreasing refcount to %u.\n", iface, ref); - - if (!ref) - d3d9_texture_cleanup(texture); - return ref; + return d3d9_texture_decref(texture); }
static HRESULT WINAPI d3d9_texture_3d_GetDevice(IDirect3DVolumeTexture9 *iface, IDirect3DDevice9 **device)
From: Zebediah Figura zfigura@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52954 --- dlls/d3d9/d3d9_private.h | 8 +++- dlls/d3d9/device.c | 36 ++++++++++++++++-- dlls/d3d9/tests/visual.c | 2 +- dlls/d3d9/texture.c | 80 ++++++++++++++++++++++++++++------------ 4 files changed, 97 insertions(+), 29 deletions(-)
diff --git a/dlls/d3d9/d3d9_private.h b/dlls/d3d9/d3d9_private.h index 4169ab74973..fe13f679db4 100644 --- a/dlls/d3d9/d3d9_private.h +++ b/dlls/d3d9/d3d9_private.h @@ -125,6 +125,7 @@ struct d3d9_device HRESULT device_init(struct d3d9_device *device, struct d3d9 *parent, struct wined3d *wined3d, UINT adapter, D3DDEVTYPE device_type, HWND focus_window, DWORD flags, D3DPRESENT_PARAMETERS *parameters, D3DDISPLAYMODEEX *mode) DECLSPEC_HIDDEN; +void d3d9_device_upload_managed_textures(struct d3d9_device *device);
struct d3d9_resource { @@ -219,7 +220,7 @@ struct d3d9_texture { IDirect3DBaseTexture9 IDirect3DBaseTexture9_iface; struct d3d9_resource resource; - struct wined3d_texture *wined3d_texture; + struct wined3d_texture *wined3d_texture, *draw_texture; struct d3d9_device *parent_device; struct list rtv_list; DWORD usage; @@ -235,6 +236,11 @@ HRESULT d3d9_texture_3d_init(struct d3d9_texture *texture, struct d3d9_device *d HRESULT d3d9_texture_cube_init(struct d3d9_texture *texture, struct d3d9_device *device, unsigned int edge_length, unsigned int level_count, DWORD usage, D3DFORMAT format, D3DPOOL pool);
+static inline struct wined3d_texture *d3d9_texture_get_draw_texture(struct d3d9_texture *texture) +{ + return texture->draw_texture ? texture->draw_texture : texture->wined3d_texture; +} + struct d3d9_texture *unsafe_impl_from_IDirect3DBaseTexture9(IDirect3DBaseTexture9 *iface) DECLSPEC_HIDDEN; void d3d9_texture_flag_auto_gen_mipmap(struct d3d9_texture *texture) DECLSPEC_HIDDEN; void d3d9_texture_gen_auto_mipmap(struct d3d9_texture *texture) DECLSPEC_HIDDEN; diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c index 5f7b3f03ae3..878eed0412d 100644 --- a/dlls/d3d9/device.c +++ b/dlls/d3d9/device.c @@ -988,7 +988,7 @@ static HRESULT CDECL reset_enum_callback(struct wined3d_resource *resource) IUnknown *parent;
wined3d_resource_get_desc(resource, &desc); - if (desc.access & WINED3D_RESOURCE_ACCESS_CPU) + if ((desc.access & WINED3D_RESOURCE_ACCESS_CPU) || (desc.usage & WINED3DUSAGE_MANAGED)) return D3D_OK;
if (desc.resource_type != WINED3D_RTYPE_TEXTURE_2D) @@ -1724,6 +1724,12 @@ static HRESULT WINAPI d3d9_device_UpdateTexture(IDirect3DDevice9Ex *iface, src_impl = unsafe_impl_from_IDirect3DBaseTexture9(src_texture); dst_impl = unsafe_impl_from_IDirect3DBaseTexture9(dst_texture);
+ if (src_impl->draw_texture || dst_impl->draw_texture) + { + WARN("Source or destination is managed; returning D3DERR_INVALIDCALL.\n"); + return D3DERR_INVALIDCALL; + } + wined3d_mutex_lock(); hr = wined3d_device_update_texture(device->wined3d_device, src_impl->wined3d_texture, dst_impl->wined3d_texture); @@ -2638,7 +2644,7 @@ static HRESULT WINAPI d3d9_device_SetTexture(IDirect3DDevice9Ex *iface, DWORD st
wined3d_mutex_lock(); wined3d_stateblock_set_texture(device->update_state, stage, - texture_impl ? texture_impl->wined3d_texture : NULL); + texture_impl ? d3d9_texture_get_draw_texture(texture_impl) : NULL); if (!device->recording) { if (stage < D3D9_MAX_TEXTURE_UNITS) @@ -3004,6 +3010,25 @@ static HRESULT d3d9_device_upload_sysmem_index_buffer(struct d3d9_device *device return S_OK; }
+void d3d9_device_upload_managed_textures(struct d3d9_device *device) +{ + const struct wined3d_stateblock_state *state = device->stateblock_state; + unsigned int i; + + for (i = 0; i < WINED3D_MAX_COMBINED_SAMPLERS; ++i) + { + struct wined3d_texture *wined3d_texture = state->textures[i]; + struct d3d9_texture *d3d9_texture; + + if (!wined3d_texture) + continue; + d3d9_texture = wined3d_texture_get_parent(wined3d_texture); + if (d3d9_texture->draw_texture) + wined3d_device_update_texture(device->wined3d_device, + d3d9_texture->wined3d_texture, d3d9_texture->draw_texture); + } +} + static HRESULT WINAPI d3d9_device_DrawPrimitive(IDirect3DDevice9Ex *iface, D3DPRIMITIVETYPE primitive_type, UINT start_vertex, UINT primitive_count) { @@ -3022,6 +3047,7 @@ static HRESULT WINAPI d3d9_device_DrawPrimitive(IDirect3DDevice9Ex *iface, } wined3d_device_apply_stateblock(device->wined3d_device, device->state); vertex_count = vertex_count_from_primitive_count(primitive_type, primitive_count); + d3d9_device_upload_managed_textures(device); d3d9_device_upload_sysmem_vertex_buffers(device, 0, start_vertex, vertex_count); d3d9_generate_auto_mipmaps(device); wined3d_device_context_set_primitive_type(device->immediate_context, @@ -3059,6 +3085,7 @@ static HRESULT WINAPI d3d9_device_DrawIndexedPrimitive(IDirect3DDevice9Ex *iface return D3DERR_INVALIDCALL; } index_count = vertex_count_from_primitive_count(primitive_type, primitive_count); + d3d9_device_upload_managed_textures(device); d3d9_device_upload_sysmem_vertex_buffers(device, base_vertex_idx, min_vertex_idx, vertex_count); d3d9_generate_auto_mipmaps(device); wined3d_device_context_set_primitive_type(device->immediate_context, @@ -3113,6 +3140,7 @@ static HRESULT WINAPI d3d9_device_DrawPrimitiveUP(IDirect3DDevice9Ex *iface, goto done;
d3d9_generate_auto_mipmaps(device); + d3d9_device_upload_managed_textures(device); wined3d_device_context_set_primitive_type(device->immediate_context, wined3d_primitive_type_from_d3d(primitive_type), 0); wined3d_device_apply_stateblock(device->wined3d_device, device->state); @@ -3174,11 +3202,11 @@ static HRESULT WINAPI d3d9_device_DrawIndexedPrimitiveUP(IDirect3DDevice9Ex *ifa hr = wined3d_stateblock_set_stream_source(device->state, 0, device->vertex_buffer.buffer, 0, vertex_stride); if (FAILED(hr)) goto done; - - d3d9_generate_auto_mipmaps(device); wined3d_stateblock_set_index_buffer(device->state, device->index_buffer.buffer, wined3dformat_from_d3dformat(index_format));
+ d3d9_generate_auto_mipmaps(device); + d3d9_device_upload_managed_textures(device); wined3d_device_apply_stateblock(device->wined3d_device, device->state); wined3d_device_context_set_primitive_type(device->immediate_context, wined3d_primitive_type_from_d3d(primitive_type), 0); diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c index 5c31d25f2eb..d8fa298d6c7 100644 --- a/dlls/d3d9/tests/visual.c +++ b/dlls/d3d9/tests/visual.c @@ -19678,7 +19678,7 @@ static void add_dirty_rect_test(void) color = getPixelColor(device, 320, 240); ok(color_match(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color); color = getPixelColor(device, 1, 1); - todo_wine ok(color_match(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color); + ok(color_match(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color); hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); ok(SUCCEEDED(hr), "Failed to present, hr %#lx.\n", hr);
diff --git a/dlls/d3d9/texture.c b/dlls/d3d9/texture.c index 5308a7da08f..884876c60de 100644 --- a/dlls/d3d9/texture.c +++ b/dlls/d3d9/texture.c @@ -38,7 +38,7 @@ static ULONG d3d9_texture_incref(struct d3d9_texture *texture) { wined3d_rendertarget_view_incref(surface->wined3d_rtv); } - wined3d_texture_incref(texture->wined3d_texture); + wined3d_texture_incref(d3d9_texture_get_draw_texture(texture)); wined3d_mutex_unlock(); }
@@ -61,7 +61,7 @@ static ULONG d3d9_texture_decref(struct d3d9_texture *texture) wined3d_shader_resource_view_decref(texture->wined3d_srv); LIST_FOR_EACH_ENTRY(surface, &texture->rtv_list, struct d3d9_surface, rtv_entry) wined3d_rendertarget_view_decref(surface->wined3d_rtv); - wined3d_texture_decref(texture->wined3d_texture); + wined3d_texture_decref(d3d9_texture_get_draw_texture(texture)); wined3d_mutex_unlock();
/* Release the device last, as it may cause the device to be destroyed. */ @@ -73,7 +73,7 @@ static ULONG d3d9_texture_decref(struct d3d9_texture *texture) static void d3d9_texture_preload(struct d3d9_texture *texture) { wined3d_mutex_lock(); - wined3d_resource_preload(wined3d_texture_get_resource(texture->wined3d_texture)); + wined3d_resource_preload(wined3d_texture_get_resource(d3d9_texture_get_draw_texture(texture))); wined3d_mutex_unlock(); }
@@ -122,7 +122,7 @@ static struct wined3d_shader_resource_view *d3d9_texture_acquire_shader_resource desc.u.texture.layer_idx = 0; desc.u.texture.layer_count = sr_desc.usage & WINED3DUSAGE_LEGACY_CUBEMAP ? 6 : 1; if (FAILED(hr = wined3d_shader_resource_view_create(&desc, - wined3d_texture_get_resource(texture->wined3d_texture), texture, + wined3d_texture_get_resource(d3d9_texture_get_draw_texture(texture)), texture, &d3d9_srv_wined3d_parent_ops, &texture->wined3d_srv))) { ERR("Failed to create shader resource view, hr %#x.\n", hr); @@ -138,6 +138,7 @@ void d3d9_texture_gen_auto_mipmap(struct d3d9_texture *texture) if (!(texture->flags & D3D9_TEXTURE_MIPMAP_DIRTY)) return; d3d9_texture_acquire_shader_resource_view(texture); + d3d9_device_upload_managed_textures(texture->parent_device); wined3d_device_context_generate_mipmaps(texture->parent_device->immediate_context, texture->wined3d_srv); texture->flags &= ~D3D9_TEXTURE_MIPMAP_DIRTY; } @@ -233,7 +234,7 @@ static DWORD WINAPI d3d9_texture_2d_SetPriority(IDirect3DTexture9 *iface, DWORD TRACE("iface %p, priority %u.\n", iface, priority);
wined3d_mutex_lock(); - resource = wined3d_texture_get_resource(texture->wined3d_texture); + resource = wined3d_texture_get_resource(d3d9_texture_get_draw_texture(texture)); ret = wined3d_resource_set_priority(resource, priority); wined3d_mutex_unlock();
@@ -249,7 +250,7 @@ static DWORD WINAPI d3d9_texture_2d_GetPriority(IDirect3DTexture9 *iface) TRACE("iface %p.\n", iface);
wined3d_mutex_lock(); - resource = wined3d_texture_get_resource(texture->wined3d_texture); + resource = wined3d_texture_get_resource(d3d9_texture_get_draw_texture(texture)); ret = wined3d_resource_get_priority(resource); wined3d_mutex_unlock();
@@ -280,7 +281,7 @@ static DWORD WINAPI d3d9_texture_2d_SetLOD(IDirect3DTexture9 *iface, DWORD lod) TRACE("iface %p, lod %u.\n", iface, lod);
wined3d_mutex_lock(); - ret = wined3d_texture_set_lod(texture->wined3d_texture, lod); + ret = wined3d_texture_set_lod(d3d9_texture_get_draw_texture(texture), lod); wined3d_mutex_unlock();
return ret; @@ -294,7 +295,7 @@ static DWORD WINAPI d3d9_texture_2d_GetLOD(IDirect3DTexture9 *iface) TRACE("iface %p.\n", iface);
wined3d_mutex_lock(); - ret = wined3d_texture_get_lod(texture->wined3d_texture); + ret = wined3d_texture_get_lod(d3d9_texture_get_draw_texture(texture)); wined3d_mutex_unlock();
return ret; @@ -607,7 +608,7 @@ static DWORD WINAPI d3d9_texture_cube_SetPriority(IDirect3DCubeTexture9 *iface, TRACE("iface %p, priority %u.\n", iface, priority);
wined3d_mutex_lock(); - resource = wined3d_texture_get_resource(texture->wined3d_texture); + resource = wined3d_texture_get_resource(d3d9_texture_get_draw_texture(texture)); ret = wined3d_resource_set_priority(resource, priority); wined3d_mutex_unlock();
@@ -623,7 +624,7 @@ static DWORD WINAPI d3d9_texture_cube_GetPriority(IDirect3DCubeTexture9 *iface) TRACE("iface %p.\n", iface);
wined3d_mutex_lock(); - resource = wined3d_texture_get_resource(texture->wined3d_texture); + resource = wined3d_texture_get_resource(d3d9_texture_get_draw_texture(texture)); ret = wined3d_resource_get_priority(resource); wined3d_mutex_unlock();
@@ -654,7 +655,7 @@ static DWORD WINAPI d3d9_texture_cube_SetLOD(IDirect3DCubeTexture9 *iface, DWORD TRACE("iface %p, lod %u.\n", iface, lod);
wined3d_mutex_lock(); - ret = wined3d_texture_set_lod(texture->wined3d_texture, lod); + ret = wined3d_texture_set_lod(d3d9_texture_get_draw_texture(texture), lod); wined3d_mutex_unlock();
return ret; @@ -668,7 +669,7 @@ static DWORD WINAPI d3d9_texture_cube_GetLOD(IDirect3DCubeTexture9 *iface) TRACE("iface %p.\n", iface);
wined3d_mutex_lock(); - ret = wined3d_texture_get_lod(texture->wined3d_texture); + ret = wined3d_texture_get_lod(d3d9_texture_get_draw_texture(texture)); wined3d_mutex_unlock();
return ret; @@ -1007,7 +1008,7 @@ static DWORD WINAPI d3d9_texture_3d_SetPriority(IDirect3DVolumeTexture9 *iface, TRACE("iface %p, priority %u.\n", iface, priority);
wined3d_mutex_lock(); - resource = wined3d_texture_get_resource(texture->wined3d_texture); + resource = wined3d_texture_get_resource(d3d9_texture_get_draw_texture(texture)); ret = wined3d_resource_set_priority(resource, priority); wined3d_mutex_unlock();
@@ -1023,7 +1024,7 @@ static DWORD WINAPI d3d9_texture_3d_GetPriority(IDirect3DVolumeTexture9 *iface) TRACE("iface %p.\n", iface);
wined3d_mutex_lock(); - resource = wined3d_texture_get_resource(texture->wined3d_texture); + resource = wined3d_texture_get_resource(d3d9_texture_get_draw_texture(texture)); ret = wined3d_resource_get_priority(resource); wined3d_mutex_unlock();
@@ -1054,7 +1055,7 @@ static DWORD WINAPI d3d9_texture_3d_SetLOD(IDirect3DVolumeTexture9 *iface, DWORD TRACE("iface %p, lod %u.\n", iface, lod);
wined3d_mutex_lock(); - ret = wined3d_texture_set_lod(texture->wined3d_texture, lod); + ret = wined3d_texture_set_lod(d3d9_texture_get_draw_texture(texture), lod); wined3d_mutex_unlock();
return ret; @@ -1068,7 +1069,7 @@ static DWORD WINAPI d3d9_texture_3d_GetLOD(IDirect3DVolumeTexture9 *iface) TRACE("iface %p.\n", iface);
wined3d_mutex_lock(); - ret = wined3d_texture_get_lod(texture->wined3d_texture); + ret = wined3d_texture_get_lod(d3d9_texture_get_draw_texture(texture)); wined3d_mutex_unlock();
return ret; @@ -1256,6 +1257,10 @@ struct d3d9_texture *unsafe_impl_from_IDirect3DBaseTexture9(IDirect3DBaseTexture static void STDMETHODCALLTYPE d3d9_texture_wined3d_object_destroyed(void *parent) { struct d3d9_texture *texture = parent; + + /* If the texture was managed, release the sysmem copy now. */ + if (texture->draw_texture) + wined3d_texture_decref(texture->wined3d_texture); d3d9_resource_cleanup(&texture->resource); heap_free(texture); } @@ -1286,7 +1291,7 @@ static HRESULT d3d9_texture_init(struct d3d9_texture *texture, struct d3d9_devic
if (desc->resource_type == WINED3D_RTYPE_TEXTURE_2D && is_gdi_compat_wined3dformat(desc->format)) flags |= WINED3D_TEXTURE_CREATE_GET_DC; - if (pool == D3DPOOL_SYSTEMMEM) + if (pool == D3DPOOL_SYSTEMMEM || pool == D3DPOOL_MANAGED) flags |= WINED3D_TEXTURE_CREATE_RECORD_DIRTY_REGIONS;
if (usage & D3DUSAGE_WRITEONLY) @@ -1341,14 +1346,43 @@ static HRESULT d3d9_texture_init(struct d3d9_texture *texture, struct d3d9_devic level_count = wined3d_log2i(max(max(desc->width, desc->height), desc->depth)) + 1;
wined3d_mutex_lock(); - hr = wined3d_texture_create(device->wined3d_device, desc, layer_count, level_count, flags, - NULL, texture, &d3d9_texture_wined3d_parent_ops, &texture->wined3d_texture); - wined3d_mutex_unlock(); - if (FAILED(hr)) + if (pool == D3DPOOL_MANAGED) + { + struct wined3d_resource_desc managed_desc = *desc; + + managed_desc.access = WINED3D_RESOURCE_ACCESS_CPU | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W; + managed_desc.bind_flags = 0; + if (FAILED(hr = wined3d_texture_create(device->wined3d_device, &managed_desc, layer_count, level_count, flags, + NULL, texture, &d3d9_null_wined3d_parent_ops, &texture->wined3d_texture))) + { + wined3d_mutex_unlock(); + WARN("Failed to create sysmem texture, hr %#x.\n", hr); + return hr; + } + + managed_desc.access = WINED3D_RESOURCE_ACCESS_GPU; + managed_desc.bind_flags = desc->bind_flags; + flags &= WINED3D_TEXTURE_CREATE_GENERATE_MIPMAPS; + if (FAILED(hr = wined3d_texture_create(device->wined3d_device, &managed_desc, layer_count, level_count, flags, + NULL, texture, &d3d9_texture_wined3d_parent_ops, &texture->draw_texture))) + { + wined3d_texture_decref(texture->wined3d_texture); + wined3d_mutex_unlock(); + WARN("Failed to create draw texture, hr %#x.\n", hr); + return hr; + } + } + else { - WARN("Failed to create wined3d texture, hr %#x.\n", hr); - return hr; + if (FAILED(hr = wined3d_texture_create(device->wined3d_device, desc, layer_count, level_count, flags, + NULL, texture, &d3d9_texture_wined3d_parent_ops, &texture->wined3d_texture))) + { + wined3d_mutex_unlock(); + WARN("Failed to create wined3d texture, hr %#x.\n", hr); + return hr; + } } + wined3d_mutex_unlock();
texture->parent_device = device; IDirect3DDevice9Ex_AddRef(&texture->parent_device->IDirect3DDevice9Ex_iface);
This merge request was approved by Jan Sikorski.