1
0
Fork 0
mirror of synced 2025-03-07 03:53:26 +01:00

win32u: Split read / write of gpu to registry to separate helpers.

This commit is contained in:
Rémi Bernon 2024-02-27 14:32:00 +01:00 committed by Alexandre Julliard
parent c67726b3d0
commit c8d2955cdc

View file

@ -96,13 +96,24 @@ struct display_device
WCHAR device_key[128]; /* DeviceKey in DISPLAY_DEVICEW */
};
struct pci_id
{
UINT16 vendor;
UINT16 device;
UINT16 subsystem;
UINT16 revision;
};
struct gpu
{
LONG refcount;
struct list entry;
char path[MAX_PATH];
WCHAR name[128];
char guid[39];
LUID luid;
unsigned int adapter_count;
UINT index;
UINT adapter_count;
};
struct adapter
@ -983,15 +994,12 @@ static unsigned int format_date( WCHAR *bufferW, LONGLONG time )
struct device_manager_ctx
{
unsigned int gpu_count;
unsigned int adapter_count;
unsigned int video_count;
unsigned int monitor_count;
unsigned int output_count;
unsigned int mode_count;
HANDLE mutex;
char gpuid[128];
char gpu_guid[39];
LUID gpu_luid;
struct gpu gpu;
HKEY adapter_key;
/* for the virtual desktop settings */
BOOL is_primary;
@ -1029,18 +1037,44 @@ static void link_device( const char *instance, const char *class )
}
}
static void add_gpu( const struct gdi_gpu *gpu, void *param )
static BOOL read_gpu_from_registry( struct gpu *gpu )
{
struct device_manager_ctx *ctx = param;
const WCHAR *desc;
char buffer[4096];
WCHAR bufferW[512];
char buffer[1024];
KEY_VALUE_PARTIAL_INFORMATION *value = (void *)buffer;
unsigned int gpu_index, size, i;
WCHAR *value_str = (WCHAR *)value->Data;
HKEY hkey, subkey;
if (!(hkey = reg_open_ascii_key( enum_key, gpu->path ))) return FALSE;
if (query_reg_ascii_value( hkey, "Driver", value, sizeof(buffer) ) && value->Type == REG_SZ)
gpu->index = wcstoul( wcsrchr( value_str, '\\' ) + 1, NULL, 16 );
if (query_reg_ascii_value( hkey, "DeviceDesc", value, sizeof(buffer) ) && value->Type == REG_SZ)
memcpy( gpu->name, value->Data, value->DataLength );
if ((subkey = reg_open_ascii_key( hkey, devpropkey_gpu_luidA )))
{
if (query_reg_value( subkey, NULL, value, sizeof(buffer) ) == sizeof(LUID))
gpu->luid = *(const LUID *)value->Data;
NtClose( subkey );
}
NtClose( hkey );
return TRUE;
}
static BOOL write_gpu_to_registry( const struct gpu *gpu, const struct pci_id *pci,
const GUID *vulkan_uuid, ULONGLONG memory_size )
{
const WCHAR *desc;
char buffer[4096], *tmp;
WCHAR bufferW[512];
unsigned int size;
HKEY subkey;
LARGE_INTEGER ft;
ULONG memory_size;
ULONGLONG qw_memory_size;
ULONG value;
HKEY hkey;
static const BOOL present = TRUE;
static const WCHAR wine_adapterW[] = {'W','i','n','e',' ','A','d','a','p','t','e','r',0};
@ -1068,43 +1102,23 @@ static void add_gpu( const struct gdi_gpu *gpu, void *param )
{'I','n','t','e','r','g','r','a','t','e','d',' ','R','A','M','D','A','C',0};
static const WCHAR driver_dateW[] = {'D','r','i','v','e','r','D','a','t','e',0};
TRACE( "%s %04X %04X %08X %02X\n", debugstr_w(gpu->name),
gpu->vendor_id, gpu->device_id, gpu->subsys_id, gpu->revision_id );
gpu_index = ctx->gpu_count++;
ctx->adapter_count = 0;
ctx->monitor_count = 0;
ctx->mode_count = 0;
if (!enum_key && !(enum_key = reg_create_ascii_key( NULL, enum_keyA, 0, NULL )))
return;
if (!ctx->mutex)
{
pthread_mutex_lock( &display_lock );
ctx->mutex = get_display_device_init_mutex();
prepare_devices();
}
sprintf( ctx->gpuid, "PCI\\VEN_%04X&DEV_%04X&SUBSYS_%08X&REV_%02X\\%08X",
gpu->vendor_id, gpu->device_id, gpu->subsys_id, gpu->revision_id, gpu_index );
size = asciiz_to_unicode( bufferW, ctx->gpuid );
if (!(hkey = reg_create_ascii_key( enum_key, ctx->gpuid, 0, NULL ))) return;
if (!(hkey = reg_create_ascii_key( enum_key, gpu->path, 0, NULL ))) return FALSE;
set_reg_ascii_value( hkey, "Class", "Display" );
set_reg_ascii_value( hkey, "ClassGUID", guid_devclass_displayA );
sprintf( buffer, "%s\\%04X", guid_devclass_displayA, gpu_index );
sprintf( buffer, "%s\\%04X", guid_devclass_displayA, gpu->index );
set_reg_ascii_value( hkey, "Driver", buffer );
sprintf( buffer, "PCI\\VEN_%04X&DEV_%04X&SUBSYS_%08X&REV_%02X",
gpu->vendor_id, gpu->device_id, gpu->subsys_id, gpu->revision_id );
strcpy( buffer, gpu->path );
if ((tmp = strrchr( buffer, '\\' ))) *tmp = 0;
size = asciiz_to_unicode( bufferW, buffer );
bufferW[size / sizeof(WCHAR)] = 0; /* for REG_MULTI_SZ */
set_reg_value( hkey, hardware_idW, REG_MULTI_SZ, bufferW, size + sizeof(WCHAR) );
if ((subkey = reg_create_ascii_key( hkey, devpkey_device_matching_device_id, 0, NULL )))
{
if (gpu->vendor_id && gpu->device_id)
if (pci->vendor && pci->device)
set_reg_value( subkey, NULL, 0xffff0000 | DEVPROP_TYPE_STRING, bufferW, size );
else
set_reg_value( subkey, NULL, 0xffff0000 | DEVPROP_TYPE_STRING, bufferW,
@ -1112,12 +1126,12 @@ static void add_gpu( const struct gdi_gpu *gpu, void *param )
NtClose( subkey );
}
if (gpu->vendor_id && gpu->device_id)
if (pci->vendor && pci->device)
{
if ((subkey = reg_create_ascii_key( hkey, devpkey_device_bus_number, 0, NULL )))
{
set_reg_value( subkey, NULL, 0xffff0000 | DEVPROP_TYPE_UINT32,
&gpu_index, sizeof(gpu_index) );
&gpu->index, sizeof(gpu->index) );
NtClose( subkey );
}
}
@ -1137,29 +1151,14 @@ static void add_gpu( const struct gdi_gpu *gpu, void *param )
if ((subkey = reg_create_ascii_key( hkey, "Device Parameters", 0, NULL )))
{
if (query_reg_ascii_value( subkey, "VideoID", value, sizeof(buffer) ) != sizeof(ctx->gpu_guid) * sizeof(WCHAR))
{
GUID guid;
uuid_create( &guid );
sprintf( ctx->gpu_guid, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
(unsigned int)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] );
TRACE( "created guid %s\n", debugstr_a(ctx->gpu_guid) );
set_reg_ascii_value( subkey, "VideoID", ctx->gpu_guid );
}
else
{
WCHAR *guidW = (WCHAR *)value->Data;
for (i = 0; i < sizeof(ctx->gpu_guid); i++) ctx->gpu_guid[i] = guidW[i];
TRACE( "got guid %s\n", debugstr_a(ctx->gpu_guid) );
}
set_reg_ascii_value( subkey, "VideoID", gpu->guid );
NtClose( subkey );
}
if ((subkey = reg_create_ascii_key( hkey, devpropkey_gpu_vulkan_uuidA, 0, NULL )))
{
set_reg_value( subkey, NULL, 0xffff0000 | DEVPROP_TYPE_GUID,
&gpu->vulkan_uuid, sizeof(gpu->vulkan_uuid) );
&vulkan_uuid, sizeof(vulkan_uuid) );
NtClose( subkey );
}
@ -1172,25 +1171,16 @@ static void add_gpu( const struct gdi_gpu *gpu, void *param )
if ((subkey = reg_create_ascii_key( hkey, devpropkey_gpu_luidA, 0, NULL )))
{
if (query_reg_value( subkey, NULL, value, sizeof(buffer) ) != sizeof(LUID))
{
NtAllocateLocallyUniqueId( &ctx->gpu_luid );
TRACE("allocated luid %08x%08x\n", (int)ctx->gpu_luid.HighPart, (int)ctx->gpu_luid.LowPart );
set_reg_value( subkey, NULL, 0xffff0000 | DEVPROP_TYPE_UINT64,
&ctx->gpu_luid, sizeof(ctx->gpu_luid) );
}
else
{
memcpy( &ctx->gpu_luid, value->Data, sizeof(ctx->gpu_luid) );
TRACE("got luid %08x%08x\n", (int)ctx->gpu_luid.HighPart, (int)ctx->gpu_luid.LowPart );
}
set_reg_value( subkey, NULL, 0xffff0000 | DEVPROP_TYPE_UINT64,
&gpu->luid, sizeof(gpu->luid) );
NtClose( subkey );
}
NtClose( hkey );
sprintf( buffer, "Class\\%s\\%04X", guid_devclass_displayA, gpu_index );
hkey = reg_create_ascii_key( control_key, buffer, 0, NULL );
sprintf( buffer, "Class\\%s\\%04X", guid_devclass_displayA, gpu->index );
if (!(hkey = reg_create_ascii_key( control_key, buffer, 0, NULL ))) return FALSE;
NtQuerySystemTime( &ft );
set_reg_value( hkey, driver_dateW, REG_SZ, bufferW, format_date( bufferW, ft.QuadPart ));
@ -1205,16 +1195,16 @@ static void add_gpu( const struct gdi_gpu *gpu, void *param )
set_reg_value( hkey, dac_typeW, REG_SZ, ramdacW, sizeof(ramdacW) );
/* If we failed to retrieve the gpu memory size set a default of 1Gb */
qw_memory_size = gpu->memory_size ? gpu->memory_size : 1073741824;
if (!memory_size) memory_size = 1073741824;
set_reg_value( hkey, qw_memory_sizeW, REG_QWORD, &qw_memory_size, sizeof(qw_memory_size) );
memory_size = (ULONG)min( gpu->memory_size, (ULONGLONG)ULONG_MAX );
set_reg_value( hkey, memory_sizeW, REG_DWORD, &memory_size, sizeof(memory_size) );
set_reg_value( hkey, qw_memory_sizeW, REG_QWORD, &memory_size, sizeof(memory_size) );
value = (ULONG)min( memory_size, (ULONGLONG)ULONG_MAX );
set_reg_value( hkey, memory_sizeW, REG_DWORD, &value, sizeof(value) );
if (gpu->vendor_id && gpu->device_id)
if (pci->vendor && pci->device)
{
/* The last seven digits are the driver number. */
switch (gpu->vendor_id)
switch (pci->vendor)
{
/* Intel */
case 0x8086:
@ -1238,8 +1228,93 @@ static void add_gpu( const struct gdi_gpu *gpu, void *param )
NtClose( hkey );
link_device( ctx->gpuid, guid_devinterface_display_adapterA );
link_device( ctx->gpuid, guid_display_device_arrivalA );
link_device( gpu->path, guid_devinterface_display_adapterA );
link_device( gpu->path, guid_display_device_arrivalA );
return TRUE;
}
static void add_gpu( const struct gdi_gpu *gpu, void *param )
{
const struct pci_id pci_id =
{
.vendor = gpu->vendor_id,
.device = gpu->device_id,
.subsystem = gpu->subsys_id,
.revision = gpu->revision_id,
};
struct device_manager_ctx *ctx = param;
char buffer[4096];
KEY_VALUE_PARTIAL_INFORMATION *value = (void *)buffer;
unsigned int i;
HKEY hkey, subkey;
TRACE( "%s %04X %04X %08X %02X\n", debugstr_w(gpu->name),
gpu->vendor_id, gpu->device_id, gpu->subsys_id, gpu->revision_id );
if (!enum_key && !(enum_key = reg_create_ascii_key( NULL, enum_keyA, 0, NULL )))
return;
if (!ctx->mutex)
{
pthread_mutex_lock( &display_lock );
ctx->mutex = get_display_device_init_mutex();
prepare_devices();
}
memset( &ctx->gpu, 0, sizeof(ctx->gpu) );
ctx->gpu.index = ctx->gpu_count;
lstrcpyW( ctx->gpu.name, gpu->name );
ctx->monitor_count = 0;
ctx->mode_count = 0;
sprintf( ctx->gpu.path, "PCI\\VEN_%04X&DEV_%04X&SUBSYS_%08X&REV_%02X\\%08X",
gpu->vendor_id, gpu->device_id, gpu->subsys_id, gpu->revision_id, ctx->gpu.index );
if (!(hkey = reg_create_ascii_key( enum_key, ctx->gpu.path, 0, NULL ))) return;
if ((subkey = reg_create_ascii_key( hkey, "Device Parameters", 0, NULL )))
{
if (query_reg_ascii_value( subkey, "VideoID", value, sizeof(buffer) ) != sizeof(ctx->gpu.guid) * sizeof(WCHAR))
{
GUID guid;
uuid_create( &guid );
sprintf( ctx->gpu.guid, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
(unsigned int)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] );
TRACE( "created guid %s\n", debugstr_a(ctx->gpu.guid) );
}
else
{
WCHAR *guidW = (WCHAR *)value->Data;
for (i = 0; i < sizeof(ctx->gpu.guid); i++) ctx->gpu.guid[i] = guidW[i];
TRACE( "got guid %s\n", debugstr_a(ctx->gpu.guid) );
}
NtClose( subkey );
}
if ((subkey = reg_create_ascii_key( hkey, devpropkey_gpu_luidA, 0, NULL )))
{
if (query_reg_value( subkey, NULL, value, sizeof(buffer) ) != sizeof(LUID))
{
NtAllocateLocallyUniqueId( &ctx->gpu.luid );
TRACE("allocated luid %08x%08x\n", (int)ctx->gpu.luid.HighPart, (int)ctx->gpu.luid.LowPart );
}
else
{
memcpy( &ctx->gpu.luid, value->Data, sizeof(ctx->gpu.luid) );
TRACE("got luid %08x%08x\n", (int)ctx->gpu.luid.HighPart, (int)ctx->gpu.luid.LowPart );
}
NtClose( subkey );
}
NtClose( hkey );
if (!write_gpu_to_registry( &ctx->gpu, &pci_id, &gpu->vulkan_uuid, gpu->memory_size ))
WARN( "Failed to write gpu to registry\n" );
else
ctx->gpu_count++;
}
static void add_adapter( const struct gdi_adapter *adapter, void *param )
@ -1258,13 +1333,13 @@ static void add_adapter( const struct gdi_adapter *adapter, void *param )
ctx->adapter_key = NULL;
}
adapter_index = ctx->adapter_count++;
adapter_index = ctx->gpu.adapter_count++;
video_index = ctx->video_count++;
ctx->monitor_count = 0;
ctx->mode_count = 0;
snprintf( buffer, ARRAY_SIZE(buffer), "\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Video\\%s\\%04x",
ctx->gpu_guid, adapter_index );
ctx->gpu.guid, adapter_index );
len = asciiz_to_unicode( bufferW, buffer ) - sizeof(WCHAR);
hkey = reg_create_ascii_key( NULL, buffer, REG_OPTION_VOLATILE | REG_OPTION_CREATE_LINK, NULL );
@ -1284,10 +1359,10 @@ static void add_adapter( const struct gdi_adapter *adapter, void *param )
else ERR( "failed to create link key\n" );
/* Following information is Wine specific, it doesn't really exist on Windows. */
snprintf( buffer, ARRAY_SIZE(buffer), "System\\CurrentControlSet\\Control\\Video\\%s\\%04x", ctx->gpu_guid, adapter_index );
snprintf( buffer, ARRAY_SIZE(buffer), "System\\CurrentControlSet\\Control\\Video\\%s\\%04x", ctx->gpu.guid, adapter_index );
ctx->adapter_key = reg_create_ascii_key( config_key, buffer, REG_OPTION_VOLATILE, NULL );
set_reg_ascii_value( ctx->adapter_key, "GPUID", ctx->gpuid );
set_reg_ascii_value( ctx->adapter_key, "GPUID", ctx->gpu.path );
set_reg_value( ctx->adapter_key, state_flagsW, REG_DWORD, &adapter->state_flags,
sizeof(adapter->state_flags) );
}
@ -1368,7 +1443,7 @@ static void add_monitor( const struct gdi_monitor *monitor, void *param )
if ((subkey = reg_create_ascii_key( hkey, devpropkey_monitor_gpu_luidA, 0, NULL )))
{
set_reg_value( subkey, NULL, 0xffff0000 | DEVPROP_TYPE_INT64,
&ctx->gpu_luid, sizeof(ctx->gpu_luid) );
&ctx->gpu.luid, sizeof(ctx->gpu.luid) );
NtClose( subkey );
}
@ -1392,7 +1467,7 @@ static void add_mode( const DEVMODEW *mode, BOOL current, void *param )
struct device_manager_ctx *ctx = param;
DEVMODEW nopos_mode;
if (!ctx->adapter_count)
if (!ctx->gpu.adapter_count)
{
static const struct gdi_adapter default_adapter =
{
@ -1556,11 +1631,9 @@ static struct gpu *find_gpu_from_path( const char *path )
static BOOL update_display_cache_from_registry(void)
{
char buffer[1024], path[MAX_PATH];
char path[MAX_PATH];
DWORD adapter_id, monitor_id, monitor_count = 0, size;
KEY_VALUE_PARTIAL_INFORMATION *value = (void *)buffer;
KEY_BASIC_INFORMATION key;
HKEY gpu_key, prop_key;
struct adapter *adapter;
struct monitor *monitor, *monitor2;
HANDLE mutex = NULL;
@ -1590,16 +1663,8 @@ static BOOL update_display_cache_from_registry(void)
LIST_FOR_EACH_ENTRY( gpu, &gpus, struct gpu, entry )
{
if (!(gpu_key = reg_open_ascii_key( enum_key, gpu->path ))) continue;
if ((prop_key = reg_open_ascii_key( gpu_key, devpropkey_gpu_luidA )))
{
if (query_reg_value( prop_key, NULL, value, sizeof(buffer) ) == sizeof(LUID))
gpu->luid = *(const LUID *)value->Data;
NtClose( prop_key );
}
NtClose( gpu_key );
if (!read_gpu_from_registry( gpu ))
WARN( "Failed to read gpu from registry\n" );
}
for (adapter_id = 0;; adapter_id++)