From: Zebediah Figura zfigura@codeweavers.com
Instead of having d3d11 create the wined3d texture, create it in dxgi instead, and let d3d11 create a d3d_texture2d object to wrap it.
This is a step towards getting rid of the create_swapchain_texture() callback, which is mildly difficult to work with and conceptually complex. --- dlls/d3d11/d3d11_private.h | 3 +- dlls/d3d11/device.c | 45 +++++++++++++++++++++- dlls/d3d11/texture.c | 77 ++++++++++++++++++++++---------------- dlls/dxgi/device.c | 28 ++++++++------ include/wine/winedxgi.idl | 2 + 5 files changed, 107 insertions(+), 48 deletions(-)
diff --git a/dlls/d3d11/d3d11_private.h b/dlls/d3d11/d3d11_private.h index 7cb3ba13c0a..226d7b6b4e1 100644 --- a/dlls/d3d11/d3d11_private.h +++ b/dlls/d3d11/d3d11_private.h @@ -148,7 +148,8 @@ static inline struct d3d_texture2d *impl_from_ID3D11Texture2D(ID3D11Texture2D *i }
HRESULT d3d_texture2d_create(struct d3d_device *device, const D3D11_TEXTURE2D_DESC *desc, - const D3D11_SUBRESOURCE_DATA *data, struct d3d_texture2d **texture) DECLSPEC_HIDDEN; + struct wined3d_texture *wined3d_texture, + const D3D11_SUBRESOURCE_DATA *data, struct d3d_texture2d **out) DECLSPEC_HIDDEN; struct d3d_texture2d *unsafe_impl_from_ID3D11Texture2D(ID3D11Texture2D *iface) DECLSPEC_HIDDEN; struct d3d_texture2d *unsafe_impl_from_ID3D10Texture2D(ID3D10Texture2D *iface) DECLSPEC_HIDDEN;
diff --git a/dlls/d3d11/device.c b/dlls/d3d11/device.c index 5cb84c59dee..cf6ab388aec 100644 --- a/dlls/d3d11/device.c +++ b/dlls/d3d11/device.c @@ -3335,7 +3335,7 @@ static HRESULT STDMETHODCALLTYPE d3d11_device_CreateTexture2D(ID3D11Device2 *ifa
TRACE("iface %p, desc %p, data %p, texture %p.\n", iface, desc, data, texture);
- if (FAILED(hr = d3d_texture2d_create(device, desc, data, &object))) + if (FAILED(hr = d3d_texture2d_create(device, desc, NULL, data, &object))) return hr;
*texture = &object->ID3D11Texture2D_iface; @@ -6021,7 +6021,7 @@ static HRESULT STDMETHODCALLTYPE d3d10_device_CreateTexture2D(ID3D10Device1 *ifa d3d11_desc.CPUAccessFlags = d3d11_cpu_access_flags_from_d3d10_cpu_access_flags(desc->CPUAccessFlags); d3d11_desc.MiscFlags = d3d11_resource_misc_flags_from_d3d10_resource_misc_flags(desc->MiscFlags);
- if (FAILED(hr = d3d_texture2d_create(device, &d3d11_desc, (const D3D11_SUBRESOURCE_DATA *)data, &object))) + if (FAILED(hr = d3d_texture2d_create(device, &d3d11_desc, NULL, (const D3D11_SUBRESOURCE_DATA *)data, &object))) return hr;
*texture = &object->ID3D10Texture2D_iface; @@ -6780,6 +6780,46 @@ static struct wined3d_device_parent * STDMETHODCALLTYPE dxgi_device_parent_get_w return &device->device_parent; }
+static HRESULT STDMETHODCALLTYPE dxgi_device_parent_swapchain_texture_created(IWineDXGIDeviceParent *iface, + struct wined3d_texture *wined3d_texture, unsigned int texture_flags, IDXGISurface **ret_surface) +{ + struct d3d_device *device = device_from_dxgi_device_parent(iface); + struct wined3d_resource_desc wined3d_desc; + struct d3d_texture2d *object; + D3D11_TEXTURE2D_DESC desc; + HRESULT hr; + + wined3d_resource_get_desc(wined3d_texture_get_resource(wined3d_texture), &wined3d_desc); + + desc.Width = wined3d_desc.width; + desc.Height = wined3d_desc.height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = dxgi_format_from_wined3dformat(wined3d_desc.format); + desc.SampleDesc.Count = wined3d_desc.multisample_type ? wined3d_desc.multisample_type : 1; + desc.SampleDesc.Quality = wined3d_desc.multisample_quality; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = d3d11_bind_flags_from_wined3d(wined3d_desc.bind_flags); + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + if (texture_flags & WINED3D_TEXTURE_CREATE_GET_DC) + { + desc.MiscFlags |= D3D11_RESOURCE_MISC_GDI_COMPATIBLE; + texture_flags &= ~WINED3D_TEXTURE_CREATE_GET_DC; + } + + if (texture_flags) + FIXME("Unhandled flags %#x.\n", texture_flags); + + if (FAILED(hr = d3d_texture2d_create(device, &desc, wined3d_texture, NULL, &object))) + return hr; + + hr = IUnknown_QueryInterface(object->dxgi_resource, &IID_IDXGISurface, (void **)ret_surface); + ID3D11Texture2D_Release(&object->ID3D11Texture2D_iface); + return hr; +} + static const struct IWineDXGIDeviceParentVtbl d3d_dxgi_device_parent_vtbl = { /* IUnknown methods */ @@ -6788,6 +6828,7 @@ static const struct IWineDXGIDeviceParentVtbl d3d_dxgi_device_parent_vtbl = dxgi_device_parent_Release, /* IWineDXGIDeviceParent methods */ dxgi_device_parent_get_wined3d_device_parent, + dxgi_device_parent_swapchain_texture_created, };
static inline struct d3d_device *device_from_wined3d_device_parent(struct wined3d_device_parent *device_parent) diff --git a/dlls/d3d11/texture.c b/dlls/d3d11/texture.c index dcc05725f65..5cd7df11f1f 100644 --- a/dlls/d3d11/texture.c +++ b/dlls/d3d11/texture.c @@ -956,11 +956,9 @@ static BOOL validate_texture2d_desc(const D3D11_TEXTURE2D_DESC *desc, D3D_FEATUR }
HRESULT d3d_texture2d_create(struct d3d_device *device, const D3D11_TEXTURE2D_DESC *desc, - const D3D11_SUBRESOURCE_DATA *data, struct d3d_texture2d **out) + struct wined3d_texture *wined3d_texture, const D3D11_SUBRESOURCE_DATA *data, struct d3d_texture2d **out) { - struct wined3d_resource_desc wined3d_desc; struct d3d_texture2d *texture; - unsigned int levels; BOOL needs_surface; DWORD flags = 0; HRESULT hr; @@ -980,38 +978,51 @@ HRESULT d3d_texture2d_create(struct d3d_device *device, const D3D11_TEXTURE2D_DE wined3d_mutex_lock(); texture->desc = *desc;
- wined3d_desc.resource_type = WINED3D_RTYPE_TEXTURE_2D; - wined3d_desc.format = wined3dformat_from_dxgi_format(desc->Format); - wined3d_desc.multisample_type = desc->SampleDesc.Count > 1 ? desc->SampleDesc.Count : WINED3D_MULTISAMPLE_NONE; - wined3d_desc.multisample_quality = desc->SampleDesc.Quality; - wined3d_desc.usage = wined3d_usage_from_d3d11(desc->Usage); - wined3d_desc.bind_flags = wined3d_bind_flags_from_d3d11(desc->BindFlags, desc->MiscFlags); - wined3d_desc.access = wined3d_access_from_d3d11(desc->Usage, - desc->Usage == D3D11_USAGE_DEFAULT ? 0 : desc->CPUAccessFlags); - wined3d_desc.width = desc->Width; - wined3d_desc.height = desc->Height; - wined3d_desc.depth = 1; - wined3d_desc.size = 0; - - levels = desc->MipLevels ? desc->MipLevels : wined3d_log2i(max(desc->Width, desc->Height)) + 1; - - if (desc->MiscFlags & D3D11_RESOURCE_MISC_GDI_COMPATIBLE) - flags |= WINED3D_TEXTURE_CREATE_GET_DC; - if (desc->MiscFlags & D3D11_RESOURCE_MISC_GENERATE_MIPS) - flags |= WINED3D_TEXTURE_CREATE_GENERATE_MIPMAPS; - - if (FAILED(hr = wined3d_texture_create(device->wined3d_device, &wined3d_desc, - desc->ArraySize, levels, flags, (struct wined3d_sub_resource_data *)data, - texture, &d3d_texture2d_wined3d_parent_ops, &texture->wined3d_texture))) + if (wined3d_texture) { - WARN("Failed to create wined3d texture, hr %#lx.\n", hr); - free(texture); - wined3d_mutex_unlock(); - if (hr == WINED3DERR_NOTAVAILABLE || hr == WINED3DERR_INVALIDCALL) - hr = E_INVALIDARG; - return hr; + wined3d_resource_set_parent(wined3d_texture_get_resource(wined3d_texture), + texture, &d3d_texture2d_wined3d_parent_ops); + wined3d_texture_incref(wined3d_texture); + texture->wined3d_texture = wined3d_texture; + } + else + { + struct wined3d_resource_desc wined3d_desc; + unsigned int levels; + + wined3d_desc.resource_type = WINED3D_RTYPE_TEXTURE_2D; + wined3d_desc.format = wined3dformat_from_dxgi_format(desc->Format); + wined3d_desc.multisample_type = desc->SampleDesc.Count > 1 ? desc->SampleDesc.Count : WINED3D_MULTISAMPLE_NONE; + wined3d_desc.multisample_quality = desc->SampleDesc.Quality; + wined3d_desc.usage = wined3d_usage_from_d3d11(desc->Usage); + wined3d_desc.bind_flags = wined3d_bind_flags_from_d3d11(desc->BindFlags, desc->MiscFlags); + wined3d_desc.access = wined3d_access_from_d3d11(desc->Usage, + desc->Usage == D3D11_USAGE_DEFAULT ? 0 : desc->CPUAccessFlags); + wined3d_desc.width = desc->Width; + wined3d_desc.height = desc->Height; + wined3d_desc.depth = 1; + wined3d_desc.size = 0; + + levels = desc->MipLevels ? desc->MipLevels : wined3d_log2i(max(desc->Width, desc->Height)) + 1; + + if (desc->MiscFlags & D3D11_RESOURCE_MISC_GDI_COMPATIBLE) + flags |= WINED3D_TEXTURE_CREATE_GET_DC; + if (desc->MiscFlags & D3D11_RESOURCE_MISC_GENERATE_MIPS) + flags |= WINED3D_TEXTURE_CREATE_GENERATE_MIPMAPS; + + if (FAILED(hr = wined3d_texture_create(device->wined3d_device, &wined3d_desc, + desc->ArraySize, levels, flags, (struct wined3d_sub_resource_data *)data, + texture, &d3d_texture2d_wined3d_parent_ops, &texture->wined3d_texture))) + { + WARN("Failed to create wined3d texture, hr %#lx.\n", hr); + free(texture); + wined3d_mutex_unlock(); + if (hr == WINED3DERR_NOTAVAILABLE || hr == WINED3DERR_INVALIDCALL) + hr = E_INVALIDARG; + return hr; + } + texture->desc.MipLevels = levels; } - texture->desc.MipLevels = levels;
needs_surface = desc->MipLevels == 1 && desc->ArraySize == 1; hr = d3d_device_create_dxgi_resource((IUnknown *)&device->ID3D10Device1_iface, diff --git a/dlls/dxgi/device.c b/dlls/dxgi/device.c index efa04e0f495..3f3a18e4639 100644 --- a/dlls/dxgi/device.c +++ b/dlls/dxgi/device.c @@ -21,6 +21,13 @@
WINE_DEFAULT_DEBUG_CHANNEL(dxgi);
+static void STDMETHODCALLTYPE dxgi_null_wined3d_object_destroyed(void *parent) {} + +static const struct wined3d_parent_ops dxgi_null_wined3d_parent_ops = +{ + dxgi_null_wined3d_object_destroyed, +}; + static inline struct dxgi_device *impl_from_IWineDXGIDevice(IWineDXGIDevice *iface) { return CONTAINING_RECORD(iface, struct dxgi_device, IWineDXGIDevice_iface); @@ -168,7 +175,7 @@ static HRESULT STDMETHODCALLTYPE dxgi_device_CreateSurface(IWineDXGIDevice *ifac const DXGI_SURFACE_DESC *desc, UINT surface_count, DXGI_USAGE usage, const DXGI_SHARED_RESOURCE *shared_resource, IDXGISurface **surface) { - struct wined3d_device_parent *device_parent; + struct dxgi_device *device = impl_from_IWineDXGIDevice(iface); struct wined3d_resource_desc surface_desc; IWineDXGIDeviceParent *dxgi_device_parent; HRESULT hr; @@ -185,8 +192,6 @@ static HRESULT STDMETHODCALLTYPE dxgi_device_CreateSurface(IWineDXGIDevice *ifac return E_FAIL; }
- device_parent = IWineDXGIDeviceParent_get_wined3d_device_parent(dxgi_device_parent); - surface_desc.resource_type = WINED3D_RTYPE_TEXTURE_2D; surface_desc.format = wined3dformat_from_dxgi_format(desc->Format); wined3d_sample_desc_from_dxgi(&surface_desc.multisample_type, @@ -204,23 +209,22 @@ static HRESULT STDMETHODCALLTYPE dxgi_device_CreateSurface(IWineDXGIDevice *ifac for (i = 0; i < surface_count; ++i) { struct wined3d_texture *wined3d_texture; - IUnknown *parent;
- if (FAILED(hr = device_parent->ops->create_swapchain_texture(device_parent, - NULL, &surface_desc, 0, &wined3d_texture))) + if (FAILED(hr = wined3d_texture_create(device->wined3d_device, &surface_desc, + 1, 1, 0, NULL, NULL, &dxgi_null_wined3d_parent_ops, &wined3d_texture))) { - ERR("Failed to create surface, hr %#lx.\n", hr); + ERR("Failed to create wined3d texture, hr %#lx.\n", hr); goto fail; }
- parent = wined3d_texture_get_parent(wined3d_texture); - hr = IUnknown_QueryInterface(parent, &IID_IDXGISurface, (void **)&surface[i]); - wined3d_texture_decref(wined3d_texture); - if (FAILED(hr)) + if (FAILED(hr = IWineDXGIDeviceParent_swapchain_texture_created( + dxgi_device_parent, wined3d_texture, 0, &surface[i]))) { - ERR("Surface should implement IDXGISurface.\n"); + wined3d_texture_decref(wined3d_texture); + ERR("Failed to create parent swapchain texture, hr %#lx.\n", hr); goto fail; } + wined3d_texture_decref(wined3d_texture);
TRACE("Created IDXGISurface %p (%u/%u).\n", surface[i], i + 1, surface_count); } diff --git a/include/wine/winedxgi.idl b/include/wine/winedxgi.idl index 64e4218204b..86447df55e9 100644 --- a/include/wine/winedxgi.idl +++ b/include/wine/winedxgi.idl @@ -62,6 +62,8 @@ interface IWineDXGIDevice : IDXGIDevice3 interface IWineDXGIDeviceParent : IUnknown { struct wined3d_device_parent *get_wined3d_device_parent(); + HRESULT swapchain_texture_created(struct wined3d_texture *texture, + unsigned int texture_flags, IDXGISurface **ret_surface); }
struct wine_dxgi_adapter_info