From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/d3d11/d3d11_private.h | 4 ++ dlls/d3d11/device.c | 2 +- dlls/d3d11/view.c | 48 ++++++++++++++++++ dlls/wined3d/adapter_gl.c | 17 +++++++ dlls/wined3d/adapter_vk.c | 28 ++++++++++ dlls/wined3d/directx.c | 17 +++++++ dlls/wined3d/texture.c | 2 + dlls/wined3d/utils.c | 1 + dlls/wined3d/view.c | 93 ++++++++++++++++++++++++++++++++++ dlls/wined3d/wined3d.spec | 4 ++ dlls/wined3d/wined3d_private.h | 17 +++++++ dlls/wined3d/wined3d_vk.h | 15 ++++++ include/wine/wined3d.h | 8 +++ 13 files changed, 255 insertions(+), 1 deletion(-)
diff --git a/dlls/d3d11/d3d11_private.h b/dlls/d3d11/d3d11_private.h index 0dd4c12cb91..7edad44fdf5 100644 --- a/dlls/d3d11/d3d11_private.h +++ b/dlls/d3d11/d3d11_private.h @@ -40,6 +40,8 @@
struct d3d_device;
+extern const struct wined3d_parent_ops d3d_null_wined3d_parent_ops; + /* TRACE helper functions */ const char *debug_d3d10_primitive_topology(D3D10_PRIMITIVE_TOPOLOGY topology); const char *debug_dxgi_format(DXGI_FORMAT format); @@ -91,6 +93,7 @@ static inline unsigned int wined3d_bind_flags_from_d3d11(UINT bind_flags, UINT m | D3D11_BIND_STREAM_OUTPUT | D3D11_BIND_RENDER_TARGET | D3D11_BIND_DEPTH_STENCIL + | D3D11_BIND_DECODER | D3D11_BIND_UNORDERED_ACCESS);
if (misc_flags & D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS) @@ -273,6 +276,7 @@ struct d3d_video_decoder_output_view LONG refcount;
struct wined3d_private_store private_store; + struct wined3d_decoder_output_view *wined3d_view; D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC desc; ID3D11Resource *resource; struct d3d_device *device; diff --git a/dlls/d3d11/device.c b/dlls/d3d11/device.c index 54b040aef21..91049c104ea 100644 --- a/dlls/d3d11/device.c +++ b/dlls/d3d11/device.c @@ -51,7 +51,7 @@ static BOOL d3d_array_reserve(void **elements, SIZE_T *capacity, SIZE_T count, S
static void STDMETHODCALLTYPE d3d_null_wined3d_object_destroyed(void *parent) {}
-static const struct wined3d_parent_ops d3d_null_wined3d_parent_ops = +const struct wined3d_parent_ops d3d_null_wined3d_parent_ops = { d3d_null_wined3d_object_destroyed, }; diff --git a/dlls/d3d11/view.c b/dlls/d3d11/view.c index 449a365362a..bb0b72b37a1 100644 --- a/dlls/d3d11/view.c +++ b/dlls/d3d11/view.c @@ -2625,6 +2625,7 @@ static ULONG STDMETHODCALLTYPE d3d11_video_decoder_output_view_Release(ID3D11Vid
if (!refcount) { + wined3d_decoder_output_view_decref(view->wined3d_view); ID3D11Device2_Release(&view->device->ID3D11Device2_iface); wined3d_private_store_cleanup(&view->private_store); free(view); @@ -2710,13 +2711,60 @@ static const struct ID3D11VideoDecoderOutputViewVtbl d3d11_video_decoder_output_ d3d11_video_decoder_output_view_GetDesc, };
+static void wined3d_vdov_desc_from_d3d11(struct wined3d_view_desc *wined3d_desc, + const D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC *desc, DXGI_FORMAT format) +{ + wined3d_desc->format_id = wined3dformat_from_dxgi_format(format); + + wined3d_desc->flags = 0; + wined3d_desc->u.texture.level_idx = 0; + wined3d_desc->u.texture.level_count = 1; + wined3d_desc->u.texture.layer_idx = desc->u.Texture2D.ArraySlice; + wined3d_desc->u.texture.layer_count = 1; +} + static HRESULT d3d_video_decoder_output_view_init(struct d3d_video_decoder_output_view *view, struct d3d_device *device, ID3D11Resource *resource, const D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC *desc) { + struct wined3d_view_desc wined3d_desc; + D3D11_RESOURCE_DIMENSION dimension; + struct d3d_texture2d *texture; + HRESULT hr; + view->ID3D11VideoDecoderOutputView_iface.lpVtbl = &d3d11_video_decoder_output_view_vtbl; view->refcount = 1; + view->desc = *desc; + + if (desc->ViewDimension != D3D11_VDOV_DIMENSION_TEXTURE2D) + { + WARN("Invalid view dimension %#x.\n", desc->ViewDimension); + return E_INVALIDARG; + } + + ID3D11Resource_GetType(resource, &dimension); + if (dimension != D3D11_RESOURCE_DIMENSION_TEXTURE2D) + { + WARN("Invalid resource dimension %#x.\n", dimension); + return E_INVALIDARG; + } + + if (!(texture = unsafe_impl_from_ID3D11Texture2D((ID3D11Texture2D *)resource))) + { + ERR("Cannot get implementation from ID3D11Texture2D.\n"); + return E_FAIL; + } + + wined3d_vdov_desc_from_d3d11(&wined3d_desc, &view->desc, texture->desc.Format);
wined3d_mutex_lock(); + if (FAILED(hr = wined3d_decoder_output_view_create(&wined3d_desc, + texture->wined3d_texture, NULL, &d3d_null_wined3d_parent_ops, &view->wined3d_view))) + { + wined3d_mutex_unlock(); + WARN("Failed to create a wined3d video decoder output view, hr %#lx.\n", hr); + return hr; + } + wined3d_private_store_init(&view->private_store); wined3d_mutex_unlock(); view->resource = resource; diff --git a/dlls/wined3d/adapter_gl.c b/dlls/wined3d/adapter_gl.c index 6f2e003b3ed..573f55ece14 100644 --- a/dlls/wined3d/adapter_gl.c +++ b/dlls/wined3d/adapter_gl.c @@ -4728,6 +4728,21 @@ static void adapter_gl_destroy_unordered_access_view(struct wined3d_unordered_ac wined3d_view_gl_destroy(resource->device, &view_gl->gl_view, &view_gl->bo_user, &view_gl->counter_bo, view_gl); }
+static HRESULT adapter_gl_create_video_decoder_output_view(const struct wined3d_view_desc *desc, + struct wined3d_texture *texture, void *parent, const struct wined3d_parent_ops *parent_ops, + struct wined3d_decoder_output_view **view) +{ + TRACE("desc %s, texture %p, parent %p, parent_ops %p, view %p.\n", + wined3d_debug_view_desc(desc, &texture->resource), texture, parent, parent_ops, view); + + return E_NOTIMPL; +} + +static void adapter_gl_destroy_video_decoder_output_view(struct wined3d_decoder_output_view *view) +{ + TRACE("view %p.\n", view); +} + static HRESULT adapter_gl_create_sampler(struct wined3d_device *device, const struct wined3d_sampler_desc *desc, void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_sampler **sampler) { @@ -4869,6 +4884,8 @@ static const struct wined3d_adapter_ops wined3d_adapter_gl_ops = .adapter_destroy_shader_resource_view = adapter_gl_destroy_shader_resource_view, .adapter_create_unordered_access_view = adapter_gl_create_unordered_access_view, .adapter_destroy_unordered_access_view = adapter_gl_destroy_unordered_access_view, + .adapter_create_video_decoder_output_view = adapter_gl_create_video_decoder_output_view, + .adapter_destroy_video_decoder_output_view = adapter_gl_destroy_video_decoder_output_view, .adapter_create_sampler = adapter_gl_create_sampler, .adapter_destroy_sampler = adapter_gl_destroy_sampler, .adapter_create_query = adapter_gl_create_query, diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index 4a9d49996c7..8219c0728d4 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -1614,6 +1614,32 @@ static void adapter_vk_destroy_unordered_access_view(struct wined3d_unordered_ac &uav_vk->counter_bo, &uav_vk->vk_counter_view, &view_vk->command_buffer_id, uav_vk); }
+static HRESULT adapter_vk_create_video_decoder_output_view(const struct wined3d_view_desc *desc, + struct wined3d_texture *texture, void *parent, const struct wined3d_parent_ops *parent_ops, + struct wined3d_decoder_output_view **view) +{ + struct wined3d_decoder_output_view_vk *view_vk; + HRESULT hr; + + TRACE("desc %s, texture %p, parent %p, parent_ops %p, view %p.\n", + wined3d_debug_view_desc(desc, &texture->resource), texture, parent, parent_ops, view); + + if (!(view_vk = calloc(1, sizeof(*view_vk)))) + return E_OUTOFMEMORY; + + if (FAILED(hr = wined3d_decoder_output_view_vk_init(view_vk, desc, texture, parent, parent_ops))) + { + WARN("Failed to initialise view, hr %#lx.\n", hr); + free(view_vk); + return hr; + } + + TRACE("Created video decoder output view %p.\n", view_vk); + *view = &view_vk->v; + + return hr; +} + static HRESULT adapter_vk_create_sampler(struct wined3d_device *device, const struct wined3d_sampler_desc *desc, void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_sampler **sampler) { @@ -1860,6 +1886,8 @@ static const struct wined3d_adapter_ops wined3d_adapter_vk_ops = .adapter_destroy_shader_resource_view = adapter_vk_destroy_shader_resource_view, .adapter_create_unordered_access_view = adapter_vk_create_unordered_access_view, .adapter_destroy_unordered_access_view = adapter_vk_destroy_unordered_access_view, + .adapter_create_video_decoder_output_view = adapter_vk_create_video_decoder_output_view, + .adapter_destroy_video_decoder_output_view = wined3d_decoder_output_view_cleanup, .adapter_create_sampler = adapter_vk_create_sampler, .adapter_destroy_sampler = adapter_vk_destroy_sampler, .adapter_create_query = adapter_vk_create_query, diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index 22c69b97410..c2e91b38bad 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -3210,6 +3210,21 @@ static void adapter_no3d_destroy_unordered_access_view(struct wined3d_unordered_ TRACE("view %p.\n", view); }
+static HRESULT adapter_no3d_create_video_decoder_output_view(const struct wined3d_view_desc *desc, + struct wined3d_texture *texture, void *parent, const struct wined3d_parent_ops *parent_ops, + struct wined3d_decoder_output_view **view) +{ + TRACE("desc %s, texture %p, parent %p, parent_ops %p, view %p.\n", + wined3d_debug_view_desc(desc, &texture->resource), texture, parent, parent_ops, view); + + return E_NOTIMPL; +} + +static void adapter_no3d_destroy_video_decoder_output_view(struct wined3d_decoder_output_view *view) +{ + TRACE("view %p.\n", view); +} + static HRESULT adapter_no3d_create_sampler(struct wined3d_device *device, const struct wined3d_sampler_desc *desc, void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_sampler **sampler) { @@ -3290,6 +3305,8 @@ static const struct wined3d_adapter_ops wined3d_adapter_no3d_ops = .adapter_destroy_shader_resource_view = adapter_no3d_destroy_shader_resource_view, .adapter_create_unordered_access_view = adapter_no3d_create_unordered_access_view, .adapter_destroy_unordered_access_view = adapter_no3d_destroy_unordered_access_view, + .adapter_create_video_decoder_output_view = adapter_no3d_create_video_decoder_output_view, + .adapter_destroy_video_decoder_output_view = adapter_no3d_destroy_video_decoder_output_view, .adapter_create_sampler = adapter_no3d_create_sampler, .adapter_destroy_sampler = adapter_no3d_destroy_sampler, .adapter_create_query = adapter_no3d_create_query, diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index d12cadd71fc..1dbb02b2428 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -5427,6 +5427,8 @@ BOOL wined3d_texture_vk_prepare_texture(struct wined3d_texture_vk *texture_vk, texture_vk->layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; else if (resource->bind_flags & WINED3D_BIND_SHADER_RESOURCE) texture_vk->layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + else if (resource->bind_flags & WINED3D_BIND_DECODER_OUTPUT) + texture_vk->layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; else { FIXME("unexpected bind flags %s, using VK_IMAGE_LAYOUT_GENERAL\n", wined3d_debug_bind_flags(resource->bind_flags)); diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index c75516aac5a..f176e09fa3c 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -4942,6 +4942,7 @@ const char *wined3d_debug_bind_flags(uint32_t bind_flags) BIND_FLAG_TO_STR(WINED3D_BIND_DEPTH_STENCIL); BIND_FLAG_TO_STR(WINED3D_BIND_UNORDERED_ACCESS); BIND_FLAG_TO_STR(WINED3D_BIND_INDIRECT_BUFFER); + BIND_FLAG_TO_STR(WINED3D_BIND_DECODER_OUTPUT); #undef BIND_FLAG_TO_STR if (bind_flags) FIXME("Unrecognised bind flag(s) %#x.\n", bind_flags); diff --git a/dlls/wined3d/view.c b/dlls/wined3d/view.c index 522f19a8e71..9ba2a177961 100644 --- a/dlls/wined3d/view.c +++ b/dlls/wined3d/view.c @@ -2599,3 +2599,96 @@ HRESULT CDECL wined3d_unordered_access_view_create(const struct wined3d_view_des adapter_ops = resource->device->adapter->adapter_ops; return adapter_ops->adapter_create_unordered_access_view(desc, resource, parent, parent_ops, view); } + +ULONG CDECL wined3d_decoder_output_view_incref(struct wined3d_decoder_output_view *view) +{ + unsigned int refcount; + + if (view->desc.flags & WINED3D_VIEW_FORWARD_REFERENCE) + return wined3d_texture_incref(view->texture); + + refcount = InterlockedIncrement(&view->refcount); + TRACE("%p increasing refcount to %u.\n", view, refcount); + + return refcount; +} + +void wined3d_decoder_output_view_cleanup(struct wined3d_decoder_output_view *view) +{ + view->parent_ops->wined3d_object_destroyed(view->parent); +} + +ULONG CDECL wined3d_decoder_output_view_decref(struct wined3d_decoder_output_view *view) +{ + unsigned int refcount; + + if (view->desc.flags & WINED3D_VIEW_FORWARD_REFERENCE) + return wined3d_texture_decref(view->texture); + + refcount = InterlockedDecrement(&view->refcount); + TRACE("%p decreasing refcount to %u.\n", view, refcount); + + if (!refcount) + { + struct wined3d_texture *texture = view->texture; + + /* Release the resource after destroying the view. + * See wined3d_shader_resource_view_decref(). */ + wined3d_mutex_lock(); + texture->resource.device->adapter->adapter_ops->adapter_destroy_video_decoder_output_view(view); + wined3d_mutex_unlock(); + wined3d_texture_decref(texture); + } + + return refcount; +} + +static HRESULT wined3d_decoder_output_view_init(struct wined3d_decoder_output_view *view, + const struct wined3d_view_desc *desc, struct wined3d_texture *texture, + void *parent, const struct wined3d_parent_ops *parent_ops) +{ + view->refcount = 1; + view->parent = parent; + view->parent_ops = parent_ops; + + if (!(texture->resource.bind_flags & WINED3D_BIND_DECODER_OUTPUT)) + return E_INVALIDARG; + /* validate_resource_view() checks that we are creating a view of a plane, + * which is required for all other types of views. + * At the same time, the only parameter that Direct3D 11 passes, and + * therefore the only parameter to validate, is the layer index. */ + if (desc->u.texture.layer_idx >= texture->layer_count) + return E_INVALIDARG; + view->desc = *desc; + + /* If WINED3D_VIEW_FORWARD_REFERENCE, the view shouldn't take a reference + * to the resource. However, the reference to the view returned by this + * function should translate to a resource reference, so we increment the + * resource's reference count anyway. */ + wined3d_texture_incref(view->texture = texture); + + return WINED3D_OK; +} + +HRESULT wined3d_decoder_output_view_vk_init(struct wined3d_decoder_output_view_vk *view_vk, + const struct wined3d_view_desc *desc, struct wined3d_texture *texture, + void *parent, const struct wined3d_parent_ops *parent_ops) +{ + TRACE("view_vk %p, desc %s, texture %p, parent %p, parent_ops %p.\n", + view_vk, wined3d_debug_view_desc(desc, &texture->resource), texture, parent, parent_ops); + + return wined3d_decoder_output_view_init(&view_vk->v, desc, texture, parent, parent_ops); +} + +HRESULT CDECL wined3d_decoder_output_view_create(const struct wined3d_view_desc *desc, + struct wined3d_texture *texture, void *parent, const struct wined3d_parent_ops *parent_ops, + struct wined3d_decoder_output_view **view) +{ + const struct wined3d_adapter_ops *adapter_ops; + + TRACE("desc %s, texture %p, parent %p, parent_ops %p, view %p.\n", + wined3d_debug_view_desc(desc, &texture->resource), texture, parent, parent_ops, view); + + adapter_ops = texture->resource.device->adapter->adapter_ops; + return adapter_ops->adapter_create_video_decoder_output_view(desc, texture, parent, parent_ops, view); +} diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec index f267752bffd..6e617648b05 100644 --- a/dlls/wined3d/wined3d.spec +++ b/dlls/wined3d/wined3d.spec @@ -44,6 +44,10 @@ @ cdecl wined3d_decoder_decref(ptr) @ cdecl wined3d_decoder_get_buffer(ptr long)
+@ cdecl wined3d_decoder_output_view_create(ptr ptr ptr ptr ptr) +@ cdecl wined3d_decoder_output_view_decref(ptr) +@ cdecl wined3d_decoder_output_view_incref(ptr) + @ cdecl wined3d_deferred_context_create(ptr ptr) @ cdecl wined3d_deferred_context_destroy(ptr) @ cdecl wined3d_deferred_context_record_command_list(ptr long ptr) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index bf8f3f12d59..e73ba018929 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2560,6 +2560,10 @@ struct wined3d_adapter_ops struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_unordered_access_view **view); void (*adapter_destroy_unordered_access_view)(struct wined3d_unordered_access_view *view); + HRESULT (*adapter_create_video_decoder_output_view)(const struct wined3d_view_desc *desc, + struct wined3d_texture *texture, void *parent, const struct wined3d_parent_ops *parent_ops, + struct wined3d_decoder_output_view **view); + void (*adapter_destroy_video_decoder_output_view)(struct wined3d_decoder_output_view *view); HRESULT (*adapter_create_sampler)(struct wined3d_device *device, const struct wined3d_sampler_desc *desc, void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_sampler **sampler); void (*adapter_destroy_sampler)(struct wined3d_sampler *sampler); @@ -4017,6 +4021,19 @@ void wined3d_unordered_access_view_invalidate_location(struct wined3d_unordered_ void wined3d_unordered_access_view_set_counter(struct wined3d_unordered_access_view *view, unsigned int value);
+struct wined3d_decoder_output_view +{ + LONG refcount; + + struct wined3d_texture *texture; + void *parent; + const struct wined3d_parent_ops *parent_ops; + + struct wined3d_view_desc desc; +}; + +void wined3d_decoder_output_view_cleanup(struct wined3d_decoder_output_view *view); + struct wined3d_swapchain_state { struct wined3d *wined3d; diff --git a/dlls/wined3d/wined3d_vk.h b/dlls/wined3d/wined3d_vk.h index 208431a15e8..fcc275490c7 100644 --- a/dlls/wined3d/wined3d_vk.h +++ b/dlls/wined3d/wined3d_vk.h @@ -1069,6 +1069,21 @@ HRESULT wined3d_unordered_access_view_vk_init(struct wined3d_unordered_access_vi void wined3d_unordered_access_view_vk_update(struct wined3d_unordered_access_view_vk *view_vk, struct wined3d_context_vk *context_vk);
+struct wined3d_decoder_output_view_vk +{ + struct wined3d_decoder_output_view v; +}; + +static inline struct wined3d_decoder_output_view_vk *wined3d_decoder_output_view_vk( + struct wined3d_decoder_output_view *view) +{ + return CONTAINING_RECORD(view, struct wined3d_decoder_output_view_vk, v); +} + +HRESULT wined3d_decoder_output_view_vk_init(struct wined3d_decoder_output_view_vk *view_vk, + const struct wined3d_view_desc *desc, struct wined3d_texture *texture, + void *parent, const struct wined3d_parent_ops *parent_ops); + struct wined3d_swapchain_vk { struct wined3d_swapchain s; diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index 9c1ad9d0808..0eb4361f40e 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -924,6 +924,7 @@ enum wined3d_memory_segment_group #define WINED3D_BIND_DEPTH_STENCIL 0x00000040 #define WINED3D_BIND_UNORDERED_ACCESS 0x00000080 #define WINED3D_BIND_INDIRECT_BUFFER 0x00000100 +#define WINED3D_BIND_DECODER_OUTPUT 0x00000200 /* Used internally. */ #define WINED3D_BIND_DECODER_SRC 0x80000000
@@ -2242,6 +2243,7 @@ struct wined3d_blend_state; struct wined3d_buffer; struct wined3d_command_list; struct wined3d_decoder; +struct wined3d_decoder_output_view; struct wined3d_depth_stencil_state; struct wined3d_device; struct wined3d_device_context; @@ -2382,6 +2384,12 @@ ULONG __cdecl wined3d_decoder_decref(struct wined3d_decoder *decoder); struct wined3d_resource * __cdecl wined3d_decoder_get_buffer( struct wined3d_decoder *decoder, enum wined3d_decoder_buffer_type type);
+HRESULT __cdecl wined3d_decoder_output_view_create(const struct wined3d_view_desc *desc, + struct wined3d_texture *texture, void *parent, const struct wined3d_parent_ops *parent_ops, + struct wined3d_decoder_output_view **view); +ULONG __cdecl wined3d_decoder_output_view_decref(struct wined3d_decoder_output_view *view); +ULONG __cdecl wined3d_decoder_output_view_incref(struct wined3d_decoder_output_view *view); + HRESULT __cdecl wined3d_deferred_context_create(struct wined3d_device *device, struct wined3d_device_context **context); void __cdecl wined3d_deferred_context_destroy(struct wined3d_device_context *context); HRESULT __cdecl wined3d_deferred_context_record_command_list(struct wined3d_device_context *context,