Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dxva2/main.c | 139 ++++++++++++++++++++++++++++++++++++++- dlls/dxva2/tests/dxva2.c | 108 ++++++++++++++++++++++++++++-- 2 files changed, 241 insertions(+), 6 deletions(-)
diff --git a/dlls/dxva2/main.c b/dlls/dxva2/main.c index 53e266d028f..af6ad25697b 100644 --- a/dlls/dxva2/main.c +++ b/dlls/dxva2/main.c @@ -65,6 +65,14 @@ struct device_manager CONDITION_VARIABLE lock; };
+struct video_processor +{ + IDirectXVideoProcessor IDirectXVideoProcessor_iface; + LONG refcount; + + IDirectXVideoProcessorService *service; +}; + static BOOL dxva_array_reserve(void **elements, size_t *capacity, size_t count, size_t size) { size_t new_capacity, max_capacity; @@ -102,6 +110,121 @@ static struct device_manager *impl_from_IDirectXVideoProcessorService(IDirectXVi return CONTAINING_RECORD(iface, struct device_manager, IDirectXVideoProcessorService_iface); }
+static struct video_processor *impl_from_IDirectXVideoProcessor(IDirectXVideoProcessor *iface) +{ + return CONTAINING_RECORD(iface, struct video_processor, IDirectXVideoProcessor_iface); +} + +static HRESULT WINAPI video_processor_QueryInterface(IDirectXVideoProcessor *iface, REFIID riid, void **obj) +{ + if (IsEqualIID(riid, &IID_IDirectXVideoProcessor) || + IsEqualIID(riid, &IID_IUnknown)) + { + *obj = iface; + IDirectXVideoProcessor_AddRef(iface); + return S_OK; + } + + WARN("Unsupported interface %s.\n", debugstr_guid(riid)); + *obj = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI video_processor_AddRef(IDirectXVideoProcessor *iface) +{ + struct video_processor *processor = impl_from_IDirectXVideoProcessor(iface); + ULONG refcount = InterlockedIncrement(&processor->refcount); + + TRACE("%p, refcount %u.\n", iface, refcount); + + return refcount; +} + +static ULONG WINAPI video_processor_Release(IDirectXVideoProcessor *iface) +{ + struct video_processor *processor = impl_from_IDirectXVideoProcessor(iface); + ULONG refcount = InterlockedDecrement(&processor->refcount); + + TRACE("%p, refcount %u.\n", iface, refcount); + + if (!refcount) + { + IDirectXVideoProcessorService_Release(processor->service); + heap_free(processor); + } + + return refcount; +} + +static HRESULT WINAPI video_processor_GetVideoProcessorService(IDirectXVideoProcessor *iface, + IDirectXVideoProcessorService **service) +{ + struct video_processor *processor = impl_from_IDirectXVideoProcessor(iface); + + TRACE("%p, %p.\n", iface, service); + + *service = processor->service; + IDirectXVideoProcessorService_AddRef(*service); + + return S_OK; +} + +static HRESULT WINAPI video_processor_GetCreationParameters(IDirectXVideoProcessor *iface, + GUID *device, DXVA2_VideoDesc *video_desc, D3DFORMAT *rt_format, UINT *maxstreams) +{ + FIXME("%p, %p, %p, %p, %p.\n", iface, device, video_desc, rt_format, maxstreams); + + if (!device && !video_desc && !rt_format && !maxstreams) + return E_INVALIDARG; + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_processor_GetVideoProcessorCaps(IDirectXVideoProcessor *iface, + DXVA2_VideoProcessorCaps *caps) +{ + FIXME("%p, %p.\n", iface, caps); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_processor_GetProcAmpRange(IDirectXVideoProcessor *iface, UINT cap, DXVA2_ValueRange *range) +{ + FIXME("%p, %u, %p.\n", iface, cap, range); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_processor_GetFilterPropertyRange(IDirectXVideoProcessor *iface, UINT setting, + DXVA2_ValueRange *range) +{ + FIXME("%p, %u, %p.\n", iface, setting, range); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_processor_VideoProcessBlt(IDirectXVideoProcessor *iface, IDirect3DSurface9 *rt, + const DXVA2_VideoProcessBltParams *params, const DXVA2_VideoSample *samples, UINT sample_count, + HANDLE *complete_handle) +{ + FIXME("%p, %p, %p, %p, %u, %p.\n", iface, rt, params, samples, sample_count, complete_handle); + + return E_NOTIMPL; +} + +static const IDirectXVideoProcessorVtbl video_processor_vtbl = +{ + video_processor_QueryInterface, + video_processor_AddRef, + video_processor_Release, + video_processor_GetVideoProcessorService, + video_processor_GetCreationParameters, + video_processor_GetVideoProcessorCaps, + video_processor_GetProcAmpRange, + video_processor_GetFilterPropertyRange, + video_processor_VideoProcessBlt, +}; + static HRESULT WINAPI device_manager_processor_service_QueryInterface(IDirectXVideoProcessorService *iface, REFIID riid, void **obj) { @@ -256,10 +379,24 @@ static HRESULT WINAPI device_manager_processor_service_CreateVideoProcessor(IDir REFGUID deviceguid, const DXVA2_VideoDesc *video_desc, D3DFORMAT rt_format, UINT max_substreams, IDirectXVideoProcessor **processor) { + struct video_processor *object; + FIXME("%p, %s, %p, %d, %u, %p.\n", iface, debugstr_guid(deviceguid), video_desc, rt_format, max_substreams, processor);
- return E_NOTIMPL; + /* FIXME: validate render target format */ + + if (!(object = heap_alloc_zero(sizeof(*object)))) + return E_OUTOFMEMORY; + + object->IDirectXVideoProcessor_iface.lpVtbl = &video_processor_vtbl; + object->refcount = 1; + object->service = iface; + IDirectXVideoProcessorService_AddRef(object->service); + + *processor = &object->IDirectXVideoProcessor_iface; + + return S_OK; }
static const IDirectXVideoProcessorServiceVtbl device_manager_processor_service_vtbl = diff --git a/dlls/dxva2/tests/dxva2.c b/dlls/dxva2/tests/dxva2.c index 9dcd3e5bf4e..84ccd3b0190 100644 --- a/dlls/dxva2/tests/dxva2.c +++ b/dlls/dxva2/tests/dxva2.c @@ -23,10 +23,11 @@ #include "initguid.h" #include "dxva2api.h"
-static int get_refcount(IUnknown *object) +static unsigned int get_refcount(void *object) { - IUnknown_AddRef(object); - return IUnknown_Release(object); + IUnknown *iface = object; + IUnknown_AddRef(iface); + return IUnknown_Release(iface); }
static HWND create_window(void) @@ -120,13 +121,13 @@ static void test_device_manager(void)
hr = IDirect3DDeviceManager9_ResetDevice(manager, device, token); ok(hr == S_OK, "Unexpected hr %#x.\n", hr); - refcount = get_refcount((IUnknown *)device); + refcount = get_refcount(device);
handle1 = NULL; hr = IDirect3DDeviceManager9_OpenDeviceHandle(manager, &handle1); ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
- refcount2 = get_refcount((IUnknown *)device); + refcount2 = get_refcount(device); ok(refcount2 == refcount, "Unexpected refcount %d.\n", refcount);
handle = NULL; @@ -357,7 +358,104 @@ done: DestroyWindow(window); }
+static void test_video_processor(void) +{ + IDirectXVideoProcessorService *service, *service2; + IDirect3DDevice9 *device; + IDirect3DDeviceManager9 *manager; + HANDLE handle, handle1; + IDirect3D9 *d3d; + HWND window; + UINT token; + HRESULT hr; + IDirectXVideoProcessor *processor, *processor2; + DXVA2_VideoDesc video_desc; + GUID guid; + D3DFORMAT format; + + window = create_window(); + d3d = Direct3DCreate9(D3D_SDK_VERSION); + ok(!!d3d, "Failed to create a D3D object.\n"); + if (!(device = create_device(d3d, window))) + { + skip("Failed to create a D3D device, skipping tests.\n"); + goto done; + } + + hr = DXVA2CreateDirect3DDeviceManager9(&token, &manager); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IDirect3DDeviceManager9_ResetDevice(manager, device, token); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + handle = NULL; + hr = IDirect3DDeviceManager9_OpenDeviceHandle(manager, &handle); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + handle1 = NULL; + hr = IDirect3DDeviceManager9_OpenDeviceHandle(manager, &handle1); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + ok(get_refcount(manager) == 1, "Unexpected refcount %u.\n", get_refcount(manager)); + + hr = IDirect3DDeviceManager9_GetVideoService(manager, handle, &IID_IDirectXVideoProcessorService, + (void **)&service); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + memset(&video_desc, 0, sizeof(video_desc)); + video_desc.SampleWidth = 64; + video_desc.SampleHeight = 64; + video_desc.Format = D3DFMT_A8R8G8B8; + + hr = IDirectXVideoProcessorService_CreateVideoProcessor(service, &DXVA2_VideoProcSoftwareDevice, &video_desc, + D3DFMT_A8R8G8B8, 1, &processor); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IDirectXVideoProcessorService_CreateVideoProcessor(service, &DXVA2_VideoProcSoftwareDevice, &video_desc, + D3DFMT_A8R8G8B8, 1, &processor2); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(processor2 != processor, "Unexpected instance.\n"); + + hr = IDirectXVideoProcessor_GetCreationParameters(processor, NULL, NULL, NULL, NULL); + ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); + + hr = IDirectXVideoProcessor_GetCreationParameters(processor, &guid, NULL, NULL, NULL); +todo_wine { + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(IsEqualGUID(&guid, &DXVA2_VideoProcSoftwareDevice), "Unexpected device guid.\n"); +} + hr = IDirectXVideoProcessor_GetCreationParameters(processor, NULL, NULL, &format, NULL); +todo_wine { + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(format == D3DFMT_A8R8G8B8, "Unexpected format %u.\n", format); +} + IDirectXVideoProcessor_Release(processor); + IDirectXVideoProcessor_Release(processor2); + + hr = IDirect3DDeviceManager9_GetVideoService(manager, handle, &IID_IDirectXVideoProcessorService, + (void **)&service2); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(service == service2, "Unexpected pointer.\n"); + + IDirectXVideoProcessorService_Release(service2); + IDirectXVideoProcessorService_Release(service); + + hr = IDirect3DDeviceManager9_CloseDeviceHandle(manager, handle); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IDirect3DDeviceManager9_CloseDeviceHandle(manager, handle1); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + IDirect3DDevice9_Release(device); + IDirect3DDeviceManager9_Release(manager); + +done: + IDirect3D9_Release(d3d); + DestroyWindow(window); +} + START_TEST(dxva2) { test_device_manager(); + test_video_processor(); }