Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- configure | 1 + configure.ac | 1 + dlls/dxva2/Makefile.in | 1 + dlls/dxva2/main.c | 147 +++++++++++++++++++++++++++- dlls/dxva2/tests/Makefile.in | 5 + dlls/dxva2/tests/dxva2.c | 181 +++++++++++++++++++++++++++++++++++ 6 files changed, 332 insertions(+), 4 deletions(-) create mode 100644 dlls/dxva2/tests/Makefile.in create mode 100644 dlls/dxva2/tests/dxva2.c
diff --git a/configure b/configure index dd23b5ab13b..106ce1625b1 100755 --- a/configure +++ b/configure @@ -20683,6 +20683,7 @@ wine_fn_config_makefile dlls/dxgi enable_dxgi wine_fn_config_makefile dlls/dxgi/tests enable_tests wine_fn_config_makefile dlls/dxguid enable_dxguid wine_fn_config_makefile dlls/dxva2 enable_dxva2 +wine_fn_config_makefile dlls/dxva2/tests enable_tests wine_fn_config_makefile dlls/esent enable_esent wine_fn_config_makefile dlls/evr enable_evr wine_fn_config_makefile dlls/evr/tests enable_tests diff --git a/configure.ac b/configure.ac index 9c5f76669df..a78610c6490 100644 --- a/configure.ac +++ b/configure.ac @@ -3269,6 +3269,7 @@ WINE_CONFIG_MAKEFILE(dlls/dxgi) WINE_CONFIG_MAKEFILE(dlls/dxgi/tests) WINE_CONFIG_MAKEFILE(dlls/dxguid) WINE_CONFIG_MAKEFILE(dlls/dxva2) +WINE_CONFIG_MAKEFILE(dlls/dxva2/tests) WINE_CONFIG_MAKEFILE(dlls/esent) WINE_CONFIG_MAKEFILE(dlls/evr) WINE_CONFIG_MAKEFILE(dlls/evr/tests) diff --git a/dlls/dxva2/Makefile.in b/dlls/dxva2/Makefile.in index 44e125e9b5f..cc7551a186b 100644 --- a/dlls/dxva2/Makefile.in +++ b/dlls/dxva2/Makefile.in @@ -1,4 +1,5 @@ MODULE = dxva2.dll +IMPORTS = uuid
EXTRADLLFLAGS = -mno-cygwin
diff --git a/dlls/dxva2/main.c b/dlls/dxva2/main.c index 782f0dfa3d4..e1eb2128439 100644 --- a/dlls/dxva2/main.c +++ b/dlls/dxva2/main.c @@ -16,19 +16,144 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
+#define COBJMACROS + #include <stdarg.h> #include "windef.h" #include "winbase.h" #include "d3d9.h" -#include "dxva2api.h" #include "physicalmonitorenumerationapi.h" #include "lowlevelmonitorconfigurationapi.h" #include "highlevelmonitorconfigurationapi.h" +#include "initguid.h" +#include "dxva2api.h"
#include "wine/debug.h" +#include "wine/heap.h"
WINE_DEFAULT_DEBUG_CHANNEL(dxva2);
+struct device_manager +{ + IDirect3DDeviceManager9 IDirect3DDeviceManager9_iface; + LONG refcount; + + UINT token; +}; + +static struct device_manager *impl_from_IDirect3DDeviceManager9(IDirect3DDeviceManager9 *iface) +{ + return CONTAINING_RECORD(iface, struct device_manager, IDirect3DDeviceManager9_iface); +} + +static HRESULT WINAPI device_manager_QueryInterface(IDirect3DDeviceManager9 *iface, REFIID riid, void **obj) +{ + TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj); + + if (IsEqualIID(&IID_IDirect3DDeviceManager9, riid) || + IsEqualIID(&IID_IUnknown, riid)) + { + *obj = iface; + IDirect3DDeviceManager9_AddRef(iface); + return S_OK; + } + + WARN("Unsupported interface %s.\n", debugstr_guid(riid)); + *obj = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI device_manager_AddRef(IDirect3DDeviceManager9 *iface) +{ + struct device_manager *manager = impl_from_IDirect3DDeviceManager9(iface); + ULONG refcount = InterlockedIncrement(&manager->refcount); + + TRACE("%p, refcount %u.\n", iface, refcount); + + return refcount; +} + +static ULONG WINAPI device_manager_Release(IDirect3DDeviceManager9 *iface) +{ + struct device_manager *manager = impl_from_IDirect3DDeviceManager9(iface); + ULONG refcount = InterlockedDecrement(&manager->refcount); + + TRACE("%p, refcount %u.\n", iface, refcount); + + if (!refcount) + { + heap_free(manager); + } + + return refcount; +} + +static HRESULT WINAPI device_manager_ResetDevice(IDirect3DDeviceManager9 *iface, IDirect3DDevice9 *device, + UINT token) +{ + FIXME("%p, %p, %#x.\n", iface, device, token); + + return E_NOTIMPL; +} + +static HRESULT WINAPI device_manager_OpenDeviceHandle(IDirect3DDeviceManager9 *iface, HANDLE *hdevice) +{ + FIXME("%p, %p.\n", iface, hdevice); + + return E_NOTIMPL; +} + +static HRESULT WINAPI device_manager_CloseDeviceHandle(IDirect3DDeviceManager9 *iface, HANDLE hdevice) +{ + FIXME("%p, %p.\n", iface, hdevice); + + return E_NOTIMPL; +} + +static HRESULT WINAPI device_manager_TestDevice(IDirect3DDeviceManager9 *iface, HANDLE hdevice) +{ + FIXME("%p, %p.\n", iface, hdevice); + + return E_NOTIMPL; +} + +static HRESULT WINAPI device_manager_LockDevice(IDirect3DDeviceManager9 *iface, HANDLE hdevice, + IDirect3DDevice9 **device, BOOL block) +{ + FIXME("%p, %p, %p, %d.\n", iface, hdevice, device, block); + + return E_NOTIMPL; +} + +static HRESULT WINAPI device_manager_UnlockDevice(IDirect3DDeviceManager9 *iface, HANDLE hdevice, BOOL savestate) +{ + FIXME("%p, %p, %d.\n", iface, hdevice, savestate); + + return E_NOTIMPL; +} + +static HRESULT WINAPI device_manager_GetVideoService(IDirect3DDeviceManager9 *iface, HANDLE hdevice, REFIID riid, + void **obj) +{ + FIXME("%p, %p, %s, %p.\n", iface, hdevice, debugstr_guid(riid), obj); + + return E_NOTIMPL; +} + +static const IDirect3DDeviceManager9Vtbl device_manager_vtbl = +{ + device_manager_QueryInterface, + device_manager_AddRef, + device_manager_Release, + device_manager_ResetDevice, + device_manager_OpenDeviceHandle, + device_manager_CloseDeviceHandle, + device_manager_TestDevice, + device_manager_LockDevice, + device_manager_UnlockDevice, + device_manager_GetVideoService, +}; + BOOL WINAPI CapabilitiesRequestAndCapabilitiesReply( HMONITOR monitor, LPSTR buffer, DWORD length ) { FIXME("(%p, %p, %d): stub\n", monitor, buffer, length); @@ -37,11 +162,25 @@ BOOL WINAPI CapabilitiesRequestAndCapabilitiesReply( HMONITOR monitor, LPSTR buf return FALSE; }
-HRESULT WINAPI DXVA2CreateDirect3DDeviceManager9( UINT *resetToken, IDirect3DDeviceManager9 **dxvManager ) +HRESULT WINAPI DXVA2CreateDirect3DDeviceManager9(UINT *token, IDirect3DDeviceManager9 **manager) { - FIXME("(%p, %p): stub\n", resetToken, dxvManager); + struct device_manager *object;
- return E_NOTIMPL; + TRACE("%p, %p.\n", token, manager); + + *manager = NULL; + + if (!(object = heap_alloc_zero(sizeof(*object)))) + return E_OUTOFMEMORY; + + object->IDirect3DDeviceManager9_iface.lpVtbl = &device_manager_vtbl; + object->refcount = 1; + object->token = GetTickCount(); + + *token = object->token; + *manager = &object->IDirect3DDeviceManager9_iface; + + return S_OK; }
HRESULT WINAPI DXVA2CreateVideoService( IDirect3DDevice9 *device, REFIID riid, void **ppv ) diff --git a/dlls/dxva2/tests/Makefile.in b/dlls/dxva2/tests/Makefile.in new file mode 100644 index 00000000000..c86c5ab42fc --- /dev/null +++ b/dlls/dxva2/tests/Makefile.in @@ -0,0 +1,5 @@ +TESTDLL = dxva2.dll +IMPORTS = dxva2 user32 d3d9 + +C_SRCS = \ + dxva2.c diff --git a/dlls/dxva2/tests/dxva2.c b/dlls/dxva2/tests/dxva2.c new file mode 100644 index 00000000000..cbcad40ca59 --- /dev/null +++ b/dlls/dxva2/tests/dxva2.c @@ -0,0 +1,181 @@ +/* + * Copyright 2020 Nikolay Sivov + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS +#include "wine/test.h" +#include "d3d9.h" + +#include "initguid.h" +#include "dxva2api.h" + +static int get_refcount(IUnknown *object) +{ + IUnknown_AddRef(object); + return IUnknown_Release(object); +} + +static HWND create_window(void) +{ + RECT r = {0, 0, 640, 480}; + + AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW | WS_VISIBLE, FALSE); + + return CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE, + 0, 0, r.right - r.left, r.bottom - r.top, NULL, NULL, NULL, NULL); +} + +static IDirect3DDevice9 *create_device(IDirect3D9 *d3d9, HWND focus_window) +{ + D3DPRESENT_PARAMETERS present_parameters = {0}; + IDirect3DDevice9 *device = NULL; + + present_parameters.BackBufferWidth = 640; + present_parameters.BackBufferHeight = 480; + present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8; + present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD; + present_parameters.hDeviceWindow = focus_window; + present_parameters.Windowed = TRUE; + present_parameters.EnableAutoDepthStencil = TRUE; + present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8; + + IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window, + D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device); + + return device; +} + +static void test_device_manager(void) +{ + IDirectXVideoProcessorService *processor_service; + IDirect3DDevice9 *device, *device2; + IDirect3DDeviceManager9 *manager; + int refcount, refcount2; + HANDLE handle, handle1; + IDirect3D9 *d3d; + HWND window; + UINT token; + HRESULT hr; + + 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_OpenDeviceHandle(manager, &handle); +todo_wine + ok(hr == DXVA2_E_NOT_INITIALIZED, "Unexpected hr %#x.\n", hr); + + /* Invalid token. */ + hr = IDirect3DDeviceManager9_ResetDevice(manager, device, token + 1); +todo_wine + ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); + + hr = IDirect3DDeviceManager9_ResetDevice(manager, device, token); +todo_wine + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + refcount = get_refcount((IUnknown *)device); + + handle1 = NULL; + hr = IDirect3DDeviceManager9_OpenDeviceHandle(manager, &handle1); +todo_wine + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + refcount2 = get_refcount((IUnknown *)device); + ok(refcount2 == refcount, "Unexpected refcount %d.\n", refcount); + + handle = NULL; + hr = IDirect3DDeviceManager9_OpenDeviceHandle(manager, &handle); +todo_wine { + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(handle != handle1, "Unexpected handle.\n"); +} + hr = IDirect3DDeviceManager9_CloseDeviceHandle(manager, handle); +todo_wine + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + /* Already closed. */ + hr = IDirect3DDeviceManager9_CloseDeviceHandle(manager, handle); +todo_wine + ok(hr == E_HANDLE, "Unexpected hr %#x.\n", hr); + + handle = NULL; + hr = IDirect3DDeviceManager9_OpenDeviceHandle(manager, &handle); +todo_wine + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IDirect3DDeviceManager9_CloseDeviceHandle(manager, handle1); +todo_wine + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IDirect3DDeviceManager9_TestDevice(manager, handle1); +todo_wine + ok(hr == E_HANDLE, "Unexpected hr %#x.\n", hr); + + handle = NULL; + hr = IDirect3DDeviceManager9_OpenDeviceHandle(manager, &handle); +todo_wine + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + handle1 = NULL; + hr = IDirect3DDeviceManager9_OpenDeviceHandle(manager, &handle1); +todo_wine + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IDirect3DDeviceManager9_GetVideoService(manager, handle, &IID_IDirectXVideoProcessorService, + (void **)&processor_service); +todo_wine + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + if (SUCCEEDED(hr)) + IDirectXVideoProcessorService_Release(processor_service); + + device2 = create_device(d3d, window); + hr = IDirect3DDeviceManager9_ResetDevice(manager, device2, token); +todo_wine + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IDirect3DDeviceManager9_GetVideoService(manager, handle, &IID_IDirectXVideoProcessorService, + (void **)&processor_service); +todo_wine + ok(hr == DXVA2_E_NEW_VIDEO_DEVICE, "Unexpected hr %#x.\n", hr); + + hr = IDirect3DDeviceManager9_TestDevice(manager, handle); +todo_wine + ok(hr == DXVA2_E_NEW_VIDEO_DEVICE, "Unexpected hr %#x.\n", hr); + + IDirect3DDevice9_Release(device); + IDirect3DDevice9_Release(device2); + + IDirect3DDeviceManager9_Release(manager); + +done: + IDirect3D9_Release(d3d); + DestroyWindow(window); +} + +START_TEST(dxva2) +{ + test_device_manager(); +}
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dxva2/main.c | 158 +++++++++++++++++++++++++++++++++++++-- dlls/dxva2/tests/dxva2.c | 16 +--- 2 files changed, 151 insertions(+), 23 deletions(-)
diff --git a/dlls/dxva2/main.c b/dlls/dxva2/main.c index e1eb2128439..7e983a43dd6 100644 --- a/dlls/dxva2/main.c +++ b/dlls/dxva2/main.c @@ -33,14 +33,59 @@
WINE_DEFAULT_DEBUG_CHANNEL(dxva2);
+enum device_handle_flags +{ + HANDLE_FLAG_OPEN = 0x1, + HANDLE_FLAG_INVALID = 0x2, +}; + +struct device_handle +{ + unsigned int flags; +}; + struct device_manager { IDirect3DDeviceManager9 IDirect3DDeviceManager9_iface; LONG refcount;
+ IDirect3DDevice9 *device; UINT token; + + struct device_handle *handles; + size_t count; + size_t capacity; + + CRITICAL_SECTION cs; };
+static BOOL dxva_array_reserve(void **elements, size_t *capacity, size_t count, size_t size) +{ + size_t new_capacity, max_capacity; + void *new_elements; + + if (count <= *capacity) + return TRUE; + + max_capacity = ~(SIZE_T)0 / size; + if (count > max_capacity) + return FALSE; + + new_capacity = max(4, *capacity); + while (new_capacity < count && new_capacity <= max_capacity / 2) + new_capacity *= 2; + if (new_capacity < count) + new_capacity = max_capacity; + + if (!(new_elements = heap_realloc(*elements, new_capacity * size))) + return FALSE; + + *elements = new_elements; + *capacity = new_capacity; + + return TRUE; +} + static struct device_manager *impl_from_IDirect3DDeviceManager9(IDirect3DDeviceManager9 *iface) { return CONTAINING_RECORD(iface, struct device_manager, IDirect3DDeviceManager9_iface); @@ -82,6 +127,10 @@ static ULONG WINAPI device_manager_Release(IDirect3DDeviceManager9 *iface)
if (!refcount) { + if (manager->device) + IDirect3DDevice9_Release(manager->device); + DeleteCriticalSection(&manager->cs); + heap_free(manager->handles); heap_free(manager); }
@@ -91,30 +140,122 @@ static ULONG WINAPI device_manager_Release(IDirect3DDeviceManager9 *iface) static HRESULT WINAPI device_manager_ResetDevice(IDirect3DDeviceManager9 *iface, IDirect3DDevice9 *device, UINT token) { - FIXME("%p, %p, %#x.\n", iface, device, token); + struct device_manager *manager = impl_from_IDirect3DDeviceManager9(iface); + size_t i;
- return E_NOTIMPL; + TRACE("%p, %p, %#x.\n", iface, device, token); + + if (token != manager->token) + return E_INVALIDARG; + + EnterCriticalSection(&manager->cs); + if (manager->device) + { + for (i = 0; i < manager->count; ++i) + manager->handles[i].flags |= HANDLE_FLAG_INVALID; + IDirect3DDevice9_Release(manager->device); + } + manager->device = device; + IDirect3DDevice9_AddRef(manager->device); + LeaveCriticalSection(&manager->cs); + + return S_OK; }
static HRESULT WINAPI device_manager_OpenDeviceHandle(IDirect3DDeviceManager9 *iface, HANDLE *hdevice) { - FIXME("%p, %p.\n", iface, hdevice); + struct device_manager *manager = impl_from_IDirect3DDeviceManager9(iface); + HRESULT hr = S_OK; + size_t i;
- return E_NOTIMPL; + TRACE("%p, %p.\n", iface, hdevice); + + *hdevice = NULL; + + EnterCriticalSection(&manager->cs); + if (!manager->device) + hr = DXVA2_E_NOT_INITIALIZED; + else + { + for (i = 0; i < manager->count; ++i) + { + if (!(manager->handles[i].flags & HANDLE_FLAG_OPEN)) + { + manager->handles[i].flags |= HANDLE_FLAG_OPEN; + *hdevice = ULongToHandle(i + 1); + break; + } + } + + if (dxva_array_reserve((void **)&manager->handles, &manager->capacity, manager->count + 1, + sizeof(*manager->handles))) + { + *hdevice = ULongToHandle(manager->count + 1); + manager->handles[manager->count].flags |= HANDLE_FLAG_OPEN; + manager->count++; + } + else + hr = E_OUTOFMEMORY; + } + LeaveCriticalSection(&manager->cs); + + return hr; +} + +static HRESULT device_manager_get_handle_index(struct device_manager *manager, HANDLE hdevice, size_t *idx) +{ + if (hdevice > ULongToHandle(manager->count)) + return E_HANDLE; + *idx = (ULONG_PTR)hdevice - 1; + return S_OK; }
static HRESULT WINAPI device_manager_CloseDeviceHandle(IDirect3DDeviceManager9 *iface, HANDLE hdevice) { - FIXME("%p, %p.\n", iface, hdevice); + struct device_manager *manager = impl_from_IDirect3DDeviceManager9(iface); + HRESULT hr; + size_t idx;
- return E_NOTIMPL; + TRACE("%p, %p.\n", iface, hdevice); + + EnterCriticalSection(&manager->cs); + if (SUCCEEDED(hr = device_manager_get_handle_index(manager, hdevice, &idx))) + { + if (manager->handles[idx].flags & HANDLE_FLAG_OPEN) + { + manager->handles[idx].flags = 0; + if (idx == manager->count - 1) + manager->count--; + } + else + hr = E_HANDLE; + } + LeaveCriticalSection(&manager->cs); + + return hr; }
static HRESULT WINAPI device_manager_TestDevice(IDirect3DDeviceManager9 *iface, HANDLE hdevice) { - FIXME("%p, %p.\n", iface, hdevice); + struct device_manager *manager = impl_from_IDirect3DDeviceManager9(iface); + HRESULT hr; + size_t idx;
- return E_NOTIMPL; + TRACE("%p, %p.\n", iface, hdevice); + + EnterCriticalSection(&manager->cs); + if (SUCCEEDED(hr = device_manager_get_handle_index(manager, hdevice, &idx))) + { + unsigned int flags = manager->handles[idx].flags; + + if (flags & HANDLE_FLAG_INVALID) + hr = DXVA2_E_NEW_VIDEO_DEVICE; + else if (!(flags & HANDLE_FLAG_OPEN)) + hr = E_HANDLE; + } + LeaveCriticalSection(&manager->cs); + + return hr; }
static HRESULT WINAPI device_manager_LockDevice(IDirect3DDeviceManager9 *iface, HANDLE hdevice, @@ -176,6 +317,7 @@ HRESULT WINAPI DXVA2CreateDirect3DDeviceManager9(UINT *token, IDirect3DDeviceMan object->IDirect3DDeviceManager9_iface.lpVtbl = &device_manager_vtbl; object->refcount = 1; object->token = GetTickCount(); + InitializeCriticalSection(&object->cs);
*token = object->token; *manager = &object->IDirect3DDeviceManager9_iface; diff --git a/dlls/dxva2/tests/dxva2.c b/dlls/dxva2/tests/dxva2.c index cbcad40ca59..605a69dd5a5 100644 --- a/dlls/dxva2/tests/dxva2.c +++ b/dlls/dxva2/tests/dxva2.c @@ -84,23 +84,19 @@ static void test_device_manager(void) ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
hr = IDirect3DDeviceManager9_OpenDeviceHandle(manager, &handle); -todo_wine ok(hr == DXVA2_E_NOT_INITIALIZED, "Unexpected hr %#x.\n", hr);
/* Invalid token. */ hr = IDirect3DDeviceManager9_ResetDevice(manager, device, token + 1); -todo_wine ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
hr = IDirect3DDeviceManager9_ResetDevice(manager, device, token); -todo_wine ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
refcount = get_refcount((IUnknown *)device);
handle1 = NULL; hr = IDirect3DDeviceManager9_OpenDeviceHandle(manager, &handle1); -todo_wine ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
refcount2 = get_refcount((IUnknown *)device); @@ -108,40 +104,32 @@ todo_wine
handle = NULL; hr = IDirect3DDeviceManager9_OpenDeviceHandle(manager, &handle); -todo_wine { ok(hr == S_OK, "Unexpected hr %#x.\n", hr); ok(handle != handle1, "Unexpected handle.\n"); -} + hr = IDirect3DDeviceManager9_CloseDeviceHandle(manager, handle); -todo_wine ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
/* Already closed. */ hr = IDirect3DDeviceManager9_CloseDeviceHandle(manager, handle); -todo_wine ok(hr == E_HANDLE, "Unexpected hr %#x.\n", hr);
handle = NULL; hr = IDirect3DDeviceManager9_OpenDeviceHandle(manager, &handle); -todo_wine ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
hr = IDirect3DDeviceManager9_CloseDeviceHandle(manager, handle1); -todo_wine ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
hr = IDirect3DDeviceManager9_TestDevice(manager, handle1); -todo_wine ok(hr == E_HANDLE, "Unexpected hr %#x.\n", hr);
handle = NULL; hr = IDirect3DDeviceManager9_OpenDeviceHandle(manager, &handle); -todo_wine ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
handle1 = NULL; hr = IDirect3DDeviceManager9_OpenDeviceHandle(manager, &handle1); -todo_wine ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
hr = IDirect3DDeviceManager9_GetVideoService(manager, handle, &IID_IDirectXVideoProcessorService, @@ -153,7 +141,6 @@ todo_wine
device2 = create_device(d3d, window); hr = IDirect3DDeviceManager9_ResetDevice(manager, device2, token); -todo_wine ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
hr = IDirect3DDeviceManager9_GetVideoService(manager, handle, &IID_IDirectXVideoProcessorService, @@ -162,7 +149,6 @@ todo_wine ok(hr == DXVA2_E_NEW_VIDEO_DEVICE, "Unexpected hr %#x.\n", hr);
hr = IDirect3DDeviceManager9_TestDevice(manager, handle); -todo_wine ok(hr == DXVA2_E_NEW_VIDEO_DEVICE, "Unexpected hr %#x.\n", hr);
IDirect3DDevice9_Release(device);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dxva2/main.c | 141 ++++++++++++++++++++++++++++++++++++++- dlls/dxva2/tests/dxva2.c | 5 +- 2 files changed, 140 insertions(+), 6 deletions(-)
diff --git a/dlls/dxva2/main.c b/dlls/dxva2/main.c index 7e983a43dd6..7ba8d9806b1 100644 --- a/dlls/dxva2/main.c +++ b/dlls/dxva2/main.c @@ -47,6 +47,7 @@ struct device_handle struct device_manager { IDirect3DDeviceManager9 IDirect3DDeviceManager9_iface; + IDirectXVideoProcessorService IDirectXVideoProcessorService_iface; LONG refcount;
IDirect3DDevice9 *device; @@ -91,6 +92,115 @@ static struct device_manager *impl_from_IDirect3DDeviceManager9(IDirect3DDeviceM return CONTAINING_RECORD(iface, struct device_manager, IDirect3DDeviceManager9_iface); }
+static struct device_manager *impl_from_IDirectXVideoProcessorService(IDirectXVideoProcessorService *iface) +{ + return CONTAINING_RECORD(iface, struct device_manager, IDirectXVideoProcessorService_iface); +} + +static HRESULT WINAPI device_manager_processor_service_QueryInterface(IDirectXVideoProcessorService *iface, + REFIID riid, void **obj) +{ + if (IsEqualIID(riid, &IID_IDirectXVideoProcessorService) || + IsEqualIID(riid, &IID_IUnknown)) + { + *obj = iface; + IDirectXVideoProcessorService_AddRef(iface); + return S_OK; + } + + WARN("Unsupported interface %s.\n", debugstr_guid(riid)); + *obj = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI device_manager_processor_service_AddRef(IDirectXVideoProcessorService *iface) +{ + struct device_manager *manager = impl_from_IDirectXVideoProcessorService(iface); + return IDirect3DDeviceManager9_AddRef(&manager->IDirect3DDeviceManager9_iface); +} + +static ULONG WINAPI device_manager_processor_service_Release(IDirectXVideoProcessorService *iface) +{ + struct device_manager *manager = impl_from_IDirectXVideoProcessorService(iface); + return IDirect3DDeviceManager9_Release(&manager->IDirect3DDeviceManager9_iface); +} + +static HRESULT WINAPI device_manager_processor_service_CreateSurface(IDirectXVideoProcessorService *iface, + UINT width, UINT height, UINT backbuffers, D3DFORMAT format, D3DPOOL pool, DWORD usage, DWORD dxvaType, + IDirect3DSurface9 **surface, HANDLE *shared_handle) +{ + FIXME("%p, %u, %u, %u, %u, %u, %u, %u, %p, %p.\n", iface, width, height, backbuffers, format, pool, usage, dxvaType, + surface, shared_handle); + + return E_NOTIMPL; +} + +static HRESULT WINAPI device_manager_processor_service_RegisterVideoProcessorSoftwareDevice( + IDirectXVideoProcessorService *iface, void *callbacks) +{ + FIXME("%p, %p.\n", iface, callbacks); + + return E_NOTIMPL; +} + +static HRESULT WINAPI device_manager_processor_service_GetVideoProcessorDeviceGuids( + IDirectXVideoProcessorService *iface, const DXVA2_VideoDesc *video_desc, UINT *count, GUID **guids) +{ + FIXME("%p, %p, %p, %p.\n", iface, video_desc, count, guids); + + return E_NOTIMPL; +} + +static HRESULT WINAPI device_manager_processor_service_GetVideoProcessorRenderTargets( + IDirectXVideoProcessorService *iface, REFGUID deviceguid, const DXVA2_VideoDesc *video_desc, UINT *count, + D3DFORMAT **formats) +{ + FIXME("%p, %s, %p, %p, %p.\n", iface, debugstr_guid(deviceguid), video_desc, count, formats); + + return E_NOTIMPL; +} + +static HRESULT WINAPI device_manager_processor_service_GetVideoProcessorSubStreamFormats( + IDirectXVideoProcessorService *iface, REFGUID deviceguid, const DXVA2_VideoDesc *video_desc, + D3DFORMAT rt_format, UINT *count, D3DFORMAT **formats) +{ + FIXME("%p, %s, %p, %u, %p, %p.\n", iface, debugstr_guid(deviceguid), video_desc, rt_format, count, formats); + + return E_NOTIMPL; +} + +static HRESULT WINAPI device_manager_processor_service_GetVideoProcessorCaps( + IDirectXVideoProcessorService *iface, REFGUID deviceguid, const DXVA2_VideoDesc *video_desc, + D3DFORMAT rt_format, DXVA2_VideoProcessorCaps *caps) +{ + FIXME("%p, %s, %p, %u, %p.\n", iface, debugstr_guid(deviceguid), video_desc, rt_format, caps); + + return E_NOTIMPL; +} + +static HRESULT WINAPI device_manager_processor_service_GetProcAmpRange( + IDirectXVideoProcessorService *iface, REFGUID deviceguid, const DXVA2_VideoDesc *video_desc, + D3DFORMAT rt_format, UINT ProcAmpCap, DXVA2_ValueRange *range) +{ + FIXME("%p, %s, %p, %u, %u, %p.\n", iface, debugstr_guid(deviceguid), video_desc, rt_format, ProcAmpCap, range); + + return E_NOTIMPL; +} + +static const IDirectXVideoProcessorServiceVtbl device_manager_processor_service_vtbl = +{ + device_manager_processor_service_QueryInterface, + device_manager_processor_service_AddRef, + device_manager_processor_service_Release, + device_manager_processor_service_CreateSurface, + device_manager_processor_service_RegisterVideoProcessorSoftwareDevice, + device_manager_processor_service_GetVideoProcessorDeviceGuids, + device_manager_processor_service_GetVideoProcessorRenderTargets, + device_manager_processor_service_GetVideoProcessorSubStreamFormats, + device_manager_processor_service_GetVideoProcessorCaps, + device_manager_processor_service_GetProcAmpRange, +}; + static HRESULT WINAPI device_manager_QueryInterface(IDirect3DDeviceManager9 *iface, REFIID riid, void **obj) { TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj); @@ -276,9 +386,35 @@ static HRESULT WINAPI device_manager_UnlockDevice(IDirect3DDeviceManager9 *iface static HRESULT WINAPI device_manager_GetVideoService(IDirect3DDeviceManager9 *iface, HANDLE hdevice, REFIID riid, void **obj) { - FIXME("%p, %p, %s, %p.\n", iface, hdevice, debugstr_guid(riid), obj); + struct device_manager *manager = impl_from_IDirect3DDeviceManager9(iface); + HRESULT hr; + size_t idx;
- return E_NOTIMPL; + TRACE("%p, %p, %s, %p.\n", iface, hdevice, debugstr_guid(riid), obj); + + EnterCriticalSection(&manager->cs); + if (SUCCEEDED(hr = device_manager_get_handle_index(manager, hdevice, &idx))) + { + unsigned int flags = manager->handles[idx].flags; + + if (flags & HANDLE_FLAG_INVALID) + hr = DXVA2_E_NEW_VIDEO_DEVICE; + else if (!(flags & HANDLE_FLAG_OPEN)) + hr = E_HANDLE; + else if (IsEqualIID(riid, &IID_IDirectXVideoProcessorService)) + { + *obj = &manager->IDirectXVideoProcessorService_iface; + IUnknown_AddRef((IUnknown *)*obj); + } + else + { + WARN("Unsupported service %s.\n", debugstr_guid(riid)); + hr = E_UNEXPECTED; + } + } + LeaveCriticalSection(&manager->cs); + + return hr; }
static const IDirect3DDeviceManager9Vtbl device_manager_vtbl = @@ -315,6 +451,7 @@ HRESULT WINAPI DXVA2CreateDirect3DDeviceManager9(UINT *token, IDirect3DDeviceMan return E_OUTOFMEMORY;
object->IDirect3DDeviceManager9_iface.lpVtbl = &device_manager_vtbl; + object->IDirectXVideoProcessorService_iface.lpVtbl = &device_manager_processor_service_vtbl; object->refcount = 1; object->token = GetTickCount(); InitializeCriticalSection(&object->cs); diff --git a/dlls/dxva2/tests/dxva2.c b/dlls/dxva2/tests/dxva2.c index 605a69dd5a5..65771fb5874 100644 --- a/dlls/dxva2/tests/dxva2.c +++ b/dlls/dxva2/tests/dxva2.c @@ -134,10 +134,8 @@ static void test_device_manager(void)
hr = IDirect3DDeviceManager9_GetVideoService(manager, handle, &IID_IDirectXVideoProcessorService, (void **)&processor_service); -todo_wine ok(hr == S_OK, "Unexpected hr %#x.\n", hr); - if (SUCCEEDED(hr)) - IDirectXVideoProcessorService_Release(processor_service); + IDirectXVideoProcessorService_Release(processor_service);
device2 = create_device(d3d, window); hr = IDirect3DDeviceManager9_ResetDevice(manager, device2, token); @@ -145,7 +143,6 @@ todo_wine
hr = IDirect3DDeviceManager9_GetVideoService(manager, handle, &IID_IDirectXVideoProcessorService, (void **)&processor_service); -todo_wine ok(hr == DXVA2_E_NEW_VIDEO_DEVICE, "Unexpected hr %#x.\n", hr);
hr = IDirect3DDeviceManager9_TestDevice(manager, handle);