winex11.drv: Initialize GPU registry data.
Signed-off-by: Zhiyi Zhang <zzhang@codeweavers.com> Signed-off-by: Huw Davies <huw@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
52a3d5db48
commit
bada31698f
|
@ -1,5 +1,5 @@
|
|||
MODULE = winex11.drv
|
||||
IMPORTS = uuid user32 gdi32 advapi32
|
||||
IMPORTS = uuid setupapi rpcrt4 user32 gdi32 advapi32
|
||||
DELAYIMPORTS = comctl32 ole32 shell32 imm32
|
||||
EXTRAINCL = $(X_CFLAGS)
|
||||
EXTRALIBS = $(X_LIBS) $(X_EXTRA_LIBS)
|
||||
|
|
|
@ -25,12 +25,38 @@
|
|||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "winuser.h"
|
||||
#include "rpc.h"
|
||||
#include "winreg.h"
|
||||
#include "initguid.h"
|
||||
#include "devguid.h"
|
||||
#include "devpkey.h"
|
||||
#include "setupapi.h"
|
||||
#define WIN32_NO_STATUS
|
||||
#include "winternl.h"
|
||||
#include "wine/debug.h"
|
||||
#include "wine/unicode.h"
|
||||
#include "x11drv.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
|
||||
|
||||
static const WCHAR driver_descW[] = {'D','r','i','v','e','r','D','e','s','c',0};
|
||||
static const WCHAR video_idW[] = {'V','i','d','e','o','I','D',0};
|
||||
static const WCHAR guid_fmtW[] = {
|
||||
'{','%','0','8','x','-','%','0','4','x','-','%','0','4','x','-','%','0','2','x','%','0','2','x','-',
|
||||
'%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x','}',0};
|
||||
static const WCHAR gpu_instance_fmtW[] = {
|
||||
'P','C','I','\\',
|
||||
'V','E','N','_','%','0','4','X','&',
|
||||
'D','E','V','_','%','0','4','X','&',
|
||||
'S','U','B','S','Y','S','_','%','0','8','X','&',
|
||||
'R','E','V','_','%','0','2','X','\\',
|
||||
'%','0','8','X',0};
|
||||
static const WCHAR gpu_hardware_id_fmtW[] = {
|
||||
'P','C','I','\\',
|
||||
'V','E','N','_','%','0','4','X','&',
|
||||
'D','E','V','_','%','0','4','X','&',
|
||||
'S','U','B','S','Y','S','_','0','0','0','0','0','0','0','0','&',
|
||||
'R','E','V','_','0','0',0};
|
||||
static const WCHAR video_keyW[] = {
|
||||
'H','A','R','D','W','A','R','E','\\',
|
||||
'D','E','V','I','C','E','M','A','P','\\',
|
||||
|
@ -47,10 +73,120 @@ void X11DRV_DisplayDevices_SetHandler(const struct x11drv_display_device_handler
|
|||
}
|
||||
}
|
||||
|
||||
/* Initialize a GPU instance */
|
||||
static BOOL X11DRV_InitGpu(HDEVINFO devinfo, const struct x11drv_gpu *gpu, INT gpu_index)
|
||||
{
|
||||
static const BOOL present = TRUE;
|
||||
SP_DEVINFO_DATA device_data = {sizeof(device_data)};
|
||||
WCHAR instanceW[MAX_PATH];
|
||||
WCHAR bufferW[1024];
|
||||
HKEY hkey = NULL;
|
||||
GUID guid;
|
||||
INT written;
|
||||
DWORD size;
|
||||
BOOL ret = FALSE;
|
||||
|
||||
sprintfW(instanceW, gpu_instance_fmtW, gpu->vendor_id, gpu->device_id, gpu->subsys_id, gpu->revision_id, gpu_index);
|
||||
if (!SetupDiOpenDeviceInfoW(devinfo, instanceW, NULL, 0, &device_data))
|
||||
{
|
||||
SetupDiCreateDeviceInfoW(devinfo, instanceW, &GUID_DEVCLASS_DISPLAY, gpu->name, NULL, 0, &device_data);
|
||||
if (!SetupDiRegisterDeviceInfo(devinfo, &device_data, 0, NULL, NULL, NULL))
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Write HardwareID registry property, REG_MULTI_SZ */
|
||||
written = sprintfW(bufferW, gpu_hardware_id_fmtW, gpu->vendor_id, gpu->device_id);
|
||||
bufferW[written + 1] = 0;
|
||||
if (!SetupDiSetDeviceRegistryPropertyW(devinfo, &device_data, SPDRP_HARDWAREID, (const BYTE *)bufferW,
|
||||
(written + 2) * sizeof(WCHAR)))
|
||||
goto done;
|
||||
|
||||
/* Write DEVPKEY_Device_IsPresent property */
|
||||
if (!SetupDiSetDevicePropertyW(devinfo, &device_data, &DEVPKEY_Device_IsPresent, DEVPROP_TYPE_BOOLEAN,
|
||||
(const BYTE *)&present, sizeof(present), 0))
|
||||
goto done;
|
||||
|
||||
/* Open driver key.
|
||||
* This is where HKLM\System\CurrentControlSet\Control\Video\{GPU GUID}\{Adapter Index} links to */
|
||||
hkey = SetupDiCreateDevRegKeyW(devinfo, &device_data, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL);
|
||||
|
||||
/* Write DriverDesc value */
|
||||
if (RegSetValueExW(hkey, driver_descW, 0, REG_SZ, (const BYTE *)gpu->name,
|
||||
(strlenW(gpu->name) + 1) * sizeof(WCHAR)))
|
||||
goto done;
|
||||
RegCloseKey(hkey);
|
||||
|
||||
/* Write GUID in VideoID in .../instance/Device Parameters, reuse the GUID if it's existent */
|
||||
hkey = SetupDiCreateDevRegKeyW(devinfo, &device_data, DICS_FLAG_GLOBAL, 0, DIREG_DEV, NULL, NULL);
|
||||
|
||||
size = sizeof(bufferW);
|
||||
if (RegQueryValueExW(hkey, video_idW, 0, NULL, (BYTE *)bufferW, &size))
|
||||
{
|
||||
UuidCreate(&guid);
|
||||
sprintfW(bufferW, guid_fmtW, guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], guid.Data4[2],
|
||||
guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
|
||||
if (RegSetValueExW(hkey, video_idW, 0, REG_SZ, (const BYTE *)bufferW, (strlenW(bufferW) + 1) * sizeof(WCHAR)))
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
done:
|
||||
RegCloseKey(hkey);
|
||||
if (!ret)
|
||||
ERR("Failed to initialize GPU\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void prepare_devices(void)
|
||||
{
|
||||
static const BOOL not_present = FALSE;
|
||||
SP_DEVINFO_DATA device_data = {sizeof(device_data)};
|
||||
HDEVINFO devinfo;
|
||||
DWORD i = 0;
|
||||
|
||||
/* FIXME:
|
||||
* Currently SetupDiGetClassDevsW with DIGCF_PRESENT is unsupported, So we need to clean up not present devices in
|
||||
* case application uses SetupDiGetClassDevsW to enumerate devices. Wrong devices could exist in registry as a result
|
||||
* of prefix copying or having devices unplugged. But then we couldn't simply delete GPUs because we need to retain
|
||||
* the same GUID for the same GPU. */
|
||||
devinfo = SetupDiGetClassDevsW(&GUID_DEVCLASS_DISPLAY, NULL, NULL, 0);
|
||||
while (SetupDiEnumDeviceInfo(devinfo, i++, &device_data))
|
||||
{
|
||||
if (!SetupDiSetDevicePropertyW(devinfo, &device_data, &DEVPKEY_Device_IsPresent, DEVPROP_TYPE_BOOLEAN,
|
||||
(const BYTE *)¬_present, sizeof(not_present), 0))
|
||||
ERR("Failed to set GPU present property\n");
|
||||
}
|
||||
SetupDiDestroyDeviceInfoList(devinfo);
|
||||
}
|
||||
|
||||
static void cleanup_devices(void)
|
||||
{
|
||||
SP_DEVINFO_DATA device_data = {sizeof(device_data)};
|
||||
HDEVINFO devinfo;
|
||||
DWORD type;
|
||||
DWORD i = 0;
|
||||
BOOL present;
|
||||
|
||||
devinfo = SetupDiGetClassDevsW(&GUID_DEVCLASS_DISPLAY, NULL, NULL, 0);
|
||||
while (SetupDiEnumDeviceInfo(devinfo, i++, &device_data))
|
||||
{
|
||||
present = FALSE;
|
||||
SetupDiGetDevicePropertyW(devinfo, &device_data, &DEVPKEY_Device_IsPresent, &type, (BYTE *)&present,
|
||||
sizeof(present), NULL, 0);
|
||||
if (!present && !SetupDiRemoveDevice(devinfo, &device_data))
|
||||
ERR("Failed to remove GPU\n");
|
||||
}
|
||||
SetupDiDestroyDeviceInfoList(devinfo);
|
||||
}
|
||||
|
||||
void X11DRV_DisplayDevices_Init(void)
|
||||
{
|
||||
static const WCHAR init_mutexW[] = {'d','i','s','p','l','a','y','_','d','e','v','i','c','e','_','i','n','i','t',0};
|
||||
HANDLE mutex;
|
||||
struct x11drv_gpu *gpus = NULL;
|
||||
INT gpu_count;
|
||||
INT gpu;
|
||||
HDEVINFO gpu_devinfo = NULL;
|
||||
HKEY video_hkey = NULL;
|
||||
DWORD disposition = 0;
|
||||
|
||||
|
@ -70,8 +206,26 @@ void X11DRV_DisplayDevices_Init(void)
|
|||
|
||||
TRACE("via %s\n", wine_dbgstr_a(handler.name));
|
||||
|
||||
prepare_devices();
|
||||
|
||||
gpu_devinfo = SetupDiCreateDeviceInfoList(&GUID_DEVCLASS_DISPLAY, NULL);
|
||||
|
||||
/* Initialize GPUs */
|
||||
if (!handler.pGetGpus(&gpus, &gpu_count))
|
||||
goto done;
|
||||
|
||||
for (gpu = 0; gpu < gpu_count; gpu++)
|
||||
{
|
||||
if (!X11DRV_InitGpu(gpu_devinfo, &gpus[gpu], gpu))
|
||||
goto done;
|
||||
}
|
||||
|
||||
done:
|
||||
cleanup_devices();
|
||||
SetupDiDestroyDeviceInfoList(gpu_devinfo);
|
||||
RegCloseKey(video_hkey);
|
||||
ReleaseMutex(mutex);
|
||||
CloseHandle(mutex);
|
||||
if (gpus)
|
||||
handler.pFreeGpus(gpus);
|
||||
}
|
||||
|
|
|
@ -667,6 +667,20 @@ void X11DRV_XRandR_Init(void) DECLSPEC_HIDDEN;
|
|||
|
||||
/* X11 display device handler. Used to initialize display device registry data */
|
||||
|
||||
/* Represent a physical GPU in the PCI slots */
|
||||
struct x11drv_gpu
|
||||
{
|
||||
/* ID to uniquely identify a GPU in handler */
|
||||
ULONG_PTR id;
|
||||
/* Name */
|
||||
WCHAR name[128];
|
||||
/* PCI ID */
|
||||
UINT vendor_id;
|
||||
UINT device_id;
|
||||
UINT subsys_id;
|
||||
UINT revision_id;
|
||||
};
|
||||
|
||||
/* Required functions for display device registry initialization */
|
||||
struct x11drv_display_device_handler
|
||||
{
|
||||
|
@ -675,6 +689,14 @@ struct x11drv_display_device_handler
|
|||
|
||||
/* Higher priority can override handlers with lower proprity */
|
||||
INT priority;
|
||||
|
||||
/* pGetGpus will be called to get a list of GPUs. First GPU has to be where the primary adapter is.
|
||||
*
|
||||
* Return FALSE on failure with parameters unchanged */
|
||||
BOOL (*pGetGpus)(struct x11drv_gpu **gpus, int *count);
|
||||
|
||||
/* pFreeGpus will be called to free a GPU list from pGetGpus */
|
||||
void (*pFreeGpus)(struct x11drv_gpu *gpus);
|
||||
};
|
||||
|
||||
extern void X11DRV_DisplayDevices_SetHandler(const struct x11drv_display_device_handler *handler) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -201,6 +201,29 @@ RECT get_primary_monitor_rect(void)
|
|||
return get_primary()->rcMonitor;
|
||||
}
|
||||
|
||||
static BOOL xinerama_get_gpus( struct x11drv_gpu **new_gpus, int *count )
|
||||
{
|
||||
static const WCHAR wine_adapterW[] = {'W','i','n','e',' ','A','d','a','p','t','e','r',0};
|
||||
struct x11drv_gpu *gpus;
|
||||
|
||||
/* Xinerama has no support for GPU, faking one */
|
||||
gpus = heap_calloc( 1, sizeof(*gpus) );
|
||||
if (!gpus)
|
||||
return FALSE;
|
||||
|
||||
lstrcpyW( gpus[0].name, wine_adapterW );
|
||||
|
||||
*new_gpus = gpus;
|
||||
*count = 1;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void xinerama_free_gpus( struct x11drv_gpu *gpus )
|
||||
{
|
||||
heap_free( gpus );
|
||||
}
|
||||
|
||||
void xinerama_init( unsigned int width, unsigned int height )
|
||||
{
|
||||
struct x11drv_display_device_handler handler;
|
||||
|
@ -239,6 +262,8 @@ void xinerama_init( unsigned int width, unsigned int height )
|
|||
|
||||
handler.name = "Xinerama";
|
||||
handler.priority = 100;
|
||||
handler.pGetGpus = xinerama_get_gpus;
|
||||
handler.pFreeGpus = xinerama_free_gpus;
|
||||
X11DRV_DisplayDevices_SetHandler( &handler );
|
||||
|
||||
TRACE( "virtual size: %s primary: %s\n",
|
||||
|
|
Loading…
Reference in New Issue