Signed-off-by: Zhiyi Zhang zzhang@codeweavers.com --- dlls/gdi32/Makefile.in | 2 +- dlls/gdi32/driver.c | 100 ++++++++++++++++++++++++++++++++++++-- dlls/gdi32/tests/driver.c | 2 + 3 files changed, 99 insertions(+), 5 deletions(-)
diff --git a/dlls/gdi32/Makefile.in b/dlls/gdi32/Makefile.in index e1ac922ce52..32b2e6959c1 100644 --- a/dlls/gdi32/Makefile.in +++ b/dlls/gdi32/Makefile.in @@ -4,7 +4,7 @@ IMPORTLIB = gdi32 IMPORTS = advapi32 EXTRAINCL = $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) EXTRALIBS = $(CARBON_LIBS) $(APPKIT_LIBS) -DELAYIMPORTS = usp10 +DELAYIMPORTS = usp10 setupapi
C_SRCS = \ bidi.c \ diff --git a/dlls/gdi32/driver.c b/dlls/gdi32/driver.c index 90977383a58..8eedc821146 100644 --- a/dlls/gdi32/driver.c +++ b/dlls/gdi32/driver.c @@ -31,10 +31,14 @@ #include "windef.h" #include "winbase.h" #include "wingdi.h" +#include "winreg.h" #include "ddrawgdi.h" #include "wine/winbase16.h" #include "winuser.h" #include "winternl.h" +#include "initguid.h" +#include "devguid.h" +#include "setupapi.h" #include "ddk/d3dkmthk.h"
#include "gdi_private.h" @@ -45,6 +49,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(driver);
+DEFINE_DEVPROPKEY(DEVPROPKEY_GPU_LUID, 0x60b193cb, 0x5276, 0x4d0f, 0x96, 0xfc, 0xf1, 0x73, 0xab, 0xad, 0x3e, 0xc6, 2); + struct graphics_driver { struct list entry; @@ -84,6 +90,7 @@ static CRITICAL_SECTION driver_section = { &critsect_debug, -1, 0, 0, 0, 0 }; static HWND (WINAPI *pGetDesktopWindow)(void); static INT (WINAPI *pGetSystemMetrics)(INT); static DPI_AWARENESS_CONTEXT (WINAPI *pSetThreadDpiAwarenessContext)(DPI_AWARENESS_CONTEXT); +static BOOL (WINAPI *pEnumDisplayDevicesW)(LPCWSTR, DWORD, DISPLAY_DEVICEW *, DWORD);
/********************************************************************** * create_driver @@ -159,6 +166,20 @@ static BOOL is_display_device( LPCWSTR name ) return TRUE; }
+static HANDLE get_display_device_init_mutex( void ) +{ + static const WCHAR init_mutex[] = {'d','i','s','p','l','a','y','_','d','e','v','i','c','e','_','i','n','i','t',0}; + HANDLE mutex = CreateMutexW( NULL, FALSE, init_mutex ); + + WaitForSingleObject( mutex, INFINITE ); + return mutex; +} + +static void release_display_device_init_mutex( HANDLE mutex ) +{ + ReleaseMutex( mutex ); + CloseHandle( mutex ); +}
/********************************************************************** * DRIVER_load_driver @@ -1351,16 +1372,89 @@ NTSTATUS WINAPI D3DKMTCloseAdapter( const D3DKMT_CLOSEADAPTER *desc ) NTSTATUS WINAPI D3DKMTOpenAdapterFromGdiDisplayName( D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME *desc ) { static const WCHAR displayW[] = {'\','\','.','\','D','I','S','P','L','A','Y'}; + static const WCHAR video_idW[] = {'V','i','d','e','o','I','D',0}; + static const WCHAR pciW[] = {'P','C','I',0}; static D3DKMT_HANDLE handle_start = 0; + DWORD size, type, device_index = 0; + DISPLAY_DEVICEW display_device; struct d3dkmt_adapter *adapter; + SP_DEVINFO_DATA device_data; + WCHAR buffer[MAX_PATH]; + BOOL found = FALSE; + HDEVINFO devinfo; + HMODULE user32; + HANDLE mutex; + LSTATUS ls; WCHAR *end; + HKEY hkey; + LUID luid; int id;
TRACE("(%p) semi-stub\n", desc);
- if (!desc || strncmpiW( desc->DeviceName, displayW, ARRAY_SIZE(displayW) )) + if (!desc) return STATUS_UNSUCCESSFUL;
+ if (!pEnumDisplayDevicesW) + { + user32 = LoadLibraryA( "user32.dll" ); + pEnumDisplayDevicesW = (void *)GetProcAddress( user32, "EnumDisplayDevicesW" ); + } + + display_device.cb = sizeof( display_device ); + while (pEnumDisplayDevicesW( NULL, device_index++, &display_device, 0 )) + { + if (lstrcmpiW( display_device.DeviceName, desc->DeviceName )) + continue; + + if (display_device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) + { + found = TRUE; + break; + } + } + + if (!found) + return STATUS_UNSUCCESSFUL; + + /* Get the GPU LUID from SetupAPI */ + mutex = get_display_device_init_mutex(); + devinfo = SetupDiGetClassDevsW( &GUID_DEVCLASS_DISPLAY, pciW, NULL, 0 ); + + found = FALSE; + device_index = 0; + device_data.cbSize = sizeof(device_data); + while (SetupDiEnumDeviceInfo( devinfo, device_index++, &device_data )) + { + hkey = SetupDiOpenDevRegKey( devinfo, &device_data, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ ); + if (hkey == INVALID_HANDLE_VALUE) + continue; + + size = sizeof(buffer); + ls = RegQueryValueExW( hkey, video_idW, 0, NULL, (BYTE *)buffer, &size ); + RegCloseKey( hkey ); + if (ls) + continue; + + /* Compare GPU UUID. DeviceKey from EnumDisplayDevices is of form + * \Registry\Machine\System\CurrentControlSet\Control\Video{GPU UUID}\0000 */ + if (strncmpiW( buffer, display_device.DeviceKey + 57, 38 )) + continue; + + if (SetupDiGetDevicePropertyW( devinfo, &device_data, &DEVPROPKEY_GPU_LUID, + &type, (BYTE *)&luid, sizeof(luid), NULL, 0) ) + { + found = TRUE; + break; + } + } + SetupDiDestroyDeviceInfoList( devinfo ); + release_display_device_init_mutex( mutex ); + + if (!found) + return STATUS_UNSUCCESSFUL; + + /* FIXME: Using display index as VidPnSourceId */ id = strtolW( desc->DeviceName + ARRAY_SIZE(displayW), &end, 10 ) - 1; if (*end) return STATUS_UNSUCCESSFUL; @@ -1376,9 +1470,7 @@ NTSTATUS WINAPI D3DKMTOpenAdapterFromGdiDisplayName( D3DKMT_OPENADAPTERFROMGDIDI LeaveCriticalSection( &driver_section );
desc->hAdapter = handle_start; - /* FIXME: Support AdapterLuid */ - desc->AdapterLuid.LowPart = 0; - desc->AdapterLuid.HighPart = 0; + desc->AdapterLuid = luid; desc->VidPnSourceId = id; return STATUS_SUCCESS; } diff --git a/dlls/gdi32/tests/driver.c b/dlls/gdi32/tests/driver.c index 6172d4a7983..c656eb4245a 100644 --- a/dlls/gdi32/tests/driver.c +++ b/dlls/gdi32/tests/driver.c @@ -86,6 +86,8 @@ static void test_D3DKMTOpenAdapterFromGdiDisplayName(void) }
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);