From: Rémi Bernon rbernon@codeweavers.com
--- include/ddk/d3dkmthk.h | 2 ++ include/ntgdi.h | 1 + 2 files changed, 3 insertions(+)
diff --git a/include/ddk/d3dkmthk.h b/include/ddk/d3dkmthk.h index c067f4773d4..de12ef4a527 100644 --- a/include/ddk/d3dkmthk.h +++ b/include/ddk/d3dkmthk.h @@ -1286,6 +1286,7 @@ extern "C" { #endif /* __cplusplus */
+NTSTATUS WINAPI D3DKMTCheckOcclusion( const D3DKMT_CHECKOCCLUSION *desc ); NTSTATUS WINAPI D3DKMTCheckVidPnExclusiveOwnership(const D3DKMT_CHECKVIDPNEXCLUSIVEOWNERSHIP *desc); NTSTATUS WINAPI D3DKMTCloseAdapter(const D3DKMT_CLOSEADAPTER *desc); NTSTATUS WINAPI D3DKMTCreateAllocation( D3DKMT_CREATEALLOCATION *params ); @@ -1304,6 +1305,7 @@ NTSTATUS WINAPI D3DKMTDestroyKeyedMutex( const D3DKMT_DESTROYKEYEDMUTEX *params NTSTATUS WINAPI D3DKMTDestroySynchronizationObject( const D3DKMT_DESTROYSYNCHRONIZATIONOBJECT *params ); NTSTATUS WINAPI D3DKMTEnumAdapters2(D3DKMT_ENUMADAPTERS2 *desc); NTSTATUS WINAPI D3DKMTEscape( const D3DKMT_ESCAPE *desc ); +NTSTATUS WINAPI D3DKMTOpenAdapterFromDeviceName( D3DKMT_OPENADAPTERFROMDEVICENAME *desc ); NTSTATUS WINAPI D3DKMTOpenAdapterFromGdiDisplayName(D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME *desc); NTSTATUS WINAPI D3DKMTOpenAdapterFromHdc( D3DKMT_OPENADAPTERFROMHDC *desc ); NTSTATUS WINAPI D3DKMTOpenAdapterFromLuid( D3DKMT_OPENADAPTERFROMLUID * desc ); diff --git a/include/ntgdi.h b/include/ntgdi.h index 5fdd666b208..81fa1eff14a 100644 --- a/include/ntgdi.h +++ b/include/ntgdi.h @@ -514,6 +514,7 @@ W32KAPI BOOL WINAPI NtGdiUnrealizeObject( HGDIOBJ obj ); W32KAPI BOOL WINAPI NtGdiUpdateColors( HDC hdc ); W32KAPI BOOL WINAPI NtGdiWidenPath( HDC hdc );
+W32KAPI NTSTATUS WINAPI NtGdiDdDDICheckOcclusion( const D3DKMT_CHECKOCCLUSION *desc ); W32KAPI NTSTATUS WINAPI NtGdiDdDDICheckVidPnExclusiveOwnership( const D3DKMT_CHECKVIDPNEXCLUSIVEOWNERSHIP *desc ); W32KAPI NTSTATUS WINAPI NtGdiDdDDICloseAdapter( const D3DKMT_CLOSEADAPTER *desc ); W32KAPI NTSTATUS WINAPI NtGdiDdDDICreateAllocation( D3DKMT_CREATEALLOCATION *params );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/gdi32/gdi32.spec | 1 + dlls/win32u/d3dkmt.c | 6 ++++++ dlls/win32u/main.c | 5 +++++ dlls/win32u/win32syscalls.h | 5 ++--- dlls/win32u/win32u.spec | 2 +- dlls/wow64win/gdi.c | 10 ++++++++++ 6 files changed, 25 insertions(+), 4 deletions(-)
diff --git a/dlls/gdi32/gdi32.spec b/dlls/gdi32/gdi32.spec index db6407135c3..28dab037a74 100644 --- a/dlls/gdi32/gdi32.spec +++ b/dlls/gdi32/gdi32.spec @@ -99,6 +99,7 @@ # @ stub CreateScaledCompatibleBitmap # @ stub CreateSessionMappedDIBSection @ stdcall CreateSolidBrush(long) +@ stdcall D3DKMTCheckOcclusion(ptr) win32u.NtGdiDdDDICheckOcclusion @ stdcall D3DKMTCheckVidPnExclusiveOwnership(ptr) win32u.NtGdiDdDDICheckVidPnExclusiveOwnership @ stdcall D3DKMTCloseAdapter(ptr) win32u.NtGdiDdDDICloseAdapter @ stdcall D3DKMTCreateAllocation(ptr) win32u.NtGdiDdDDICreateAllocation diff --git a/dlls/win32u/d3dkmt.c b/dlls/win32u/d3dkmt.c index 7fd4a4950da..1016b02ad5f 100644 --- a/dlls/win32u/d3dkmt.c +++ b/dlls/win32u/d3dkmt.c @@ -540,6 +540,12 @@ NTSTATUS WINAPI NtGdiDdDDISetVidPnSourceOwner( const D3DKMT_SETVIDPNSOURCEOWNER return STATUS_SUCCESS; }
+NTSTATUS WINAPI NtGdiDdDDICheckOcclusion( const D3DKMT_CHECKOCCLUSION *desc ) +{ + FIXME( "desc %p stub!\n", desc ); + return STATUS_PROCEDURE_NOT_FOUND; +} + /****************************************************************************** * NtGdiDdDDICheckVidPnExclusiveOwnership (win32u.@) */ diff --git a/dlls/win32u/main.c b/dlls/win32u/main.c index 5e37770a7e7..97fba697718 100644 --- a/dlls/win32u/main.c +++ b/dlls/win32u/main.c @@ -211,6 +211,11 @@ HBRUSH SYSCALL_API NtGdiCreateSolidBrush( COLORREF color, HBRUSH brush ) SYSCALL_FUNC( NtGdiCreateSolidBrush ); }
+NTSTATUS SYSCALL_API NtGdiDdDDICheckOcclusion( const D3DKMT_CHECKOD3DKMT_CHECKOCCLUSION *desc ) +{ + SYSCALL_FUNC( NtGdiDdDDICheckOcclusion ); +} + NTSTATUS SYSCALL_API NtGdiDdDDICheckVidPnExclusiveOwnership( const D3DKMT_CHECKVIDPNEXCLUSIVEOWNERSHIP *desc ) { SYSCALL_FUNC( NtGdiDdDDICheckVidPnExclusiveOwnership ); diff --git a/dlls/win32u/win32syscalls.h b/dlls/win32u/win32syscalls.h index aa3777c8cc9..6fe9b47087c 100644 --- a/dlls/win32u/win32syscalls.h +++ b/dlls/win32u/win32syscalls.h @@ -213,7 +213,7 @@ SYSCALL_ENTRY( 0x10d1, NtGdiDdDDICheckMultiPlaneOverlaySupport, 0 ) \ SYSCALL_ENTRY( 0x10d2, NtGdiDdDDICheckMultiPlaneOverlaySupport2, 0 ) \ SYSCALL_ENTRY( 0x10d3, NtGdiDdDDICheckMultiPlaneOverlaySupport3, 0 ) \ - SYSCALL_ENTRY( 0x10d4, NtGdiDdDDICheckOcclusion, 0 ) \ + SYSCALL_ENTRY( 0x10d4, NtGdiDdDDICheckOcclusion, 4 ) \ SYSCALL_ENTRY( 0x10d5, NtGdiDdDDICheckSharedResourceAccess, 0 ) \ SYSCALL_ENTRY( 0x10d6, NtGdiDdDDICheckVidPnExclusiveOwnership, 4 ) \ SYSCALL_ENTRY( 0x10d7, NtGdiDdDDICloseAdapter, 4 ) \ @@ -1755,7 +1755,7 @@ SYSCALL_ENTRY( 0x10d1, NtGdiDdDDICheckMultiPlaneOverlaySupport, 0 ) \ SYSCALL_ENTRY( 0x10d2, NtGdiDdDDICheckMultiPlaneOverlaySupport2, 0 ) \ SYSCALL_ENTRY( 0x10d3, NtGdiDdDDICheckMultiPlaneOverlaySupport3, 0 ) \ - SYSCALL_ENTRY( 0x10d4, NtGdiDdDDICheckOcclusion, 0 ) \ + SYSCALL_ENTRY( 0x10d4, NtGdiDdDDICheckOcclusion, 8 ) \ SYSCALL_ENTRY( 0x10d5, NtGdiDdDDICheckSharedResourceAccess, 0 ) \ SYSCALL_ENTRY( 0x10d6, NtGdiDdDDICheckVidPnExclusiveOwnership, 8 ) \ SYSCALL_ENTRY( 0x10d7, NtGdiDdDDICloseAdapter, 8 ) \ @@ -3269,7 +3269,6 @@ SYSCALL_STUB( NtGdiDdDDICheckMultiPlaneOverlaySupport ) \ SYSCALL_STUB( NtGdiDdDDICheckMultiPlaneOverlaySupport2 ) \ SYSCALL_STUB( NtGdiDdDDICheckMultiPlaneOverlaySupport3 ) \ - SYSCALL_STUB( NtGdiDdDDICheckOcclusion ) \ SYSCALL_STUB( NtGdiDdDDICheckSharedResourceAccess ) \ SYSCALL_STUB( NtGdiDdDDIConfigureSharedResource ) \ SYSCALL_STUB( NtGdiDdDDICreateBundleObject ) \ diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec index c6917ed89cb..adc5f2f19b5 100644 --- a/dlls/win32u/win32u.spec +++ b/dlls/win32u/win32u.spec @@ -211,7 +211,7 @@ @ stub -syscall NtGdiDdDDICheckMultiPlaneOverlaySupport @ stub -syscall NtGdiDdDDICheckMultiPlaneOverlaySupport2 @ stub -syscall NtGdiDdDDICheckMultiPlaneOverlaySupport3 -@ stub -syscall NtGdiDdDDICheckOcclusion +@ stdcall -syscall NtGdiDdDDICheckOcclusion(ptr) @ stub -syscall NtGdiDdDDICheckSharedResourceAccess @ stdcall -syscall NtGdiDdDDICheckVidPnExclusiveOwnership(ptr) @ stdcall -syscall NtGdiDdDDICloseAdapter(ptr) diff --git a/dlls/wow64win/gdi.c b/dlls/wow64win/gdi.c index 62f77927ae0..d8b4fd89249 100644 --- a/dlls/wow64win/gdi.c +++ b/dlls/wow64win/gdi.c @@ -399,6 +399,16 @@ NTSTATUS WINAPI wow64_NtGdiCreateSolidBrush( UINT *args ) return HandleToUlong( NtGdiCreateSolidBrush( color, brush )); }
+NTSTATUS WINAPI wow64_NtGdiDdDDICheckOcclusion( UINT *args ) +{ + struct + { + HWND hWnd; + } *desc32 = get_ptr( &args ); + D3DKMT_CHECKOCCLUSION desc = {.hWnd = desc32->hWnd}; + return NtGdiDdDDICheckOcclusion( &desc ); +} + NTSTATUS WINAPI wow64_NtGdiDdDDICheckVidPnExclusiveOwnership( UINT *args ) { const D3DKMT_CHECKVIDPNEXCLUSIVEOWNERSHIP *desc = get_ptr( &args );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/gdi32/tests/Makefile.in | 1 - dlls/gdi32/tests/driver.c | 1255 --------------------------------- dlls/win32u/tests/Makefile.in | 3 +- dlls/win32u/tests/d3dkmt.c | 1109 +++++++++++++++++++++++++++++ 4 files changed, 1111 insertions(+), 1257 deletions(-) delete mode 100644 dlls/gdi32/tests/driver.c create mode 100644 dlls/win32u/tests/d3dkmt.c
diff --git a/dlls/gdi32/tests/Makefile.in b/dlls/gdi32/tests/Makefile.in index 39eab4e869a..3ea3cdce957 100644 --- a/dlls/gdi32/tests/Makefile.in +++ b/dlls/gdi32/tests/Makefile.in @@ -7,7 +7,6 @@ SOURCES = \ clipping.c \ dc.c \ dib.c \ - driver.c \ font.c \ gdiobj.c \ generated.c \ diff --git a/dlls/gdi32/tests/driver.c b/dlls/gdi32/tests/driver.c deleted file mode 100644 index d5380962129..00000000000 --- a/dlls/gdi32/tests/driver.c +++ /dev/null @@ -1,1255 +0,0 @@ -/* - * Unit test suite for kernel mode graphics driver - * - * Copyright 2019 Zhiyi Zhang - * - * 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 - */ - -#include <stdarg.h> - -#include "ntstatus.h" -#define WIN32_NO_STATUS -#include "windef.h" -#include "winbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "winternl.h" -#include "dwmapi.h" -#include "ddk/d3dkmthk.h" -#include "initguid.h" -#include "setupapi.h" -#include "ntddvdeo.h" -#include "devpkey.h" -#include "cfgmgr32.h" - -#include "wine/test.h" - -static const WCHAR display1W[] = L"\\.\DISPLAY1"; - -DEFINE_DEVPROPKEY(DEVPROPKEY_GPU_LUID, 0x60b193cb, 0x5276, 0x4d0f, 0x96, 0xfc, 0xf1, 0x73, 0xab, 0xad, 0x3e, 0xc6, 2); - -static NTSTATUS (WINAPI *pD3DKMTCheckOcclusion)(const D3DKMT_CHECKOCCLUSION *); -static NTSTATUS (WINAPI *pD3DKMTCheckVidPnExclusiveOwnership)(const D3DKMT_CHECKVIDPNEXCLUSIVEOWNERSHIP *); -static NTSTATUS (WINAPI *pD3DKMTCloseAdapter)(const D3DKMT_CLOSEADAPTER *); -static NTSTATUS (WINAPI *pD3DKMTCreateDevice)(D3DKMT_CREATEDEVICE *); -static NTSTATUS (WINAPI *pD3DKMTDestroyDevice)(const D3DKMT_DESTROYDEVICE *); -static NTSTATUS (WINAPI *pD3DKMTEnumAdapters2)(D3DKMT_ENUMADAPTERS2 *); -static NTSTATUS (WINAPI *pD3DKMTOpenAdapterFromDeviceName)(D3DKMT_OPENADAPTERFROMDEVICENAME *); -static NTSTATUS (WINAPI *pD3DKMTOpenAdapterFromGdiDisplayName)(D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME *); -static NTSTATUS (WINAPI *pD3DKMTOpenAdapterFromHdc)(D3DKMT_OPENADAPTERFROMHDC *); -static NTSTATUS (WINAPI *pD3DKMTSetVidPnSourceOwner)(const D3DKMT_SETVIDPNSOURCEOWNER *); -static NTSTATUS (WINAPI *pD3DKMTQueryAdapterInfo)(D3DKMT_QUERYADAPTERINFO *); -static NTSTATUS (WINAPI *pD3DKMTQueryVideoMemoryInfo)(D3DKMT_QUERYVIDEOMEMORYINFO *); -static HRESULT (WINAPI *pDwmEnableComposition)(UINT); - -static BOOL get_primary_adapter_name(WCHAR *name) -{ - DISPLAY_DEVICEW dd; - DWORD adapter_idx; - - dd.cb = sizeof(dd); - for (adapter_idx = 0; EnumDisplayDevicesW(NULL, adapter_idx, &dd, 0); ++adapter_idx) - { - if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) - { - lstrcpyW(name, dd.DeviceName); - return TRUE; - } - } - - return FALSE; -} - -static void test_D3DKMTOpenAdapterFromGdiDisplayName(void) -{ - D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME open_adapter_gdi_desc; - D3DKMT_CLOSEADAPTER close_adapter_desc; - DISPLAY_DEVICEW display_device = {sizeof(display_device)}; - NTSTATUS status; - DWORD i; - - lstrcpyW(open_adapter_gdi_desc.DeviceName, display1W); - if (!pD3DKMTOpenAdapterFromGdiDisplayName - || pD3DKMTOpenAdapterFromGdiDisplayName(&open_adapter_gdi_desc) == STATUS_PROCEDURE_NOT_FOUND) - { - win_skip("D3DKMTOpenAdapterFromGdiDisplayName() is unavailable.\n"); - return; - } - - close_adapter_desc.hAdapter = open_adapter_gdi_desc.hAdapter; - status = pD3DKMTCloseAdapter(&close_adapter_desc); - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - - /* Invalid parameters */ - status = pD3DKMTOpenAdapterFromGdiDisplayName(NULL); - ok(status == STATUS_UNSUCCESSFUL, "Got unexpected return code %#lx.\n", status); - - memset(&open_adapter_gdi_desc, 0, sizeof(open_adapter_gdi_desc)); - status = pD3DKMTOpenAdapterFromGdiDisplayName(&open_adapter_gdi_desc); - ok(status == STATUS_UNSUCCESSFUL, "Got unexpected return code %#lx.\n", status); - - /* Open adapter */ - for (i = 0; EnumDisplayDevicesW(NULL, i, &display_device, 0); ++i) - { - lstrcpyW(open_adapter_gdi_desc.DeviceName, display_device.DeviceName); - status = pD3DKMTOpenAdapterFromGdiDisplayName(&open_adapter_gdi_desc); - if (display_device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - else - { - ok(status == STATUS_UNSUCCESSFUL, "Got unexpected return code %#lx.\n", status); - continue; - } - - ok(open_adapter_gdi_desc.hAdapter, "Expect not null.\n"); - ok(open_adapter_gdi_desc.AdapterLuid.LowPart || open_adapter_gdi_desc.AdapterLuid.HighPart, - "Expect LUID not zero.\n"); - - close_adapter_desc.hAdapter = open_adapter_gdi_desc.hAdapter; - status = pD3DKMTCloseAdapter(&close_adapter_desc); - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - } -} - -static void test_D3DKMTOpenAdapterFromHdc(void) -{ - DISPLAY_DEVICEW display_device = {sizeof(display_device)}; - D3DKMT_OPENADAPTERFROMHDC open_adapter_hdc_desc; - D3DKMT_CLOSEADAPTER close_adapter_desc; - INT adapter_count = 0; - NTSTATUS status; - HDC hdc; - DWORD i; - - if (!pD3DKMTOpenAdapterFromHdc) - { - win_skip("D3DKMTOpenAdapterFromHdc() is missing.\n"); - return; - } - - /* Invalid parameters */ - /* Passing a NULL pointer crashes on Windows 10 >= 2004 */ - if (0) status = pD3DKMTOpenAdapterFromHdc(NULL); - - memset(&open_adapter_hdc_desc, 0, sizeof(open_adapter_hdc_desc)); - status = pD3DKMTOpenAdapterFromHdc(&open_adapter_hdc_desc); - if (status == STATUS_PROCEDURE_NOT_FOUND) - { - win_skip("D3DKMTOpenAdapterFromHdc() is not supported.\n"); - return; - } - todo_wine ok(status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#lx.\n", status); - - /* Open adapter */ - for (i = 0; EnumDisplayDevicesW(NULL, i, &display_device, 0); ++i) - { - if (!(display_device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)) - continue; - - adapter_count++; - - hdc = CreateDCW(0, display_device.DeviceName, 0, NULL); - open_adapter_hdc_desc.hDc = hdc; - status = pD3DKMTOpenAdapterFromHdc(&open_adapter_hdc_desc); - todo_wine ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - todo_wine ok(open_adapter_hdc_desc.hAdapter, "Expect not null.\n"); - DeleteDC(hdc); - - if (status == STATUS_SUCCESS) - { - close_adapter_desc.hAdapter = open_adapter_hdc_desc.hAdapter; - status = pD3DKMTCloseAdapter(&close_adapter_desc); - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - } - } - - /* HDC covering more than two adapters is invalid for D3DKMTOpenAdapterFromHdc */ - hdc = GetDC(0); - open_adapter_hdc_desc.hDc = hdc; - status = pD3DKMTOpenAdapterFromHdc(&open_adapter_hdc_desc); - ReleaseDC(0, hdc); - todo_wine ok(status == (adapter_count > 1 ? STATUS_INVALID_PARAMETER : STATUS_SUCCESS), - "Got unexpected return code %#lx.\n", status); - if (status == STATUS_SUCCESS) - { - close_adapter_desc.hAdapter = open_adapter_hdc_desc.hAdapter; - status = pD3DKMTCloseAdapter(&close_adapter_desc); - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - } -} - -static void test_D3DKMTEnumAdapters2(void) -{ - D3DKMT_ENUMADAPTERS2 enum_adapters_2_desc = {0}; - D3DKMT_CLOSEADAPTER close_adapter_desc; - NTSTATUS status; - UINT i; - - if (!pD3DKMTEnumAdapters2 || pD3DKMTEnumAdapters2(&enum_adapters_2_desc) == STATUS_PROCEDURE_NOT_FOUND) - { - win_skip("D3DKMTEnumAdapters2() is unavailable.\n"); - return; - } - - /* Invalid parameters */ - status = pD3DKMTEnumAdapters2(NULL); - ok(status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#lx.\n", status); - - /* Query the array to allocate */ - memset(&enum_adapters_2_desc, 0, sizeof(enum_adapters_2_desc)); - status = pD3DKMTEnumAdapters2(&enum_adapters_2_desc); - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - ok(enum_adapters_2_desc.NumAdapters == 32 /* win10 and older */ || enum_adapters_2_desc.NumAdapters == 34 /* win11 */, - "Got unexpected value %lu.\n", enum_adapters_2_desc.NumAdapters); - - /* Allocate the array */ - enum_adapters_2_desc.pAdapters = calloc(enum_adapters_2_desc.NumAdapters, sizeof(D3DKMT_ADAPTERINFO)); - ok(!!enum_adapters_2_desc.pAdapters, "Expect not null.\n"); - - /* Enumerate adapters */ - status = pD3DKMTEnumAdapters2(&enum_adapters_2_desc); - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - ok(enum_adapters_2_desc.NumAdapters, "Expect not zero.\n"); - - for (i = 0; i < enum_adapters_2_desc.NumAdapters; ++i) - { - ok(enum_adapters_2_desc.pAdapters[i].hAdapter, "Expect not null.\n"); - ok(enum_adapters_2_desc.pAdapters[i].AdapterLuid.LowPart || enum_adapters_2_desc.pAdapters[i].AdapterLuid.HighPart, - "Expect LUID not zero.\n"); - - close_adapter_desc.hAdapter = enum_adapters_2_desc.pAdapters[i].hAdapter; - status = pD3DKMTCloseAdapter(&close_adapter_desc); - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - } - - /* Check for insufficient buffer */ - enum_adapters_2_desc.NumAdapters = 0; - status = pD3DKMTEnumAdapters2(&enum_adapters_2_desc); - ok(status == STATUS_BUFFER_TOO_SMALL, "Got unexpected return code %#lx.\n", status); - - free(enum_adapters_2_desc.pAdapters); -} - -static void test_D3DKMTCloseAdapter(void) -{ - D3DKMT_CLOSEADAPTER close_adapter_desc; - NTSTATUS status; - - if (!pD3DKMTCloseAdapter || pD3DKMTCloseAdapter(NULL) == STATUS_PROCEDURE_NOT_FOUND) - { - win_skip("D3DKMTCloseAdapter() is unavailable.\n"); - return; - } - - /* Invalid parameters */ - status = pD3DKMTCloseAdapter(NULL); - ok(status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#lx.\n", status); - - memset(&close_adapter_desc, 0, sizeof(close_adapter_desc)); - status = pD3DKMTCloseAdapter(&close_adapter_desc); - ok(status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#lx.\n", status); -} - -static void test_D3DKMTCreateDevice(void) -{ - D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME open_adapter_gdi_desc; - D3DKMT_CREATEDEVICE create_device_desc; - D3DKMT_CLOSEADAPTER close_adapter_desc; - D3DKMT_DESTROYDEVICE destroy_device_desc; - NTSTATUS status; - - if (!pD3DKMTCreateDevice || pD3DKMTCreateDevice(NULL) == STATUS_PROCEDURE_NOT_FOUND) - { - win_skip("D3DKMTCreateDevice() is unavailable.\n"); - return; - } - - /* Invalid parameters */ - status = pD3DKMTCreateDevice(NULL); - ok(status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#lx.\n", status); - - memset(&create_device_desc, 0, sizeof(create_device_desc)); - status = pD3DKMTCreateDevice(&create_device_desc); - ok(status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#lx.\n", status); - - lstrcpyW(open_adapter_gdi_desc.DeviceName, display1W); - status = pD3DKMTOpenAdapterFromGdiDisplayName(&open_adapter_gdi_desc); - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - - /* Create device */ - create_device_desc.hAdapter = open_adapter_gdi_desc.hAdapter; - status = pD3DKMTCreateDevice(&create_device_desc); - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - ok(create_device_desc.hDevice, "Expect not null.\n"); - ok(create_device_desc.pCommandBuffer == NULL, "Expect null.\n"); - ok(create_device_desc.CommandBufferSize == 0, "Got wrong value %#x.\n", create_device_desc.CommandBufferSize); - ok(create_device_desc.pAllocationList == NULL, "Expect null.\n"); - ok(create_device_desc.AllocationListSize == 0, "Got wrong value %#x.\n", create_device_desc.AllocationListSize); - ok(create_device_desc.pPatchLocationList == NULL, "Expect null.\n"); - ok(create_device_desc.PatchLocationListSize == 0, "Got wrong value %#x.\n", create_device_desc.PatchLocationListSize); - - destroy_device_desc.hDevice = create_device_desc.hDevice; - status = pD3DKMTDestroyDevice(&destroy_device_desc); - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - - close_adapter_desc.hAdapter = open_adapter_gdi_desc.hAdapter; - status = pD3DKMTCloseAdapter(&close_adapter_desc); - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); -} - -static void test_D3DKMTDestroyDevice(void) -{ - D3DKMT_DESTROYDEVICE destroy_device_desc; - NTSTATUS status; - - if (!pD3DKMTDestroyDevice || pD3DKMTDestroyDevice(NULL) == STATUS_PROCEDURE_NOT_FOUND) - { - win_skip("D3DKMTDestroyDevice() is unavailable.\n"); - return; - } - - /* Invalid parameters */ - status = pD3DKMTDestroyDevice(NULL); - ok(status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#lx.\n", status); - - memset(&destroy_device_desc, 0, sizeof(destroy_device_desc)); - status = pD3DKMTDestroyDevice(&destroy_device_desc); - ok(status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#lx.\n", status); -} - -static void test_D3DKMTCheckVidPnExclusiveOwnership(void) -{ - static const DWORD timeout = 1000; - static const DWORD wait_step = 100; - D3DKMT_CREATEDEVICE create_device_desc, create_device_desc2; - D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME open_adapter_gdi_desc; - D3DKMT_CHECKVIDPNEXCLUSIVEOWNERSHIP check_owner_desc; - D3DKMT_DESTROYDEVICE destroy_device_desc; - D3DKMT_CLOSEADAPTER close_adapter_desc; - D3DKMT_VIDPNSOURCEOWNER_TYPE owner_type; - D3DKMT_SETVIDPNSOURCEOWNER set_owner_desc; - DWORD total_time; - NTSTATUS status; - INT i; - - /* Test cases using single device */ - static const struct test_data1 - { - D3DKMT_VIDPNSOURCEOWNER_TYPE owner_type; - NTSTATUS expected_set_status; - NTSTATUS expected_check_status; - } tests1[] = { - /* 0 */ - {-1, STATUS_SUCCESS, STATUS_SUCCESS}, - {D3DKMT_VIDPNSOURCEOWNER_UNOWNED, STATUS_SUCCESS, STATUS_SUCCESS}, - {-1, STATUS_SUCCESS, STATUS_SUCCESS}, - {D3DKMT_VIDPNSOURCEOWNER_SHARED, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS}, - {-1, STATUS_SUCCESS, STATUS_SUCCESS}, - {D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, STATUS_SUCCESS, STATUS_GRAPHICS_PRESENT_OCCLUDED}, - {-1, STATUS_SUCCESS, STATUS_SUCCESS}, - {D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVEGDI, STATUS_INVALID_PARAMETER, STATUS_SUCCESS}, - {-1, STATUS_SUCCESS, STATUS_SUCCESS}, - {D3DKMT_VIDPNSOURCEOWNER_EMULATED, STATUS_SUCCESS, STATUS_SUCCESS}, - /* 10 */ - {-1, STATUS_SUCCESS, STATUS_SUCCESS}, - {D3DKMT_VIDPNSOURCEOWNER_UNOWNED, STATUS_SUCCESS, STATUS_SUCCESS}, - {D3DKMT_VIDPNSOURCEOWNER_UNOWNED, STATUS_SUCCESS, STATUS_SUCCESS}, - {-1, STATUS_SUCCESS, STATUS_SUCCESS}, - {D3DKMT_VIDPNSOURCEOWNER_UNOWNED, STATUS_SUCCESS, STATUS_SUCCESS}, - {D3DKMT_VIDPNSOURCEOWNER_SHARED, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS}, - {-1, STATUS_SUCCESS, STATUS_SUCCESS}, - {D3DKMT_VIDPNSOURCEOWNER_UNOWNED, STATUS_SUCCESS, STATUS_SUCCESS}, - {D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, STATUS_SUCCESS, STATUS_GRAPHICS_PRESENT_OCCLUDED}, - {-1, STATUS_SUCCESS, STATUS_SUCCESS}, - /* 20 */ - {D3DKMT_VIDPNSOURCEOWNER_UNOWNED, STATUS_SUCCESS, STATUS_SUCCESS}, - {D3DKMT_VIDPNSOURCEOWNER_EMULATED, STATUS_SUCCESS, STATUS_SUCCESS}, - {-1, STATUS_SUCCESS, STATUS_SUCCESS}, - {D3DKMT_VIDPNSOURCEOWNER_SHARED, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS}, - {D3DKMT_VIDPNSOURCEOWNER_UNOWNED, STATUS_SUCCESS, STATUS_SUCCESS}, - {-1, STATUS_SUCCESS, STATUS_SUCCESS}, - {D3DKMT_VIDPNSOURCEOWNER_SHARED, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS}, - {D3DKMT_VIDPNSOURCEOWNER_SHARED, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS}, - {-1, STATUS_SUCCESS, STATUS_SUCCESS}, - {D3DKMT_VIDPNSOURCEOWNER_SHARED, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS}, - /* 30 */ - {D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, STATUS_SUCCESS, STATUS_GRAPHICS_PRESENT_OCCLUDED}, - {-1, STATUS_SUCCESS, STATUS_SUCCESS}, - {D3DKMT_VIDPNSOURCEOWNER_SHARED, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS}, - {D3DKMT_VIDPNSOURCEOWNER_EMULATED, STATUS_SUCCESS, STATUS_SUCCESS}, - {-1, STATUS_SUCCESS, STATUS_SUCCESS}, - {D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, STATUS_SUCCESS, STATUS_GRAPHICS_PRESENT_OCCLUDED}, - {D3DKMT_VIDPNSOURCEOWNER_UNOWNED, STATUS_SUCCESS, STATUS_SUCCESS}, - {-1, STATUS_SUCCESS, STATUS_SUCCESS}, - {D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, STATUS_SUCCESS, STATUS_GRAPHICS_PRESENT_OCCLUDED}, - {D3DKMT_VIDPNSOURCEOWNER_SHARED, STATUS_INVALID_PARAMETER, STATUS_GRAPHICS_PRESENT_OCCLUDED}, - /* 40 */ - {-1, STATUS_SUCCESS, STATUS_SUCCESS}, - {D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, STATUS_SUCCESS, STATUS_GRAPHICS_PRESENT_OCCLUDED}, - {D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, STATUS_SUCCESS, STATUS_GRAPHICS_PRESENT_OCCLUDED}, - {-1, STATUS_SUCCESS, STATUS_SUCCESS}, - {D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, STATUS_SUCCESS, STATUS_GRAPHICS_PRESENT_OCCLUDED}, - {D3DKMT_VIDPNSOURCEOWNER_EMULATED, STATUS_INVALID_PARAMETER, STATUS_GRAPHICS_PRESENT_OCCLUDED}, - {-1, STATUS_SUCCESS, STATUS_SUCCESS}, - {D3DKMT_VIDPNSOURCEOWNER_EMULATED, STATUS_SUCCESS, STATUS_SUCCESS}, - {D3DKMT_VIDPNSOURCEOWNER_UNOWNED, STATUS_SUCCESS, STATUS_SUCCESS}, - {-1, STATUS_SUCCESS, STATUS_SUCCESS}, - /* 50 */ - {D3DKMT_VIDPNSOURCEOWNER_EMULATED, STATUS_SUCCESS, STATUS_SUCCESS}, - {D3DKMT_VIDPNSOURCEOWNER_SHARED, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS}, - {-1, STATUS_SUCCESS, STATUS_SUCCESS}, - {D3DKMT_VIDPNSOURCEOWNER_EMULATED, STATUS_SUCCESS, STATUS_SUCCESS}, - {D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, STATUS_INVALID_PARAMETER, STATUS_SUCCESS}, - {-1, STATUS_SUCCESS, STATUS_SUCCESS}, - {D3DKMT_VIDPNSOURCEOWNER_EMULATED, STATUS_SUCCESS, STATUS_SUCCESS}, - {D3DKMT_VIDPNSOURCEOWNER_EMULATED, STATUS_SUCCESS, STATUS_SUCCESS}, - {-1, STATUS_SUCCESS, STATUS_SUCCESS}, - {D3DKMT_VIDPNSOURCEOWNER_EMULATED + 1, STATUS_INVALID_PARAMETER, STATUS_SUCCESS}, - }; - - /* Test cases using two devices consecutively */ - static const struct test_data2 - { - D3DKMT_VIDPNSOURCEOWNER_TYPE set_owner_type1; - D3DKMT_VIDPNSOURCEOWNER_TYPE set_owner_type2; - NTSTATUS expected_set_status1; - NTSTATUS expected_set_status2; - NTSTATUS expected_check_status; - } tests2[] = { - /* 0 */ - {D3DKMT_VIDPNSOURCEOWNER_UNOWNED, D3DKMT_VIDPNSOURCEOWNER_UNOWNED, STATUS_SUCCESS, STATUS_SUCCESS, STATUS_SUCCESS}, - {D3DKMT_VIDPNSOURCEOWNER_UNOWNED, D3DKMT_VIDPNSOURCEOWNER_SHARED, STATUS_SUCCESS, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS}, - {D3DKMT_VIDPNSOURCEOWNER_UNOWNED, D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, STATUS_SUCCESS, STATUS_SUCCESS, STATUS_GRAPHICS_PRESENT_OCCLUDED}, - {D3DKMT_VIDPNSOURCEOWNER_UNOWNED, D3DKMT_VIDPNSOURCEOWNER_EMULATED, STATUS_SUCCESS, STATUS_SUCCESS, STATUS_SUCCESS}, - {D3DKMT_VIDPNSOURCEOWNER_SHARED, D3DKMT_VIDPNSOURCEOWNER_UNOWNED, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS, STATUS_SUCCESS}, - {D3DKMT_VIDPNSOURCEOWNER_SHARED, D3DKMT_VIDPNSOURCEOWNER_SHARED, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS}, - {D3DKMT_VIDPNSOURCEOWNER_SHARED, D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS, STATUS_GRAPHICS_PRESENT_OCCLUDED}, - {D3DKMT_VIDPNSOURCEOWNER_SHARED, D3DKMT_VIDPNSOURCEOWNER_EMULATED, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS, STATUS_SUCCESS}, - {D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, D3DKMT_VIDPNSOURCEOWNER_UNOWNED, STATUS_SUCCESS, STATUS_SUCCESS, STATUS_GRAPHICS_PRESENT_OCCLUDED}, - {D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, D3DKMT_VIDPNSOURCEOWNER_SHARED, STATUS_SUCCESS, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_GRAPHICS_PRESENT_OCCLUDED}, - /* 10 */ - {D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, STATUS_SUCCESS, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_GRAPHICS_PRESENT_OCCLUDED}, - {D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, D3DKMT_VIDPNSOURCEOWNER_EMULATED, STATUS_SUCCESS, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_GRAPHICS_PRESENT_OCCLUDED}, - {D3DKMT_VIDPNSOURCEOWNER_EMULATED, D3DKMT_VIDPNSOURCEOWNER_UNOWNED, STATUS_SUCCESS, STATUS_SUCCESS, STATUS_SUCCESS}, - {D3DKMT_VIDPNSOURCEOWNER_EMULATED, D3DKMT_VIDPNSOURCEOWNER_SHARED, STATUS_SUCCESS, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS}, - {D3DKMT_VIDPNSOURCEOWNER_EMULATED, D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, STATUS_SUCCESS, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS}, - {D3DKMT_VIDPNSOURCEOWNER_EMULATED, D3DKMT_VIDPNSOURCEOWNER_EMULATED, STATUS_SUCCESS, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS}, - {-1, D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, -1, STATUS_SUCCESS, STATUS_GRAPHICS_PRESENT_OCCLUDED}, - {D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, -1, STATUS_SUCCESS, STATUS_SUCCESS, STATUS_GRAPHICS_PRESENT_OCCLUDED}, - }; - - if (!pD3DKMTCheckVidPnExclusiveOwnership || pD3DKMTCheckVidPnExclusiveOwnership(NULL) == STATUS_PROCEDURE_NOT_FOUND) - { - /* This is a stub in some drivers (e.g. nulldrv) */ - skip("D3DKMTCheckVidPnExclusiveOwnership() is unavailable.\n"); - return; - } - - /* Invalid parameters */ - status = pD3DKMTCheckVidPnExclusiveOwnership(NULL); - ok(status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#lx.\n", status); - - memset(&check_owner_desc, 0, sizeof(check_owner_desc)); - status = pD3DKMTCheckVidPnExclusiveOwnership(&check_owner_desc); - ok(status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#lx.\n", status); - - /* Test cases */ - lstrcpyW(open_adapter_gdi_desc.DeviceName, display1W); - status = pD3DKMTOpenAdapterFromGdiDisplayName(&open_adapter_gdi_desc); - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - - memset(&create_device_desc, 0, sizeof(create_device_desc)); - create_device_desc.hAdapter = open_adapter_gdi_desc.hAdapter; - status = pD3DKMTCreateDevice(&create_device_desc); - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - - check_owner_desc.hAdapter = open_adapter_gdi_desc.hAdapter; - check_owner_desc.VidPnSourceId = open_adapter_gdi_desc.VidPnSourceId; - for (i = 0; i < ARRAY_SIZE(tests1); ++i) - { - set_owner_desc.hDevice = create_device_desc.hDevice; - if (tests1[i].owner_type != -1) - { - owner_type = tests1[i].owner_type; - set_owner_desc.pType = &owner_type; - set_owner_desc.pVidPnSourceId = &open_adapter_gdi_desc.VidPnSourceId; - set_owner_desc.VidPnSourceCount = 1; - } - else - { - set_owner_desc.pType = NULL; - set_owner_desc.pVidPnSourceId = NULL; - set_owner_desc.VidPnSourceCount = 0; - } - status = pD3DKMTSetVidPnSourceOwner(&set_owner_desc); - ok(status == tests1[i].expected_set_status || - /* win8 doesn't support D3DKMT_VIDPNSOURCEOWNER_EMULATED */ - (status == STATUS_INVALID_PARAMETER && tests1[i].owner_type == D3DKMT_VIDPNSOURCEOWNER_EMULATED) - || (status == STATUS_SUCCESS && tests1[i].owner_type == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE - && tests1[i - 1].owner_type == D3DKMT_VIDPNSOURCEOWNER_EMULATED), - "Got unexpected return code %#lx at test %d.\n", status, i); - - status = pD3DKMTCheckVidPnExclusiveOwnership(&check_owner_desc); - /* If don't sleep, D3DKMTCheckVidPnExclusiveOwnership may get STATUS_GRAPHICS_PRESENT_UNOCCLUDED instead - * of STATUS_SUCCESS */ - if ((tests1[i].expected_check_status == STATUS_SUCCESS && status == STATUS_GRAPHICS_PRESENT_UNOCCLUDED)) - { - total_time = 0; - do - { - Sleep(wait_step); - total_time += wait_step; - status = pD3DKMTCheckVidPnExclusiveOwnership(&check_owner_desc); - } while (status == STATUS_GRAPHICS_PRESENT_UNOCCLUDED && total_time < timeout); - } - ok(status == tests1[i].expected_check_status - || (status == STATUS_GRAPHICS_PRESENT_OCCLUDED /* win8 */ - && tests1[i].owner_type == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE - && tests1[i - 1].owner_type == D3DKMT_VIDPNSOURCEOWNER_EMULATED), - "Got unexpected return code %#lx at test %d.\n", status, i); - } - - /* Set owner and unset owner using different devices */ - memset(&create_device_desc2, 0, sizeof(create_device_desc2)); - create_device_desc2.hAdapter = open_adapter_gdi_desc.hAdapter; - status = pD3DKMTCreateDevice(&create_device_desc2); - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - - /* Set owner with the first device */ - set_owner_desc.hDevice = create_device_desc.hDevice; - owner_type = D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE; - set_owner_desc.pType = &owner_type; - set_owner_desc.pVidPnSourceId = &open_adapter_gdi_desc.VidPnSourceId; - set_owner_desc.VidPnSourceCount = 1; - status = pD3DKMTSetVidPnSourceOwner(&set_owner_desc); - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - status = pD3DKMTCheckVidPnExclusiveOwnership(&check_owner_desc); - ok(status == STATUS_GRAPHICS_PRESENT_OCCLUDED, "Got unexpected return code %#lx.\n", status); - - /* Unset owner with the second device */ - set_owner_desc.hDevice = create_device_desc2.hDevice; - set_owner_desc.pType = NULL; - set_owner_desc.pVidPnSourceId = NULL; - set_owner_desc.VidPnSourceCount = 0; - status = pD3DKMTSetVidPnSourceOwner(&set_owner_desc); - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - status = pD3DKMTCheckVidPnExclusiveOwnership(&check_owner_desc); - /* No effect */ - ok(status == STATUS_GRAPHICS_PRESENT_OCCLUDED, "Got unexpected return code %#lx.\n", status); - - /* Unset owner with the first device */ - set_owner_desc.hDevice = create_device_desc.hDevice; - set_owner_desc.pType = NULL; - set_owner_desc.pVidPnSourceId = NULL; - set_owner_desc.VidPnSourceCount = 0; - status = pD3DKMTSetVidPnSourceOwner(&set_owner_desc); - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - status = pD3DKMTCheckVidPnExclusiveOwnership(&check_owner_desc); - /* Proves that the correct device is needed to unset owner */ - ok(status == STATUS_SUCCESS || status == STATUS_GRAPHICS_PRESENT_UNOCCLUDED, "Got unexpected return code %#lx.\n", - status); - - /* Set owner with the first device, set owner again with the second device */ - for (i = 0; i < ARRAY_SIZE(tests2); ++i) - { - if (tests2[i].set_owner_type1 != -1) - { - set_owner_desc.hDevice = create_device_desc.hDevice; - owner_type = tests2[i].set_owner_type1; - set_owner_desc.pType = &owner_type; - set_owner_desc.pVidPnSourceId = &open_adapter_gdi_desc.VidPnSourceId; - set_owner_desc.VidPnSourceCount = 1; - /* If don't sleep, D3DKMTSetVidPnSourceOwner may return STATUS_OK for D3DKMT_VIDPNSOURCEOWNER_SHARED. - * Other owner type doesn't seems to be affected. */ - if (tests2[i].set_owner_type1 == D3DKMT_VIDPNSOURCEOWNER_SHARED) - Sleep(timeout); - status = pD3DKMTSetVidPnSourceOwner(&set_owner_desc); - ok(status == tests2[i].expected_set_status1 - || (status == STATUS_INVALID_PARAMETER /* win8 */ - && tests2[i].set_owner_type1 == D3DKMT_VIDPNSOURCEOWNER_EMULATED), - "Got unexpected return code %#lx at test %d.\n", status, i); - } - - if (tests2[i].set_owner_type2 != -1) - { - set_owner_desc.hDevice = create_device_desc2.hDevice; - owner_type = tests2[i].set_owner_type2; - set_owner_desc.pType = &owner_type; - set_owner_desc.pVidPnSourceId = &open_adapter_gdi_desc.VidPnSourceId; - set_owner_desc.VidPnSourceCount = 1; - status = pD3DKMTSetVidPnSourceOwner(&set_owner_desc); - ok(status == tests2[i].expected_set_status2 - || (status == STATUS_INVALID_PARAMETER /* win8 */ - && tests2[i].set_owner_type2 == D3DKMT_VIDPNSOURCEOWNER_EMULATED) - || (status == STATUS_SUCCESS && tests2[i].set_owner_type1 == D3DKMT_VIDPNSOURCEOWNER_EMULATED - && tests2[i].set_owner_type2 == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE), - "Got unexpected return code %#lx at test %d.\n", status, i); - } - - status = pD3DKMTCheckVidPnExclusiveOwnership(&check_owner_desc); - if ((tests2[i].expected_check_status == STATUS_SUCCESS && status == STATUS_GRAPHICS_PRESENT_UNOCCLUDED)) - { - total_time = 0; - do - { - Sleep(wait_step); - total_time += wait_step; - status = pD3DKMTCheckVidPnExclusiveOwnership(&check_owner_desc); - } while (status == STATUS_GRAPHICS_PRESENT_UNOCCLUDED && total_time < timeout); - } - ok(status == tests2[i].expected_check_status - || (status == STATUS_GRAPHICS_PRESENT_OCCLUDED /* win8 */ - && tests2[i].set_owner_type2 == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE - && tests2[i].set_owner_type1 == D3DKMT_VIDPNSOURCEOWNER_EMULATED), - "Got unexpected return code %#lx at test %d.\n", status, i); - - /* Unset owner with first device */ - if (tests2[i].set_owner_type1 != -1) - { - set_owner_desc.hDevice = create_device_desc.hDevice; - set_owner_desc.pType = NULL; - set_owner_desc.pVidPnSourceId = NULL; - set_owner_desc.VidPnSourceCount = 0; - status = pD3DKMTSetVidPnSourceOwner(&set_owner_desc); - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx at test %d.\n", status, i); - } - - /* Unset owner with second device */ - if (tests2[i].set_owner_type2 != -1) - { - set_owner_desc.hDevice = create_device_desc2.hDevice; - set_owner_desc.pType = NULL; - set_owner_desc.pVidPnSourceId = NULL; - set_owner_desc.VidPnSourceCount = 0; - status = pD3DKMTSetVidPnSourceOwner(&set_owner_desc); - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx at test %d.\n", status, i); - } - } - - /* Destroy devices holding ownership */ - set_owner_desc.hDevice = create_device_desc.hDevice; - owner_type = D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE; - set_owner_desc.pType = &owner_type; - set_owner_desc.pVidPnSourceId = &open_adapter_gdi_desc.VidPnSourceId; - set_owner_desc.VidPnSourceCount = 1; - status = pD3DKMTSetVidPnSourceOwner(&set_owner_desc); - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - - destroy_device_desc.hDevice = create_device_desc.hDevice; - status = pD3DKMTDestroyDevice(&destroy_device_desc); - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - - set_owner_desc.hDevice = create_device_desc2.hDevice; - owner_type = D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE; - set_owner_desc.pType = &owner_type; - set_owner_desc.pVidPnSourceId = &open_adapter_gdi_desc.VidPnSourceId; - set_owner_desc.VidPnSourceCount = 1; - status = pD3DKMTSetVidPnSourceOwner(&set_owner_desc); - /* So ownership is released when device is destroyed. otherwise the return code should be - * STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE */ - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - - destroy_device_desc.hDevice = create_device_desc2.hDevice; - status = pD3DKMTDestroyDevice(&destroy_device_desc); - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - - close_adapter_desc.hAdapter = open_adapter_gdi_desc.hAdapter; - status = pD3DKMTCloseAdapter(&close_adapter_desc); - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); -} - -static void test_D3DKMTSetVidPnSourceOwner(void) -{ - D3DKMT_SETVIDPNSOURCEOWNER set_owner_desc = {0}; - NTSTATUS status; - - if (!pD3DKMTSetVidPnSourceOwner || pD3DKMTSetVidPnSourceOwner(&set_owner_desc) == STATUS_PROCEDURE_NOT_FOUND) - { - /* This is a stub in some drivers (e.g. nulldrv) */ - skip("D3DKMTSetVidPnSourceOwner() is unavailable.\n"); - return; - } - - /* Invalid parameters */ - status = pD3DKMTSetVidPnSourceOwner(&set_owner_desc); - ok(status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#lx.\n", status); -} - -static void test_D3DKMTCheckOcclusion(void) -{ - DISPLAY_DEVICEW display_device = {sizeof(display_device)}; - D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME open_adapter_gdi_desc; - D3DKMT_CHECKVIDPNEXCLUSIVEOWNERSHIP check_owner_desc; - D3DKMT_SETVIDPNSOURCEOWNER set_owner_desc; - D3DKMT_DESTROYDEVICE destroy_device_desc; - D3DKMT_VIDPNSOURCEOWNER_TYPE owner_type; - D3DKMT_CLOSEADAPTER close_adapter_desc; - D3DKMT_CREATEDEVICE create_device_desc; - D3DKMT_CHECKOCCLUSION occlusion_desc; - NTSTATUS expected_occlusion, status; - INT i, adapter_count = 0; - HWND hwnd, hwnd2; - HRESULT hr; - - if (!pD3DKMTCheckOcclusion || pD3DKMTCheckOcclusion(NULL) == STATUS_PROCEDURE_NOT_FOUND) - { - todo_wine win_skip("D3DKMTCheckOcclusion() is unavailable.\n"); - return; - } - - /* NULL parameter check */ - status = pD3DKMTCheckOcclusion(NULL); - ok(status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#lx.\n", status); - - occlusion_desc.hWnd = NULL; - status = pD3DKMTCheckOcclusion(&occlusion_desc); - ok(status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#lx.\n", status); - - hwnd = CreateWindowA("static", "static1", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0, 0, 200, 200, 0, 0, 0, 0); - ok(hwnd != NULL, "Failed to create window.\n"); - - occlusion_desc.hWnd = hwnd; - status = pD3DKMTCheckOcclusion(&occlusion_desc); - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - - /* Minimized state doesn't affect D3DKMTCheckOcclusion */ - ShowWindow(hwnd, SW_MINIMIZE); - occlusion_desc.hWnd = hwnd; - status = pD3DKMTCheckOcclusion(&occlusion_desc); - flaky - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - ShowWindow(hwnd, SW_SHOWNORMAL); - - /* Invisible state doesn't affect D3DKMTCheckOcclusion */ - ShowWindow(hwnd, SW_HIDE); - occlusion_desc.hWnd = hwnd; - status = pD3DKMTCheckOcclusion(&occlusion_desc); - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - ShowWindow(hwnd, SW_SHOW); - - /* hwnd2 covers hwnd */ - hwnd2 = CreateWindowA("static", "static2", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 200, 200, 0, 0, 0, 0); - ok(hwnd2 != NULL, "Failed to create window.\n"); - - occlusion_desc.hWnd = hwnd; - status = pD3DKMTCheckOcclusion(&occlusion_desc); - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - - occlusion_desc.hWnd = hwnd2; - status = pD3DKMTCheckOcclusion(&occlusion_desc); - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - - /* Composition doesn't affect D3DKMTCheckOcclusion */ - if (pDwmEnableComposition) - { - hr = pDwmEnableComposition(DWM_EC_DISABLECOMPOSITION); - ok(hr == S_OK, "Failed to disable composition.\n"); - - occlusion_desc.hWnd = hwnd; - status = pD3DKMTCheckOcclusion(&occlusion_desc); - /* This result means that D3DKMTCheckOcclusion doesn't check composition status despite MSDN says it will */ - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - - occlusion_desc.hWnd = hwnd2; - status = pD3DKMTCheckOcclusion(&occlusion_desc); - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - - ShowWindow(hwnd, SW_MINIMIZE); - occlusion_desc.hWnd = hwnd; - status = pD3DKMTCheckOcclusion(&occlusion_desc); - flaky - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - ShowWindow(hwnd, SW_SHOWNORMAL); - - ShowWindow(hwnd, SW_HIDE); - occlusion_desc.hWnd = hwnd; - status = pD3DKMTCheckOcclusion(&occlusion_desc); - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - ShowWindow(hwnd, SW_SHOW); - - hr = pDwmEnableComposition(DWM_EC_ENABLECOMPOSITION); - ok(hr == S_OK, "Failed to enable composition.\n"); - } - else - skip("Skip testing composition.\n"); - - lstrcpyW(open_adapter_gdi_desc.DeviceName, display1W); - status = pD3DKMTOpenAdapterFromGdiDisplayName(&open_adapter_gdi_desc); - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - - memset(&create_device_desc, 0, sizeof(create_device_desc)); - create_device_desc.hAdapter = open_adapter_gdi_desc.hAdapter; - status = pD3DKMTCreateDevice(&create_device_desc); - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - - check_owner_desc.hAdapter = open_adapter_gdi_desc.hAdapter; - check_owner_desc.VidPnSourceId = open_adapter_gdi_desc.VidPnSourceId; - status = pD3DKMTCheckVidPnExclusiveOwnership(&check_owner_desc); - /* D3DKMTCheckVidPnExclusiveOwnership gets STATUS_GRAPHICS_PRESENT_UNOCCLUDED sometimes and with some delay, - * it will always return STATUS_SUCCESS. So there are some timing issues here. */ - ok(status == STATUS_SUCCESS || status == STATUS_GRAPHICS_PRESENT_UNOCCLUDED, "Got unexpected return code %#lx.\n", status); - - /* Test D3DKMTCheckOcclusion relationship with video present source owner */ - set_owner_desc.hDevice = create_device_desc.hDevice; - owner_type = D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE; - set_owner_desc.pType = &owner_type; - set_owner_desc.pVidPnSourceId = &open_adapter_gdi_desc.VidPnSourceId; - set_owner_desc.VidPnSourceCount = 1; - status = pD3DKMTSetVidPnSourceOwner(&set_owner_desc); - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - - for (i = 0; EnumDisplayDevicesW(NULL, i, &display_device, 0); ++i) - { - if ((display_device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)) - adapter_count++; - } - /* STATUS_GRAPHICS_PRESENT_OCCLUDED on single monitor system. STATUS_SUCCESS on multiple monitor system. */ - expected_occlusion = adapter_count > 1 ? STATUS_SUCCESS : STATUS_GRAPHICS_PRESENT_OCCLUDED; - - occlusion_desc.hWnd = hwnd; - status = pD3DKMTCheckOcclusion(&occlusion_desc); - ok(status == expected_occlusion, "Got unexpected return code %#lx.\n", status); - - /* Note hwnd2 is not actually occluded but D3DKMTCheckOcclusion reports STATUS_GRAPHICS_PRESENT_OCCLUDED as well */ - SetWindowPos(hwnd2, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); - ShowWindow(hwnd2, SW_SHOW); - occlusion_desc.hWnd = hwnd2; - status = pD3DKMTCheckOcclusion(&occlusion_desc); - ok(status == expected_occlusion, "Got unexpected return code %#lx.\n", status); - - /* Now hwnd is HWND_TOPMOST. Still reports STATUS_GRAPHICS_PRESENT_OCCLUDED */ - ok(SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE), "Failed to SetWindowPos.\n"); - ok(GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST, "No WS_EX_TOPMOST style.\n"); - occlusion_desc.hWnd = hwnd; - status = pD3DKMTCheckOcclusion(&occlusion_desc); - ok(status == expected_occlusion, "Got unexpected return code %#lx.\n", status); - - DestroyWindow(hwnd2); - occlusion_desc.hWnd = hwnd; - status = pD3DKMTCheckOcclusion(&occlusion_desc); - ok(status == expected_occlusion, "Got unexpected return code %#lx.\n", status); - - check_owner_desc.hAdapter = open_adapter_gdi_desc.hAdapter; - check_owner_desc.VidPnSourceId = open_adapter_gdi_desc.VidPnSourceId; - status = pD3DKMTCheckVidPnExclusiveOwnership(&check_owner_desc); - ok(status == STATUS_GRAPHICS_PRESENT_OCCLUDED, "Got unexpected return code %#lx.\n", status); - - /* Unset video present source owner */ - set_owner_desc.hDevice = create_device_desc.hDevice; - set_owner_desc.pType = NULL; - set_owner_desc.pVidPnSourceId = NULL; - set_owner_desc.VidPnSourceCount = 0; - status = pD3DKMTSetVidPnSourceOwner(&set_owner_desc); - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - - occlusion_desc.hWnd = hwnd; - status = pD3DKMTCheckOcclusion(&occlusion_desc); - flaky - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - - check_owner_desc.hAdapter = open_adapter_gdi_desc.hAdapter; - check_owner_desc.VidPnSourceId = open_adapter_gdi_desc.VidPnSourceId; - status = pD3DKMTCheckVidPnExclusiveOwnership(&check_owner_desc); - flaky - ok(status == STATUS_SUCCESS || status == STATUS_GRAPHICS_PRESENT_UNOCCLUDED, "Got unexpected return code %#lx.\n", status); - - destroy_device_desc.hDevice = create_device_desc.hDevice; - status = pD3DKMTDestroyDevice(&destroy_device_desc); - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - - close_adapter_desc.hAdapter = open_adapter_gdi_desc.hAdapter; - status = pD3DKMTCloseAdapter(&close_adapter_desc); - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - DestroyWindow(hwnd); -} - -static void test_D3DKMTOpenAdapterFromDeviceName_deviface(const GUID *devinterface_guid, - NTSTATUS expected_status, BOOL todo) -{ - BYTE iface_detail_buffer[sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) + 256 * sizeof(WCHAR)]; - SP_DEVINFO_DATA device_data = {sizeof(device_data)}; - SP_DEVICE_INTERFACE_DATA iface = {sizeof(iface)}; - SP_DEVICE_INTERFACE_DETAIL_DATA_W *iface_data; - D3DKMT_OPENADAPTERFROMDEVICENAME device_name; - D3DKMT_CLOSEADAPTER close_adapter_desc; - DEVPROPTYPE type; - NTSTATUS status; - unsigned int i; - HDEVINFO set; - LUID luid; - BOOL ret; - - set = SetupDiGetClassDevsW(devinterface_guid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); - ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevs failed, error %lu.\n", GetLastError()); - - iface_data = (SP_DEVICE_INTERFACE_DETAIL_DATA_W *)iface_detail_buffer; - iface_data->cbSize = sizeof(*iface_data); - device_name.pDeviceName = iface_data->DevicePath; - - i = 0; - while (SetupDiEnumDeviceInterfaces(set, NULL, devinterface_guid, i, &iface)) - { - ret = SetupDiGetDeviceInterfaceDetailW(set, &iface, iface_data, - sizeof(iface_detail_buffer), NULL, &device_data ); - ok(ret, "Got unexpected ret %d, GetLastError() %lu.\n", ret, GetLastError()); - - status = pD3DKMTOpenAdapterFromDeviceName(&device_name); - ok(status == expected_status, "Got status %#lx, expected %#lx.\n", status, expected_status); - - if (!status) - { - ret = SetupDiGetDevicePropertyW(set, &device_data, &DEVPROPKEY_GPU_LUID, &type, - (BYTE *)&luid, sizeof(luid), NULL, 0); - ok(ret || GetLastError() == ERROR_NOT_FOUND, "Got unexpected ret %d, GetLastError() %lu.\n", - ret, GetLastError()); - - if (ret) - { - ret = RtlEqualLuid( &luid, &device_name.AdapterLuid); - ok(ret, "Luid does not match.\n"); - } - else - { - skip("Luid not found.\n"); - } - - close_adapter_desc.hAdapter = device_name.hAdapter; - status = pD3DKMTCloseAdapter(&close_adapter_desc); - ok(!status, "Got unexpected status %#lx.\n", status); - } - ++i; - } - if (!i) - win_skip("No devices found.\n"); - - SetupDiDestroyDeviceInfoList( set ); -} - -static void test_D3DKMTOpenAdapterFromDeviceName(void) -{ - D3DKMT_OPENADAPTERFROMDEVICENAME device_name; - NTSTATUS status; - - /* Make sure display devices are initialized. */ - SendMessageW(GetDesktopWindow(), WM_NULL, 0, 0); - - status = pD3DKMTOpenAdapterFromDeviceName(NULL); - if (status == STATUS_PROCEDURE_NOT_FOUND) - { - win_skip("D3DKMTOpenAdapterFromDeviceName() is not supported.\n"); - return; - } - ok(status == STATUS_INVALID_PARAMETER, "Got unexpected status %#lx.\n", status); - - memset(&device_name, 0, sizeof(device_name)); - status = pD3DKMTOpenAdapterFromDeviceName(&device_name); - ok(status == STATUS_INVALID_PARAMETER, "Got unexpected status %#lx.\n", status); - - winetest_push_context("GUID_DEVINTERFACE_DISPLAY_ADAPTER"); - test_D3DKMTOpenAdapterFromDeviceName_deviface(&GUID_DEVINTERFACE_DISPLAY_ADAPTER, STATUS_INVALID_PARAMETER, TRUE); - winetest_pop_context(); - - winetest_push_context("GUID_DISPLAY_DEVICE_ARRIVAL"); - test_D3DKMTOpenAdapterFromDeviceName_deviface(&GUID_DISPLAY_DEVICE_ARRIVAL, STATUS_SUCCESS, FALSE); - winetest_pop_context(); -} - -static void test_D3DKMTQueryVideoMemoryInfo(void) -{ - static const D3DKMT_MEMORY_SEGMENT_GROUP groups[] = {D3DKMT_MEMORY_SEGMENT_GROUP_LOCAL, - D3DKMT_MEMORY_SEGMENT_GROUP_NON_LOCAL}; - D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME open_adapter_desc; - D3DKMT_QUERYVIDEOMEMORYINFO query_memory_info; - D3DKMT_CLOSEADAPTER close_adapter_desc; - NTSTATUS status; - unsigned int i; - BOOL ret; - - if (!pD3DKMTQueryVideoMemoryInfo) - { - win_skip("D3DKMTQueryVideoMemoryInfo() is unavailable.\n"); - return; - } - - ret = get_primary_adapter_name(open_adapter_desc.DeviceName); - ok(ret, "Failed to get primary adapter name.\n"); - status = pD3DKMTOpenAdapterFromGdiDisplayName(&open_adapter_desc); - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - - /* Normal query */ - for (i = 0; i < ARRAY_SIZE(groups); ++i) - { - winetest_push_context("group %d", groups[i]); - - query_memory_info.hProcess = NULL; - query_memory_info.hAdapter = open_adapter_desc.hAdapter; - query_memory_info.PhysicalAdapterIndex = 0; - query_memory_info.MemorySegmentGroup = groups[i]; - status = pD3DKMTQueryVideoMemoryInfo(&query_memory_info); - todo_wine_if (status == STATUS_INVALID_PARAMETER) /* fails on Wine without a Vulkan adapter */ - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - ok(query_memory_info.Budget >= query_memory_info.AvailableForReservation, - "Unexpected budget %I64u and reservation %I64u.\n", query_memory_info.Budget, - query_memory_info.AvailableForReservation); - ok(query_memory_info.CurrentUsage <= query_memory_info.Budget, - "Unexpected current usage %I64u.\n", query_memory_info.CurrentUsage); - ok(query_memory_info.CurrentReservation == 0, - "Unexpected current reservation %I64u.\n", query_memory_info.CurrentReservation); - - winetest_pop_context(); - } - - /* Query using the current process handle */ - query_memory_info.hProcess = GetCurrentProcess(); - status = pD3DKMTQueryVideoMemoryInfo(&query_memory_info); - todo_wine_if (status == STATUS_INVALID_PARAMETER) /* fails on Wine without a Vulkan adapter */ - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - - /* Query using a process handle without PROCESS_QUERY_INFORMATION privilege */ - query_memory_info.hProcess = OpenProcess(PROCESS_SET_INFORMATION, FALSE, GetCurrentProcessId()); - ok(!!query_memory_info.hProcess, "OpenProcess failed, error %ld.\n", GetLastError()); - status = pD3DKMTQueryVideoMemoryInfo(&query_memory_info); - ok(status == STATUS_ACCESS_DENIED, "Got unexpected return code %#lx.\n", status); - CloseHandle(query_memory_info.hProcess); - query_memory_info.hProcess = NULL; - - /* Query using an invalid process handle */ - query_memory_info.hProcess = (HANDLE)0xdeadbeef; - status = pD3DKMTQueryVideoMemoryInfo(&query_memory_info); - ok(status == STATUS_INVALID_HANDLE, "Got unexpected return code %#lx.\n", status); - query_memory_info.hProcess = NULL; - - /* Query using an invalid adapter handle */ - query_memory_info.hAdapter = (D3DKMT_HANDLE)0xdeadbeef; - status = pD3DKMTQueryVideoMemoryInfo(&query_memory_info); - ok(status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#lx.\n", status); - query_memory_info.hAdapter = open_adapter_desc.hAdapter; - - /* Query using an invalid adapter index */ - query_memory_info.PhysicalAdapterIndex = 99; - status = pD3DKMTQueryVideoMemoryInfo(&query_memory_info); - ok(status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#lx.\n", status); - query_memory_info.PhysicalAdapterIndex = 0; - - /* Query using an invalid memory segment group */ - query_memory_info.MemorySegmentGroup = D3DKMT_MEMORY_SEGMENT_GROUP_NON_LOCAL + 1; - status = pD3DKMTQueryVideoMemoryInfo(&query_memory_info); - ok(status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#lx.\n", status); - - close_adapter_desc.hAdapter = open_adapter_desc.hAdapter; - status = pD3DKMTCloseAdapter(&close_adapter_desc); - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); -} - -static void test_gpu_device_properties_guid(const GUID *devinterface_guid) -{ - BYTE iface_detail_buffer[sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) + 256 * sizeof(WCHAR)]; - SP_DEVINFO_DATA device_data = {sizeof(device_data)}; - SP_DEVICE_INTERFACE_DATA iface = {sizeof(iface)}; - SP_DEVICE_INTERFACE_DETAIL_DATA_W *iface_data; - WCHAR device_id[256]; - DEVPROPTYPE type; - unsigned int i; - UINT32 value; - HDEVINFO set; - BOOL ret; - - /* Make sure display devices are initialized. */ - SendMessageW(GetDesktopWindow(), WM_NULL, 0, 0); - - set = SetupDiGetClassDevsW(devinterface_guid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); - ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevs failed, error %lu.\n", GetLastError()); - - iface_data = (SP_DEVICE_INTERFACE_DETAIL_DATA_W *)iface_detail_buffer; - iface_data->cbSize = sizeof(*iface_data); - - i = 0; - while (SetupDiEnumDeviceInterfaces(set, NULL, devinterface_guid, i, &iface)) - { - ret = SetupDiGetDeviceInterfaceDetailW(set, &iface, iface_data, - sizeof(iface_detail_buffer), NULL, &device_data ); - ok(ret, "Got unexpected ret %d, GetLastError() %lu.\n", ret, GetLastError()); - - ret = SetupDiGetDevicePropertyW(set, &device_data, &DEVPKEY_Device_MatchingDeviceId, &type, - (BYTE *)device_id, sizeof(device_id), NULL, 0); - ok(ret, "Got unexpected ret %d, GetLastError() %lu.\n", ret, GetLastError()); - ok(type == DEVPROP_TYPE_STRING, "Got type %ld.\n", type); - - ret = SetupDiGetDevicePropertyW(set, &device_data, &DEVPKEY_Device_BusNumber, &type, - (BYTE *)&value, sizeof(value), NULL, 0); - if (!wcsicmp(device_id, L"root\basicrender") || !wcsicmp(device_id, L"root\basicdisplay")) - { - ok(!ret, "Found Bus Id.\n"); - } - else - { - ok(ret, "Got unexpected ret %d, GetLastError() %lu, %s.\n", ret, GetLastError(), debugstr_w(device_id)); - ok(type == DEVPROP_TYPE_UINT32, "Got type %ld.\n", type); - } - - ret = SetupDiGetDevicePropertyW(set, &device_data, &DEVPKEY_Device_RemovalPolicy, &type, - (BYTE *)&value, sizeof(value), NULL, 0); - ok(ret, "Got unexpected ret %d, GetLastError() %lu, %s.\n", ret, GetLastError(), debugstr_w(device_id)); - ok(value == CM_REMOVAL_POLICY_EXPECT_NO_REMOVAL || value == CM_REMOVAL_POLICY_EXPECT_ORDERLY_REMOVAL - || value == CM_REMOVAL_POLICY_EXPECT_SURPRISE_REMOVAL, "Got value %d.\n", value); - ok(type == DEVPROP_TYPE_UINT32, "Got type %ld.\n", type); - ++i; - } - SetupDiDestroyDeviceInfoList(set); -} - -static void test_gpu_device_properties(void) -{ - winetest_push_context("GUID_DEVINTERFACE_DISPLAY_ADAPTER"); - test_gpu_device_properties_guid(&GUID_DEVINTERFACE_DISPLAY_ADAPTER); - winetest_pop_context(); - winetest_push_context("GUID_DISPLAY_DEVICE_ARRIVAL"); - test_gpu_device_properties_guid(&GUID_DISPLAY_DEVICE_ARRIVAL); - winetest_pop_context(); -} - -static void test_D3DKMTQueryAdapterInfo(void) -{ - D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME open_adapter_desc; - D3DKMT_QUERYADAPTERINFO query_adapter_info; - D3DKMT_CLOSEADAPTER close_adapter_desc; - unsigned char buffer[1024]; - NTSTATUS status; - unsigned int i; - BOOL ret; - - static const struct - { - KMTQUERYADAPTERINFOTYPE type; - UINT size; - } - tests[] = - { - {KMTQAITYPE_CHECKDRIVERUPDATESTATUS, sizeof(BOOL)}, - {KMTQAITYPE_DRIVERVERSION, sizeof(D3DKMT_DRIVERVERSION)}, - }; - - if (!pD3DKMTQueryAdapterInfo) - { - win_skip("D3DKMTQueryAdapterInfo() is unavailable.\n"); - return; - } - - ret = get_primary_adapter_name(open_adapter_desc.DeviceName); - ok(ret, "Failed to get primary adapter name.\n"); - status = pD3DKMTOpenAdapterFromGdiDisplayName(&open_adapter_desc); - if (status == STATUS_PROCEDURE_NOT_FOUND) - { - win_skip("D3DKMTOpenAdapterFromGdiDisplayName() is not supported.\n"); - return; - } - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - - for (i = 0; i < ARRAY_SIZE(tests); i++) - { - winetest_push_context("type %d", tests[i].type); - - /* NULL buffer */ - query_adapter_info.hAdapter = open_adapter_desc.hAdapter; - query_adapter_info.Type = tests[i].type; - query_adapter_info.pPrivateDriverData = NULL; - query_adapter_info.PrivateDriverDataSize = tests[i].size; - status = pD3DKMTQueryAdapterInfo(&query_adapter_info); - ok(status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#lx.\n", status); - - /* Insufficient buffer size */ - query_adapter_info.pPrivateDriverData = buffer; - query_adapter_info.PrivateDriverDataSize = tests[i].size - 1; - status = pD3DKMTQueryAdapterInfo(&query_adapter_info); - ok(status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#lx.\n", status); - - /* Normal */ - query_adapter_info.pPrivateDriverData = buffer; - query_adapter_info.PrivateDriverDataSize = tests[i].size; - status = pD3DKMTQueryAdapterInfo(&query_adapter_info); - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); - if (status != STATUS_SUCCESS) - { - winetest_pop_context(); - continue; - } - - switch (tests[i].type) - { - case KMTQAITYPE_CHECKDRIVERUPDATESTATUS: - { - BOOL *value = query_adapter_info.pPrivateDriverData; - ok(*value == FALSE, "Expected %d, got %d.\n", FALSE, *value); - break; - } - case KMTQAITYPE_DRIVERVERSION: - { - D3DKMT_DRIVERVERSION *value = query_adapter_info.pPrivateDriverData; - ok(*value >= KMT_DRIVERVERSION_WDDM_1_3, "Expected %d >= %d.\n", *value, - KMT_DRIVERVERSION_WDDM_1_3); - break; - } - default: - { - ok(0, "Type %d is not handled.\n", tests[i].type); - } - } - - winetest_pop_context(); - } - - close_adapter_desc.hAdapter = open_adapter_desc.hAdapter; - status = pD3DKMTCloseAdapter(&close_adapter_desc); - ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status); -} - -START_TEST(driver) -{ - HMODULE gdi32 = GetModuleHandleA("gdi32.dll"); - HMODULE dwmapi = LoadLibraryA("dwmapi.dll"); - - pD3DKMTCheckOcclusion = (void *)GetProcAddress(gdi32, "D3DKMTCheckOcclusion"); - pD3DKMTCheckVidPnExclusiveOwnership = (void *)GetProcAddress(gdi32, "D3DKMTCheckVidPnExclusiveOwnership"); - pD3DKMTCloseAdapter = (void *)GetProcAddress(gdi32, "D3DKMTCloseAdapter"); - pD3DKMTCreateDevice = (void *)GetProcAddress(gdi32, "D3DKMTCreateDevice"); - pD3DKMTDestroyDevice = (void *)GetProcAddress(gdi32, "D3DKMTDestroyDevice"); - pD3DKMTEnumAdapters2 = (void *)GetProcAddress(gdi32, "D3DKMTEnumAdapters2"); - pD3DKMTOpenAdapterFromDeviceName = (void *)GetProcAddress(gdi32, "D3DKMTOpenAdapterFromDeviceName"); - pD3DKMTOpenAdapterFromGdiDisplayName = (void *)GetProcAddress(gdi32, "D3DKMTOpenAdapterFromGdiDisplayName"); - pD3DKMTOpenAdapterFromHdc = (void *)GetProcAddress(gdi32, "D3DKMTOpenAdapterFromHdc"); - pD3DKMTSetVidPnSourceOwner = (void *)GetProcAddress(gdi32, "D3DKMTSetVidPnSourceOwner"); - pD3DKMTQueryAdapterInfo = (void *)GetProcAddress(gdi32, "D3DKMTQueryAdapterInfo"); - pD3DKMTQueryVideoMemoryInfo = (void *)GetProcAddress(gdi32, "D3DKMTQueryVideoMemoryInfo"); - - if (dwmapi) - pDwmEnableComposition = (void *)GetProcAddress(dwmapi, "DwmEnableComposition"); - - test_D3DKMTOpenAdapterFromGdiDisplayName(); - test_D3DKMTOpenAdapterFromHdc(); - test_D3DKMTEnumAdapters2(); - test_D3DKMTCloseAdapter(); - test_D3DKMTCreateDevice(); - test_D3DKMTDestroyDevice(); - test_D3DKMTCheckVidPnExclusiveOwnership(); - test_D3DKMTSetVidPnSourceOwner(); - test_D3DKMTCheckOcclusion(); - test_D3DKMTOpenAdapterFromDeviceName(); - test_D3DKMTQueryAdapterInfo(); - test_D3DKMTQueryVideoMemoryInfo(); - test_gpu_device_properties(); - - FreeLibrary(dwmapi); -} diff --git a/dlls/win32u/tests/Makefile.in b/dlls/win32u/tests/Makefile.in index 96abadaba0f..541812f754c 100644 --- a/dlls/win32u/tests/Makefile.in +++ b/dlls/win32u/tests/Makefile.in @@ -1,5 +1,6 @@ TESTDLL = win32u.dll -IMPORTS = imm32 user32 gdi32 win32u +IMPORTS = imm32 user32 gdi32 dwmapi setupapi win32u
SOURCES = \ + d3dkmt.c \ win32u.c diff --git a/dlls/win32u/tests/d3dkmt.c b/dlls/win32u/tests/d3dkmt.c new file mode 100644 index 00000000000..1af92036a1b --- /dev/null +++ b/dlls/win32u/tests/d3dkmt.c @@ -0,0 +1,1109 @@ +/* + * Unit test suite for kernel mode graphics driver + * + * Copyright 2019 Zhiyi Zhang + * + * 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 + */ + +#include <stdarg.h> + +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winuser.h" +#include "winternl.h" +#include "dwmapi.h" +#include "ddk/d3dkmthk.h" +#include "initguid.h" +#include "setupapi.h" +#include "ntddvdeo.h" +#include "devpkey.h" +#include "cfgmgr32.h" + +#include "wine/test.h" + +static const WCHAR display1W[] = L"\\.\DISPLAY1"; + +DEFINE_DEVPROPKEY(DEVPROPKEY_GPU_LUID, 0x60b193cb, 0x5276, 0x4d0f, 0x96, 0xfc, 0xf1, 0x73, 0xab, 0xad, 0x3e, 0xc6, 2); + +static BOOL get_primary_adapter_name( WCHAR *name ) +{ + DISPLAY_DEVICEW dd; + DWORD adapter_idx; + + dd.cb = sizeof(dd); + for (adapter_idx = 0; EnumDisplayDevicesW( NULL, adapter_idx, &dd, 0 ); ++adapter_idx) + { + if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) + { + lstrcpyW( name, dd.DeviceName ); + return TRUE; + } + } + + return FALSE; +} + +static void test_D3DKMTOpenAdapterFromGdiDisplayName(void) +{ + D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME open_adapter_gdi_desc; + D3DKMT_CLOSEADAPTER close_adapter_desc; + DISPLAY_DEVICEW display_device = {sizeof(display_device)}; + NTSTATUS status; + DWORD i; + + lstrcpyW( open_adapter_gdi_desc.DeviceName, display1W ); + status = D3DKMTOpenAdapterFromGdiDisplayName( &open_adapter_gdi_desc ); + ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + close_adapter_desc.hAdapter = open_adapter_gdi_desc.hAdapter; + status = D3DKMTCloseAdapter( &close_adapter_desc ); + ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + + /* Invalid parameters */ + status = D3DKMTOpenAdapterFromGdiDisplayName( NULL ); + ok( status == STATUS_UNSUCCESSFUL, "Got unexpected return code %#lx.\n", status ); + + memset( &open_adapter_gdi_desc, 0, sizeof(open_adapter_gdi_desc) ); + status = D3DKMTOpenAdapterFromGdiDisplayName( &open_adapter_gdi_desc ); + ok( status == STATUS_UNSUCCESSFUL, "Got unexpected return code %#lx.\n", status ); + + /* Open adapter */ + for (i = 0; EnumDisplayDevicesW( NULL, i, &display_device, 0 ); ++i) + { + lstrcpyW( open_adapter_gdi_desc.DeviceName, display_device.DeviceName ); + status = D3DKMTOpenAdapterFromGdiDisplayName( &open_adapter_gdi_desc ); + if (display_device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) + ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + else + { + ok( status == STATUS_UNSUCCESSFUL, "Got unexpected return code %#lx.\n", status ); + continue; + } + + ok( open_adapter_gdi_desc.hAdapter, "Expect not null.\n" ); + ok( open_adapter_gdi_desc.AdapterLuid.LowPart || open_adapter_gdi_desc.AdapterLuid.HighPart, + "Expect LUID not zero.\n" ); + + close_adapter_desc.hAdapter = open_adapter_gdi_desc.hAdapter; + status = D3DKMTCloseAdapter( &close_adapter_desc ); + ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + } +} + +static void test_D3DKMTOpenAdapterFromHdc(void) +{ + DISPLAY_DEVICEW display_device = {sizeof(display_device)}; + D3DKMT_OPENADAPTERFROMHDC open_adapter_hdc_desc; + D3DKMT_CLOSEADAPTER close_adapter_desc; + INT adapter_count = 0; + NTSTATUS status; + HDC hdc; + DWORD i; + + /* Invalid parameters */ + /* Passing a NULL pointer crashes on Windows 10 >= 2004 */ + if (0) status = D3DKMTOpenAdapterFromHdc( NULL ); + + memset( &open_adapter_hdc_desc, 0, sizeof(open_adapter_hdc_desc) ); + status = D3DKMTOpenAdapterFromHdc( &open_adapter_hdc_desc ); + todo_wine ok( status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#lx.\n", status ); + + /* Open adapter */ + for (i = 0; EnumDisplayDevicesW( NULL, i, &display_device, 0 ); ++i) + { + if (!(display_device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)) continue; + + adapter_count++; + + hdc = CreateDCW( 0, display_device.DeviceName, 0, NULL ); + open_adapter_hdc_desc.hDc = hdc; + status = D3DKMTOpenAdapterFromHdc( &open_adapter_hdc_desc ); + todo_wine ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + todo_wine ok( open_adapter_hdc_desc.hAdapter, "Expect not null.\n" ); + DeleteDC( hdc ); + + if (status == STATUS_SUCCESS) + { + close_adapter_desc.hAdapter = open_adapter_hdc_desc.hAdapter; + status = D3DKMTCloseAdapter( &close_adapter_desc ); + ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + } + } + + /* HDC covering more than two adapters is invalid for D3DKMTOpenAdapterFromHdc */ + hdc = GetDC( 0 ); + open_adapter_hdc_desc.hDc = hdc; + status = D3DKMTOpenAdapterFromHdc( &open_adapter_hdc_desc ); + ReleaseDC( 0, hdc ); + todo_wine ok( status == (adapter_count > 1 ? STATUS_INVALID_PARAMETER : STATUS_SUCCESS), + "Got unexpected return code %#lx.\n", status ); + if (status == STATUS_SUCCESS) + { + close_adapter_desc.hAdapter = open_adapter_hdc_desc.hAdapter; + status = D3DKMTCloseAdapter( &close_adapter_desc ); + ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + } +} + +static void test_D3DKMTEnumAdapters2(void) +{ + D3DKMT_ENUMADAPTERS2 enum_adapters_2_desc = {0}; + D3DKMT_CLOSEADAPTER close_adapter_desc; + NTSTATUS status; + UINT i; + + /* Invalid parameters */ + status = D3DKMTEnumAdapters2( NULL ); + ok( status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#lx.\n", status ); + + /* Query the array to allocate */ + memset( &enum_adapters_2_desc, 0, sizeof(enum_adapters_2_desc) ); + status = D3DKMTEnumAdapters2( &enum_adapters_2_desc ); + ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + ok( enum_adapters_2_desc.NumAdapters == 32 /* win10 and older */ || enum_adapters_2_desc.NumAdapters == 34 /* win11 */, + "Got unexpected value %lu.\n", enum_adapters_2_desc.NumAdapters ); + + /* Allocate the array */ + enum_adapters_2_desc.pAdapters = calloc( enum_adapters_2_desc.NumAdapters, sizeof(D3DKMT_ADAPTERINFO) ); + ok( !!enum_adapters_2_desc.pAdapters, "Expect not null.\n" ); + + /* Enumerate adapters */ + status = D3DKMTEnumAdapters2( &enum_adapters_2_desc ); + ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + ok( enum_adapters_2_desc.NumAdapters, "Expect not zero.\n" ); + + for (i = 0; i < enum_adapters_2_desc.NumAdapters; ++i) + { + ok( enum_adapters_2_desc.pAdapters[i].hAdapter, "Expect not null.\n" ); + ok( enum_adapters_2_desc.pAdapters[i].AdapterLuid.LowPart || + enum_adapters_2_desc.pAdapters[i].AdapterLuid.HighPart, + "Expect LUID not zero.\n" ); + + close_adapter_desc.hAdapter = enum_adapters_2_desc.pAdapters[i].hAdapter; + status = D3DKMTCloseAdapter( &close_adapter_desc ); + ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + } + + /* Check for insufficient buffer */ + enum_adapters_2_desc.NumAdapters = 0; + status = D3DKMTEnumAdapters2( &enum_adapters_2_desc ); + ok( status == STATUS_BUFFER_TOO_SMALL, "Got unexpected return code %#lx.\n", status ); + + free( enum_adapters_2_desc.pAdapters ); +} + +static void test_D3DKMTCloseAdapter(void) +{ + D3DKMT_CLOSEADAPTER close_adapter_desc; + NTSTATUS status; + + /* Invalid parameters */ + status = D3DKMTCloseAdapter( NULL ); + ok( status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#lx.\n", status ); + + memset( &close_adapter_desc, 0, sizeof(close_adapter_desc) ); + status = D3DKMTCloseAdapter( &close_adapter_desc ); + ok( status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#lx.\n", status ); +} + +static void test_D3DKMTCreateDevice(void) +{ + D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME open_adapter_gdi_desc; + D3DKMT_CREATEDEVICE create_device_desc; + D3DKMT_CLOSEADAPTER close_adapter_desc; + D3DKMT_DESTROYDEVICE destroy_device_desc; + NTSTATUS status; + + /* Invalid parameters */ + status = D3DKMTCreateDevice( NULL ); + ok( status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#lx.\n", status ); + + memset( &create_device_desc, 0, sizeof(create_device_desc) ); + status = D3DKMTCreateDevice( &create_device_desc ); + ok( status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#lx.\n", status ); + + lstrcpyW( open_adapter_gdi_desc.DeviceName, display1W ); + status = D3DKMTOpenAdapterFromGdiDisplayName( &open_adapter_gdi_desc ); + ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + + /* Create device */ + create_device_desc.hAdapter = open_adapter_gdi_desc.hAdapter; + status = D3DKMTCreateDevice( &create_device_desc ); + ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + ok( create_device_desc.hDevice, "Expect not null.\n" ); + ok( create_device_desc.pCommandBuffer == NULL, "Expect null.\n" ); + ok( create_device_desc.CommandBufferSize == 0, "Got wrong value %#x.\n", create_device_desc.CommandBufferSize ); + ok( create_device_desc.pAllocationList == NULL, "Expect null.\n" ); + ok( create_device_desc.AllocationListSize == 0, "Got wrong value %#x.\n", create_device_desc.AllocationListSize ); + ok( create_device_desc.pPatchLocationList == NULL, "Expect null.\n" ); + ok( create_device_desc.PatchLocationListSize == 0, "Got wrong value %#x.\n", + create_device_desc.PatchLocationListSize ); + + destroy_device_desc.hDevice = create_device_desc.hDevice; + status = D3DKMTDestroyDevice( &destroy_device_desc ); + ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + + close_adapter_desc.hAdapter = open_adapter_gdi_desc.hAdapter; + status = D3DKMTCloseAdapter( &close_adapter_desc ); + ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); +} + +static void test_D3DKMTDestroyDevice(void) +{ + D3DKMT_DESTROYDEVICE destroy_device_desc; + NTSTATUS status; + + /* Invalid parameters */ + status = D3DKMTDestroyDevice( NULL ); + ok( status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#lx.\n", status ); + + memset( &destroy_device_desc, 0, sizeof(destroy_device_desc) ); + status = D3DKMTDestroyDevice( &destroy_device_desc ); + ok( status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#lx.\n", status ); +} + +static void test_D3DKMTCheckVidPnExclusiveOwnership(void) +{ + static const DWORD timeout = 1000; + static const DWORD wait_step = 100; + D3DKMT_CREATEDEVICE create_device_desc, create_device_desc2; + D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME open_adapter_gdi_desc; + D3DKMT_CHECKVIDPNEXCLUSIVEOWNERSHIP check_owner_desc; + D3DKMT_DESTROYDEVICE destroy_device_desc; + D3DKMT_CLOSEADAPTER close_adapter_desc; + D3DKMT_VIDPNSOURCEOWNER_TYPE owner_type; + D3DKMT_SETVIDPNSOURCEOWNER set_owner_desc; + DWORD total_time; + NTSTATUS status; + INT i; + + /* Test cases using single device */ + static const struct test_data1 + { + D3DKMT_VIDPNSOURCEOWNER_TYPE owner_type; + NTSTATUS expected_set_status; + NTSTATUS expected_check_status; + } + tests1[] = + { + /* 0 */ + {-1, STATUS_SUCCESS, STATUS_SUCCESS}, + {D3DKMT_VIDPNSOURCEOWNER_UNOWNED, STATUS_SUCCESS, STATUS_SUCCESS}, + {-1, STATUS_SUCCESS, STATUS_SUCCESS}, + {D3DKMT_VIDPNSOURCEOWNER_SHARED, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS}, + {-1, STATUS_SUCCESS, STATUS_SUCCESS}, + {D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, STATUS_SUCCESS, STATUS_GRAPHICS_PRESENT_OCCLUDED}, + {-1, STATUS_SUCCESS, STATUS_SUCCESS}, + {D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVEGDI, STATUS_INVALID_PARAMETER, STATUS_SUCCESS}, + {-1, STATUS_SUCCESS, STATUS_SUCCESS}, + {D3DKMT_VIDPNSOURCEOWNER_EMULATED, STATUS_SUCCESS, STATUS_SUCCESS}, + /* 10 */ + {-1, STATUS_SUCCESS, STATUS_SUCCESS}, + {D3DKMT_VIDPNSOURCEOWNER_UNOWNED, STATUS_SUCCESS, STATUS_SUCCESS}, + {D3DKMT_VIDPNSOURCEOWNER_UNOWNED, STATUS_SUCCESS, STATUS_SUCCESS}, + {-1, STATUS_SUCCESS, STATUS_SUCCESS}, + {D3DKMT_VIDPNSOURCEOWNER_UNOWNED, STATUS_SUCCESS, STATUS_SUCCESS}, + {D3DKMT_VIDPNSOURCEOWNER_SHARED, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS}, + {-1, STATUS_SUCCESS, STATUS_SUCCESS}, + {D3DKMT_VIDPNSOURCEOWNER_UNOWNED, STATUS_SUCCESS, STATUS_SUCCESS}, + {D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, STATUS_SUCCESS, STATUS_GRAPHICS_PRESENT_OCCLUDED}, + {-1, STATUS_SUCCESS, STATUS_SUCCESS}, + /* 20 */ + {D3DKMT_VIDPNSOURCEOWNER_UNOWNED, STATUS_SUCCESS, STATUS_SUCCESS}, + {D3DKMT_VIDPNSOURCEOWNER_EMULATED, STATUS_SUCCESS, STATUS_SUCCESS}, + {-1, STATUS_SUCCESS, STATUS_SUCCESS}, + {D3DKMT_VIDPNSOURCEOWNER_SHARED, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS}, + {D3DKMT_VIDPNSOURCEOWNER_UNOWNED, STATUS_SUCCESS, STATUS_SUCCESS}, + {-1, STATUS_SUCCESS, STATUS_SUCCESS}, + {D3DKMT_VIDPNSOURCEOWNER_SHARED, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS}, + {D3DKMT_VIDPNSOURCEOWNER_SHARED, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS}, + {-1, STATUS_SUCCESS, STATUS_SUCCESS}, + {D3DKMT_VIDPNSOURCEOWNER_SHARED, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS}, + /* 30 */ + {D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, STATUS_SUCCESS, STATUS_GRAPHICS_PRESENT_OCCLUDED}, + {-1, STATUS_SUCCESS, STATUS_SUCCESS}, + {D3DKMT_VIDPNSOURCEOWNER_SHARED, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS}, + {D3DKMT_VIDPNSOURCEOWNER_EMULATED, STATUS_SUCCESS, STATUS_SUCCESS}, + {-1, STATUS_SUCCESS, STATUS_SUCCESS}, + {D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, STATUS_SUCCESS, STATUS_GRAPHICS_PRESENT_OCCLUDED}, + {D3DKMT_VIDPNSOURCEOWNER_UNOWNED, STATUS_SUCCESS, STATUS_SUCCESS}, + {-1, STATUS_SUCCESS, STATUS_SUCCESS}, + {D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, STATUS_SUCCESS, STATUS_GRAPHICS_PRESENT_OCCLUDED}, + {D3DKMT_VIDPNSOURCEOWNER_SHARED, STATUS_INVALID_PARAMETER, STATUS_GRAPHICS_PRESENT_OCCLUDED}, + /* 40 */ + {-1, STATUS_SUCCESS, STATUS_SUCCESS}, + {D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, STATUS_SUCCESS, STATUS_GRAPHICS_PRESENT_OCCLUDED}, + {D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, STATUS_SUCCESS, STATUS_GRAPHICS_PRESENT_OCCLUDED}, + {-1, STATUS_SUCCESS, STATUS_SUCCESS}, + {D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, STATUS_SUCCESS, STATUS_GRAPHICS_PRESENT_OCCLUDED}, + {D3DKMT_VIDPNSOURCEOWNER_EMULATED, STATUS_INVALID_PARAMETER, STATUS_GRAPHICS_PRESENT_OCCLUDED}, + {-1, STATUS_SUCCESS, STATUS_SUCCESS}, + {D3DKMT_VIDPNSOURCEOWNER_EMULATED, STATUS_SUCCESS, STATUS_SUCCESS}, + {D3DKMT_VIDPNSOURCEOWNER_UNOWNED, STATUS_SUCCESS, STATUS_SUCCESS}, + {-1, STATUS_SUCCESS, STATUS_SUCCESS}, + /* 50 */ + {D3DKMT_VIDPNSOURCEOWNER_EMULATED, STATUS_SUCCESS, STATUS_SUCCESS}, + {D3DKMT_VIDPNSOURCEOWNER_SHARED, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS}, + {-1, STATUS_SUCCESS, STATUS_SUCCESS}, + {D3DKMT_VIDPNSOURCEOWNER_EMULATED, STATUS_SUCCESS, STATUS_SUCCESS}, + {D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, STATUS_INVALID_PARAMETER, STATUS_SUCCESS}, + {-1, STATUS_SUCCESS, STATUS_SUCCESS}, + {D3DKMT_VIDPNSOURCEOWNER_EMULATED, STATUS_SUCCESS, STATUS_SUCCESS}, + {D3DKMT_VIDPNSOURCEOWNER_EMULATED, STATUS_SUCCESS, STATUS_SUCCESS}, + {-1, STATUS_SUCCESS, STATUS_SUCCESS}, + {D3DKMT_VIDPNSOURCEOWNER_EMULATED + 1, STATUS_INVALID_PARAMETER, STATUS_SUCCESS}, + }; + + /* Test cases using two devices consecutively */ + static const struct test_data2 + { + D3DKMT_VIDPNSOURCEOWNER_TYPE set_owner_type1; + D3DKMT_VIDPNSOURCEOWNER_TYPE set_owner_type2; + NTSTATUS expected_set_status1; + NTSTATUS expected_set_status2; + NTSTATUS expected_check_status; + } + tests2[] = + { + /* 0 */ + {D3DKMT_VIDPNSOURCEOWNER_UNOWNED, D3DKMT_VIDPNSOURCEOWNER_UNOWNED, STATUS_SUCCESS, STATUS_SUCCESS, STATUS_SUCCESS}, + {D3DKMT_VIDPNSOURCEOWNER_UNOWNED, D3DKMT_VIDPNSOURCEOWNER_SHARED, STATUS_SUCCESS, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS}, + {D3DKMT_VIDPNSOURCEOWNER_UNOWNED, D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, STATUS_SUCCESS, STATUS_SUCCESS, STATUS_GRAPHICS_PRESENT_OCCLUDED}, + {D3DKMT_VIDPNSOURCEOWNER_UNOWNED, D3DKMT_VIDPNSOURCEOWNER_EMULATED, STATUS_SUCCESS, STATUS_SUCCESS, STATUS_SUCCESS}, + {D3DKMT_VIDPNSOURCEOWNER_SHARED, D3DKMT_VIDPNSOURCEOWNER_UNOWNED, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS, STATUS_SUCCESS}, + {D3DKMT_VIDPNSOURCEOWNER_SHARED, D3DKMT_VIDPNSOURCEOWNER_SHARED, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS}, + {D3DKMT_VIDPNSOURCEOWNER_SHARED, D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS, STATUS_GRAPHICS_PRESENT_OCCLUDED}, + {D3DKMT_VIDPNSOURCEOWNER_SHARED, D3DKMT_VIDPNSOURCEOWNER_EMULATED, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS, STATUS_SUCCESS}, + {D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, D3DKMT_VIDPNSOURCEOWNER_UNOWNED, STATUS_SUCCESS, STATUS_SUCCESS, STATUS_GRAPHICS_PRESENT_OCCLUDED}, + {D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, D3DKMT_VIDPNSOURCEOWNER_SHARED, STATUS_SUCCESS, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_GRAPHICS_PRESENT_OCCLUDED}, + /* 10 */ + {D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, STATUS_SUCCESS, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_GRAPHICS_PRESENT_OCCLUDED}, + {D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, D3DKMT_VIDPNSOURCEOWNER_EMULATED, STATUS_SUCCESS, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_GRAPHICS_PRESENT_OCCLUDED}, + {D3DKMT_VIDPNSOURCEOWNER_EMULATED, D3DKMT_VIDPNSOURCEOWNER_UNOWNED, STATUS_SUCCESS, STATUS_SUCCESS, STATUS_SUCCESS}, + {D3DKMT_VIDPNSOURCEOWNER_EMULATED, D3DKMT_VIDPNSOURCEOWNER_SHARED, STATUS_SUCCESS, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS}, + {D3DKMT_VIDPNSOURCEOWNER_EMULATED, D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, STATUS_SUCCESS, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS}, + {D3DKMT_VIDPNSOURCEOWNER_EMULATED, D3DKMT_VIDPNSOURCEOWNER_EMULATED, STATUS_SUCCESS, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS}, + {-1, D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, -1, STATUS_SUCCESS, STATUS_GRAPHICS_PRESENT_OCCLUDED}, + {D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, -1, STATUS_SUCCESS, STATUS_SUCCESS, STATUS_GRAPHICS_PRESENT_OCCLUDED}, + }; + + /* Invalid parameters */ + status = D3DKMTCheckVidPnExclusiveOwnership( NULL ); + ok( status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#lx.\n", status ); + + memset( &check_owner_desc, 0, sizeof(check_owner_desc) ); + status = D3DKMTCheckVidPnExclusiveOwnership( &check_owner_desc ); + ok( status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#lx.\n", status ); + + /* Test cases */ + lstrcpyW( open_adapter_gdi_desc.DeviceName, display1W ); + status = D3DKMTOpenAdapterFromGdiDisplayName( &open_adapter_gdi_desc ); + ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + + memset( &create_device_desc, 0, sizeof(create_device_desc) ); + create_device_desc.hAdapter = open_adapter_gdi_desc.hAdapter; + status = D3DKMTCreateDevice( &create_device_desc ); + ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + + check_owner_desc.hAdapter = open_adapter_gdi_desc.hAdapter; + check_owner_desc.VidPnSourceId = open_adapter_gdi_desc.VidPnSourceId; + for (i = 0; i < ARRAY_SIZE(tests1); ++i) + { + set_owner_desc.hDevice = create_device_desc.hDevice; + if (tests1[i].owner_type != -1) + { + owner_type = tests1[i].owner_type; + set_owner_desc.pType = &owner_type; + set_owner_desc.pVidPnSourceId = &open_adapter_gdi_desc.VidPnSourceId; + set_owner_desc.VidPnSourceCount = 1; + } + else + { + set_owner_desc.pType = NULL; + set_owner_desc.pVidPnSourceId = NULL; + set_owner_desc.VidPnSourceCount = 0; + } + status = D3DKMTSetVidPnSourceOwner( &set_owner_desc ); + ok( status == tests1[i].expected_set_status, "Got unexpected return code %#lx at test %d.\n", status, i ); + + status = D3DKMTCheckVidPnExclusiveOwnership( &check_owner_desc ); + /* If don't sleep, D3DKMTCheckVidPnExclusiveOwnership may get + * STATUS_GRAPHICS_PRESENT_UNOCCLUDED instead of STATUS_SUCCESS */ + if ((tests1[i].expected_check_status == STATUS_SUCCESS && status == STATUS_GRAPHICS_PRESENT_UNOCCLUDED)) + { + total_time = 0; + do + { + Sleep( wait_step ); + total_time += wait_step; + status = D3DKMTCheckVidPnExclusiveOwnership( &check_owner_desc ); + } while (status == STATUS_GRAPHICS_PRESENT_UNOCCLUDED && total_time < timeout); + } + ok( status == tests1[i].expected_check_status, "Got unexpected return code %#lx at test %d.\n", status, i ); + } + + /* Set owner and unset owner using different devices */ + memset( &create_device_desc2, 0, sizeof(create_device_desc2) ); + create_device_desc2.hAdapter = open_adapter_gdi_desc.hAdapter; + status = D3DKMTCreateDevice( &create_device_desc2 ); + ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + + /* Set owner with the first device */ + set_owner_desc.hDevice = create_device_desc.hDevice; + owner_type = D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE; + set_owner_desc.pType = &owner_type; + set_owner_desc.pVidPnSourceId = &open_adapter_gdi_desc.VidPnSourceId; + set_owner_desc.VidPnSourceCount = 1; + status = D3DKMTSetVidPnSourceOwner( &set_owner_desc ); + ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + status = D3DKMTCheckVidPnExclusiveOwnership( &check_owner_desc ); + ok( status == STATUS_GRAPHICS_PRESENT_OCCLUDED, "Got unexpected return code %#lx.\n", status ); + + /* Unset owner with the second device */ + set_owner_desc.hDevice = create_device_desc2.hDevice; + set_owner_desc.pType = NULL; + set_owner_desc.pVidPnSourceId = NULL; + set_owner_desc.VidPnSourceCount = 0; + status = D3DKMTSetVidPnSourceOwner( &set_owner_desc ); + ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + status = D3DKMTCheckVidPnExclusiveOwnership( &check_owner_desc ); + /* No effect */ + ok( status == STATUS_GRAPHICS_PRESENT_OCCLUDED, "Got unexpected return code %#lx.\n", status ); + + /* Unset owner with the first device */ + set_owner_desc.hDevice = create_device_desc.hDevice; + set_owner_desc.pType = NULL; + set_owner_desc.pVidPnSourceId = NULL; + set_owner_desc.VidPnSourceCount = 0; + status = D3DKMTSetVidPnSourceOwner( &set_owner_desc ); + ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + status = D3DKMTCheckVidPnExclusiveOwnership( &check_owner_desc ); + /* Proves that the correct device is needed to unset owner */ + ok( status == STATUS_SUCCESS || status == STATUS_GRAPHICS_PRESENT_UNOCCLUDED, + "Got unexpected return code %#lx.\n", status ); + + /* Set owner with the first device, set owner again with the second device */ + for (i = 0; i < ARRAY_SIZE(tests2); ++i) + { + if (tests2[i].set_owner_type1 != -1) + { + set_owner_desc.hDevice = create_device_desc.hDevice; + owner_type = tests2[i].set_owner_type1; + set_owner_desc.pType = &owner_type; + set_owner_desc.pVidPnSourceId = &open_adapter_gdi_desc.VidPnSourceId; + set_owner_desc.VidPnSourceCount = 1; + /* If don't sleep, D3DKMTSetVidPnSourceOwner may return STATUS_OK for + * D3DKMT_VIDPNSOURCEOWNER_SHARED. Other owner type doesn't seems to be affected. */ + if (tests2[i].set_owner_type1 == D3DKMT_VIDPNSOURCEOWNER_SHARED) Sleep( timeout ); + status = D3DKMTSetVidPnSourceOwner( &set_owner_desc ); + ok( status == tests2[i].expected_set_status1, "Got unexpected return code %#lx at test %d.\n", status, i ); + } + + if (tests2[i].set_owner_type2 != -1) + { + set_owner_desc.hDevice = create_device_desc2.hDevice; + owner_type = tests2[i].set_owner_type2; + set_owner_desc.pType = &owner_type; + set_owner_desc.pVidPnSourceId = &open_adapter_gdi_desc.VidPnSourceId; + set_owner_desc.VidPnSourceCount = 1; + status = D3DKMTSetVidPnSourceOwner( &set_owner_desc ); + ok( status == tests2[i].expected_set_status2, "Got unexpected return code %#lx at test %d.\n", status, i ); + } + + status = D3DKMTCheckVidPnExclusiveOwnership( &check_owner_desc ); + if ((tests2[i].expected_check_status == STATUS_SUCCESS && status == STATUS_GRAPHICS_PRESENT_UNOCCLUDED)) + { + total_time = 0; + do + { + Sleep( wait_step ); + total_time += wait_step; + status = D3DKMTCheckVidPnExclusiveOwnership( &check_owner_desc ); + } while (status == STATUS_GRAPHICS_PRESENT_UNOCCLUDED && total_time < timeout); + } + ok( status == tests2[i].expected_check_status, "Got unexpected return code %#lx at test %d.\n", status, i ); + + /* Unset owner with first device */ + if (tests2[i].set_owner_type1 != -1) + { + set_owner_desc.hDevice = create_device_desc.hDevice; + set_owner_desc.pType = NULL; + set_owner_desc.pVidPnSourceId = NULL; + set_owner_desc.VidPnSourceCount = 0; + status = D3DKMTSetVidPnSourceOwner( &set_owner_desc ); + ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx at test %d.\n", status, i ); + } + + /* Unset owner with second device */ + if (tests2[i].set_owner_type2 != -1) + { + set_owner_desc.hDevice = create_device_desc2.hDevice; + set_owner_desc.pType = NULL; + set_owner_desc.pVidPnSourceId = NULL; + set_owner_desc.VidPnSourceCount = 0; + status = D3DKMTSetVidPnSourceOwner( &set_owner_desc ); + ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx at test %d.\n", status, i ); + } + } + + /* Destroy devices holding ownership */ + set_owner_desc.hDevice = create_device_desc.hDevice; + owner_type = D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE; + set_owner_desc.pType = &owner_type; + set_owner_desc.pVidPnSourceId = &open_adapter_gdi_desc.VidPnSourceId; + set_owner_desc.VidPnSourceCount = 1; + status = D3DKMTSetVidPnSourceOwner( &set_owner_desc ); + ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + + destroy_device_desc.hDevice = create_device_desc.hDevice; + status = D3DKMTDestroyDevice( &destroy_device_desc ); + ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + + set_owner_desc.hDevice = create_device_desc2.hDevice; + owner_type = D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE; + set_owner_desc.pType = &owner_type; + set_owner_desc.pVidPnSourceId = &open_adapter_gdi_desc.VidPnSourceId; + set_owner_desc.VidPnSourceCount = 1; + status = D3DKMTSetVidPnSourceOwner( &set_owner_desc ); + /* So ownership is released when device is destroyed. otherwise the return code should be + * STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE */ + ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + + destroy_device_desc.hDevice = create_device_desc2.hDevice; + status = D3DKMTDestroyDevice( &destroy_device_desc ); + ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + + close_adapter_desc.hAdapter = open_adapter_gdi_desc.hAdapter; + status = D3DKMTCloseAdapter( &close_adapter_desc ); + ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); +} + +static void test_D3DKMTSetVidPnSourceOwner(void) +{ + D3DKMT_SETVIDPNSOURCEOWNER set_owner_desc = {0}; + NTSTATUS status; + + /* Invalid parameters */ + status = D3DKMTSetVidPnSourceOwner( &set_owner_desc ); + ok( status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#lx.\n", status ); +} + +static void test_D3DKMTCheckOcclusion(void) +{ + DISPLAY_DEVICEW display_device = {sizeof(display_device)}; + D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME open_adapter_gdi_desc; + D3DKMT_CHECKVIDPNEXCLUSIVEOWNERSHIP check_owner_desc; + D3DKMT_SETVIDPNSOURCEOWNER set_owner_desc; + D3DKMT_DESTROYDEVICE destroy_device_desc; + D3DKMT_VIDPNSOURCEOWNER_TYPE owner_type; + D3DKMT_CLOSEADAPTER close_adapter_desc; + D3DKMT_CREATEDEVICE create_device_desc; + D3DKMT_CHECKOCCLUSION occlusion_desc; + NTSTATUS expected_occlusion, status; + INT i, adapter_count = 0; + HWND hwnd, hwnd2; + HRESULT hr; + + /* NULL parameter check */ + status = D3DKMTCheckOcclusion( NULL ); + todo_wine ok( status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#lx.\n", status ); + + occlusion_desc.hWnd = NULL; + status = D3DKMTCheckOcclusion( &occlusion_desc ); + todo_wine ok( status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#lx.\n", status ); + + hwnd = CreateWindowA( "static", "static1", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0, 0, 200, 200, 0, 0, 0, 0 ); + ok( hwnd != NULL, "Failed to create window.\n" ); + + occlusion_desc.hWnd = hwnd; + status = D3DKMTCheckOcclusion( &occlusion_desc ); + todo_wine ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + + /* Minimized state doesn't affect D3DKMTCheckOcclusion */ + ShowWindow( hwnd, SW_MINIMIZE ); + occlusion_desc.hWnd = hwnd; + status = D3DKMTCheckOcclusion( &occlusion_desc ); + flaky ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + ShowWindow( hwnd, SW_SHOWNORMAL ); + + /* Invisible state doesn't affect D3DKMTCheckOcclusion */ + ShowWindow( hwnd, SW_HIDE ); + occlusion_desc.hWnd = hwnd; + status = D3DKMTCheckOcclusion( &occlusion_desc ); + todo_wine ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + ShowWindow( hwnd, SW_SHOW ); + + /* hwnd2 covers hwnd */ + hwnd2 = CreateWindowA( "static", "static2", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 200, + 200, 0, 0, 0, 0 ); + ok( hwnd2 != NULL, "Failed to create window.\n" ); + + occlusion_desc.hWnd = hwnd; + status = D3DKMTCheckOcclusion( &occlusion_desc ); + todo_wine ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + + occlusion_desc.hWnd = hwnd2; + status = D3DKMTCheckOcclusion( &occlusion_desc ); + todo_wine ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + + /* Composition doesn't affect D3DKMTCheckOcclusion */ + hr = DwmEnableComposition( DWM_EC_DISABLECOMPOSITION ); + ok( hr == S_OK, "Failed to disable composition.\n" ); + + occlusion_desc.hWnd = hwnd; + status = D3DKMTCheckOcclusion( &occlusion_desc ); + /* This result means that D3DKMTCheckOcclusion doesn't check composition status despite MSDN says it will */ + todo_wine ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + + occlusion_desc.hWnd = hwnd2; + status = D3DKMTCheckOcclusion( &occlusion_desc ); + todo_wine ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + + ShowWindow( hwnd, SW_MINIMIZE ); + occlusion_desc.hWnd = hwnd; + status = D3DKMTCheckOcclusion( &occlusion_desc ); + flaky ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + ShowWindow( hwnd, SW_SHOWNORMAL ); + + ShowWindow( hwnd, SW_HIDE ); + occlusion_desc.hWnd = hwnd; + status = D3DKMTCheckOcclusion( &occlusion_desc ); + todo_wine ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + ShowWindow( hwnd, SW_SHOW ); + + hr = DwmEnableComposition( DWM_EC_ENABLECOMPOSITION ); + ok( hr == S_OK, "Failed to enable composition.\n" ); + + + lstrcpyW( open_adapter_gdi_desc.DeviceName, display1W ); + status = D3DKMTOpenAdapterFromGdiDisplayName( &open_adapter_gdi_desc ); + ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + + memset( &create_device_desc, 0, sizeof(create_device_desc) ); + create_device_desc.hAdapter = open_adapter_gdi_desc.hAdapter; + status = D3DKMTCreateDevice( &create_device_desc ); + ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + + check_owner_desc.hAdapter = open_adapter_gdi_desc.hAdapter; + check_owner_desc.VidPnSourceId = open_adapter_gdi_desc.VidPnSourceId; + status = D3DKMTCheckVidPnExclusiveOwnership( &check_owner_desc ); + /* D3DKMTCheckVidPnExclusiveOwnership gets STATUS_GRAPHICS_PRESENT_UNOCCLUDED sometimes and with + * some delay, it will always return STATUS_SUCCESS. So there are some timing issues here. */ + ok( status == STATUS_SUCCESS || status == STATUS_GRAPHICS_PRESENT_UNOCCLUDED, + "Got unexpected return code %#lx.\n", status ); + + /* Test D3DKMTCheckOcclusion relationship with video present source owner */ + set_owner_desc.hDevice = create_device_desc.hDevice; + owner_type = D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE; + set_owner_desc.pType = &owner_type; + set_owner_desc.pVidPnSourceId = &open_adapter_gdi_desc.VidPnSourceId; + set_owner_desc.VidPnSourceCount = 1; + status = D3DKMTSetVidPnSourceOwner( &set_owner_desc ); + ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + + for (i = 0; EnumDisplayDevicesW( NULL, i, &display_device, 0 ); ++i) + if ((display_device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)) adapter_count++; + /* STATUS_GRAPHICS_PRESENT_OCCLUDED on single monitor system. STATUS_SUCCESS on multiple monitor system. */ + expected_occlusion = adapter_count > 1 ? STATUS_SUCCESS : STATUS_GRAPHICS_PRESENT_OCCLUDED; + + occlusion_desc.hWnd = hwnd; + status = D3DKMTCheckOcclusion( &occlusion_desc ); + todo_wine ok( status == expected_occlusion, "Got unexpected return code %#lx.\n", status ); + + /* Note hwnd2 is not actually occluded but D3DKMTCheckOcclusion reports STATUS_GRAPHICS_PRESENT_OCCLUDED as well */ + SetWindowPos( hwnd2, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE ); + ShowWindow( hwnd2, SW_SHOW ); + occlusion_desc.hWnd = hwnd2; + status = D3DKMTCheckOcclusion( &occlusion_desc ); + todo_wine ok( status == expected_occlusion, "Got unexpected return code %#lx.\n", status ); + + /* Now hwnd is HWND_TOPMOST. Still reports STATUS_GRAPHICS_PRESENT_OCCLUDED */ + ok( SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE ), + "Failed to SetWindowPos.\n" ); + ok( GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOPMOST, "No WS_EX_TOPMOST style.\n" ); + occlusion_desc.hWnd = hwnd; + status = D3DKMTCheckOcclusion( &occlusion_desc ); + todo_wine ok( status == expected_occlusion, "Got unexpected return code %#lx.\n", status ); + + DestroyWindow( hwnd2 ); + occlusion_desc.hWnd = hwnd; + status = D3DKMTCheckOcclusion( &occlusion_desc ); + todo_wine ok( status == expected_occlusion, "Got unexpected return code %#lx.\n", status ); + + check_owner_desc.hAdapter = open_adapter_gdi_desc.hAdapter; + check_owner_desc.VidPnSourceId = open_adapter_gdi_desc.VidPnSourceId; + status = D3DKMTCheckVidPnExclusiveOwnership( &check_owner_desc ); + ok( status == STATUS_GRAPHICS_PRESENT_OCCLUDED, "Got unexpected return code %#lx.\n", status ); + + /* Unset video present source owner */ + set_owner_desc.hDevice = create_device_desc.hDevice; + set_owner_desc.pType = NULL; + set_owner_desc.pVidPnSourceId = NULL; + set_owner_desc.VidPnSourceCount = 0; + status = D3DKMTSetVidPnSourceOwner( &set_owner_desc ); + ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + + occlusion_desc.hWnd = hwnd; + status = D3DKMTCheckOcclusion( &occlusion_desc ); + flaky ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + + check_owner_desc.hAdapter = open_adapter_gdi_desc.hAdapter; + check_owner_desc.VidPnSourceId = open_adapter_gdi_desc.VidPnSourceId; + status = D3DKMTCheckVidPnExclusiveOwnership( &check_owner_desc ); + flaky ok( status == STATUS_SUCCESS || status == STATUS_GRAPHICS_PRESENT_UNOCCLUDED, + "Got unexpected return code %#lx.\n", status ); + + destroy_device_desc.hDevice = create_device_desc.hDevice; + status = D3DKMTDestroyDevice( &destroy_device_desc ); + ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + + close_adapter_desc.hAdapter = open_adapter_gdi_desc.hAdapter; + status = D3DKMTCloseAdapter( &close_adapter_desc ); + ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + DestroyWindow( hwnd ); +} + +static void test_D3DKMTOpenAdapterFromDeviceName_deviface( const GUID *devinterface_guid, NTSTATUS expected_status, BOOL todo ) +{ + BYTE iface_detail_buffer[sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) + 256 * sizeof(WCHAR)]; + SP_DEVINFO_DATA device_data = {sizeof(device_data)}; + SP_DEVICE_INTERFACE_DATA iface = {sizeof(iface)}; + SP_DEVICE_INTERFACE_DETAIL_DATA_W *iface_data; + D3DKMT_OPENADAPTERFROMDEVICENAME device_name; + D3DKMT_CLOSEADAPTER close_adapter_desc; + DEVPROPTYPE type; + NTSTATUS status; + unsigned int i; + HDEVINFO set; + LUID luid; + BOOL ret; + + set = SetupDiGetClassDevsW( devinterface_guid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT ); + ok( set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevs failed, error %lu.\n", GetLastError() ); + + iface_data = (SP_DEVICE_INTERFACE_DETAIL_DATA_W *)iface_detail_buffer; + iface_data->cbSize = sizeof(*iface_data); + device_name.pDeviceName = iface_data->DevicePath; + + i = 0; + while (SetupDiEnumDeviceInterfaces( set, NULL, devinterface_guid, i, &iface )) + { + ret = SetupDiGetDeviceInterfaceDetailW( set, &iface, iface_data, sizeof(iface_detail_buffer), NULL, &device_data ); + ok( ret, "Got unexpected ret %d, GetLastError() %lu.\n", ret, GetLastError() ); + + status = D3DKMTOpenAdapterFromDeviceName( &device_name ); + ok( status == expected_status, "Got status %#lx, expected %#lx.\n", status, expected_status ); + + if (!status) + { + ret = SetupDiGetDevicePropertyW( set, &device_data, &DEVPROPKEY_GPU_LUID, &type, + (BYTE *)&luid, sizeof(luid), NULL, 0 ); + ok( ret || GetLastError() == ERROR_NOT_FOUND, "Got unexpected ret %d, GetLastError() %lu.\n", ret, GetLastError() ); + + if (ret) + { + ret = RtlEqualLuid( &luid, &device_name.AdapterLuid ); + ok( ret, "Luid does not match.\n" ); + } + else + { + skip( "Luid not found.\n" ); + } + + close_adapter_desc.hAdapter = device_name.hAdapter; + status = D3DKMTCloseAdapter( &close_adapter_desc ); + ok( !status, "Got unexpected status %#lx.\n", status ); + } + ++i; + } + if (!i) win_skip( "No devices found.\n" ); + + SetupDiDestroyDeviceInfoList( set ); +} + +static void test_D3DKMTOpenAdapterFromDeviceName(void) +{ + D3DKMT_OPENADAPTERFROMDEVICENAME device_name; + NTSTATUS status; + + /* Make sure display devices are initialized. */ + SendMessageW( GetDesktopWindow(), WM_NULL, 0, 0 ); + + status = D3DKMTOpenAdapterFromDeviceName( NULL ); + ok( status == STATUS_INVALID_PARAMETER, "Got unexpected status %#lx.\n", status ); + + memset( &device_name, 0, sizeof(device_name) ); + status = D3DKMTOpenAdapterFromDeviceName( &device_name ); + ok( status == STATUS_INVALID_PARAMETER, "Got unexpected status %#lx.\n", status ); + + winetest_push_context( "GUID_DEVINTERFACE_DISPLAY_ADAPTER" ); + test_D3DKMTOpenAdapterFromDeviceName_deviface( &GUID_DEVINTERFACE_DISPLAY_ADAPTER, STATUS_INVALID_PARAMETER, TRUE ); + winetest_pop_context(); + + winetest_push_context( "GUID_DISPLAY_DEVICE_ARRIVAL" ); + test_D3DKMTOpenAdapterFromDeviceName_deviface( &GUID_DISPLAY_DEVICE_ARRIVAL, STATUS_SUCCESS, FALSE ); + winetest_pop_context(); +} + +static void test_D3DKMTQueryVideoMemoryInfo(void) +{ + static const D3DKMT_MEMORY_SEGMENT_GROUP groups[] = {D3DKMT_MEMORY_SEGMENT_GROUP_LOCAL, D3DKMT_MEMORY_SEGMENT_GROUP_NON_LOCAL}; + D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME open_adapter_desc; + D3DKMT_QUERYVIDEOMEMORYINFO query_memory_info; + D3DKMT_CLOSEADAPTER close_adapter_desc; + NTSTATUS status; + unsigned int i; + BOOL ret; + + ret = get_primary_adapter_name( open_adapter_desc.DeviceName ); + ok( ret, "Failed to get primary adapter name.\n" ); + status = D3DKMTOpenAdapterFromGdiDisplayName( &open_adapter_desc ); + ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + + /* Normal query */ + for (i = 0; i < ARRAY_SIZE(groups); ++i) + { + winetest_push_context( "group %d", groups[i] ); + + query_memory_info.hProcess = NULL; + query_memory_info.hAdapter = open_adapter_desc.hAdapter; + query_memory_info.PhysicalAdapterIndex = 0; + query_memory_info.MemorySegmentGroup = groups[i]; + status = D3DKMTQueryVideoMemoryInfo( &query_memory_info ); + todo_wine_if( status == STATUS_INVALID_PARAMETER ) /* fails on Wine without a Vulkan adapter */ + ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + ok( query_memory_info.Budget >= query_memory_info.AvailableForReservation, + "Unexpected budget %I64u and reservation %I64u.\n", query_memory_info.Budget, + query_memory_info.AvailableForReservation ); + ok( query_memory_info.CurrentUsage <= query_memory_info.Budget, + "Unexpected current usage %I64u.\n", query_memory_info.CurrentUsage ); + ok( query_memory_info.CurrentReservation == 0, "Unexpected current reservation %I64u.\n", + query_memory_info.CurrentReservation ); + + winetest_pop_context(); + } + + /* Query using the current process handle */ + query_memory_info.hProcess = GetCurrentProcess(); + status = D3DKMTQueryVideoMemoryInfo( &query_memory_info ); + todo_wine_if( status == STATUS_INVALID_PARAMETER ) /* fails on Wine without a Vulkan adapter */ + ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + + /* Query using a process handle without PROCESS_QUERY_INFORMATION privilege */ + query_memory_info.hProcess = OpenProcess( PROCESS_SET_INFORMATION, FALSE, GetCurrentProcessId() ); + ok( !!query_memory_info.hProcess, "OpenProcess failed, error %ld.\n", GetLastError() ); + status = D3DKMTQueryVideoMemoryInfo( &query_memory_info ); + ok( status == STATUS_ACCESS_DENIED, "Got unexpected return code %#lx.\n", status ); + CloseHandle( query_memory_info.hProcess ); + query_memory_info.hProcess = NULL; + + /* Query using an invalid process handle */ + query_memory_info.hProcess = (HANDLE)0xdeadbeef; + status = D3DKMTQueryVideoMemoryInfo( &query_memory_info ); + ok( status == STATUS_INVALID_HANDLE, "Got unexpected return code %#lx.\n", status ); + query_memory_info.hProcess = NULL; + + /* Query using an invalid adapter handle */ + query_memory_info.hAdapter = (D3DKMT_HANDLE)0xdeadbeef; + status = D3DKMTQueryVideoMemoryInfo( &query_memory_info ); + ok( status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#lx.\n", status ); + query_memory_info.hAdapter = open_adapter_desc.hAdapter; + + /* Query using an invalid adapter index */ + query_memory_info.PhysicalAdapterIndex = 99; + status = D3DKMTQueryVideoMemoryInfo( &query_memory_info ); + ok( status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#lx.\n", status ); + query_memory_info.PhysicalAdapterIndex = 0; + + /* Query using an invalid memory segment group */ + query_memory_info.MemorySegmentGroup = D3DKMT_MEMORY_SEGMENT_GROUP_NON_LOCAL + 1; + status = D3DKMTQueryVideoMemoryInfo( &query_memory_info ); + ok( status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#lx.\n", status ); + + close_adapter_desc.hAdapter = open_adapter_desc.hAdapter; + status = D3DKMTCloseAdapter( &close_adapter_desc ); + ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); +} + +static void test_gpu_device_properties_guid( const GUID *devinterface_guid ) +{ + BYTE iface_detail_buffer[sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) + 256 * sizeof(WCHAR)]; + SP_DEVINFO_DATA device_data = {sizeof(device_data)}; + SP_DEVICE_INTERFACE_DATA iface = {sizeof(iface)}; + SP_DEVICE_INTERFACE_DETAIL_DATA_W *iface_data; + WCHAR device_id[256]; + DEVPROPTYPE type; + unsigned int i; + UINT32 value; + HDEVINFO set; + BOOL ret; + + /* Make sure display devices are initialized. */ + SendMessageW( GetDesktopWindow(), WM_NULL, 0, 0 ); + + set = SetupDiGetClassDevsW( devinterface_guid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT ); + ok( set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevs failed, error %lu.\n", GetLastError() ); + + iface_data = (SP_DEVICE_INTERFACE_DETAIL_DATA_W *)iface_detail_buffer; + iface_data->cbSize = sizeof(*iface_data); + + i = 0; + while (SetupDiEnumDeviceInterfaces( set, NULL, devinterface_guid, i, &iface )) + { + ret = SetupDiGetDeviceInterfaceDetailW( set, &iface, iface_data, sizeof(iface_detail_buffer), NULL, &device_data ); + ok( ret, "Got unexpected ret %d, GetLastError() %lu.\n", ret, GetLastError() ); + + ret = SetupDiGetDevicePropertyW( set, &device_data, &DEVPKEY_Device_MatchingDeviceId, &type, + (BYTE *)device_id, sizeof(device_id), NULL, 0 ); + ok( ret, "Got unexpected ret %d, GetLastError() %lu.\n", ret, GetLastError() ); + ok( type == DEVPROP_TYPE_STRING, "Got type %ld.\n", type ); + + ret = SetupDiGetDevicePropertyW( set, &device_data, &DEVPKEY_Device_BusNumber, &type, + (BYTE *)&value, sizeof(value), NULL, 0 ); + if (!wcsicmp( device_id, L"root\basicrender" ) || + !wcsicmp( device_id, L"root\basicdisplay" )) + ok( !ret, "Found Bus Id.\n" ); + else + { + ok( ret, "Got unexpected ret %d, GetLastError() %lu, %s.\n", ret, GetLastError(), + debugstr_w(device_id)); + ok( type == DEVPROP_TYPE_UINT32, "Got type %ld.\n", type ); + } + + ret = SetupDiGetDevicePropertyW( set, &device_data, &DEVPKEY_Device_RemovalPolicy, &type, + (BYTE *)&value, sizeof(value), NULL, 0 ); + ok( ret, "Got unexpected ret %d, GetLastError() %lu, %s.\n", ret, GetLastError(), debugstr_w(device_id)); + ok( value == CM_REMOVAL_POLICY_EXPECT_NO_REMOVAL || value == CM_REMOVAL_POLICY_EXPECT_ORDERLY_REMOVAL || + value == CM_REMOVAL_POLICY_EXPECT_SURPRISE_REMOVAL, "Got value %d.\n", value ); + ok( type == DEVPROP_TYPE_UINT32, "Got type %ld.\n", type ); + ++i; + } + SetupDiDestroyDeviceInfoList( set ); +} + +static void test_gpu_device_properties(void) +{ + winetest_push_context( "GUID_DEVINTERFACE_DISPLAY_ADAPTER" ); + test_gpu_device_properties_guid( &GUID_DEVINTERFACE_DISPLAY_ADAPTER ); + winetest_pop_context(); + winetest_push_context( "GUID_DISPLAY_DEVICE_ARRIVAL" ); + test_gpu_device_properties_guid( &GUID_DISPLAY_DEVICE_ARRIVAL ); + winetest_pop_context(); +} + +static void test_D3DKMTQueryAdapterInfo(void) +{ + D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME open_adapter_desc; + D3DKMT_QUERYADAPTERINFO query_adapter_info; + D3DKMT_CLOSEADAPTER close_adapter_desc; + unsigned char buffer[1024]; + NTSTATUS status; + unsigned int i; + BOOL ret; + + static const struct + { + KMTQUERYADAPTERINFOTYPE type; + UINT size; + } + tests[] = + { + {KMTQAITYPE_CHECKDRIVERUPDATESTATUS, sizeof(BOOL)}, + {KMTQAITYPE_DRIVERVERSION, sizeof(D3DKMT_DRIVERVERSION)}, + }; + + ret = get_primary_adapter_name( open_adapter_desc.DeviceName ); + ok( ret, "Failed to get primary adapter name.\n" ); + status = D3DKMTOpenAdapterFromGdiDisplayName( &open_adapter_desc ); + ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + + for (i = 0; i < ARRAY_SIZE(tests); i++) + { + winetest_push_context( "type %d", tests[i].type ); + + /* NULL buffer */ + query_adapter_info.hAdapter = open_adapter_desc.hAdapter; + query_adapter_info.Type = tests[i].type; + query_adapter_info.pPrivateDriverData = NULL; + query_adapter_info.PrivateDriverDataSize = tests[i].size; + status = D3DKMTQueryAdapterInfo( &query_adapter_info ); + ok( status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#lx.\n", status ); + + /* Insufficient buffer size */ + query_adapter_info.pPrivateDriverData = buffer; + query_adapter_info.PrivateDriverDataSize = tests[i].size - 1; + status = D3DKMTQueryAdapterInfo( &query_adapter_info ); + ok( status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#lx.\n", status ); + + /* Normal */ + query_adapter_info.pPrivateDriverData = buffer; + query_adapter_info.PrivateDriverDataSize = tests[i].size; + status = D3DKMTQueryAdapterInfo( &query_adapter_info ); + ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + if (status != STATUS_SUCCESS) + { + winetest_pop_context(); + continue; + } + + switch (tests[i].type) + { + case KMTQAITYPE_CHECKDRIVERUPDATESTATUS: + { + BOOL *value = query_adapter_info.pPrivateDriverData; + ok( *value == FALSE, "Expected %d, got %d.\n", FALSE, *value ); + break; + } + case KMTQAITYPE_DRIVERVERSION: + { + D3DKMT_DRIVERVERSION *value = query_adapter_info.pPrivateDriverData; + ok( *value >= KMT_DRIVERVERSION_WDDM_1_3, "Expected %d >= %d.\n", *value, KMT_DRIVERVERSION_WDDM_1_3 ); + break; + } + default: + ok( 0, "Type %d is not handled.\n", tests[i].type ); + break; + } + + winetest_pop_context(); + } + + close_adapter_desc.hAdapter = open_adapter_desc.hAdapter; + status = D3DKMTCloseAdapter( &close_adapter_desc ); + ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); +} + +START_TEST( d3dkmt ) +{ + /* native win32u.dll fails if user32 is not loaded, so make sure it's fully initialized */ + GetDesktopWindow(); + + test_D3DKMTOpenAdapterFromGdiDisplayName(); + test_D3DKMTOpenAdapterFromHdc(); + test_D3DKMTEnumAdapters2(); + test_D3DKMTCloseAdapter(); + test_D3DKMTCreateDevice(); + test_D3DKMTDestroyDevice(); + test_D3DKMTCheckVidPnExclusiveOwnership(); + test_D3DKMTSetVidPnSourceOwner(); + test_D3DKMTCheckOcclusion(); + test_D3DKMTOpenAdapterFromDeviceName(); + test_D3DKMTQueryAdapterInfo(); + test_D3DKMTQueryVideoMemoryInfo(); + test_gpu_device_properties(); +}
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/tests/d3dkmt.c | 41 +++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-)
diff --git a/dlls/win32u/tests/d3dkmt.c b/dlls/win32u/tests/d3dkmt.c index 1af92036a1b..2c8b164b9f3 100644 --- a/dlls/win32u/tests/d3dkmt.c +++ b/dlls/win32u/tests/d3dkmt.c @@ -41,6 +41,15 @@ static const WCHAR display1W[] = L"\\.\DISPLAY1";
DEFINE_DEVPROPKEY(DEVPROPKEY_GPU_LUID, 0x60b193cb, 0x5276, 0x4d0f, 0x96, 0xfc, 0xf1, 0x73, 0xab, 0xad, 0x3e, 0xc6, 2);
+#define check_d3dkmt_local( a, b ) check_d3dkmt_local_( __LINE__, a, b ) +static void check_d3dkmt_local_( int line, D3DKMT_HANDLE handle, D3DKMT_HANDLE *next_local ) +{ + ok_(__FILE__, line)( handle & 0xc0000000, "got %#x\n", handle ); + ok_(__FILE__, line)( handle && !(handle & 0x3f), "got %#x\n", handle ); + if (next_local && *next_local) ok_(__FILE__, line)( handle == *next_local, "got %#x, expected %#x\n", handle, *next_local ); + if (next_local) *next_local = handle + 0x40; +} + static BOOL get_primary_adapter_name( WCHAR *name ) { DISPLAY_DEVICEW dd; @@ -64,12 +73,13 @@ static void test_D3DKMTOpenAdapterFromGdiDisplayName(void) D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME open_adapter_gdi_desc; D3DKMT_CLOSEADAPTER close_adapter_desc; DISPLAY_DEVICEW display_device = {sizeof(display_device)}; + D3DKMT_HANDLE next_local = 0; NTSTATUS status; DWORD i;
lstrcpyW( open_adapter_gdi_desc.DeviceName, display1W ); status = D3DKMTOpenAdapterFromGdiDisplayName( &open_adapter_gdi_desc ); - ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + todo_wine check_d3dkmt_local( open_adapter_gdi_desc.hAdapter, &next_local ); close_adapter_desc.hAdapter = open_adapter_gdi_desc.hAdapter; status = D3DKMTCloseAdapter( &close_adapter_desc ); ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); @@ -94,8 +104,7 @@ static void test_D3DKMTOpenAdapterFromGdiDisplayName(void) ok( status == STATUS_UNSUCCESSFUL, "Got unexpected return code %#lx.\n", status ); continue; } - - ok( open_adapter_gdi_desc.hAdapter, "Expect not null.\n" ); + todo_wine check_d3dkmt_local( open_adapter_gdi_desc.hAdapter, &next_local ); ok( open_adapter_gdi_desc.AdapterLuid.LowPart || open_adapter_gdi_desc.AdapterLuid.HighPart, "Expect LUID not zero.\n" );
@@ -110,6 +119,7 @@ static void test_D3DKMTOpenAdapterFromHdc(void) DISPLAY_DEVICEW display_device = {sizeof(display_device)}; D3DKMT_OPENADAPTERFROMHDC open_adapter_hdc_desc; D3DKMT_CLOSEADAPTER close_adapter_desc; + D3DKMT_HANDLE next_local = 0; INT adapter_count = 0; NTSTATUS status; HDC hdc; @@ -134,7 +144,7 @@ static void test_D3DKMTOpenAdapterFromHdc(void) open_adapter_hdc_desc.hDc = hdc; status = D3DKMTOpenAdapterFromHdc( &open_adapter_hdc_desc ); todo_wine ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); - todo_wine ok( open_adapter_hdc_desc.hAdapter, "Expect not null.\n" ); + todo_wine check_d3dkmt_local( open_adapter_hdc_desc.hAdapter, &next_local ); DeleteDC( hdc );
if (status == STATUS_SUCCESS) @@ -154,6 +164,7 @@ static void test_D3DKMTOpenAdapterFromHdc(void) "Got unexpected return code %#lx.\n", status ); if (status == STATUS_SUCCESS) { + todo_wine check_d3dkmt_local( open_adapter_hdc_desc.hAdapter, &next_local ); close_adapter_desc.hAdapter = open_adapter_hdc_desc.hAdapter; status = D3DKMTCloseAdapter( &close_adapter_desc ); ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); @@ -164,6 +175,7 @@ static void test_D3DKMTEnumAdapters2(void) { D3DKMT_ENUMADAPTERS2 enum_adapters_2_desc = {0}; D3DKMT_CLOSEADAPTER close_adapter_desc; + D3DKMT_HANDLE next_local = 0; NTSTATUS status; UINT i;
@@ -189,7 +201,7 @@ static void test_D3DKMTEnumAdapters2(void)
for (i = 0; i < enum_adapters_2_desc.NumAdapters; ++i) { - ok( enum_adapters_2_desc.pAdapters[i].hAdapter, "Expect not null.\n" ); + todo_wine check_d3dkmt_local( enum_adapters_2_desc.pAdapters[i].hAdapter, &next_local ); ok( enum_adapters_2_desc.pAdapters[i].AdapterLuid.LowPart || enum_adapters_2_desc.pAdapters[i].AdapterLuid.HighPart, "Expect LUID not zero.\n" ); @@ -227,6 +239,7 @@ static void test_D3DKMTCreateDevice(void) D3DKMT_CREATEDEVICE create_device_desc; D3DKMT_CLOSEADAPTER close_adapter_desc; D3DKMT_DESTROYDEVICE destroy_device_desc; + D3DKMT_HANDLE next_local = 0; NTSTATUS status;
/* Invalid parameters */ @@ -240,12 +253,13 @@ static void test_D3DKMTCreateDevice(void) lstrcpyW( open_adapter_gdi_desc.DeviceName, display1W ); status = D3DKMTOpenAdapterFromGdiDisplayName( &open_adapter_gdi_desc ); ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + todo_wine check_d3dkmt_local( open_adapter_gdi_desc.hAdapter, &next_local );
/* Create device */ create_device_desc.hAdapter = open_adapter_gdi_desc.hAdapter; status = D3DKMTCreateDevice( &create_device_desc ); ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); - ok( create_device_desc.hDevice, "Expect not null.\n" ); + todo_wine check_d3dkmt_local( create_device_desc.hDevice, &next_local ); ok( create_device_desc.pCommandBuffer == NULL, "Expect null.\n" ); ok( create_device_desc.CommandBufferSize == 0, "Got wrong value %#x.\n", create_device_desc.CommandBufferSize ); ok( create_device_desc.pAllocationList == NULL, "Expect null.\n" ); @@ -288,6 +302,7 @@ static void test_D3DKMTCheckVidPnExclusiveOwnership(void) D3DKMT_CLOSEADAPTER close_adapter_desc; D3DKMT_VIDPNSOURCEOWNER_TYPE owner_type; D3DKMT_SETVIDPNSOURCEOWNER set_owner_desc; + D3DKMT_HANDLE next_local = 0; DWORD total_time; NTSTATUS status; INT i; @@ -414,11 +429,13 @@ static void test_D3DKMTCheckVidPnExclusiveOwnership(void) lstrcpyW( open_adapter_gdi_desc.DeviceName, display1W ); status = D3DKMTOpenAdapterFromGdiDisplayName( &open_adapter_gdi_desc ); ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + todo_wine check_d3dkmt_local( open_adapter_gdi_desc.hAdapter, &next_local );
memset( &create_device_desc, 0, sizeof(create_device_desc) ); create_device_desc.hAdapter = open_adapter_gdi_desc.hAdapter; status = D3DKMTCreateDevice( &create_device_desc ); ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + todo_wine check_d3dkmt_local( create_device_desc.hDevice, &next_local );
check_owner_desc.hAdapter = open_adapter_gdi_desc.hAdapter; check_owner_desc.VidPnSourceId = open_adapter_gdi_desc.VidPnSourceId; @@ -462,6 +479,7 @@ static void test_D3DKMTCheckVidPnExclusiveOwnership(void) create_device_desc2.hAdapter = open_adapter_gdi_desc.hAdapter; status = D3DKMTCreateDevice( &create_device_desc2 ); ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + todo_wine check_d3dkmt_local( create_device_desc2.hDevice, &next_local );
/* Set owner with the first device */ set_owner_desc.hDevice = create_device_desc.hDevice; @@ -615,6 +633,7 @@ static void test_D3DKMTCheckOcclusion(void) D3DKMT_CREATEDEVICE create_device_desc; D3DKMT_CHECKOCCLUSION occlusion_desc; NTSTATUS expected_occlusion, status; + D3DKMT_HANDLE next_local = 0; INT i, adapter_count = 0; HWND hwnd, hwnd2; HRESULT hr; @@ -689,15 +708,16 @@ static void test_D3DKMTCheckOcclusion(void) hr = DwmEnableComposition( DWM_EC_ENABLECOMPOSITION ); ok( hr == S_OK, "Failed to enable composition.\n" );
- lstrcpyW( open_adapter_gdi_desc.DeviceName, display1W ); status = D3DKMTOpenAdapterFromGdiDisplayName( &open_adapter_gdi_desc ); ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + todo_wine check_d3dkmt_local( open_adapter_gdi_desc.hAdapter, &next_local );
memset( &create_device_desc, 0, sizeof(create_device_desc) ); create_device_desc.hAdapter = open_adapter_gdi_desc.hAdapter; status = D3DKMTCreateDevice( &create_device_desc ); ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + todo_wine check_d3dkmt_local( create_device_desc.hDevice, &next_local );
check_owner_desc.hAdapter = open_adapter_gdi_desc.hAdapter; check_owner_desc.VidPnSourceId = open_adapter_gdi_desc.VidPnSourceId; @@ -786,6 +806,7 @@ static void test_D3DKMTOpenAdapterFromDeviceName_deviface( const GUID *devinterf SP_DEVICE_INTERFACE_DETAIL_DATA_W *iface_data; D3DKMT_OPENADAPTERFROMDEVICENAME device_name; D3DKMT_CLOSEADAPTER close_adapter_desc; + D3DKMT_HANDLE next_local = 0; DEVPROPTYPE type; NTSTATUS status; unsigned int i; @@ -811,6 +832,8 @@ static void test_D3DKMTOpenAdapterFromDeviceName_deviface( const GUID *devinterf
if (!status) { + todo_wine check_d3dkmt_local( device_name.hAdapter, &next_local ); + ret = SetupDiGetDevicePropertyW( set, &device_data, &DEVPROPKEY_GPU_LUID, &type, (BYTE *)&luid, sizeof(luid), NULL, 0 ); ok( ret || GetLastError() == ERROR_NOT_FOUND, "Got unexpected ret %d, GetLastError() %lu.\n", ret, GetLastError() ); @@ -866,6 +889,7 @@ static void test_D3DKMTQueryVideoMemoryInfo(void) D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME open_adapter_desc; D3DKMT_QUERYVIDEOMEMORYINFO query_memory_info; D3DKMT_CLOSEADAPTER close_adapter_desc; + D3DKMT_HANDLE next_local = 0; NTSTATUS status; unsigned int i; BOOL ret; @@ -874,6 +898,7 @@ static void test_D3DKMTQueryVideoMemoryInfo(void) ok( ret, "Failed to get primary adapter name.\n" ); status = D3DKMTOpenAdapterFromGdiDisplayName( &open_adapter_desc ); ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + todo_wine check_d3dkmt_local( open_adapter_desc.hAdapter, &next_local );
/* Normal query */ for (i = 0; i < ARRAY_SIZE(groups); ++i) @@ -1011,6 +1036,7 @@ static void test_D3DKMTQueryAdapterInfo(void) D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME open_adapter_desc; D3DKMT_QUERYADAPTERINFO query_adapter_info; D3DKMT_CLOSEADAPTER close_adapter_desc; + D3DKMT_HANDLE next_local = 0; unsigned char buffer[1024]; NTSTATUS status; unsigned int i; @@ -1031,6 +1057,7 @@ static void test_D3DKMTQueryAdapterInfo(void) ok( ret, "Failed to get primary adapter name.\n" ); status = D3DKMTOpenAdapterFromGdiDisplayName( &open_adapter_desc ); ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); + todo_wine check_d3dkmt_local( open_adapter_desc.hAdapter, &next_local );
for (i = 0; i < ARRAY_SIZE(tests); i++) {
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/d3dkmt.c | 246 ++++++++++++++++++++++++------------- dlls/win32u/tests/d3dkmt.c | 28 ++--- 2 files changed, 176 insertions(+), 98 deletions(-)
diff --git a/dlls/win32u/d3dkmt.c b/dlls/win32u/d3dkmt.c index 1016b02ad5f..cdad56d1448 100644 --- a/dlls/win32u/d3dkmt.c +++ b/dlls/win32u/d3dkmt.c @@ -22,6 +22,7 @@
#include "config.h"
+#include <assert.h> #include <pthread.h>
#include "ntstatus.h" @@ -32,17 +33,29 @@
WINE_DEFAULT_DEBUG_CHANNEL(vulkan);
+enum d3dkmt_type +{ + D3DKMT_ADAPTER = 1, + D3DKMT_DEVICE = 2, + D3DKMT_SOURCE = 3, +}; + +struct d3dkmt_object +{ + enum d3dkmt_type type; /* object type */ + D3DKMT_HANDLE local; /* object local handle */ +}; + struct d3dkmt_adapter { - D3DKMT_HANDLE handle; /* Kernel mode graphics adapter handle */ - struct list entry; /* List entry */ - VkPhysicalDevice vk_device; /* Vulkan physical device */ + struct d3dkmt_object obj; /* object header */ + LUID luid; /* LUID of the adapter */ };
struct d3dkmt_device { - D3DKMT_HANDLE handle; /* Kernel mode graphics device handle*/ - struct list entry; /* List entry */ + struct d3dkmt_object obj; /* object header */ + LUID luid; /* LUID of the device adapter */ };
struct d3dkmt_vidpn_source @@ -54,10 +67,106 @@ struct d3dkmt_vidpn_source };
static pthread_mutex_t d3dkmt_lock = PTHREAD_MUTEX_INITIALIZER; -static struct list d3dkmt_adapters = LIST_INIT( d3dkmt_adapters ); -static struct list d3dkmt_devices = LIST_INIT( d3dkmt_devices ); static struct list d3dkmt_vidpn_sources = LIST_INIT( d3dkmt_vidpn_sources ); /* VidPN source information list */
+static struct d3dkmt_object **objects; +static unsigned int object_count, object_capacity, last_index; + +/* return the position of the first object which handle is not less than + * the given local handle, d3dkmt_lock must be held. */ +static unsigned int object_handle_lower_bound( D3DKMT_HANDLE local ) +{ + unsigned int begin = 0, end = object_count, mid; + + while (begin < end) + { + mid = begin + (end - begin) / 2; + if (objects[mid]->local < local) begin = mid + 1; + else end = mid; + } + + return begin; +} + +/* allocate a d3dkmt object with a local handle */ +static NTSTATUS alloc_object_handle( struct d3dkmt_object *object ) +{ + D3DKMT_HANDLE handle = 0; + unsigned int index; + + pthread_mutex_lock( &d3dkmt_lock ); + + if (object_count >= object_capacity) + { + unsigned int capacity = max( 32, object_capacity * 3 / 2 ); + struct d3dkmt_object **tmp; + assert( capacity > object_capacity ); + + if (capacity >= 0xffff) goto done; + if (!(tmp = realloc( objects, capacity * sizeof(*objects) ))) goto done; + object_capacity = capacity; + objects = tmp; + } + + last_index += 0x40; + handle = object->local = (last_index & ~0xc0000000) | 0x40000000; + index = object_handle_lower_bound( object->local ); + if (index < object_count) memmove( objects + index + 1, objects, (object_count - index) * sizeof(*objects) ); + objects[index] = object; + object_count++; + +done: + pthread_mutex_unlock( &d3dkmt_lock ); + return handle ? STATUS_SUCCESS : STATUS_NO_MEMORY; +} + +/* free a d3dkmt local object handle */ +static void free_object_handle( struct d3dkmt_object *object ) +{ + unsigned int index; + + pthread_mutex_lock( &d3dkmt_lock ); + index = object_handle_lower_bound( object->local ); + assert( index < object_count && objects[index] == object ); + object_count--; + object->local = 0; + memmove( objects + index, objects + index + 1, (object_count - index) * sizeof(*objects) ); + pthread_mutex_unlock( &d3dkmt_lock ); +} + +/* return a pointer to a d3dkmt object from its local handle */ +static void *get_d3dkmt_object( D3DKMT_HANDLE local, enum d3dkmt_type type ) +{ + struct d3dkmt_object *object; + unsigned int index; + + pthread_mutex_lock( &d3dkmt_lock ); + index = object_handle_lower_bound( local ); + if (index >= object_count) object = NULL; + else object = objects[index]; + pthread_mutex_unlock( &d3dkmt_lock ); + + if (!object || object->local != local || (type != -1 && object->type != type)) return NULL; + return object; +} + +static NTSTATUS d3dkmt_object_alloc( UINT size, enum d3dkmt_type type, void **obj ) +{ + struct d3dkmt_object *object; + + if (!(object = calloc( 1, size ))) return STATUS_NO_MEMORY; + object->type = type; + + *obj = object; + return STATUS_SUCCESS; +} + +static void d3dkmt_object_free( struct d3dkmt_object *object ) +{ + if (object->local) free_object_handle( object ); + free( object ); +} + static VkInstance d3dkmt_vk_instance; /* Vulkan instance for D3DKMT functions */ static PFN_vkGetPhysicalDeviceMemoryProperties2KHR pvkGetPhysicalDeviceMemoryProperties2KHR; static PFN_vkGetPhysicalDeviceMemoryProperties pvkGetPhysicalDeviceMemoryProperties; @@ -117,15 +226,6 @@ static BOOL d3dkmt_use_vulkan(void) return !!d3dkmt_vk_instance; }
-/* d3dkmt_lock must be held */ -static struct d3dkmt_adapter *find_adapter_from_handle( D3DKMT_HANDLE handle ) -{ - struct d3dkmt_adapter *adapter; - LIST_FOR_EACH_ENTRY( adapter, &d3dkmt_adapters, struct d3dkmt_adapter, entry ) - if (adapter->handle == handle) return adapter; - return NULL; -} - /****************************************************************************** * NtGdiDdDDIOpenAdapterFromHdc (win32u.@) */ @@ -149,23 +249,15 @@ NTSTATUS WINAPI NtGdiDdDDIEscape( const D3DKMT_ESCAPE *desc ) */ NTSTATUS WINAPI NtGdiDdDDICloseAdapter( const D3DKMT_CLOSEADAPTER *desc ) { - NTSTATUS status = STATUS_INVALID_PARAMETER; - struct d3dkmt_adapter *adapter; + struct d3dkmt_object *adapter;
TRACE( "(%p)\n", desc );
if (!desc || !desc->hAdapter) return STATUS_INVALID_PARAMETER; + if (!(adapter = get_d3dkmt_object( desc->hAdapter, D3DKMT_ADAPTER ))) return STATUS_INVALID_PARAMETER;
- pthread_mutex_lock( &d3dkmt_lock ); - if ((adapter = find_adapter_from_handle( desc->hAdapter ))) - { - list_remove( &adapter->entry ); - status = STATUS_SUCCESS; - } - pthread_mutex_unlock( &d3dkmt_lock ); - - free( adapter ); - return status; + d3dkmt_object_free( adapter ); + return STATUS_SUCCESS; }
static UINT get_vulkan_physical_devices( VkPhysicalDevice **devices ) @@ -191,10 +283,17 @@ static UINT get_vulkan_physical_devices( VkPhysicalDevice **devices ) return device_count; }
-static VkPhysicalDevice get_vulkan_physical_device( const GUID *uuid ) +static VkPhysicalDevice get_vulkan_physical_device( const LUID *luid ) { VkPhysicalDevice *devices, device; UINT device_count, i; + GUID uuid; + + if (!get_vulkan_uuid_from_luid( luid, &uuid )) + { + WARN( "Failed to find Vulkan device with LUID %08x:%08x.\n", luid->HighPart, luid->LowPart ); + return VK_NULL_HANDLE; + }
if (!(device_count = get_vulkan_physical_devices( &devices ))) return VK_NULL_HANDLE;
@@ -204,7 +303,7 @@ static VkPhysicalDevice get_vulkan_physical_device( const GUID *uuid ) VkPhysicalDeviceProperties2 properties2 = {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, .pNext = &id};
pvkGetPhysicalDeviceProperties2KHR( devices[i], &properties2 ); - if (IsEqualGUID( uuid, id.deviceUUID )) + if (IsEqualGUID( &uuid, id.deviceUUID )) { device = devices[i]; break; @@ -220,26 +319,22 @@ static VkPhysicalDevice get_vulkan_physical_device( const GUID *uuid ) */ NTSTATUS WINAPI NtGdiDdDDIOpenAdapterFromLuid( D3DKMT_OPENADAPTERFROMLUID *desc ) { - static D3DKMT_HANDLE handle_start = 0; struct d3dkmt_adapter *adapter; - GUID uuid = {0}; + NTSTATUS status;
- if (!(adapter = calloc( 1, sizeof(*adapter) ))) return STATUS_NO_MEMORY; + if ((status = d3dkmt_object_alloc( sizeof(*adapter), D3DKMT_ADAPTER, (void **)&adapter ))) return status; + if ((status = alloc_object_handle( &adapter->obj ))) goto failed;
- if (!d3dkmt_use_vulkan()) - WARN( "Vulkan is unavailable.\n" ); - else if (!get_vulkan_uuid_from_luid( &desc->AdapterLuid, &uuid )) - WARN( "Failed to find Vulkan device with LUID %08x:%08x.\n", - desc->AdapterLuid.HighPart, desc->AdapterLuid.LowPart ); - else if (!(adapter->vk_device = get_vulkan_physical_device( &uuid ))) - WARN( "Failed to find vulkan device with GUID %s\n", debugstr_guid( &uuid ) ); - - pthread_mutex_lock( &d3dkmt_lock ); - desc->hAdapter = adapter->handle = ++handle_start; - list_add_tail( &d3dkmt_adapters, &adapter->entry ); - pthread_mutex_unlock( &d3dkmt_lock ); + if (!d3dkmt_use_vulkan()) WARN( "Vulkan is unavailable.\n" ); + else if (!get_vulkan_physical_device( &desc->AdapterLuid )) WARN( "Failed to find vulkan device\n" ); + else adapter->luid = desc->AdapterLuid;
+ desc->hAdapter = adapter->obj.local; return STATUS_SUCCESS; + +failed: + d3dkmt_object_free( &adapter->obj ); + return status; }
/****************************************************************************** @@ -247,33 +342,27 @@ NTSTATUS WINAPI NtGdiDdDDIOpenAdapterFromLuid( D3DKMT_OPENADAPTERFROMLUID *desc */ NTSTATUS WINAPI NtGdiDdDDICreateDevice( D3DKMT_CREATEDEVICE *desc ) { - static D3DKMT_HANDLE handle_start = 0; + struct d3dkmt_adapter *adapter; struct d3dkmt_device *device; - BOOL found = FALSE; + NTSTATUS status;
TRACE( "(%p)\n", desc );
if (!desc) return STATUS_INVALID_PARAMETER; + if (desc->Flags.LegacyMode || desc->Flags.RequestVSync || desc->Flags.DisableGpuTimeout) FIXME( "Flags unsupported.\n" );
- pthread_mutex_lock( &d3dkmt_lock ); - found = !!find_adapter_from_handle( desc->hAdapter ); - pthread_mutex_unlock( &d3dkmt_lock ); - - if (!found) return STATUS_INVALID_PARAMETER; + if (!(adapter = get_d3dkmt_object( desc->hAdapter, D3DKMT_ADAPTER ))) return STATUS_INVALID_PARAMETER; + if ((status = d3dkmt_object_alloc( sizeof(*device), D3DKMT_DEVICE, (void **)&device ))) return status; + if ((status = alloc_object_handle( &device->obj ))) goto failed;
- if (desc->Flags.LegacyMode || desc->Flags.RequestVSync || desc->Flags.DisableGpuTimeout) - FIXME( "Flags unsupported.\n" ); - - device = calloc( 1, sizeof(*device) ); - if (!device) return STATUS_NO_MEMORY; - - pthread_mutex_lock( &d3dkmt_lock ); - device->handle = ++handle_start; - list_add_tail( &d3dkmt_devices, &device->entry ); - pthread_mutex_unlock( &d3dkmt_lock ); + device->luid = adapter->luid;
- desc->hDevice = device->handle; + desc->hDevice = device->obj.local; return STATUS_SUCCESS; + +failed: + d3dkmt_object_free( &device->obj ); + return status; }
/****************************************************************************** @@ -282,29 +371,17 @@ NTSTATUS WINAPI NtGdiDdDDICreateDevice( D3DKMT_CREATEDEVICE *desc ) NTSTATUS WINAPI NtGdiDdDDIDestroyDevice( const D3DKMT_DESTROYDEVICE *desc ) { D3DKMT_SETVIDPNSOURCEOWNER set_owner_desc = {0}; - struct d3dkmt_device *device, *found = NULL; + struct d3dkmt_object *device;
TRACE( "(%p)\n", desc );
if (!desc || !desc->hDevice) return STATUS_INVALID_PARAMETER; - - pthread_mutex_lock( &d3dkmt_lock ); - LIST_FOR_EACH_ENTRY( device, &d3dkmt_devices, struct d3dkmt_device, entry ) - { - if (device->handle == desc->hDevice) - { - list_remove( &device->entry ); - found = device; - break; - } - } - pthread_mutex_unlock( &d3dkmt_lock ); - - if (!found) return STATUS_INVALID_PARAMETER; + if (!(device = get_d3dkmt_object( desc->hDevice, D3DKMT_DEVICE ))) return STATUS_INVALID_PARAMETER;
set_owner_desc.hDevice = desc->hDevice; NtGdiDdDDISetVidPnSourceOwner( &set_owner_desc ); - free( found ); + + d3dkmt_object_free( device ); return STATUS_SUCCESS; }
@@ -364,6 +441,7 @@ NTSTATUS WINAPI NtGdiDdDDIQueryVideoMemoryInfo( D3DKMT_QUERYVIDEOMEMORYINFO *des { VkPhysicalDeviceMemoryBudgetPropertiesEXT budget; VkPhysicalDeviceMemoryProperties2 properties2; + VkPhysicalDevice phys_dev; struct d3dkmt_adapter *adapter; OBJECT_BASIC_INFORMATION info; NTSTATUS status; @@ -384,19 +462,20 @@ NTSTATUS WINAPI NtGdiDdDDIQueryVideoMemoryInfo( D3DKMT_QUERYVIDEOMEMORYINFO *des if (status != STATUS_SUCCESS) return status; if (!(info.GrantedAccess & PROCESS_QUERY_INFORMATION)) return STATUS_ACCESS_DENIED;
+ if (!(adapter = get_d3dkmt_object( desc->hAdapter, D3DKMT_ADAPTER ))) return STATUS_INVALID_PARAMETER; + desc->Budget = 0; desc->CurrentUsage = 0; desc->CurrentReservation = 0; desc->AvailableForReservation = 0;
- pthread_mutex_lock( &d3dkmt_lock ); - if ((adapter = find_adapter_from_handle( desc->hAdapter )) && adapter->vk_device) + if ((phys_dev = get_vulkan_physical_device( &adapter->luid ))) { memset( &budget, 0, sizeof(budget) ); budget.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT; properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2; properties2.pNext = &budget; - pvkGetPhysicalDeviceMemoryProperties2KHR( adapter->vk_device, &properties2 ); + pvkGetPhysicalDeviceMemoryProperties2KHR( phys_dev, &properties2 ); for (i = 0; i < properties2.memoryProperties.memoryHeapCount; ++i) { if ((desc->MemorySegmentGroup == D3DKMT_MEMORY_SEGMENT_GROUP_LOCAL && @@ -410,9 +489,8 @@ NTSTATUS WINAPI NtGdiDdDDIQueryVideoMemoryInfo( D3DKMT_QUERYVIDEOMEMORYINFO *des } desc->AvailableForReservation = desc->Budget / 2; } - pthread_mutex_unlock( &d3dkmt_lock );
- return adapter ? STATUS_SUCCESS : STATUS_INVALID_PARAMETER; + return STATUS_SUCCESS; }
/****************************************************************************** diff --git a/dlls/win32u/tests/d3dkmt.c b/dlls/win32u/tests/d3dkmt.c index 2c8b164b9f3..1ad2e3a3b6d 100644 --- a/dlls/win32u/tests/d3dkmt.c +++ b/dlls/win32u/tests/d3dkmt.c @@ -79,7 +79,7 @@ static void test_D3DKMTOpenAdapterFromGdiDisplayName(void)
lstrcpyW( open_adapter_gdi_desc.DeviceName, display1W ); status = D3DKMTOpenAdapterFromGdiDisplayName( &open_adapter_gdi_desc ); - todo_wine check_d3dkmt_local( open_adapter_gdi_desc.hAdapter, &next_local ); + check_d3dkmt_local( open_adapter_gdi_desc.hAdapter, &next_local ); close_adapter_desc.hAdapter = open_adapter_gdi_desc.hAdapter; status = D3DKMTCloseAdapter( &close_adapter_desc ); ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); @@ -104,7 +104,7 @@ static void test_D3DKMTOpenAdapterFromGdiDisplayName(void) ok( status == STATUS_UNSUCCESSFUL, "Got unexpected return code %#lx.\n", status ); continue; } - todo_wine check_d3dkmt_local( open_adapter_gdi_desc.hAdapter, &next_local ); + check_d3dkmt_local( open_adapter_gdi_desc.hAdapter, &next_local ); ok( open_adapter_gdi_desc.AdapterLuid.LowPart || open_adapter_gdi_desc.AdapterLuid.HighPart, "Expect LUID not zero.\n" );
@@ -164,7 +164,7 @@ static void test_D3DKMTOpenAdapterFromHdc(void) "Got unexpected return code %#lx.\n", status ); if (status == STATUS_SUCCESS) { - todo_wine check_d3dkmt_local( open_adapter_hdc_desc.hAdapter, &next_local ); + check_d3dkmt_local( open_adapter_hdc_desc.hAdapter, &next_local ); close_adapter_desc.hAdapter = open_adapter_hdc_desc.hAdapter; status = D3DKMTCloseAdapter( &close_adapter_desc ); ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); @@ -201,7 +201,7 @@ static void test_D3DKMTEnumAdapters2(void)
for (i = 0; i < enum_adapters_2_desc.NumAdapters; ++i) { - todo_wine check_d3dkmt_local( enum_adapters_2_desc.pAdapters[i].hAdapter, &next_local ); + check_d3dkmt_local( enum_adapters_2_desc.pAdapters[i].hAdapter, &next_local ); ok( enum_adapters_2_desc.pAdapters[i].AdapterLuid.LowPart || enum_adapters_2_desc.pAdapters[i].AdapterLuid.HighPart, "Expect LUID not zero.\n" ); @@ -253,13 +253,13 @@ static void test_D3DKMTCreateDevice(void) lstrcpyW( open_adapter_gdi_desc.DeviceName, display1W ); status = D3DKMTOpenAdapterFromGdiDisplayName( &open_adapter_gdi_desc ); ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); - todo_wine check_d3dkmt_local( open_adapter_gdi_desc.hAdapter, &next_local ); + check_d3dkmt_local( open_adapter_gdi_desc.hAdapter, &next_local );
/* Create device */ create_device_desc.hAdapter = open_adapter_gdi_desc.hAdapter; status = D3DKMTCreateDevice( &create_device_desc ); ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); - todo_wine check_d3dkmt_local( create_device_desc.hDevice, &next_local ); + check_d3dkmt_local( create_device_desc.hDevice, &next_local ); ok( create_device_desc.pCommandBuffer == NULL, "Expect null.\n" ); ok( create_device_desc.CommandBufferSize == 0, "Got wrong value %#x.\n", create_device_desc.CommandBufferSize ); ok( create_device_desc.pAllocationList == NULL, "Expect null.\n" ); @@ -429,13 +429,13 @@ static void test_D3DKMTCheckVidPnExclusiveOwnership(void) lstrcpyW( open_adapter_gdi_desc.DeviceName, display1W ); status = D3DKMTOpenAdapterFromGdiDisplayName( &open_adapter_gdi_desc ); ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); - todo_wine check_d3dkmt_local( open_adapter_gdi_desc.hAdapter, &next_local ); + check_d3dkmt_local( open_adapter_gdi_desc.hAdapter, &next_local );
memset( &create_device_desc, 0, sizeof(create_device_desc) ); create_device_desc.hAdapter = open_adapter_gdi_desc.hAdapter; status = D3DKMTCreateDevice( &create_device_desc ); ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); - todo_wine check_d3dkmt_local( create_device_desc.hDevice, &next_local ); + check_d3dkmt_local( create_device_desc.hDevice, &next_local );
check_owner_desc.hAdapter = open_adapter_gdi_desc.hAdapter; check_owner_desc.VidPnSourceId = open_adapter_gdi_desc.VidPnSourceId; @@ -479,7 +479,7 @@ static void test_D3DKMTCheckVidPnExclusiveOwnership(void) create_device_desc2.hAdapter = open_adapter_gdi_desc.hAdapter; status = D3DKMTCreateDevice( &create_device_desc2 ); ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); - todo_wine check_d3dkmt_local( create_device_desc2.hDevice, &next_local ); + check_d3dkmt_local( create_device_desc2.hDevice, &next_local );
/* Set owner with the first device */ set_owner_desc.hDevice = create_device_desc.hDevice; @@ -711,13 +711,13 @@ static void test_D3DKMTCheckOcclusion(void) lstrcpyW( open_adapter_gdi_desc.DeviceName, display1W ); status = D3DKMTOpenAdapterFromGdiDisplayName( &open_adapter_gdi_desc ); ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); - todo_wine check_d3dkmt_local( open_adapter_gdi_desc.hAdapter, &next_local ); + check_d3dkmt_local( open_adapter_gdi_desc.hAdapter, &next_local );
memset( &create_device_desc, 0, sizeof(create_device_desc) ); create_device_desc.hAdapter = open_adapter_gdi_desc.hAdapter; status = D3DKMTCreateDevice( &create_device_desc ); ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); - todo_wine check_d3dkmt_local( create_device_desc.hDevice, &next_local ); + check_d3dkmt_local( create_device_desc.hDevice, &next_local );
check_owner_desc.hAdapter = open_adapter_gdi_desc.hAdapter; check_owner_desc.VidPnSourceId = open_adapter_gdi_desc.VidPnSourceId; @@ -832,7 +832,7 @@ static void test_D3DKMTOpenAdapterFromDeviceName_deviface( const GUID *devinterf
if (!status) { - todo_wine check_d3dkmt_local( device_name.hAdapter, &next_local ); + check_d3dkmt_local( device_name.hAdapter, &next_local );
ret = SetupDiGetDevicePropertyW( set, &device_data, &DEVPROPKEY_GPU_LUID, &type, (BYTE *)&luid, sizeof(luid), NULL, 0 ); @@ -898,7 +898,7 @@ static void test_D3DKMTQueryVideoMemoryInfo(void) ok( ret, "Failed to get primary adapter name.\n" ); status = D3DKMTOpenAdapterFromGdiDisplayName( &open_adapter_desc ); ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); - todo_wine check_d3dkmt_local( open_adapter_desc.hAdapter, &next_local ); + check_d3dkmt_local( open_adapter_desc.hAdapter, &next_local );
/* Normal query */ for (i = 0; i < ARRAY_SIZE(groups); ++i) @@ -1057,7 +1057,7 @@ static void test_D3DKMTQueryAdapterInfo(void) ok( ret, "Failed to get primary adapter name.\n" ); status = D3DKMTOpenAdapterFromGdiDisplayName( &open_adapter_desc ); ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); - todo_wine check_d3dkmt_local( open_adapter_desc.hAdapter, &next_local ); + check_d3dkmt_local( open_adapter_desc.hAdapter, &next_local );
for (i = 0; i < ARRAY_SIZE(tests); i++) {