From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/dxgi/device.c | 3 +- dlls/dxgi/dxgi_private.h | 5 +- dlls/dxgi/resource.c | 109 +++++++++++++++++++++++++++------ 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, 131 insertions(+), 29 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..483aac4d566 100644 --- a/dlls/dxgi/dxgi_private.h +++ b/dlls/dxgi/dxgi_private.h @@ -204,11 +204,14 @@ struct dxgi_resource LONG refcount; struct wined3d_private_store private_store; IDXGIDevice *device; + IDXGIResource1 *parent_resource; struct wined3d_resource *wined3d_resource; + unsigned int subresource_idx; HDC dc; };
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..67921de005b 100644 --- a/dlls/dxgi/resource.c +++ b/dlls/dxgi/resource.c @@ -31,6 +31,7 @@ static inline struct dxgi_resource *impl_from_IUnknown(IUnknown *iface) static HRESULT STDMETHODCALLTYPE dxgi_resource_inner_QueryInterface(IUnknown *iface, REFIID riid, void **out) { struct dxgi_resource *resource = impl_from_IUnknown(iface); + bool is_subresource = !!resource->parent_resource;
TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
@@ -42,8 +43,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 ((!is_subresource && (IsEqualGUID(riid, &IID_IDXGIResource) + || IsEqualGUID(riid, &IID_IDXGIResource1))) || IsEqualGUID(riid, &IID_IDXGIDeviceSubObject) || IsEqualGUID(riid, &IID_IDXGIObject) || IsEqualGUID(riid, &IID_IUnknown)) @@ -78,6 +79,8 @@ static ULONG STDMETHODCALLTYPE dxgi_resource_inner_Release(IUnknown *iface)
if (!refcount) { + if (resource->parent_resource) + IDXGIResource1_Release(resource->parent_resource); wined3d_private_store_cleanup(&resource->private_store); free(resource); } @@ -152,17 +155,24 @@ 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; + bool is_subresource = !!resource->parent_resource, is_buffer = false; + struct wined3d_sub_resource_desc subresource_desc; + struct wined3d_resource_desc resource_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, &subresource_desc); + if (is_subresource) + { + wined3d_resource_get_desc(resource->wined3d_resource, &resource_desc); + is_buffer = resource_desc.resource_type == WINED3D_RTYPE_BUFFER; + } wined3d_mutex_unlock(); - desc->Width = wined3d_desc.width; - desc->Height = wined3d_desc.height; - desc->Format = dxgi_format_from_wined3dformat(wined3d_desc.format); - dxgi_sample_desc_from_wined3d(&desc->SampleDesc, wined3d_desc.multisample_type, wined3d_desc.multisample_quality); + desc->Width = subresource_desc.width; + desc->Height = subresource_desc.height; + desc->Format = is_buffer ? DXGI_FORMAT_UNKNOWN : dxgi_format_from_wined3dformat(subresource_desc.format); + dxgi_sample_desc_from_wined3d(&desc->SampleDesc, subresource_desc.multisample_type, subresource_desc.multisample_quality);
return S_OK; } @@ -183,7 +193,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 +208,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 +224,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 +245,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 +256,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->parent_resource) + 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 +441,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 +516,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 +539,17 @@ HRESULT dxgi_resource_init(struct dxgi_resource *resource, IDXGIDevice *device, resource->device = device; resource->wined3d_resource = wined3d_resource; resource->dc = NULL; + 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);