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