For React Native.
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/d3d11/tests/d3d11.c | 13 +++--- dlls/dxgi/device.c | 2 +- dlls/dxgi/dxgi_private.h | 2 +- dlls/dxgi/resource.c | 92 +++++++++++++++++++++++++--------------- 4 files changed, 67 insertions(+), 42 deletions(-)
diff --git a/dlls/d3d11/tests/d3d11.c b/dlls/d3d11/tests/d3d11.c index a8ab542029b..b17535b9603 100644 --- a/dlls/d3d11/tests/d3d11.c +++ b/dlls/d3d11/tests/d3d11.c @@ -35162,7 +35162,7 @@ static void test_shared_resource(D3D_FEATURE_LEVEL feature_level) hr = ID3D11Texture2D_QueryInterface(tex, &IID_IDXGIResource, (void **)&res); ok(hr == S_OK, "got %#lx.\n", hr); hr = ID3D11Texture2D_QueryInterface(tex, &IID_IDXGIResource1, (void **)&res1); - todo_wine ok(hr == S_OK, "got %#lx.\n", hr); + ok(hr == S_OK, "got %#lx.\n", hr); if (FAILED(hr)) goto test_done;
@@ -35170,21 +35170,24 @@ static void test_shared_resource(D3D_FEATURE_LEVEL feature_level) hr = IDXGIResource_GetSharedHandle(res, &h); if (nthandle) { - ok(hr == E_INVALIDARG, "got %#lx.\n", hr); + todo_wine ok(hr == E_INVALIDARG, "got %#lx.\n", hr); ok(h == (HANDLE)0xdeadbeef, "got %p.\n", h); } else if (desc.MiscFlags) { - ok(hr == S_OK, "got %#lx.\n", hr); + todo_wine ok(hr == S_OK, "got %#lx.\n", hr); ok(is_kmt_handle(h), "wrong handle %p.\n", h); handle = h; } else { - ok(hr == S_OK, "got %#lx.\n", hr); - ok(!h, "got %p.\n", h); + todo_wine ok(hr == S_OK, "got %#lx.\n", hr); + todo_wine ok(!h, "got %p.\n", h); }
+ if (FAILED(hr)) + goto test_done; + h = (HANDLE)0xdeadbeef; hr = IDXGIResource1_CreateSharedHandle(res1, NULL, GENERIC_ALL | DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE, NULL, &h); diff --git a/dlls/dxgi/device.c b/dlls/dxgi/device.c index dec9425073c..4325785e9c2 100644 --- a/dlls/dxgi/device.c +++ b/dlls/dxgi/device.c @@ -355,7 +355,7 @@ static HRESULT STDMETHODCALLTYPE dxgi_device_create_resource(IWineDXGIDevice *if }
TRACE("Created resource %p.\n", object); - *resource = outer ? &object->IUnknown_iface : (IUnknown *)&object->IDXGIResource_iface; + *resource = outer ? &object->IUnknown_iface : (IUnknown *)&object->IDXGIResource1_iface;
return S_OK; } diff --git a/dlls/dxgi/dxgi_private.h b/dlls/dxgi/dxgi_private.h index 164bc107c6e..8e5c03b087b 100644 --- a/dlls/dxgi/dxgi_private.h +++ b/dlls/dxgi/dxgi_private.h @@ -198,7 +198,7 @@ BOOL dxgi_validate_swapchain_desc(const DXGI_SWAP_CHAIN_DESC1 *desc); struct dxgi_resource { IDXGISurface1 IDXGISurface1_iface; - IDXGIResource IDXGIResource_iface; + IDXGIResource1 IDXGIResource1_iface; IUnknown IUnknown_iface; IUnknown *outer_unknown; LONG refcount; diff --git a/dlls/dxgi/resource.c b/dlls/dxgi/resource.c index 0a2fa097456..deb98235589 100644 --- a/dlls/dxgi/resource.c +++ b/dlls/dxgi/resource.c @@ -42,12 +42,13 @@ static HRESULT STDMETHODCALLTYPE dxgi_resource_inner_QueryInterface(IUnknown *if return S_OK; } else if (IsEqualGUID(riid, &IID_IDXGIResource) + || IsEqualGUID(riid, &IID_IDXGIResource1) || IsEqualGUID(riid, &IID_IDXGIDeviceSubObject) || IsEqualGUID(riid, &IID_IDXGIObject) || IsEqualGUID(riid, &IID_IUnknown)) { - IDXGIResource_AddRef(&resource->IDXGIResource_iface); - *out = &resource->IDXGIResource_iface; + IDXGIResource1_AddRef(&resource->IDXGIResource1_iface); + *out = &resource->IDXGIResource1_iface; return S_OK; }
@@ -94,19 +95,19 @@ static HRESULT STDMETHODCALLTYPE dxgi_surface_QueryInterface(IDXGISurface1 *ifac void **object) { struct dxgi_resource *resource = impl_from_IDXGISurface1(iface); - return IDXGIResource_QueryInterface(&resource->IDXGIResource_iface, riid, object); + return IDXGIResource1_QueryInterface(&resource->IDXGIResource1_iface, riid, object); }
static ULONG STDMETHODCALLTYPE dxgi_surface_AddRef(IDXGISurface1 *iface) { struct dxgi_resource *resource = impl_from_IDXGISurface1(iface); - return IDXGIResource_AddRef(&resource->IDXGIResource_iface); + return IDXGIResource1_AddRef(&resource->IDXGIResource1_iface); }
static ULONG STDMETHODCALLTYPE dxgi_surface_Release(IDXGISurface1 *iface) { struct dxgi_resource *resource = impl_from_IDXGISurface1(iface); - return IDXGIResource_Release(&resource->IDXGIResource_iface); + return IDXGIResource1_Release(&resource->IDXGIResource1_iface); }
/* IDXGIObject methods */ @@ -115,27 +116,27 @@ static HRESULT STDMETHODCALLTYPE dxgi_surface_SetPrivateData(IDXGISurface1 *ifac REFGUID guid, UINT data_size, const void *data) { struct dxgi_resource *resource = impl_from_IDXGISurface1(iface); - return IDXGIResource_SetPrivateData(&resource->IDXGIResource_iface, guid, data_size, data); + return IDXGIResource1_SetPrivateData(&resource->IDXGIResource1_iface, guid, data_size, data); }
static HRESULT STDMETHODCALLTYPE dxgi_surface_SetPrivateDataInterface(IDXGISurface1 *iface, REFGUID guid, const IUnknown *object) { struct dxgi_resource *resource = impl_from_IDXGISurface1(iface); - return IDXGIResource_SetPrivateDataInterface(&resource->IDXGIResource_iface, guid, object); + return IDXGIResource1_SetPrivateDataInterface(&resource->IDXGIResource1_iface, guid, object); }
static HRESULT STDMETHODCALLTYPE dxgi_surface_GetPrivateData(IDXGISurface1 *iface, REFGUID guid, UINT *data_size, void *data) { struct dxgi_resource *resource = impl_from_IDXGISurface1(iface); - return IDXGIResource_GetPrivateData(&resource->IDXGIResource_iface, guid, data_size, data); + return IDXGIResource1_GetPrivateData(&resource->IDXGIResource1_iface, guid, data_size, data); }
static HRESULT STDMETHODCALLTYPE dxgi_surface_GetParent(IDXGISurface1 *iface, REFIID riid, void **parent) { struct dxgi_resource *resource = impl_from_IDXGISurface1(iface); - return IDXGIResource_GetParent(&resource->IDXGIResource_iface, riid, parent); + return IDXGIResource1_GetParent(&resource->IDXGIResource1_iface, riid, parent); }
/* IDXGIDeviceSubObject methods */ @@ -143,7 +144,7 @@ static HRESULT STDMETHODCALLTYPE dxgi_surface_GetParent(IDXGISurface1 *iface, RE static HRESULT STDMETHODCALLTYPE dxgi_surface_GetDevice(IDXGISurface1 *iface, REFIID riid, void **device) { struct dxgi_resource *resource = impl_from_IDXGISurface1(iface); - return IDXGIResource_GetDevice(&resource->IDXGIResource_iface, riid, device); + return IDXGIResource1_GetDevice(&resource->IDXGIResource1_iface, riid, device); }
/* IDXGISurface methods */ @@ -259,70 +260,70 @@ static const struct IDXGISurface1Vtbl dxgi_surface_vtbl = dxgi_surface_ReleaseDC, };
-static inline struct dxgi_resource *impl_from_IDXGIResource(IDXGIResource *iface) +static inline struct dxgi_resource *impl_from_IDXGIResource1(IDXGIResource1 *iface) { - return CONTAINING_RECORD(iface, struct dxgi_resource, IDXGIResource_iface); + return CONTAINING_RECORD(iface, struct dxgi_resource, IDXGIResource1_iface); }
/* IUnknown methods */
-static HRESULT STDMETHODCALLTYPE dxgi_resource_QueryInterface(IDXGIResource *iface, REFIID riid, +static HRESULT STDMETHODCALLTYPE dxgi_resource_QueryInterface(IDXGIResource1 *iface, REFIID riid, void **object) { - struct dxgi_resource *resource = impl_from_IDXGIResource(iface); + struct dxgi_resource *resource = impl_from_IDXGIResource1(iface); TRACE("Forwarding to outer IUnknown\n"); return IUnknown_QueryInterface(resource->outer_unknown, riid, object); }
-static ULONG STDMETHODCALLTYPE dxgi_resource_AddRef(IDXGIResource *iface) +static ULONG STDMETHODCALLTYPE dxgi_resource_AddRef(IDXGIResource1 *iface) { - struct dxgi_resource *resource = impl_from_IDXGIResource(iface); + struct dxgi_resource *resource = impl_from_IDXGIResource1(iface); TRACE("Forwarding to outer IUnknown\n"); return IUnknown_AddRef(resource->outer_unknown); }
-static ULONG STDMETHODCALLTYPE dxgi_resource_Release(IDXGIResource *iface) +static ULONG STDMETHODCALLTYPE dxgi_resource_Release(IDXGIResource1 *iface) { - struct dxgi_resource *resource = impl_from_IDXGIResource(iface); + struct dxgi_resource *resource = impl_from_IDXGIResource1(iface); TRACE("Forwarding to outer IUnknown\n"); return IUnknown_Release(resource->outer_unknown); }
/* IDXGIObject methods */
-static HRESULT STDMETHODCALLTYPE dxgi_resource_SetPrivateData(IDXGIResource *iface, +static HRESULT STDMETHODCALLTYPE dxgi_resource_SetPrivateData(IDXGIResource1 *iface, REFGUID guid, UINT data_size, const void *data) { - struct dxgi_resource *resource = impl_from_IDXGIResource(iface); + struct dxgi_resource *resource = impl_from_IDXGIResource1(iface);
TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
return dxgi_set_private_data(&resource->private_store, guid, data_size, data); }
-static HRESULT STDMETHODCALLTYPE dxgi_resource_SetPrivateDataInterface(IDXGIResource *iface, +static HRESULT STDMETHODCALLTYPE dxgi_resource_SetPrivateDataInterface(IDXGIResource1 *iface, REFGUID guid, const IUnknown *object) { - struct dxgi_resource *resource = impl_from_IDXGIResource(iface); + struct dxgi_resource *resource = impl_from_IDXGIResource1(iface);
TRACE("iface %p, guid %s, object %p.\n", iface, debugstr_guid(guid), object);
return dxgi_set_private_data_interface(&resource->private_store, guid, object); }
-static HRESULT STDMETHODCALLTYPE dxgi_resource_GetPrivateData(IDXGIResource *iface, +static HRESULT STDMETHODCALLTYPE dxgi_resource_GetPrivateData(IDXGIResource1 *iface, REFGUID guid, UINT *data_size, void *data) { - struct dxgi_resource *resource = impl_from_IDXGIResource(iface); + struct dxgi_resource *resource = impl_from_IDXGIResource1(iface);
TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
return dxgi_get_private_data(&resource->private_store, guid, data_size, data); }
-static HRESULT STDMETHODCALLTYPE dxgi_resource_GetParent(IDXGIResource *iface, REFIID riid, void **parent) +static HRESULT STDMETHODCALLTYPE dxgi_resource_GetParent(IDXGIResource1 *iface, REFIID riid, void **parent) { - struct dxgi_resource *resource = impl_from_IDXGIResource(iface); + struct dxgi_resource *resource = impl_from_IDXGIResource1(iface);
TRACE("iface %p, riid %s, parent %p.\n", iface, debugstr_guid(riid), parent);
@@ -331,9 +332,9 @@ static HRESULT STDMETHODCALLTYPE dxgi_resource_GetParent(IDXGIResource *iface, R
/* IDXGIDeviceSubObject methods */
-static HRESULT STDMETHODCALLTYPE dxgi_resource_GetDevice(IDXGIResource *iface, REFIID riid, void **device) +static HRESULT STDMETHODCALLTYPE dxgi_resource_GetDevice(IDXGIResource1 *iface, REFIID riid, void **device) { - struct dxgi_resource *resource = impl_from_IDXGIResource(iface); + struct dxgi_resource *resource = impl_from_IDXGIResource1(iface);
TRACE("iface %p, riid %s, device %p.\n", iface, debugstr_guid(riid), device);
@@ -341,16 +342,16 @@ static HRESULT STDMETHODCALLTYPE dxgi_resource_GetDevice(IDXGIResource *iface, R }
/* IDXGIResource methods */ -static HRESULT STDMETHODCALLTYPE dxgi_resource_GetSharedHandle(IDXGIResource *iface, HANDLE *shared_handle) +static HRESULT STDMETHODCALLTYPE dxgi_resource_GetSharedHandle(IDXGIResource1 *iface, HANDLE *shared_handle) { FIXME("iface %p, shared_handle %p stub!\n", iface, shared_handle);
return E_NOTIMPL; }
-static HRESULT STDMETHODCALLTYPE dxgi_resource_GetUsage(IDXGIResource *iface, DXGI_USAGE *usage) +static HRESULT STDMETHODCALLTYPE dxgi_resource_GetUsage(IDXGIResource1 *iface, DXGI_USAGE *usage) { - struct dxgi_resource *resource = impl_from_IDXGIResource(iface); + struct dxgi_resource *resource = impl_from_IDXGIResource1(iface); struct wined3d_resource_desc resource_desc;
TRACE("iface %p, usage %p.\n", iface, usage); @@ -381,21 +382,39 @@ static HRESULT STDMETHODCALLTYPE dxgi_resource_GetUsage(IDXGIResource *iface, DX return S_OK; }
-static HRESULT STDMETHODCALLTYPE dxgi_resource_SetEvictionPriority(IDXGIResource *iface, UINT eviction_priority) +static HRESULT STDMETHODCALLTYPE dxgi_resource_SetEvictionPriority(IDXGIResource1 *iface, UINT eviction_priority) { FIXME("iface %p, eviction_priority %u stub!\n", iface, eviction_priority);
return E_NOTIMPL; }
-static HRESULT STDMETHODCALLTYPE dxgi_resource_GetEvictionPriority(IDXGIResource *iface, UINT *eviction_priority) +static HRESULT STDMETHODCALLTYPE dxgi_resource_GetEvictionPriority(IDXGIResource1 *iface, UINT *eviction_priority) { FIXME("iface %p, eviction_priority %p stub!\n", iface, eviction_priority);
return E_NOTIMPL; }
-static const struct IDXGIResourceVtbl dxgi_resource_vtbl = +/* IDXGIResource1 methods */ +static HRESULT STDMETHODCALLTYPE dxgi_resource_CreateSubresourceSurface(IDXGIResource1 *iface, + UINT index, IDXGISurface2 **surface) +{ + FIXME("iface %p, index %u, surface %p stub!\n", iface, index, surface); + + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE dxgi_resource_CreateSharedHandle(IDXGIResource1 *iface, + const SECURITY_ATTRIBUTES *attributes, DWORD access, const WCHAR *name, HANDLE *handle) +{ + FIXME("iface %p, attributes %p, access %#lx, name %s, handle %p stub!\n", iface, attributes, + access, wine_dbgstr_w(name), handle); + + return E_NOTIMPL; +} + +static const struct IDXGIResource1Vtbl dxgi_resource_vtbl = { /* IUnknown methods */ dxgi_resource_QueryInterface, @@ -413,6 +432,9 @@ static const struct IDXGIResourceVtbl dxgi_resource_vtbl = dxgi_resource_GetUsage, dxgi_resource_SetEvictionPriority, dxgi_resource_GetEvictionPriority, + /* IDXGIResource1 methods */ + dxgi_resource_CreateSubresourceSurface, + dxgi_resource_CreateSharedHandle, };
static const struct IUnknownVtbl dxgi_resource_inner_unknown_vtbl = @@ -436,7 +458,7 @@ HRESULT dxgi_resource_init(struct dxgi_resource *resource, IDXGIDevice *device, } else resource->IDXGISurface1_iface.lpVtbl = NULL; - resource->IDXGIResource_iface.lpVtbl = &dxgi_resource_vtbl; + resource->IDXGIResource1_iface.lpVtbl = &dxgi_resource_vtbl; resource->IUnknown_iface.lpVtbl = &dxgi_resource_inner_unknown_vtbl; resource->refcount = 1; wined3d_private_store_init(&resource->private_store);
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/dxgi/dxgi_private.h | 2 +- dlls/dxgi/resource.c | 83 +++++++++++++++++++++++----------------- dlls/dxgi/tests/dxgi.c | 2 + 3 files changed, 51 insertions(+), 36 deletions(-)
diff --git a/dlls/dxgi/dxgi_private.h b/dlls/dxgi/dxgi_private.h index 8e5c03b087b..bd3bbc7a370 100644 --- a/dlls/dxgi/dxgi_private.h +++ b/dlls/dxgi/dxgi_private.h @@ -197,7 +197,7 @@ BOOL dxgi_validate_swapchain_desc(const DXGI_SWAP_CHAIN_DESC1 *desc); /* IDXGISurface/IDXGIResource */ struct dxgi_resource { - IDXGISurface1 IDXGISurface1_iface; + IDXGISurface2 IDXGISurface2_iface; IDXGIResource1 IDXGIResource1_iface; IUnknown IUnknown_iface; IUnknown *outer_unknown; diff --git a/dlls/dxgi/resource.c b/dlls/dxgi/resource.c index deb98235589..0d5241f858c 100644 --- a/dlls/dxgi/resource.c +++ b/dlls/dxgi/resource.c @@ -34,11 +34,12 @@ static HRESULT STDMETHODCALLTYPE dxgi_resource_inner_QueryInterface(IUnknown *if
TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
- if ((IsEqualGUID(riid, &IID_IDXGISurface1) - || IsEqualGUID(riid, &IID_IDXGISurface)) && resource->IDXGISurface1_iface.lpVtbl != NULL) + if ((IsEqualGUID(riid, &IID_IDXGISurface2) + || IsEqualGUID(riid, &IID_IDXGISurface1) + || IsEqualGUID(riid, &IID_IDXGISurface)) && resource->IDXGISurface2_iface.lpVtbl != NULL) { - IDXGISurface1_AddRef(&resource->IDXGISurface1_iface); - *out = &resource->IDXGISurface1_iface; + IDXGISurface2_AddRef(&resource->IDXGISurface2_iface); + *out = &resource->IDXGISurface2_iface; return S_OK; } else if (IsEqualGUID(riid, &IID_IDXGIResource) @@ -84,73 +85,73 @@ static ULONG STDMETHODCALLTYPE dxgi_resource_inner_Release(IUnknown *iface) return refcount; }
-static inline struct dxgi_resource *impl_from_IDXGISurface1(IDXGISurface1 *iface) +static inline struct dxgi_resource *impl_from_IDXGISurface2(IDXGISurface2 *iface) { - return CONTAINING_RECORD(iface, struct dxgi_resource, IDXGISurface1_iface); + return CONTAINING_RECORD(iface, struct dxgi_resource, IDXGISurface2_iface); }
/* IUnknown methods */
-static HRESULT STDMETHODCALLTYPE dxgi_surface_QueryInterface(IDXGISurface1 *iface, REFIID riid, +static HRESULT STDMETHODCALLTYPE dxgi_surface_QueryInterface(IDXGISurface2 *iface, REFIID riid, void **object) { - struct dxgi_resource *resource = impl_from_IDXGISurface1(iface); + struct dxgi_resource *resource = impl_from_IDXGISurface2(iface); return IDXGIResource1_QueryInterface(&resource->IDXGIResource1_iface, riid, object); }
-static ULONG STDMETHODCALLTYPE dxgi_surface_AddRef(IDXGISurface1 *iface) +static ULONG STDMETHODCALLTYPE dxgi_surface_AddRef(IDXGISurface2 *iface) { - struct dxgi_resource *resource = impl_from_IDXGISurface1(iface); + struct dxgi_resource *resource = impl_from_IDXGISurface2(iface); return IDXGIResource1_AddRef(&resource->IDXGIResource1_iface); }
-static ULONG STDMETHODCALLTYPE dxgi_surface_Release(IDXGISurface1 *iface) +static ULONG STDMETHODCALLTYPE dxgi_surface_Release(IDXGISurface2 *iface) { - struct dxgi_resource *resource = impl_from_IDXGISurface1(iface); + struct dxgi_resource *resource = impl_from_IDXGISurface2(iface); return IDXGIResource1_Release(&resource->IDXGIResource1_iface); }
/* IDXGIObject methods */
-static HRESULT STDMETHODCALLTYPE dxgi_surface_SetPrivateData(IDXGISurface1 *iface, +static HRESULT STDMETHODCALLTYPE dxgi_surface_SetPrivateData(IDXGISurface2 *iface, REFGUID guid, UINT data_size, const void *data) { - struct dxgi_resource *resource = impl_from_IDXGISurface1(iface); + struct dxgi_resource *resource = impl_from_IDXGISurface2(iface); return IDXGIResource1_SetPrivateData(&resource->IDXGIResource1_iface, guid, data_size, data); }
-static HRESULT STDMETHODCALLTYPE dxgi_surface_SetPrivateDataInterface(IDXGISurface1 *iface, +static HRESULT STDMETHODCALLTYPE dxgi_surface_SetPrivateDataInterface(IDXGISurface2 *iface, REFGUID guid, const IUnknown *object) { - struct dxgi_resource *resource = impl_from_IDXGISurface1(iface); + struct dxgi_resource *resource = impl_from_IDXGISurface2(iface); return IDXGIResource1_SetPrivateDataInterface(&resource->IDXGIResource1_iface, guid, object); }
-static HRESULT STDMETHODCALLTYPE dxgi_surface_GetPrivateData(IDXGISurface1 *iface, +static HRESULT STDMETHODCALLTYPE dxgi_surface_GetPrivateData(IDXGISurface2 *iface, REFGUID guid, UINT *data_size, void *data) { - struct dxgi_resource *resource = impl_from_IDXGISurface1(iface); + struct dxgi_resource *resource = impl_from_IDXGISurface2(iface); return IDXGIResource1_GetPrivateData(&resource->IDXGIResource1_iface, guid, data_size, data); }
-static HRESULT STDMETHODCALLTYPE dxgi_surface_GetParent(IDXGISurface1 *iface, REFIID riid, void **parent) +static HRESULT STDMETHODCALLTYPE dxgi_surface_GetParent(IDXGISurface2 *iface, REFIID riid, void **parent) { - struct dxgi_resource *resource = impl_from_IDXGISurface1(iface); + struct dxgi_resource *resource = impl_from_IDXGISurface2(iface); return IDXGIResource1_GetParent(&resource->IDXGIResource1_iface, riid, parent); }
/* IDXGIDeviceSubObject methods */
-static HRESULT STDMETHODCALLTYPE dxgi_surface_GetDevice(IDXGISurface1 *iface, REFIID riid, void **device) +static HRESULT STDMETHODCALLTYPE dxgi_surface_GetDevice(IDXGISurface2 *iface, REFIID riid, void **device) { - struct dxgi_resource *resource = impl_from_IDXGISurface1(iface); + struct dxgi_resource *resource = impl_from_IDXGISurface2(iface); return IDXGIResource1_GetDevice(&resource->IDXGIResource1_iface, riid, device); }
/* IDXGISurface methods */ -static HRESULT STDMETHODCALLTYPE dxgi_surface_GetDesc(IDXGISurface1 *iface, DXGI_SURFACE_DESC *desc) +static HRESULT STDMETHODCALLTYPE dxgi_surface_GetDesc(IDXGISurface2 *iface, DXGI_SURFACE_DESC *desc) { - struct dxgi_resource *resource = impl_from_IDXGISurface1(iface); + struct dxgi_resource *resource = impl_from_IDXGISurface2(iface); struct wined3d_resource_desc wined3d_desc;
TRACE("iface %p, desc %p.\n", iface, desc); @@ -166,9 +167,9 @@ static HRESULT STDMETHODCALLTYPE dxgi_surface_GetDesc(IDXGISurface1 *iface, DXGI return S_OK; }
-static HRESULT STDMETHODCALLTYPE dxgi_surface_Map(IDXGISurface1 *iface, DXGI_MAPPED_RECT *mapped_rect, UINT flags) +static HRESULT STDMETHODCALLTYPE dxgi_surface_Map(IDXGISurface2 *iface, DXGI_MAPPED_RECT *mapped_rect, UINT flags) { - struct dxgi_resource *resource = impl_from_IDXGISurface1(iface); + struct dxgi_resource *resource = impl_from_IDXGISurface2(iface); struct wined3d_map_desc wined3d_map_desc; DWORD wined3d_map_flags = 0; HRESULT hr; @@ -191,9 +192,9 @@ static HRESULT STDMETHODCALLTYPE dxgi_surface_Map(IDXGISurface1 *iface, DXGI_MAP return hr; }
-static HRESULT STDMETHODCALLTYPE dxgi_surface_Unmap(IDXGISurface1 *iface) +static HRESULT STDMETHODCALLTYPE dxgi_surface_Unmap(IDXGISurface2 *iface) { - struct dxgi_resource *resource = impl_from_IDXGISurface1(iface); + struct dxgi_resource *resource = impl_from_IDXGISurface2(iface);
TRACE("iface %p.\n", iface); wined3d_resource_unmap(resource->wined3d_resource, 0); @@ -201,9 +202,9 @@ static HRESULT STDMETHODCALLTYPE dxgi_surface_Unmap(IDXGISurface1 *iface) }
/* IDXGISurface1 methods */ -static HRESULT STDMETHODCALLTYPE dxgi_surface_GetDC(IDXGISurface1 *iface, BOOL discard, HDC *hdc) +static HRESULT STDMETHODCALLTYPE dxgi_surface_GetDC(IDXGISurface2 *iface, BOOL discard, HDC *hdc) { - struct dxgi_resource *resource = impl_from_IDXGISurface1(iface); + struct dxgi_resource *resource = impl_from_IDXGISurface2(iface); HRESULT hr;
FIXME("iface %p, discard %d, hdc %p semi-stub!\n", iface, discard, hdc); @@ -221,9 +222,9 @@ static HRESULT STDMETHODCALLTYPE dxgi_surface_GetDC(IDXGISurface1 *iface, BOOL d return hr; }
-static HRESULT STDMETHODCALLTYPE dxgi_surface_ReleaseDC(IDXGISurface1 *iface, RECT *dirty_rect) +static HRESULT STDMETHODCALLTYPE dxgi_surface_ReleaseDC(IDXGISurface2 *iface, RECT *dirty_rect) { - struct dxgi_resource *resource = impl_from_IDXGISurface1(iface); + struct dxgi_resource *resource = impl_from_IDXGISurface2(iface); HRESULT hr;
TRACE("iface %p, rect %s\n", iface, wine_dbgstr_rect(dirty_rect)); @@ -238,7 +239,17 @@ static HRESULT STDMETHODCALLTYPE dxgi_surface_ReleaseDC(IDXGISurface1 *iface, RE return hr; }
-static const struct IDXGISurface1Vtbl dxgi_surface_vtbl = +/* IDXGISurface2 methods */ +static HRESULT STDMETHODCALLTYPE dxgi_surface_GetResource(IDXGISurface2 *iface, REFIID iid, + void **parent_resource, UINT *subresource_idx) +{ + FIXME("iface %p, iid %s, parent_resource %p, subresource_idx %p stub!\n", iface, + wine_dbgstr_guid(iid), parent_resource, subresource_idx); + + return E_NOTIMPL; +} + +static const struct IDXGISurface2Vtbl dxgi_surface_vtbl = { /* IUnknown methods */ dxgi_surface_QueryInterface, @@ -258,6 +269,8 @@ static const struct IDXGISurface1Vtbl dxgi_surface_vtbl = /* IDXGISurface1 methods */ dxgi_surface_GetDC, dxgi_surface_ReleaseDC, + /* IDXGISurface2 methods */ + dxgi_surface_GetResource, };
static inline struct dxgi_resource *impl_from_IDXGIResource1(IDXGIResource1 *iface) @@ -454,10 +467,10 @@ HRESULT dxgi_resource_init(struct dxgi_resource *resource, IDXGIDevice *device, if ((desc.resource_type == WINED3D_RTYPE_TEXTURE_1D || desc.resource_type == WINED3D_RTYPE_TEXTURE_2D) && needs_surface) { - resource->IDXGISurface1_iface.lpVtbl = &dxgi_surface_vtbl; + resource->IDXGISurface2_iface.lpVtbl = &dxgi_surface_vtbl; } else - resource->IDXGISurface1_iface.lpVtbl = NULL; + resource->IDXGISurface2_iface.lpVtbl = NULL; resource->IDXGIResource1_iface.lpVtbl = &dxgi_resource_vtbl; resource->IUnknown_iface.lpVtbl = &dxgi_resource_inner_unknown_vtbl; resource->refcount = 1; diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c index 1db69469c90..1cb7cff60f4 100644 --- a/dlls/dxgi/tests/dxgi.c +++ b/dlls/dxgi/tests/dxgi.c @@ -1270,6 +1270,8 @@ static void test_create_surface(void) check_interface(surface, &IID_ID3D11Texture2D, TRUE, TRUE); /* Not available on all Windows versions. */ check_interface(surface, &IID_IDXGISurface1, TRUE, TRUE); + /* Not available on all Windows versions. */ + check_interface(surface, &IID_IDXGISurface2, TRUE, TRUE);
IDXGISurface_Release(surface); refcount = IDXGIDevice_Release(device);
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/dxgi/tests/dxgi.c | 269 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 269 insertions(+)
diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c index 1cb7cff60f4..91f54586047 100644 --- a/dlls/dxgi/tests/dxgi.c +++ b/dlls/dxgi/tests/dxgi.c @@ -7997,6 +7997,274 @@ static void run_on_d3d12(void (*test_func)(IUnknown *device, BOOL is_d3d12)) ok(!refcount, "Device has %lu references left.\n", refcount); }
+static void test_subresource_surface(void) +{ + unsigned int expected_width, expected_height, expected_pitch; + unsigned int i, j, subresource_index, subresource_count; + IDXGIResource1 *resource, *parent_resource; + DXGI_SURFACE_DESC surface_desc; + DXGI_MAPPED_RECT mapped_rect; + ID3D10Device *d3d10_device; + IDXGIDevice *dxgi_device; + IDXGISurface2 *surface; + ULONG refcount; + HRESULT hr; + + static const struct + { + unsigned int resource_type; /* 0 -> ID3D10Buffer, 1~3 -> ID3D10Texture1/2/3D */ + unsigned int width; + unsigned int height; + unsigned int expected_pitch; + unsigned int mip_levels; + unsigned int array_size; + HRESULT hr; + } + tests[] = + { + {0, 512, 1, 512, 1, 1, S_OK}, + {1, 512, 1, 2048, 1, 1, S_OK}, + {1, 512, 1, 2048, 4, 4, S_OK}, + {2, 512, 512, 2048, 1, 1, S_OK}, + {2, 512, 512, 2048, 4, 4, S_OK}, + {3, 512, 512, 2048, 1, 1, S_OK}, + {3, 512, 512, 2048, 2, 1, S_OK}, + {3, 512, 512, 2048, 1, 2, E_INVALIDARG}, + }; + + if (!(dxgi_device = create_device(0))) + { + skip("Failed to create device.\n"); + return; + } + + hr = IDXGIDevice_QueryInterface(dxgi_device, &IID_ID3D10Device, (void **)&d3d10_device); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + for (i = 0; i < ARRAY_SIZE(tests); i++) + { + winetest_push_context("%d", i); + + /* ID3D10Buffer */ + if (tests[i].resource_type == 0) + { + D3D10_BUFFER_DESC buffer_desc; + ID3D10Buffer *buffer; + + buffer_desc.ByteWidth = tests[i].width; + buffer_desc.Usage = D3D10_USAGE_STAGING; + buffer_desc.BindFlags = 0; + buffer_desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ; + buffer_desc.MiscFlags = 0; + hr = ID3D10Device_CreateBuffer(d3d10_device, &buffer_desc, NULL, &buffer); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + hr = ID3D10Buffer_QueryInterface(buffer, &IID_IDXGIResource1, (void **)&resource); + ID3D10Buffer_Release(buffer); + } + /* ID3D10Texture1D */ + else if (tests[i].resource_type == 1) + { + D3D10_TEXTURE1D_DESC texture_desc; + ID3D10Texture1D *texture; + + texture_desc.Width = tests[i].width; + texture_desc.MipLevels = tests[i].mip_levels; + texture_desc.ArraySize = tests[i].array_size; + texture_desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + texture_desc.Usage = D3D10_USAGE_STAGING; + texture_desc.BindFlags = 0; + texture_desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ; + texture_desc.MiscFlags = 0; + hr = ID3D10Device_CreateTexture1D(d3d10_device, &texture_desc, NULL, &texture); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + hr = ID3D10Texture1D_QueryInterface(texture, &IID_IDXGIResource1, (void **)&resource); + ID3D10Texture1D_Release(texture); + } + /* ID3D10Texture2D */ + else if (tests[i].resource_type == 2) + { + D3D10_TEXTURE2D_DESC texture_desc; + ID3D10Texture2D *texture; + + texture_desc.Width = tests[i].width; + texture_desc.Height = tests[i].height; + texture_desc.MipLevels = tests[i].mip_levels; + texture_desc.ArraySize = tests[i].array_size; + texture_desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + texture_desc.SampleDesc.Count = 1; + texture_desc.SampleDesc.Quality = 0; + texture_desc.Usage = D3D10_USAGE_STAGING; + texture_desc.BindFlags = 0; + texture_desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ; + texture_desc.MiscFlags = 0; + hr = ID3D10Device_CreateTexture2D(d3d10_device, &texture_desc, NULL, &texture); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + hr = ID3D10Texture2D_QueryInterface(texture, &IID_IDXGIResource1, (void **)&resource); + ID3D10Texture2D_Release(texture); + } + /* ID3D10Texture3D */ + else if (tests[i].resource_type == 3) + { + D3D10_TEXTURE3D_DESC texture_desc; + ID3D10Texture3D *texture; + + texture_desc.Width = tests[i].width; + texture_desc.Height = tests[i].height; + texture_desc.Depth = tests[i].array_size; + texture_desc.MipLevels = tests[i].mip_levels; + texture_desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + texture_desc.Usage = D3D10_USAGE_STAGING; + texture_desc.BindFlags = 0; + texture_desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ; + texture_desc.MiscFlags = 0; + hr = ID3D10Device_CreateTexture3D(d3d10_device, &texture_desc, NULL, &texture); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + hr = ID3D10Texture3D_QueryInterface(texture, &IID_IDXGIResource1, (void **)&resource); + ID3D10Texture3D_Release(texture); + } + else + { + ok(0, "Unexpected resource type %u.\n", tests[i].resource_type); + winetest_pop_context(); + continue; + } + + if (FAILED(hr)) + { + win_skip("Failed to query IDXGIResource1.\n"); + ID3D10Device_Release(d3d10_device); + refcount = IDXGIDevice_Release(dxgi_device); + ok(!refcount, "Device has %lu references left.\n", refcount); + winetest_pop_context(); + return; + } + + subresource_count = tests[i].mip_levels * tests[i].array_size; + + /* IDXGISurface2::GetResource() for non-subresource surfaces */ + hr = IDXGIResource1_QueryInterface(resource, &IID_IDXGISurface2, (void **)&surface); + /* IDXGISurface2 might be unavailable because Windows version is too old or the resource + * have multiple mipmap levels or an array of textures */ + if (hr == S_OK) + { + /* NULL parent resource pointer */ + hr = IDXGISurface2_GetResource(surface, &IID_IDXGIResource1, NULL, &subresource_index); + ok(hr == E_POINTER, "Got unexpected hr %#lx.\n", hr); + + /* Invalid IID */ + parent_resource = (void *)0xdeadbeef; + subresource_index = 1234; + hr = IDXGISurface2_GetResource(surface, &IID_IDXGIFactory, (void **)&parent_resource, + &subresource_index); + ok(hr == E_NOINTERFACE, "Got unexpected hr %#lx.\n", hr); + ok(parent_resource == NULL, "Got unexpected parent_resource %p.\n", parent_resource); + ok(subresource_index == 1234, "Got unexpected subresource_index %u.\n", subresource_index); + + /* Normal */ + hr = IDXGISurface2_GetResource(surface, &IID_IDXGIResource1, (void **)&parent_resource, + &subresource_index); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ok(parent_resource == resource, "Got unexpected parent resource.\n"); + ok(subresource_index == 0, "Got unexpected subresource index %u.\n", subresource_index); + + IDXGIResource1_Release(parent_resource); + IDXGISurface2_Release(surface); + } + + /* Tests for subresource surfaces */ + for (j = 0; j < subresource_count; j++) + { + winetest_push_context("%d", j); + + refcount = get_refcount(resource); + ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount); + hr = IDXGIResource1_CreateSubresourceSurface(resource, j, &surface); + todo_wine + ok(hr == tests[i].hr, "Got unexpected hr %#lx.\n", hr); + if (FAILED(hr)) + { + winetest_pop_context(); + continue; + } + refcount = get_refcount(resource); + ok(refcount == 2, "Got unexpected refcount %lu.\n", refcount); + + check_interface(surface, &IID_IDXGISurface, TRUE, FALSE); + check_interface(surface, &IID_IDXGISurface1, TRUE, FALSE); + check_interface(surface, &IID_IDXGIDeviceSubObject, TRUE, FALSE); + check_interface(surface, &IID_IDXGIObject, TRUE, FALSE); + check_interface(surface, &IID_IUnknown, TRUE, FALSE); + /* No outer interfaces */ + check_interface(surface, &IID_ID3D10Buffer, FALSE, FALSE); + check_interface(surface, &IID_ID3D10Texture1D, FALSE, FALSE); + check_interface(surface, &IID_ID3D10Texture2D, FALSE, FALSE); + check_interface(surface, &IID_ID3D10Texture3D, FALSE, FALSE); + check_interface(surface, &IID_ID3D11Buffer, FALSE, FALSE); + check_interface(surface, &IID_ID3D11Texture1D, FALSE, FALSE); + check_interface(surface, &IID_ID3D11Texture2D, FALSE, FALSE); + check_interface(surface, &IID_ID3D11Texture3D, FALSE, FALSE); + check_interface(surface, &IID_ID3D10Resource, FALSE, FALSE); + check_interface(surface, &IID_ID3D11Resource, FALSE, FALSE); + /* Note that IDXGIResource and IDXGIResource1 are not supported for subresource surfaces */ + check_interface(surface, &IID_IDXGIResource, FALSE, FALSE); + check_interface(surface, &IID_IDXGIResource1, FALSE, FALSE); + + /* IDXGISurface::GetDesc() */ + hr = IDXGISurface2_GetDesc(surface, &surface_desc); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + expected_width = tests[i].width >> (j % tests[i].mip_levels); + if (tests[i].resource_type <= 1) + expected_height = 1; + else + expected_height = tests[i].height >> (j % tests[i].mip_levels); + expected_pitch = tests[i].expected_pitch >> (j % tests[i].mip_levels); + + ok(surface_desc.Width == expected_width, "Expected width %u, got %u.\n", expected_width, + surface_desc.Width); + ok(surface_desc.Height == expected_height, "Expected height %u, got height %u.\n", + expected_height, surface_desc.Height); + ok(surface_desc.Format == (tests[i].resource_type ? DXGI_FORMAT_B8G8R8A8_UNORM : DXGI_FORMAT_UNKNOWN), + "Got unexpected format %#x.\n", surface_desc.Format); + ok(surface_desc.SampleDesc.Count == 1, "Got unexpected sample count %u.\n", + surface_desc.SampleDesc.Count); + ok(surface_desc.SampleDesc.Quality == 0, "Got unexpected sample quality %u.\n", + surface_desc.SampleDesc.Quality); + + /* IDXGISurface::Map() */ + hr = IDXGISurface2_Map(surface, &mapped_rect, DXGI_MAP_READ); + ok(mapped_rect.Pitch == expected_pitch, "Expected pitch %u, got %u.\n", + expected_pitch, mapped_rect.Pitch); + hr = IDXGISurface2_Unmap(surface); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + /* IDXGISurface2::GetResource() */ + hr = IDXGISurface2_GetResource(surface, &IID_IDXGIResource1, (void **)&parent_resource, + &subresource_index); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ok(parent_resource == resource, "Got unexpected parent resource.\n"); + ok(subresource_index == j, "Got unexpected subresource index %u.\n", subresource_index); + IDXGIResource1_Release(parent_resource); + + IDXGISurface2_Release(surface); + winetest_pop_context(); + } + + /* Out of range subresource index */ + surface = (IDXGISurface2 *)0xdeadbeef; + hr = IDXGIResource1_CreateSubresourceSurface(resource, j, &surface); + todo_wine + ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr); + ok(surface == (IDXGISurface2 *)0xdeadbeef, "Got unexpected surface %p.\n", surface); + IDXGIResource1_Release(resource); + winetest_pop_context(); + } + + ID3D10Device_Release(d3d10_device); + refcount = IDXGIDevice_Release(dxgi_device); + ok(!refcount, "Device has %lu references left.\n", refcount); +} + START_TEST(dxgi) { HMODULE dxgi_module, d3d11_module, d3d12_module, gdi32_module; @@ -8045,6 +8313,7 @@ START_TEST(dxgi) queue_test(test_query_video_memory_info); queue_test(test_check_interface_support); queue_test(test_create_surface); + queue_test(test_subresource_surface); queue_test(test_parents); queue_test(test_output); queue_test(test_find_closest_matching_mode);
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/dxgi/device.c | 3 +- dlls/dxgi/dxgi_private.h | 7 ++- dlls/dxgi/resource.c | 100 +++++++++++++++++++++++++++------ dlls/dxgi/tests/dxgi.c | 2 - dlls/wined3d/buffer.c | 6 ++ dlls/wined3d/resource.c | 15 +++++ dlls/wined3d/texture.c | 8 +++ dlls/wined3d/wined3d.spec | 2 + dlls/wined3d/wined3d_private.h | 7 +-- include/wine/wined3d.h | 3 + 10 files changed, 127 insertions(+), 26 deletions(-)
diff --git a/dlls/dxgi/device.c b/dlls/dxgi/device.c index 4325785e9c2..46d252f2b67 100644 --- a/dlls/dxgi/device.c +++ b/dlls/dxgi/device.c @@ -347,7 +347,8 @@ static HRESULT STDMETHODCALLTYPE dxgi_device_create_resource(IWineDXGIDevice *if return E_OUTOFMEMORY; }
- if (FAILED(hr = dxgi_resource_init(object, (IDXGIDevice *)iface, outer, needs_surface, wined3d_resource))) + if (FAILED(hr = dxgi_resource_init(object, (IDXGIDevice *)iface, outer, needs_surface, + wined3d_resource, NULL, 0))) { WARN("Failed to initialize resource, hr %#lx.\n", hr); free(object); diff --git a/dlls/dxgi/dxgi_private.h b/dlls/dxgi/dxgi_private.h index bd3bbc7a370..cdc0dfbe00d 100644 --- a/dlls/dxgi/dxgi_private.h +++ b/dlls/dxgi/dxgi_private.h @@ -206,9 +206,14 @@ struct dxgi_resource IDXGIDevice *device; struct wined3d_resource *wined3d_resource; HDC dc; + IDXGIResource1 *parent_resource; + unsigned int subresource_idx; + BOOL is_subresource:1; + BOOL is_buffer:1; };
HRESULT dxgi_resource_init(struct dxgi_resource *resource, IDXGIDevice *device, - IUnknown *outer, BOOL needs_surface, struct wined3d_resource *wined3d_resource); + IUnknown *outer, BOOL needs_surface, struct wined3d_resource *wined3d_resource, + IDXGIResource1 *parent_resource, unsigned int subresource_index);
#endif /* __WINE_DXGI_PRIVATE_H */ diff --git a/dlls/dxgi/resource.c b/dlls/dxgi/resource.c index 0d5241f858c..c18ccca3e25 100644 --- a/dlls/dxgi/resource.c +++ b/dlls/dxgi/resource.c @@ -42,8 +42,8 @@ static HRESULT STDMETHODCALLTYPE dxgi_resource_inner_QueryInterface(IUnknown *if *out = &resource->IDXGISurface2_iface; return S_OK; } - else if (IsEqualGUID(riid, &IID_IDXGIResource) - || IsEqualGUID(riid, &IID_IDXGIResource1) + else if ((!resource->is_subresource && (IsEqualGUID(riid, &IID_IDXGIResource) + || IsEqualGUID(riid, &IID_IDXGIResource1))) || IsEqualGUID(riid, &IID_IDXGIDeviceSubObject) || IsEqualGUID(riid, &IID_IDXGIObject) || IsEqualGUID(riid, &IID_IUnknown)) @@ -78,6 +78,8 @@ static ULONG STDMETHODCALLTYPE dxgi_resource_inner_Release(IUnknown *iface)
if (!refcount) { + if (resource->is_subresource) + IDXGIResource1_Release(resource->parent_resource); wined3d_private_store_cleanup(&resource->private_store); free(resource); } @@ -152,16 +154,19 @@ static HRESULT STDMETHODCALLTYPE dxgi_surface_GetDevice(IDXGISurface2 *iface, RE static HRESULT STDMETHODCALLTYPE dxgi_surface_GetDesc(IDXGISurface2 *iface, DXGI_SURFACE_DESC *desc) { struct dxgi_resource *resource = impl_from_IDXGISurface2(iface); - struct wined3d_resource_desc wined3d_desc; + struct wined3d_sub_resource_desc wined3d_desc;
TRACE("iface %p, desc %p.\n", iface, desc);
wined3d_mutex_lock(); - wined3d_resource_get_desc(resource->wined3d_resource, &wined3d_desc); + wined3d_resource_get_sub_resource_desc(resource->wined3d_resource, resource->subresource_idx, &wined3d_desc); wined3d_mutex_unlock(); desc->Width = wined3d_desc.width; desc->Height = wined3d_desc.height; - desc->Format = dxgi_format_from_wined3dformat(wined3d_desc.format); + if (resource->is_subresource && resource->is_buffer) + desc->Format = DXGI_FORMAT_UNKNOWN; + else + desc->Format = dxgi_format_from_wined3dformat(wined3d_desc.format); dxgi_sample_desc_from_wined3d(&desc->SampleDesc, wined3d_desc.multisample_type, wined3d_desc.multisample_quality);
return S_OK; @@ -183,7 +188,8 @@ static HRESULT STDMETHODCALLTYPE dxgi_surface_Map(IDXGISurface2 *iface, DXGI_MAP if (flags & DXGI_MAP_DISCARD) wined3d_map_flags |= WINED3D_MAP_DISCARD;
- if (SUCCEEDED(hr = wined3d_resource_map(resource->wined3d_resource, 0, &wined3d_map_desc, NULL, wined3d_map_flags))) + if (SUCCEEDED(hr = wined3d_resource_map(resource->wined3d_resource, resource->subresource_idx, + &wined3d_map_desc, NULL, wined3d_map_flags))) { mapped_rect->Pitch = wined3d_map_desc.row_pitch; mapped_rect->pBits = wined3d_map_desc.data; @@ -197,7 +203,7 @@ static HRESULT STDMETHODCALLTYPE dxgi_surface_Unmap(IDXGISurface2 *iface) struct dxgi_resource *resource = impl_from_IDXGISurface2(iface);
TRACE("iface %p.\n", iface); - wined3d_resource_unmap(resource->wined3d_resource, 0); + wined3d_resource_unmap(resource->wined3d_resource, resource->subresource_idx); return S_OK; }
@@ -213,7 +219,8 @@ static HRESULT STDMETHODCALLTYPE dxgi_surface_GetDC(IDXGISurface2 *iface, BOOL d return E_INVALIDARG;
wined3d_mutex_lock(); - hr = wined3d_texture_get_dc(wined3d_texture_from_resource(resource->wined3d_resource), 0, hdc); + hr = wined3d_texture_get_dc(wined3d_texture_from_resource(resource->wined3d_resource), + resource->subresource_idx, hdc); wined3d_mutex_unlock();
if (SUCCEEDED(hr)) @@ -233,7 +240,8 @@ static HRESULT STDMETHODCALLTYPE dxgi_surface_ReleaseDC(IDXGISurface2 *iface, RE FIXME("dirty rectangle is ignored.\n");
wined3d_mutex_lock(); - hr = wined3d_texture_release_dc(wined3d_texture_from_resource(resource->wined3d_resource), 0, resource->dc); + hr = wined3d_texture_release_dc(wined3d_texture_from_resource(resource->wined3d_resource), + resource->subresource_idx, resource->dc); wined3d_mutex_unlock();
return hr; @@ -243,10 +251,25 @@ static HRESULT STDMETHODCALLTYPE dxgi_surface_ReleaseDC(IDXGISurface2 *iface, RE static HRESULT STDMETHODCALLTYPE dxgi_surface_GetResource(IDXGISurface2 *iface, REFIID iid, void **parent_resource, UINT *subresource_idx) { - FIXME("iface %p, iid %s, parent_resource %p, subresource_idx %p stub!\n", iface, + struct dxgi_resource *resource = impl_from_IDXGISurface2(iface); + HRESULT hr; + + TRACE("iface %p, iid %s, parent_resource %p, subresource_idx %p stub!\n", iface, wine_dbgstr_guid(iid), parent_resource, subresource_idx);
- return E_NOTIMPL; + if (!parent_resource) + return E_POINTER; + + if (resource->is_subresource) + hr = IDXGIResource1_QueryInterface(resource->parent_resource, iid, parent_resource); + else + hr = IDXGIResource1_QueryInterface(&resource->IDXGIResource1_iface, iid, parent_resource); + + if (SUCCEEDED(hr)) + *subresource_idx = resource->subresource_idx; + else + parent_resource = NULL; + return hr; }
static const struct IDXGISurface2Vtbl dxgi_surface_vtbl = @@ -413,9 +436,38 @@ static HRESULT STDMETHODCALLTYPE dxgi_resource_GetEvictionPriority(IDXGIResource static HRESULT STDMETHODCALLTYPE dxgi_resource_CreateSubresourceSurface(IDXGIResource1 *iface, UINT index, IDXGISurface2 **surface) { - FIXME("iface %p, index %u, surface %p stub!\n", iface, index, surface); + struct dxgi_resource *resource = impl_from_IDXGIResource1(iface), *subresource; + struct wined3d_resource_desc desc; + unsigned int subresource_count; + HRESULT hr;
- return E_NOTIMPL; + TRACE("iface %p, index %u, surface %p.\n", iface, index, surface); + + wined3d_mutex_lock(); + wined3d_resource_get_desc(resource->wined3d_resource, &desc); + subresource_count = wined3d_resource_get_sub_resource_count(resource->wined3d_resource); + wined3d_mutex_unlock(); + + if ((desc.resource_type == WINED3D_RTYPE_TEXTURE_3D && desc.depth > 1) + || index >= subresource_count) + return E_INVALIDARG; + + if (!(subresource = calloc(1, sizeof(*subresource)))) + { + ERR("Failed to allocate DXGI subresource surface object memory.\n"); + return E_OUTOFMEMORY; + } + + if (FAILED(hr = dxgi_resource_init(subresource, resource->device, NULL, TRUE, + resource->wined3d_resource, iface, index))) + { + WARN("Failed to initialise resource, hr %#lx.\n", hr); + free(subresource); + return hr; + } + + *surface = &subresource->IDXGISurface2_iface; + return S_OK; }
static HRESULT STDMETHODCALLTYPE dxgi_resource_CreateSharedHandle(IDXGIResource1 *iface, @@ -459,13 +511,16 @@ static const struct IUnknownVtbl dxgi_resource_inner_unknown_vtbl = };
HRESULT dxgi_resource_init(struct dxgi_resource *resource, IDXGIDevice *device, - IUnknown *outer, BOOL needs_surface, struct wined3d_resource *wined3d_resource) + IUnknown *outer, BOOL needs_surface, struct wined3d_resource *wined3d_resource, + IDXGIResource1 *parent_resource, unsigned int subresource_index) { struct wined3d_resource_desc desc; + BOOL is_subresource;
+ is_subresource = !!parent_resource; wined3d_resource_get_desc(wined3d_resource, &desc); - if ((desc.resource_type == WINED3D_RTYPE_TEXTURE_1D || desc.resource_type == WINED3D_RTYPE_TEXTURE_2D) - && needs_surface) + if (((desc.resource_type == WINED3D_RTYPE_TEXTURE_1D || desc.resource_type == WINED3D_RTYPE_TEXTURE_2D) + && needs_surface) || is_subresource) { resource->IDXGISurface2_iface.lpVtbl = &dxgi_surface_vtbl; } @@ -479,6 +534,19 @@ HRESULT dxgi_resource_init(struct dxgi_resource *resource, IDXGIDevice *device, resource->device = device; resource->wined3d_resource = wined3d_resource; resource->dc = NULL; + resource->is_buffer = desc.resource_type == WINED3D_RTYPE_BUFFER; + resource->is_subresource = is_subresource; + if (is_subresource) + { + resource->parent_resource = parent_resource; + IDXGIResource1_AddRef(parent_resource); + resource->subresource_idx = subresource_index; + } + else + { + resource->parent_resource = NULL; + resource->subresource_idx = 0; + }
return S_OK; } diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c index 91f54586047..cb8bec5c666 100644 --- a/dlls/dxgi/tests/dxgi.c +++ b/dlls/dxgi/tests/dxgi.c @@ -8179,7 +8179,6 @@ static void test_subresource_surface(void) refcount = get_refcount(resource); ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount); hr = IDXGIResource1_CreateSubresourceSurface(resource, j, &surface); - todo_wine ok(hr == tests[i].hr, "Got unexpected hr %#lx.\n", hr); if (FAILED(hr)) { @@ -8253,7 +8252,6 @@ static void test_subresource_surface(void) /* Out of range subresource index */ surface = (IDXGISurface2 *)0xdeadbeef; hr = IDXGIResource1_CreateSubresourceSurface(resource, j, &surface); - todo_wine ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr); ok(surface == (IDXGISurface2 *)0xdeadbeef, "Got unexpected surface %p.\n", surface); IDXGIResource1_Release(resource); diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c index a656f9edb2b..5e1f0dedee0 100644 --- a/dlls/wined3d/buffer.c +++ b/dlls/wined3d/buffer.c @@ -524,6 +524,11 @@ struct wined3d_resource * CDECL wined3d_buffer_get_resource(struct wined3d_buffe return &buffer->resource; }
+unsigned int buffer_resource_get_sub_resource_count(struct wined3d_resource *resource) +{ + return 1; +} + static HRESULT buffer_resource_sub_resource_get_desc(struct wined3d_resource *resource, unsigned int sub_resource_idx, struct wined3d_sub_resource_desc *desc) { @@ -922,6 +927,7 @@ static const struct wined3d_resource_ops buffer_resource_ops = buffer_resource_decref, buffer_resource_preload, buffer_resource_unload, + buffer_resource_get_sub_resource_count, buffer_resource_sub_resource_get_desc, buffer_resource_sub_resource_get_map_pitch, buffer_resource_sub_resource_map, diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c index 2b02424633a..edc8b9ca79d 100644 --- a/dlls/wined3d/resource.c +++ b/dlls/wined3d/resource.c @@ -266,6 +266,21 @@ unsigned int CDECL wined3d_resource_get_priority(const struct wined3d_resource * return resource->priority; }
+unsigned int CDECL wined3d_resource_get_sub_resource_count(struct wined3d_resource *resource) +{ + TRACE("resource %p.\n", resource); + + return resource->resource_ops->resource_get_sub_resource_count(resource); +} + +HRESULT CDECL wined3d_resource_get_sub_resource_desc(struct wined3d_resource *resource, + unsigned int sub_resource_idx, struct wined3d_sub_resource_desc *desc) +{ + TRACE("resource %p, sub_resource_idx %u, desc %p.\n", resource, sub_resource_idx, desc); + + return resource->resource_ops->resource_sub_resource_get_desc(resource, sub_resource_idx, desc); +} + void * CDECL wined3d_resource_get_parent(const struct wined3d_resource *resource) { return resource->parent; diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 178b37fadc8..e0271151735 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -3422,6 +3422,13 @@ static void texture_resource_unload(struct wined3d_resource *resource) resource_unload(&texture->resource); }
+static unsigned int texture_resource_get_sub_resource_count(struct wined3d_resource *resource) +{ + const struct wined3d_texture *texture = texture_from_resource(resource); + + return texture->level_count * texture->layer_count; +} + static HRESULT texture_resource_sub_resource_get_desc(struct wined3d_resource *resource, unsigned int sub_resource_idx, struct wined3d_sub_resource_desc *desc) { @@ -3611,6 +3618,7 @@ static const struct wined3d_resource_ops texture_resource_ops = texture_resource_decref, texture_resource_preload, texture_resource_unload, + texture_resource_get_sub_resource_count, texture_resource_sub_resource_get_desc, texture_resource_sub_resource_get_map_pitch, texture_resource_sub_resource_map, diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec index dba67917004..94e418ca885 100644 --- a/dlls/wined3d/wined3d.spec +++ b/dlls/wined3d/wined3d.spec @@ -209,6 +209,8 @@ @ cdecl wined3d_resource_get_desc(ptr ptr) @ cdecl wined3d_resource_get_parent(ptr) @ cdecl wined3d_resource_get_priority(ptr) +@ cdecl wined3d_resource_get_sub_resource_count(ptr) +@ cdecl wined3d_resource_get_sub_resource_desc(ptr long ptr) @ cdecl wined3d_resource_map(ptr long ptr ptr long) @ cdecl wined3d_resource_preload(ptr) @ cdecl wined3d_resource_set_parent(ptr ptr ptr) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 71e3ac7a24d..262435d17ab 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -3255,6 +3255,7 @@ struct wined3d_resource_ops ULONG (*resource_decref)(struct wined3d_resource *resource); void (*resource_preload)(struct wined3d_resource *resource); void (*resource_unload)(struct wined3d_resource *resource); + unsigned int (*resource_get_sub_resource_count)(struct wined3d_resource *resource); HRESULT (*resource_sub_resource_get_desc)(struct wined3d_resource *resource, unsigned int sub_resource_idx, struct wined3d_sub_resource_desc *desc); void (*resource_sub_resource_get_map_pitch)(struct wined3d_resource *resource, @@ -3315,12 +3316,6 @@ static inline ULONG wined3d_resource_decref(struct wined3d_resource *resource) return resource->resource_ops->resource_decref(resource); }
-static inline HRESULT wined3d_resource_get_sub_resource_desc(struct wined3d_resource *resource, - unsigned int sub_resource_idx, struct wined3d_sub_resource_desc *desc) -{ - return resource->resource_ops->resource_sub_resource_get_desc(resource, sub_resource_idx, desc); -} - static inline void wined3d_resource_get_sub_resource_map_pitch(struct wined3d_resource *resource, unsigned int sub_resource_idx, unsigned int *row_pitch, unsigned int *slice_pitch) { diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index 11aa2499c05..3b5edd9639a 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -2738,6 +2738,9 @@ void __cdecl wined3d_resource_get_desc(const struct wined3d_resource *resource, struct wined3d_resource_desc *desc); void * __cdecl wined3d_resource_get_parent(const struct wined3d_resource *resource); unsigned int __cdecl wined3d_resource_get_priority(const struct wined3d_resource *resource); +unsigned int __cdecl wined3d_resource_get_sub_resource_count(struct wined3d_resource *resource); +HRESULT __cdecl wined3d_resource_get_sub_resource_desc(struct wined3d_resource *resource, + unsigned int sub_resource_idx, struct wined3d_sub_resource_desc *desc); HRESULT __cdecl wined3d_resource_map(struct wined3d_resource *resource, unsigned int sub_resource_idx, struct wined3d_map_desc *map_desc, const struct wined3d_box *box, uint32_t flags); void __cdecl wined3d_resource_preload(struct wined3d_resource *resource);
``` + BOOL is_subresource:1; + BOOL is_buffer:1; ```
BOOL is a signed type; you don't want to use it in bitfields. Since there's only two members I'd use "bool" instead. Moreover, though, both of these members seem redundant? is_subresource is equivalent to !!parent_resource, and is_buffer can be retrieved from wined3d_resource_get_desc().
The idea of keeping this struct as "dxgi_resource" while using it for non-resources seems dubious to me. I don't know that it's worth using a separate structure either, but if we don't, we should probably rename to dxgi_surface.
``` + wined3d_resource_get_desc(resource->wined3d_resource, &desc); + subresource_count = wined3d_resource_get_sub_resource_count(resource->wined3d_resource); ```
I guess this is fine but I may send a patch later to just move layer_count and level_count to wined3d_resource_desc...