-- v2: d3d11: Implement DecoderBeginFrame() and DecoderEndFrame(). d3d11: Create a wined3d video decoder output view.
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/wined3d/context_vk.c | 4 +- dlls/wined3d/decoder.c | 84 +++++++++++++++++++++++++++++++++++++++ dlls/wined3d/wined3d_vk.h | 7 +++- 3 files changed, 92 insertions(+), 3 deletions(-)
diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c index f0a9b454f39..42c54faeb8b 100644 --- a/dlls/wined3d/context_vk.c +++ b/dlls/wined3d/context_vk.c @@ -381,7 +381,7 @@ VkDeviceMemory wined3d_context_vk_allocate_vram_chunk_memory(struct wined3d_cont return vk_memory; }
-static struct wined3d_allocator_block *wined3d_context_vk_allocate_memory(struct wined3d_context_vk *context_vk, +struct wined3d_allocator_block *wined3d_context_vk_allocate_memory(struct wined3d_context_vk *context_vk, unsigned int memory_type, VkDeviceSize size, VkDeviceMemory *vk_memory) { struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device); @@ -410,7 +410,7 @@ static struct wined3d_allocator_block *wined3d_context_vk_allocate_memory(struct return block; }
-static void wined3d_context_vk_free_memory(struct wined3d_context_vk *context_vk, struct wined3d_allocator_block *block) +void wined3d_context_vk_free_memory(struct wined3d_context_vk *context_vk, struct wined3d_allocator_block *block) { struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
diff --git a/dlls/wined3d/decoder.c b/dlls/wined3d/decoder.c index bb43d61067b..db6883fe619 100644 --- a/dlls/wined3d/decoder.c +++ b/dlls/wined3d/decoder.c @@ -97,6 +97,8 @@ struct wined3d_decoder_vk struct wined3d_decoder d; VkVideoSessionKHR vk_session; uint64_t command_buffer_id; + struct wined3d_allocator_block *session_memory; + VkDeviceMemory vk_session_memory; };
static struct wined3d_decoder_vk *wined3d_decoder_vk(struct wined3d_decoder *decoder) @@ -198,12 +200,19 @@ static void wined3d_decoder_vk_get_profiles(struct wined3d_adapter *adapter, uns static void wined3d_decoder_vk_destroy_object(void *object) { struct wined3d_decoder_vk *decoder_vk = object; + struct wined3d_device_vk *device_vk = wined3d_device_vk(decoder_vk->d.device); + struct wined3d_vk_info *vk_info = &device_vk->vk_info; struct wined3d_context_vk *context_vk;
TRACE("decoder_vk %p.\n", decoder_vk);
context_vk = wined3d_context_vk(context_acquire(decoder_vk->d.device, NULL, 0));
+ if (decoder_vk->session_memory) + wined3d_context_vk_free_memory(context_vk, decoder_vk->session_memory); + else + VK_CALL(vkFreeMemory(device_vk->vk_device, decoder_vk->vk_session_memory, NULL)); + wined3d_context_vk_destroy_vk_video_session(context_vk, decoder_vk->vk_session, decoder_vk->command_buffer_id);
free(decoder_vk); @@ -216,6 +225,79 @@ static void wined3d_decoder_vk_destroy(struct wined3d_decoder *decoder) wined3d_cs_destroy_object(decoder->device->cs, wined3d_decoder_vk_destroy_object, decoder_vk); }
+static void bind_video_session_memory(struct wined3d_decoder_vk *decoder_vk) +{ + struct wined3d_adapter_vk *adapter_vk = wined3d_adapter_vk(decoder_vk->d.device->adapter); + struct wined3d_device_vk *device_vk = wined3d_device_vk(decoder_vk->d.device); + const struct wined3d_vk_info *vk_info = &device_vk->vk_info; + VkVideoSessionMemoryRequirementsKHR *requirements; + VkBindVideoSessionMemoryInfoKHR *memory; + struct wined3d_context_vk *context_vk; + uint32_t count; + VkResult vr; + + context_vk = wined3d_context_vk(context_acquire(&device_vk->d, NULL, 0)); + + VK_CALL(vkGetVideoSessionMemoryRequirementsKHR(device_vk->vk_device, decoder_vk->vk_session, &count, NULL)); + + if (!(requirements = calloc(count, sizeof(*requirements)))) + { + context_release(&context_vk->c); + return; + } + + for (uint32_t i = 0; i < count; ++i) + requirements[i].sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_MEMORY_REQUIREMENTS_KHR; + + VK_CALL(vkGetVideoSessionMemoryRequirementsKHR(device_vk->vk_device, decoder_vk->vk_session, &count, requirements)); + + if (!(memory = calloc(count, sizeof(*memory)))) + { + free(requirements); + context_release(&context_vk->c); + return; + } + + for (uint32_t i = 0; i < count; ++i) + { + unsigned int memory_type_idx; + + /* It's not at all clear what memory properties we should be passing + * here. The spec doesn't say, and it doesn't give a hint as to what's + * most performant either. + * + * Of course, this is a terrible, terrible API generally speaking, and + * there is no reason for it to exist. */ + memory_type_idx = wined3d_adapter_vk_get_memory_type_index(adapter_vk, + requirements[i].memoryRequirements.memoryTypeBits, 0); + if (memory_type_idx == ~0u) + { + ERR("Failed to find suitable memory type.\n"); + goto out; + } + if (requirements[i].memoryRequirements.alignment > WINED3D_ALLOCATOR_MIN_BLOCK_SIZE) + ERR("Required alignment is %I64u, but we only support %u.\n", + requirements[i].memoryRequirements.alignment, WINED3D_ALLOCATOR_MIN_BLOCK_SIZE); + decoder_vk->session_memory = wined3d_context_vk_allocate_memory(context_vk, + memory_type_idx, requirements[i].memoryRequirements.size, &decoder_vk->vk_session_memory); + + memory[i].sType = VK_STRUCTURE_TYPE_BIND_VIDEO_SESSION_MEMORY_INFO_KHR; + memory[i].memoryBindIndex = requirements[i].memoryBindIndex; + memory[i].memory = decoder_vk->vk_session_memory; + memory[i].memoryOffset = decoder_vk->session_memory ? decoder_vk->session_memory->offset : 0; + memory[i].memorySize = requirements[i].memoryRequirements.size; + } + + if ((vr = VK_CALL(vkBindVideoSessionMemoryKHR(device_vk->vk_device, + decoder_vk->vk_session, count, memory))) != VK_SUCCESS) + ERR("Failed to bind memory, vr %s.\n", wined3d_debug_vkresult(vr)); + +out: + free(requirements); + free(memory); + context_release(&context_vk->c); +} + static void wined3d_decoder_vk_cs_init(void *object) { VkVideoDecodeH264CapabilitiesKHR h264_caps = {.sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_CAPABILITIES_KHR}; @@ -270,6 +352,8 @@ static void wined3d_decoder_vk_cs_init(void *object) }
TRACE("Created video session 0x%s.\n", wine_dbgstr_longlong(decoder_vk->vk_session)); + + bind_video_session_memory(decoder_vk); }
static HRESULT wined3d_decoder_vk_create(struct wined3d_device *device, diff --git a/dlls/wined3d/wined3d_vk.h b/dlls/wined3d/wined3d_vk.h index add8ec3cb3b..208431a15e8 100644 --- a/dlls/wined3d/wined3d_vk.h +++ b/dlls/wined3d/wined3d_vk.h @@ -216,8 +216,10 @@ struct wined3d_device_vk; VK_DEVICE_PFN(vkGetSwapchainImagesKHR) \ VK_DEVICE_PFN(vkQueuePresentKHR) \ /* VK_KHR_video_queue */ \ + VK_DEVICE_EXT_PFN(vkBindVideoSessionMemoryKHR) \ VK_DEVICE_EXT_PFN(vkCreateVideoSessionKHR) \ - VK_DEVICE_EXT_PFN(vkDestroyVideoSessionKHR) + VK_DEVICE_EXT_PFN(vkDestroyVideoSessionKHR) \ + VK_DEVICE_EXT_PFN(vkGetVideoSessionMemoryRequirementsKHR)
#define DECLARE_VK_PFN(name) PFN_##name name;
@@ -674,6 +676,8 @@ static inline struct wined3d_context_vk *wined3d_context_vk(struct wined3d_conte return CONTAINING_RECORD(context, struct wined3d_context_vk, c); }
+struct wined3d_allocator_block *wined3d_context_vk_allocate_memory(struct wined3d_context_vk *context_vk, + unsigned int memory_type, VkDeviceSize size, VkDeviceMemory *vk_memory); bool wined3d_context_vk_allocate_query(struct wined3d_context_vk *context_vk, enum wined3d_query_type type, struct wined3d_query_pool_idx_vk *pool_idx); VkDeviceMemory wined3d_context_vk_allocate_vram_chunk_memory(struct wined3d_context_vk *context_vk, @@ -714,6 +718,7 @@ void wined3d_context_vk_destroy_vk_pipeline(struct wined3d_context_vk *context_v void wined3d_context_vk_destroy_vk_video_session(struct wined3d_context_vk *context_vk, VkPipeline vk_video_session, uint64_t command_buffer_id); void wined3d_context_vk_end_current_render_pass(struct wined3d_context_vk *context_vk); +void wined3d_context_vk_free_memory(struct wined3d_context_vk *context_vk, struct wined3d_allocator_block *block); VkCommandBuffer wined3d_context_vk_get_command_buffer(struct wined3d_context_vk *context_vk); struct wined3d_pipeline_layout_vk *wined3d_context_vk_get_pipeline_layout(struct wined3d_context_vk *context_vk, VkDescriptorSetLayoutBinding *bindings, SIZE_T binding_count);
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/d3d11/d3d11_private.h | 1 + dlls/d3d11/decoder.c | 6 ++++ dlls/d3d11/device.c | 31 ++++++++++++++--- dlls/wined3d/decoder.c | 70 ++++++++++++++++++++++++++++++++++++-- dlls/wined3d/wined3d.spec | 1 + include/wine/wined3d.h | 9 +++++ 6 files changed, 111 insertions(+), 7 deletions(-)
diff --git a/dlls/d3d11/d3d11_private.h b/dlls/d3d11/d3d11_private.h index 910ad226269..0dd4c12cb91 100644 --- a/dlls/d3d11/d3d11_private.h +++ b/dlls/d3d11/d3d11_private.h @@ -628,6 +628,7 @@ struct d3d_video_decoder
HRESULT d3d_video_decoder_create(struct d3d_device *device, const D3D11_VIDEO_DECODER_DESC *desc, const D3D11_VIDEO_DECODER_CONFIG *config, struct d3d_video_decoder **decoder); +struct d3d_video_decoder *unsafe_impl_from_ID3D11VideoDecoder(ID3D11VideoDecoder *iface);
/* Layered device */ enum dxgi_device_layer_id diff --git a/dlls/d3d11/decoder.c b/dlls/d3d11/decoder.c index 1e61dea0581..2e5db2a0230 100644 --- a/dlls/d3d11/decoder.c +++ b/dlls/d3d11/decoder.c @@ -211,3 +211,9 @@ HRESULT d3d_video_decoder_create(struct d3d_device *device, const D3D11_VIDEO_DE *decoder = object; return S_OK; } + +struct d3d_video_decoder *unsafe_impl_from_ID3D11VideoDecoder(ID3D11VideoDecoder *iface) +{ + assert(iface->lpVtbl == &d3d11_video_decoder_vtbl); + return impl_from_ID3D11VideoDecoder(iface); +} diff --git a/dlls/d3d11/device.c b/dlls/d3d11/device.c index 9d4c137b3de..54b040aef21 100644 --- a/dlls/d3d11/device.c +++ b/dlls/d3d11/device.c @@ -3171,17 +3171,38 @@ static HRESULT STDMETHODCALLTYPE d3d11_video_context_SetPrivateDataInterface( }
static HRESULT STDMETHODCALLTYPE d3d11_video_context_GetDecoderBuffer(ID3D11VideoContext *iface, - ID3D11VideoDecoder *decoder, D3D11_VIDEO_DECODER_BUFFER_TYPE type, UINT *size, void **buffer) + ID3D11VideoDecoder *decoder, D3D11_VIDEO_DECODER_BUFFER_TYPE type, UINT *size, void **data) { - FIXME("iface %p, decoder %p, type %#x, size %p, buffer %p, stub!\n", iface, decoder, type, size, buffer); - return E_NOTIMPL; + struct d3d_video_decoder *decoder_impl = unsafe_impl_from_ID3D11VideoDecoder(decoder); + struct wined3d_map_desc map_desc; + struct wined3d_resource *buffer; + HRESULT hr; + + TRACE("iface %p, decoder %p, type %#x, size %p, data %p.\n", iface, decoder, type, size, data); + + if (!(buffer = wined3d_decoder_get_buffer(decoder_impl->wined3d_decoder, (enum wined3d_decoder_buffer_type)type))) + return E_NOTIMPL; + + if (SUCCEEDED(hr = wined3d_resource_map(buffer, 0, &map_desc, NULL, WINED3D_MAP_WRITE | WINED3D_MAP_DISCARD))) + { + *size = map_desc.row_pitch; + *data = map_desc.data; + } + return hr; }
static HRESULT STDMETHODCALLTYPE d3d11_video_context_ReleaseDecoderBuffer(ID3D11VideoContext *iface, ID3D11VideoDecoder *decoder, D3D11_VIDEO_DECODER_BUFFER_TYPE type) { - FIXME("iface %p, decoder %p, type %#x, stub!\n", iface, decoder, type); - return E_NOTIMPL; + struct d3d_video_decoder *decoder_impl = unsafe_impl_from_ID3D11VideoDecoder(decoder); + struct wined3d_resource *buffer; + + TRACE("iface %p, decoder %p, type %#x.\n", iface, decoder, type); + + if (!(buffer = wined3d_decoder_get_buffer(decoder_impl->wined3d_decoder, (enum wined3d_decoder_buffer_type)type))) + return E_NOTIMPL; + + return wined3d_resource_unmap(buffer, 0); }
static HRESULT STDMETHODCALLTYPE d3d11_video_context_DecoderBeginFrame(ID3D11VideoContext *iface, diff --git a/dlls/wined3d/decoder.c b/dlls/wined3d/decoder.c index db6883fe619..262e8921d22 100644 --- a/dlls/wined3d/decoder.c +++ b/dlls/wined3d/decoder.c @@ -26,8 +26,16 @@ struct wined3d_decoder LONG ref; struct wined3d_device *device; struct wined3d_decoder_desc desc; + struct wined3d_buffer *parameters, *matrix, *slice_control; };
+static void wined3d_decoder_cleanup(struct wined3d_decoder *decoder) +{ + wined3d_buffer_decref(decoder->parameters); + wined3d_buffer_decref(decoder->matrix); + wined3d_buffer_decref(decoder->slice_control); +} + ULONG CDECL wined3d_decoder_decref(struct wined3d_decoder *decoder) { unsigned int refcount = InterlockedDecrement(&decoder->ref); @@ -59,12 +67,45 @@ static bool is_supported_codec(struct wined3d_adapter *adapter, const GUID *code return false; }
-static void wined3d_decoder_init(struct wined3d_decoder *decoder, +static HRESULT wined3d_decoder_init(struct wined3d_decoder *decoder, struct wined3d_device *device, const struct wined3d_decoder_desc *desc) { + HRESULT hr; + + struct wined3d_buffer_desc buffer_desc = + { + .access = WINED3D_RESOURCE_ACCESS_CPU | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W, + }; + decoder->ref = 1; decoder->device = device; decoder->desc = *desc; + + buffer_desc.byte_width = sizeof(DXVA_PicParams_H264); + if (FAILED(hr = wined3d_buffer_create(device, &buffer_desc, + NULL, NULL, &wined3d_null_parent_ops, &decoder->parameters))) + return hr; + + buffer_desc.byte_width = sizeof(DXVA_Qmatrix_H264); + if (FAILED(hr = wined3d_buffer_create(device, &buffer_desc, + NULL, NULL, &wined3d_null_parent_ops, &decoder->matrix))) + { + wined3d_buffer_decref(decoder->parameters); + return hr; + } + + /* NVidia gives 64 * sizeof(DXVA_Slice_H264_Long). + * AMD gives 4096 bytes. Pick the smaller one. */ + buffer_desc.byte_width = 4096; + if (FAILED(hr = wined3d_buffer_create(device, &buffer_desc, + NULL, NULL, &wined3d_null_parent_ops, &decoder->slice_control))) + { + wined3d_buffer_decref(decoder->matrix); + wined3d_buffer_decref(decoder->parameters); + return hr; + } + + return S_OK; }
HRESULT CDECL wined3d_decoder_create(struct wined3d_device *device, @@ -222,6 +263,7 @@ static void wined3d_decoder_vk_destroy(struct wined3d_decoder *decoder) { struct wined3d_decoder_vk *decoder_vk = wined3d_decoder_vk(decoder);
+ wined3d_decoder_cleanup(decoder); wined3d_cs_destroy_object(decoder->device->cs, wined3d_decoder_vk_destroy_object, decoder_vk); }
@@ -360,11 +402,16 @@ static HRESULT wined3d_decoder_vk_create(struct wined3d_device *device, const struct wined3d_decoder_desc *desc, struct wined3d_decoder **decoder) { struct wined3d_decoder_vk *object; + HRESULT hr;
if (!(object = calloc(1, sizeof(*object)))) return E_OUTOFMEMORY;
- wined3d_decoder_init(&object->d, device, desc); + if (FAILED(hr = wined3d_decoder_init(&object->d, device, desc))) + { + free(object); + return hr; + }
wined3d_cs_init_object(device->cs, wined3d_decoder_vk_cs_init, object);
@@ -380,3 +427,22 @@ const struct wined3d_decoder_ops wined3d_decoder_vk_ops = .create = wined3d_decoder_vk_create, .destroy = wined3d_decoder_vk_destroy, }; + +struct wined3d_resource * CDECL wined3d_decoder_get_buffer( + struct wined3d_decoder *decoder, enum wined3d_decoder_buffer_type type) +{ + switch (type) + { + case WINED3D_DECODER_BUFFER_INVERSE_QUANTIZATION_MATRIX: + return &decoder->matrix->resource; + + case WINED3D_DECODER_BUFFER_PICTURE_PARAMETERS: + return &decoder->parameters->resource; + + case WINED3D_DECODER_BUFFER_SLICE_CONTROL: + return &decoder->slice_control->resource; + } + + FIXME("Unhandled buffer type %#x.\n", type); + return NULL; +} diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec index 6fdc2002ca3..f267752bffd 100644 --- a/dlls/wined3d/wined3d.spec +++ b/dlls/wined3d/wined3d.spec @@ -42,6 +42,7 @@
@ cdecl wined3d_decoder_create(ptr ptr ptr) @ cdecl wined3d_decoder_decref(ptr) +@ cdecl wined3d_decoder_get_buffer(ptr long)
@ cdecl wined3d_deferred_context_create(ptr ptr) @ cdecl wined3d_deferred_context_destroy(ptr) diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index 27e211a0b4e..8ea24f70b86 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -858,6 +858,13 @@ enum wined3d_pipeline WINED3D_PIPELINE_COUNT, };
+enum wined3d_decoder_buffer_type +{ + WINED3D_DECODER_BUFFER_PICTURE_PARAMETERS = 0, + WINED3D_DECODER_BUFFER_INVERSE_QUANTIZATION_MATRIX = 4, + WINED3D_DECODER_BUFFER_SLICE_CONTROL = 5, +}; + enum wined3d_memory_segment_group { WINED3D_MEMORY_SEGMENT_GROUP_LOCAL = 0, @@ -2369,6 +2376,8 @@ ULONG __cdecl wined3d_command_list_incref(struct wined3d_command_list *list); HRESULT __cdecl wined3d_decoder_create(struct wined3d_device *device, const struct wined3d_decoder_desc *desc, struct wined3d_decoder **decoder); 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_deferred_context_create(struct wined3d_device *device, struct wined3d_device_context **context); void __cdecl wined3d_deferred_context_destroy(struct wined3d_device_context *context);
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/wined3d/buffer.c | 2 ++ dlls/wined3d/decoder.c | 23 ++++++++++++++++++++++- include/wine/wined3d.h | 3 +++ 3 files changed, 27 insertions(+), 1 deletion(-)
diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c index 608be16b9df..a656f9edb2b 100644 --- a/dlls/wined3d/buffer.c +++ b/dlls/wined3d/buffer.c @@ -1142,6 +1142,8 @@ VkBufferUsageFlags vk_buffer_usage_from_bind_flags(uint32_t bind_flags) usage |= VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT; if (bind_flags & WINED3D_BIND_INDIRECT_BUFFER) usage |= VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT; + if (bind_flags & WINED3D_BIND_DECODER_SRC) + usage |= VK_BUFFER_USAGE_VIDEO_DECODE_SRC_BIT_KHR; if (bind_flags & (WINED3D_BIND_RENDER_TARGET | WINED3D_BIND_DEPTH_STENCIL)) FIXME("Ignoring some bind flags %#x.\n", bind_flags); return usage; diff --git a/dlls/wined3d/decoder.c b/dlls/wined3d/decoder.c index 262e8921d22..20a54851075 100644 --- a/dlls/wined3d/decoder.c +++ b/dlls/wined3d/decoder.c @@ -26,11 +26,12 @@ struct wined3d_decoder LONG ref; struct wined3d_device *device; struct wined3d_decoder_desc desc; - struct wined3d_buffer *parameters, *matrix, *slice_control; + struct wined3d_buffer *bitstream, *parameters, *matrix, *slice_control; };
static void wined3d_decoder_cleanup(struct wined3d_decoder *decoder) { + wined3d_buffer_decref(decoder->bitstream); wined3d_buffer_decref(decoder->parameters); wined3d_buffer_decref(decoder->matrix); wined3d_buffer_decref(decoder->slice_control); @@ -105,6 +106,23 @@ static HRESULT wined3d_decoder_init(struct wined3d_decoder *decoder, return hr; }
+ /* NVidia makes this buffer as large as width * height (as if each pixel + * is at most 1 byte). AMD makes it larger than that. + * Go with the smaller of the two. */ + buffer_desc.byte_width = desc->width * desc->height; + buffer_desc.bind_flags = WINED3D_BIND_DECODER_SRC; + buffer_desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP_W; + buffer_desc.usage = WINED3DUSAGE_DYNAMIC; + + if (FAILED(hr = wined3d_buffer_create(device, &buffer_desc, + NULL, NULL, &wined3d_null_parent_ops, &decoder->bitstream))) + { + wined3d_buffer_decref(decoder->matrix); + wined3d_buffer_decref(decoder->parameters); + wined3d_buffer_decref(decoder->slice_control); + return hr; + } + return S_OK; }
@@ -433,6 +451,9 @@ struct wined3d_resource * CDECL wined3d_decoder_get_buffer( { switch (type) { + case WINED3D_DECODER_BUFFER_BITSTREAM: + return &decoder->bitstream->resource; + case WINED3D_DECODER_BUFFER_INVERSE_QUANTIZATION_MATRIX: return &decoder->matrix->resource;
diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index 8ea24f70b86..9c1ad9d0808 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -863,6 +863,7 @@ enum wined3d_decoder_buffer_type WINED3D_DECODER_BUFFER_PICTURE_PARAMETERS = 0, WINED3D_DECODER_BUFFER_INVERSE_QUANTIZATION_MATRIX = 4, WINED3D_DECODER_BUFFER_SLICE_CONTROL = 5, + WINED3D_DECODER_BUFFER_BITSTREAM = 6, };
enum wined3d_memory_segment_group @@ -923,6 +924,8 @@ enum wined3d_memory_segment_group #define WINED3D_BIND_DEPTH_STENCIL 0x00000040 #define WINED3D_BIND_UNORDERED_ACCESS 0x00000080 #define WINED3D_BIND_INDIRECT_BUFFER 0x00000100 +/* Used internally. */ +#define WINED3D_BIND_DECODER_SRC 0x80000000
#define WINED3DUSAGE_SOFTWAREPROCESSING 0x00000010 #define WINED3DUSAGE_DONOTCLIP 0x00000020
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,
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/d3d11/d3d11_private.h | 2 ++ dlls/d3d11/device.c | 18 ++++++++++++++---- dlls/d3d11/view.c | 9 +++++++++ dlls/wined3d/decoder.c | 34 ++++++++++++++++++++++++++++++++++ dlls/wined3d/wined3d.spec | 2 ++ include/wine/wined3d.h | 3 +++ 6 files changed, 64 insertions(+), 4 deletions(-)
diff --git a/dlls/d3d11/d3d11_private.h b/dlls/d3d11/d3d11_private.h index 7edad44fdf5..426ac0772c5 100644 --- a/dlls/d3d11/d3d11_private.h +++ b/dlls/d3d11/d3d11_private.h @@ -284,6 +284,8 @@ struct d3d_video_decoder_output_view
HRESULT d3d_video_decoder_output_view_create(struct d3d_device *device, ID3D11Resource *resource, const D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC *desc, struct d3d_video_decoder_output_view **view); +struct d3d_video_decoder_output_view *unsafe_impl_from_ID3D11VideoDecoderOutputView( + ID3D11VideoDecoderOutputView *iface);
/* ID3D11InputLayout, ID3D10InputLayout */ struct d3d_input_layout diff --git a/dlls/d3d11/device.c b/dlls/d3d11/device.c index 91049c104ea..64baad68859 100644 --- a/dlls/d3d11/device.c +++ b/dlls/d3d11/device.c @@ -3208,15 +3208,25 @@ static HRESULT STDMETHODCALLTYPE d3d11_video_context_ReleaseDecoderBuffer(ID3D11 static HRESULT STDMETHODCALLTYPE d3d11_video_context_DecoderBeginFrame(ID3D11VideoContext *iface, ID3D11VideoDecoder *decoder, ID3D11VideoDecoderOutputView *view, UINT key_size, const void *key) { - FIXME("iface %p, decoder %p, view %p, key_size %u, key %p, stub!\n", iface, decoder, view, key_size, key); - return E_NOTIMPL; + struct d3d_video_decoder_output_view *view_impl = unsafe_impl_from_ID3D11VideoDecoderOutputView(view); + struct d3d_video_decoder *decoder_impl = unsafe_impl_from_ID3D11VideoDecoder(decoder); + + TRACE("iface %p, decoder %p, view %p, key_size %u, key %p.\n", iface, decoder, view, key_size, key); + + if (key_size) + FIXME("Ignoring encryption key.\n"); + + return wined3d_decoder_begin_frame(decoder_impl->wined3d_decoder, view_impl->wined3d_view); }
static HRESULT STDMETHODCALLTYPE d3d11_video_context_DecoderEndFrame( ID3D11VideoContext *iface, ID3D11VideoDecoder *decoder) { - FIXME("iface %p, decoder %p, stub!\n", iface, decoder); - return E_NOTIMPL; + struct d3d_video_decoder *decoder_impl = unsafe_impl_from_ID3D11VideoDecoder(decoder); + + TRACE("iface %p, decoder %p.\n", iface, decoder); + + return wined3d_decoder_end_frame(decoder_impl->wined3d_decoder); }
static HRESULT STDMETHODCALLTYPE d3d11_video_context_SubmitDecoderBuffers(ID3D11VideoContext *iface, diff --git a/dlls/d3d11/view.c b/dlls/d3d11/view.c index bb0b72b37a1..ea7d6c5563c 100644 --- a/dlls/d3d11/view.c +++ b/dlls/d3d11/view.c @@ -2797,3 +2797,12 @@ HRESULT d3d_video_decoder_output_view_create(struct d3d_device *device, ID3D11Re
return S_OK; } + +struct d3d_video_decoder_output_view *unsafe_impl_from_ID3D11VideoDecoderOutputView(ID3D11VideoDecoderOutputView *iface) +{ + if (!iface) + return NULL; + assert(iface->lpVtbl == &d3d11_video_decoder_output_view_vtbl); + + return impl_from_ID3D11VideoDecoderOutputView(iface); +} diff --git a/dlls/wined3d/decoder.c b/dlls/wined3d/decoder.c index 20a54851075..1a33f759174 100644 --- a/dlls/wined3d/decoder.c +++ b/dlls/wined3d/decoder.c @@ -27,6 +27,7 @@ struct wined3d_decoder struct wined3d_device *device; struct wined3d_decoder_desc desc; struct wined3d_buffer *bitstream, *parameters, *matrix, *slice_control; + struct wined3d_decoder_output_view *output_view; };
static void wined3d_decoder_cleanup(struct wined3d_decoder *decoder) @@ -467,3 +468,36 @@ struct wined3d_resource * CDECL wined3d_decoder_get_buffer( FIXME("Unhandled buffer type %#x.\n", type); return NULL; } + +HRESULT CDECL wined3d_decoder_begin_frame(struct wined3d_decoder *decoder, + struct wined3d_decoder_output_view *view) +{ + TRACE("decoder %p, view %p.\n", decoder, view); + + if (decoder->output_view) + { + ERR("Already in frame.\n"); + return E_INVALIDARG; + } + + wined3d_decoder_output_view_incref(view); + decoder->output_view = view; + + return S_OK; +} + +HRESULT CDECL wined3d_decoder_end_frame(struct wined3d_decoder *decoder) +{ + TRACE("decoder %p.\n", decoder); + + if (!decoder->output_view) + { + ERR("Not in frame.\n"); + return E_INVALIDARG; + } + + wined3d_decoder_output_view_decref(decoder->output_view); + decoder->output_view = NULL; + + return S_OK; +} diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec index 6e617648b05..e9125e52cf6 100644 --- a/dlls/wined3d/wined3d.spec +++ b/dlls/wined3d/wined3d.spec @@ -40,8 +40,10 @@ @ cdecl wined3d_command_list_decref(ptr) @ cdecl wined3d_command_list_incref(ptr)
+@ cdecl wined3d_decoder_begin_frame(ptr ptr) @ cdecl wined3d_decoder_create(ptr ptr ptr) @ cdecl wined3d_decoder_decref(ptr) +@ cdecl wined3d_decoder_end_frame(ptr) @ cdecl wined3d_decoder_get_buffer(ptr long)
@ cdecl wined3d_decoder_output_view_create(ptr ptr ptr ptr ptr) diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index 0eb4361f40e..7a0434925c0 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -2378,9 +2378,12 @@ ULONG __cdecl wined3d_buffer_incref(struct wined3d_buffer *buffer); ULONG __cdecl wined3d_command_list_decref(struct wined3d_command_list *list); ULONG __cdecl wined3d_command_list_incref(struct wined3d_command_list *list);
+HRESULT __cdecl wined3d_decoder_begin_frame(struct wined3d_decoder *decoder, + struct wined3d_decoder_output_view *view); HRESULT __cdecl wined3d_decoder_create(struct wined3d_device *device, const struct wined3d_decoder_desc *desc, struct wined3d_decoder **decoder); ULONG __cdecl wined3d_decoder_decref(struct wined3d_decoder *decoder); +HRESULT __cdecl wined3d_decoder_end_frame(struct wined3d_decoder *decoder); struct wined3d_resource * __cdecl wined3d_decoder_get_buffer( struct wined3d_decoder *decoder, enum wined3d_decoder_buffer_type type);
This merge request was approved by Jan Sikorski.