dxgi: Introduce IWineDXGIDeviceParent::register_swapchain_texture() and use it in IDXGIDevice::CreateSurface().

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.
This commit is contained in:
Zebediah Figura 2023-04-10 15:53:26 -05:00 committed by Alexandre Julliard
parent f443b9e042
commit 4413e94908
5 changed files with 109 additions and 50 deletions

View file

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

View file

@ -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_register_swapchain_texture(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_register_swapchain_texture,
};
static inline struct d3d_device *device_from_wined3d_device_parent(struct wined3d_device_parent *device_parent)

View file

@ -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,

View file

@ -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]);
if (FAILED(hr = IWineDXGIDeviceParent_register_swapchain_texture(
dxgi_device_parent, wined3d_texture, 0, &surface[i])))
{
wined3d_texture_decref(wined3d_texture);
ERR("Failed to create parent swapchain texture, hr %#lx.\n", hr);
goto fail;
}
wined3d_texture_decref(wined3d_texture);
if (FAILED(hr))
{
ERR("Surface should implement IDXGISurface.\n");
goto fail;
}
TRACE("Created IDXGISurface %p (%u/%u).\n", surface[i], i + 1, surface_count);
}

View file

@ -62,6 +62,8 @@ interface IWineDXGIDevice : IDXGIDevice3
interface IWineDXGIDeviceParent : IUnknown
{
struct wined3d_device_parent *get_wined3d_device_parent();
HRESULT register_swapchain_texture(struct wined3d_texture *texture,
unsigned int texture_flags, IDXGISurface **ret_surface);
}
struct wine_dxgi_adapter_info