Skip to content

Instantly share code, notes, and snippets.

@Saancreed
Created December 19, 2023 23:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save Saancreed/0aa3f4188846146698f5da3dfa0dfcbd to your computer and use it in GitHub Desktop.
Save Saancreed/0aa3f4188846146698f5da3dfa0dfcbd to your computer and use it in GitHub Desktop.
Wine HAGS hack
commit abb67b8aee120c52847abda19efb7641eeb184ac
Author: Krzysztof Bogacki <krzysztof.bogacki@leancode.pl>
Date: Tue Dec 19 23:51:33 2023 +0100
gdi32,win32u,winex11: Implement D3DKMTEnumAdapters2.
diff --git a/dlls/gdi32/gdi32.spec b/dlls/gdi32/gdi32.spec
index 0ad4711..69ad9b2 100644
--- a/dlls/gdi32/gdi32.spec
+++ b/dlls/gdi32/gdi32.spec
@@ -79,6 +79,7 @@
@ stdcall D3DKMTCreateDevice(ptr) win32u.NtGdiDdDDICreateDevice
@ stdcall D3DKMTDestroyDCFromMemory(ptr) win32u.NtGdiDdDDIDestroyDCFromMemory
@ stdcall D3DKMTDestroyDevice(ptr) win32u.NtGdiDdDDIDestroyDevice
+@ stdcall D3DKMTEnumAdapters2(ptr) win32u.NtGdiDdDDIEnumAdapters2
@ stdcall D3DKMTEscape(ptr) win32u.NtGdiDdDDIEscape
@ stdcall D3DKMTOpenAdapterFromDeviceName(ptr) win32u.NtGdiDdDDIOpenAdapterFromDeviceName
@ stdcall D3DKMTOpenAdapterFromGdiDisplayName(ptr)
diff --git a/dlls/win32u/dibdrv/dc.c b/dlls/win32u/dibdrv/dc.c
index 7fe4b76..0a4b0ac 100644
--- a/dlls/win32u/dibdrv/dc.c
+++ b/dlls/win32u/dibdrv/dc.c
@@ -709,6 +709,7 @@ const struct gdi_dc_funcs dib_driver =
NULL, /* pUnrealizePalette */
NULL, /* pD3DKMTCheckVidPnExclusiveOwnership */
NULL, /* pD3DKMTCloseAdapter */
+ NULL, /* pD3DKMTEnumAdapters2 */
NULL, /* pD3DKMTOpenAdapterFromLuid */
NULL, /* pD3DKMTQueryVideoMemoryInfo */
NULL, /* pD3DKMTSetVidPnSourceOwner */
@@ -1270,6 +1271,7 @@ static const struct gdi_dc_funcs window_driver =
NULL, /* pUnrealizePalette */
NULL, /* pD3DKMTCheckVidPnExclusiveOwnership */
NULL, /* pD3DKMTCloseAdapter */
+ NULL, /* pD3DKMTEnumAdapters2 */
NULL, /* pD3DKMTOpenAdapterFromLuid */
NULL, /* pD3DKMTQueryVideoMemoryInfo */
NULL, /* pD3DKMTSetVidPnSourceOwner */
diff --git a/dlls/win32u/driver.c b/dlls/win32u/driver.c
index 3065a61..3f7b9e4 100644
--- a/dlls/win32u/driver.c
+++ b/dlls/win32u/driver.c
@@ -54,6 +54,7 @@ static struct user_driver_funcs null_user_driver;
static struct list d3dkmt_adapters = LIST_INIT( d3dkmt_adapters );
static struct list d3dkmt_devices = LIST_INIT( d3dkmt_devices );
+static D3DKMT_HANDLE handle_start = 0;
static pthread_mutex_t driver_lock = PTHREAD_MUTEX_INITIALIZER;
static WCHAR driver_load_error[80];
@@ -549,6 +550,11 @@ static NTSTATUS nulldrv_D3DKMTCloseAdapter( const D3DKMT_CLOSEADAPTER *desc )
return STATUS_PROCEDURE_NOT_FOUND;
}
+static NTSTATUS nulldrv_D3DKMTEnumAdapters2( D3DKMT_ENUMADAPTERS2 *desc )
+{
+ return STATUS_PROCEDURE_NOT_FOUND;
+}
+
static NTSTATUS nulldrv_D3DKMTOpenAdapterFromLuid( D3DKMT_OPENADAPTERFROMLUID *desc )
{
return STATUS_PROCEDURE_NOT_FOUND;
@@ -657,6 +663,7 @@ const struct gdi_dc_funcs null_driver =
nulldrv_UnrealizePalette, /* pUnrealizePalette */
nulldrv_D3DKMTCheckVidPnExclusiveOwnership, /* pD3DKMTCheckVidPnExclusiveOwnership */
nulldrv_D3DKMTCloseAdapter, /* pD3DKMTCloseAdapter */
+ nulldrv_D3DKMTEnumAdapters2, /* pD3DKMTEnumAdapters2 */
nulldrv_D3DKMTOpenAdapterFromLuid, /* pD3DKMTOpenAdapterFromLuid */
nulldrv_D3DKMTQueryVideoMemoryInfo, /* pD3DKMTQueryVideoMemoryInfo */
nulldrv_D3DKMTSetVidPnSourceOwner, /* pD3DKMTSetVidPnSourceOwner */
@@ -1526,6 +1533,46 @@ NTSTATUS WINAPI NtGdiDdDDICloseAdapter( const D3DKMT_CLOSEADAPTER *desc )
return status;
}
+/******************************************************************************
+ * NtGdiDdDDIEnumAdapters2 (win32u.@)
+ */
+NTSTATUS WINAPI NtGdiDdDDIEnumAdapters2( D3DKMT_ENUMADAPTERS2 *desc )
+{
+ NTSTATUS status = STATUS_UNSUCCESSFUL;
+ struct d3dkmt_adapter *adapter;
+ ULONG i;
+
+ TRACE("(%p)\n", desc);
+
+ if (!desc) return STATUS_INVALID_PARAMETER;
+
+ if (get_display_driver()->pD3DKMTEnumAdapters2)
+ {
+ if (desc->pAdapters)
+ {
+ pthread_mutex_lock( &driver_lock );
+
+ for (i = 0; i < desc->NumAdapters; ++i)
+ {
+ if (!(adapter = malloc( sizeof( *adapter ) )))
+ {
+ pthread_mutex_unlock( &driver_lock );
+ return STATUS_NO_MEMORY;
+ }
+
+ desc->pAdapters[i].hAdapter = adapter->handle = ++handle_start;
+ list_add_tail( &d3dkmt_adapters, &adapter->entry );
+ }
+
+ pthread_mutex_unlock( &driver_lock );
+ }
+
+ status = get_display_driver()->pD3DKMTEnumAdapters2( desc );
+ }
+
+ return status;
+}
+
/******************************************************************************
* NtGdiDdDDIOpenAdapterFromDeviceName (win32u.@)
*/
@@ -1551,7 +1598,6 @@ NTSTATUS WINAPI NtGdiDdDDIOpenAdapterFromDeviceName( D3DKMT_OPENADAPTERFROMDEVIC
*/
NTSTATUS WINAPI NtGdiDdDDIOpenAdapterFromLuid( D3DKMT_OPENADAPTERFROMLUID *desc )
{
- static D3DKMT_HANDLE handle_start = 0;
struct d3dkmt_adapter *adapter;
if (!(adapter = malloc( sizeof( *adapter ) ))) return STATUS_NO_MEMORY;
diff --git a/dlls/win32u/emfdrv.c b/dlls/win32u/emfdrv.c
index 069ad9d..9c07f9e 100644
--- a/dlls/win32u/emfdrv.c
+++ b/dlls/win32u/emfdrv.c
@@ -521,6 +521,7 @@ static const struct gdi_dc_funcs emfdrv_driver =
NULL, /* pUnrealizePalette */
NULL, /* pD3DKMTCheckVidPnExclusiveOwnership */
NULL, /* pD3DKMTCloseAdapter */
+ NULL, /* pD3DKMTEnumAdapters2 */
NULL, /* pD3DKMTOpenAdapterFromLuid */
NULL, /* pD3DKMTQueryVideoMemoryInfo */
NULL, /* pD3DKMTSetVidPnSourceOwner */
diff --git a/dlls/win32u/font.c b/dlls/win32u/font.c
index af1a9b9..2f84ff3 100644
--- a/dlls/win32u/font.c
+++ b/dlls/win32u/font.c
@@ -4774,6 +4774,7 @@ const struct gdi_dc_funcs font_driver =
NULL, /* pUnrealizePalette */
NULL, /* pD3DKMTCheckVidPnExclusiveOwnership */
NULL, /* pD3DKMTCloseAdapter */
+ NULL, /* pD3DKMTEnumAdapters2 */
NULL, /* pD3DKMTOpenAdapterFromLuid */
NULL, /* pD3DKMTQueryVideoMemoryInfo */
NULL, /* pD3DKMTSetVidPnSourceOwner */
diff --git a/dlls/win32u/main.c b/dlls/win32u/main.c
index 2dc66e5..3f910c2 100644
--- a/dlls/win32u/main.c
+++ b/dlls/win32u/main.c
@@ -236,6 +236,11 @@ NTSTATUS SYSCALL_API NtGdiDdDDIDestroyDevice( const D3DKMT_DESTROYDEVICE *desc )
__ASM_SYSCALL_FUNC( __id_NtGdiDdDDIDestroyDevice );
}
+NTSTATUS SYSCALL_API NtGdiDdDDIEnumAdapters2( D3DKMT_ENUMADAPTERS2 *desc )
+{
+ __ASM_SYSCALL_FUNC( __id_NtGdiDdDDIEnumAdapters2 );
+}
+
NTSTATUS SYSCALL_API NtGdiDdDDIEscape( const D3DKMT_ESCAPE *desc )
{
__ASM_SYSCALL_FUNC( __id_NtGdiDdDDIEscape );
diff --git a/dlls/win32u/path.c b/dlls/win32u/path.c
index e0c96f5..6d494a9 100644
--- a/dlls/win32u/path.c
+++ b/dlls/win32u/path.c
@@ -2120,6 +2120,7 @@ const struct gdi_dc_funcs path_driver =
NULL, /* pUnrealizePalette */
NULL, /* pD3DKMTCheckVidPnExclusiveOwnership */
NULL, /* pD3DKMTCloseAdapter */
+ NULL, /* pD3DKMTEnumAdapters2 */
NULL, /* pD3DKMTOpenAdapterFromLuid */
NULL, /* pD3DKMTQueryVideoMemoryInfo */
NULL, /* pD3DKMTSetVidPnSourceOwner */
diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec
index 24dccb6..76a60bf 100644
--- a/dlls/win32u/win32u.spec
+++ b/dlls/win32u/win32u.spec
@@ -223,7 +223,7 @@
@ stub NtGdiDdDDIDispMgrSourceOperation
@ stub NtGdiDdDDIDispMgrTargetOperation
@ stub NtGdiDdDDIEnumAdapters
-@ stub NtGdiDdDDIEnumAdapters2
+@ stdcall -syscall NtGdiDdDDIEnumAdapters2(ptr)
@ stdcall -syscall NtGdiDdDDIEscape(ptr)
@ stub NtGdiDdDDIEvict
@ stub NtGdiDdDDIExtractBundleObject
diff --git a/dlls/winex11.drv/init.c b/dlls/winex11.drv/init.c
index 71e9207..840a4a8 100644
--- a/dlls/winex11.drv/init.c
+++ b/dlls/winex11.drv/init.c
@@ -415,6 +415,7 @@ static const struct user_driver_funcs x11drv_funcs =
.dc_funcs.pUnrealizePalette = X11DRV_UnrealizePalette,
.dc_funcs.pD3DKMTCheckVidPnExclusiveOwnership = X11DRV_D3DKMTCheckVidPnExclusiveOwnership,
.dc_funcs.pD3DKMTCloseAdapter = X11DRV_D3DKMTCloseAdapter,
+ .dc_funcs.pD3DKMTEnumAdapters2 = X11DRV_D3DKMTEnumAdapters2,
.dc_funcs.pD3DKMTOpenAdapterFromLuid = X11DRV_D3DKMTOpenAdapterFromLuid,
.dc_funcs.pD3DKMTQueryVideoMemoryInfo = X11DRV_D3DKMTQueryVideoMemoryInfo,
.dc_funcs.pD3DKMTSetVidPnSourceOwner = X11DRV_D3DKMTSetVidPnSourceOwner,
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index 666bd48..cf49660 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -160,6 +160,7 @@ extern BOOL X11DRV_Chord( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
INT xstart, INT ystart, INT xend, INT yend );
extern NTSTATUS X11DRV_D3DKMTCheckVidPnExclusiveOwnership( const D3DKMT_CHECKVIDPNEXCLUSIVEOWNERSHIP *desc );
extern NTSTATUS X11DRV_D3DKMTCloseAdapter( const D3DKMT_CLOSEADAPTER *desc );
+extern NTSTATUS X11DRV_D3DKMTEnumAdapters2( D3DKMT_ENUMADAPTERS2 *desc );
extern NTSTATUS X11DRV_D3DKMTOpenAdapterFromLuid( D3DKMT_OPENADAPTERFROMLUID *desc );
extern NTSTATUS X11DRV_D3DKMTQueryVideoMemoryInfo( D3DKMT_QUERYVIDEOMEMORYINFO *desc );
extern NTSTATUS X11DRV_D3DKMTSetVidPnSourceOwner( const D3DKMT_SETVIDPNSOURCEOWNER *desc );
diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c
index c4978d1..e523b85 100644
--- a/dlls/winex11.drv/x11drv_main.c
+++ b/dlls/winex11.drv/x11drv_main.c
@@ -1241,6 +1241,243 @@ static void release_display_device_init_mutex(HANDLE mutex)
NtClose( mutex );
}
+/* Find the Vulkan device LUID corresponding to a GUID */
+static BOOL get_vulkan_luid_from_uuid( const GUID *uuid, LUID *luid )
+{
+ static const WCHAR class_guidW[] = {'C','l','a','s','s','G','U','I','D',0};
+ static const WCHAR devpropkey_gpu_vulkan_uuidW[] =
+ {
+ 'P','r','o','p','e','r','t','i','e','s',
+ '\\','{','2','3','3','A','9','E','F','3','-','A','F','C','4','-','4','A','B','D',
+ '-','B','5','6','4','-','C','3','2','F','2','1','F','1','5','3','5','C','}',
+ '\\','0','0','0','2'
+ };
+ static const WCHAR devpropkey_gpu_luidW[] =
+ {
+ 'P','r','o','p','e','r','t','i','e','s',
+ '\\','{','6','0','B','1','9','3','C','B','-','5','2','7','6','-','4','D','0','F',
+ '-','9','6','F','C','-','F','1','7','3','A','B','A','D','3','E','C','6','}',
+ '\\','0','0','0','2'
+ };
+ static const WCHAR guid_devclass_displayW[] =
+ {'{','4','D','3','6','E','9','6','8','-','E','3','2','5','-','1','1','C','E','-',
+ 'B','F','C','1','-','0','8','0','0','2','B','E','1','0','3','1','8','}',0};
+ static const WCHAR pci_keyW[] =
+ {
+ '\\','R','e','g','i','s','t','r','y',
+ '\\','M','a','c','h','i','n','e',
+ '\\','S','y','s','t','e','m',
+ '\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t',
+ '\\','E','n','u','m',
+ '\\','P','C','I'
+ };
+ char buffer[4096];
+ KEY_VALUE_PARTIAL_INFORMATION *value = (void *)buffer;
+ HKEY subkey, device_key, prop_key, pci_key;
+ KEY_NODE_INFORMATION *key = (void *)buffer;
+ DWORD size, i = 0;
+ HANDLE mutex;
+
+ mutex = get_display_device_init_mutex();
+
+ pci_key = reg_open_key(NULL, pci_keyW, sizeof(pci_keyW));
+ while (!NtEnumerateKey(pci_key, i++, KeyNodeInformation, key, sizeof(buffer), &size))
+ {
+ unsigned int j = 0;
+
+ if (!(subkey = reg_open_key(pci_key, key->Name, key->NameLength)))
+ continue;
+
+ while (!NtEnumerateKey(subkey, j++, KeyNodeInformation, key, sizeof(buffer), &size))
+ {
+ if (!(device_key = reg_open_key(subkey, key->Name, key->NameLength)))
+ continue;
+
+ size = query_reg_value(device_key, class_guidW, value, sizeof(buffer));
+ if (size != sizeof(guid_devclass_displayW) ||
+ wcscmp((WCHAR *)value->Data, guid_devclass_displayW))
+ {
+ NtClose(device_key);
+ continue;
+ }
+
+ if (!(prop_key = reg_open_key(device_key, devpropkey_gpu_vulkan_uuidW,
+ sizeof(devpropkey_gpu_vulkan_uuidW))))
+ {
+ NtClose(device_key);
+ continue;
+ }
+
+ size = query_reg_value(prop_key, NULL, value, sizeof(buffer));
+ NtClose(prop_key);
+ if (size != sizeof(GUID) || memcmp(value->Data, uuid, sizeof(GUID)))
+ {
+ NtClose(device_key);
+ continue;
+ }
+
+ if (!(prop_key = reg_open_key(device_key, devpropkey_gpu_luidW,
+ sizeof(devpropkey_gpu_luidW))))
+ {
+ NtClose(device_key);
+ continue;
+ }
+
+ size = query_reg_value(prop_key, NULL, value, sizeof(buffer));
+ NtClose(prop_key);
+ if (size != sizeof(LUID))
+ {
+ NtClose(device_key);
+ continue;
+ }
+
+ *luid = *(const LUID *)value->Data;
+ NtClose(device_key);
+ NtClose(subkey);
+ NtClose(pci_key);
+ release_display_device_init_mutex(mutex);
+ return TRUE;
+ }
+ NtClose(subkey);
+ }
+ NtClose(pci_key);
+
+ release_display_device_init_mutex(mutex);
+ return FALSE;
+}
+
+NTSTATUS X11DRV_D3DKMTEnumAdapters2( D3DKMT_ENUMADAPTERS2 *desc )
+{
+ static const char *extensions[] =
+ {
+ VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
+ VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME,
+ };
+ const struct vulkan_funcs *vulkan_funcs;
+ PFN_vkGetPhysicalDeviceProperties2KHR pvkGetPhysicalDeviceProperties2KHR;
+ PFN_vkEnumeratePhysicalDevices pvkEnumeratePhysicalDevices;
+ VkPhysicalDevice *vk_physical_devices = NULL;
+ VkPhysicalDeviceProperties2 properties2;
+ NTSTATUS status = STATUS_UNSUCCESSFUL;
+ UINT device_count = 0, device_idx = 0;
+ struct x11_d3dkmt_adapter *adapter;
+ VkInstanceCreateInfo create_info;
+ VkPhysicalDeviceIDProperties id;
+ VkResult vr;
+ LUID luid;
+
+ if (!(vulkan_funcs = get_vulkan_driver(WINE_VULKAN_DRIVER_VERSION)))
+ {
+ WARN("Vulkan is unavailable.\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ pthread_mutex_lock(&d3dkmt_mutex);
+
+ if (!d3dkmt_vk_instance)
+ {
+ memset(&create_info, 0, sizeof(create_info));
+ create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
+ create_info.enabledExtensionCount = ARRAY_SIZE(extensions);
+ create_info.ppEnabledExtensionNames = extensions;
+
+ vr = vulkan_funcs->p_vkCreateInstance(&create_info, NULL, &d3dkmt_vk_instance);
+ if (vr != VK_SUCCESS)
+ {
+ WARN("Failed to create a Vulkan instance, vr %d.\n", vr);
+ goto done;
+ }
+ }
+
+#define LOAD_VK_FUNC(f) \
+ if (!(p##f = (void *)vulkan_funcs->p_vkGetInstanceProcAddr(d3dkmt_vk_instance, #f))) \
+ { \
+ WARN("Failed to load " #f ".\n"); \
+ goto done; \
+ }
+
+ LOAD_VK_FUNC(vkEnumeratePhysicalDevices)
+ LOAD_VK_FUNC(vkGetPhysicalDeviceProperties2KHR)
+#undef LOAD_VK_FUNC
+
+ vr = pvkEnumeratePhysicalDevices(d3dkmt_vk_instance, &device_count, NULL);
+ if (vr != VK_SUCCESS || !device_count)
+ {
+ WARN("No Vulkan device found, vr %d, device_count %d.\n", vr, device_count);
+ goto done;
+ }
+
+ if (!desc->pAdapters)
+ {
+ status = STATUS_SUCCESS;
+ goto done;
+ }
+ else if (desc->NumAdapters < device_count)
+ {
+ status = STATUS_BUFFER_TOO_SMALL;
+ goto done;
+ }
+
+ if (!(vk_physical_devices = calloc(device_count, sizeof(*vk_physical_devices))))
+ {
+ status = STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ vr = pvkEnumeratePhysicalDevices(d3dkmt_vk_instance, &device_count, vk_physical_devices);
+ if (vr != VK_SUCCESS)
+ {
+ WARN("vkEnumeratePhysicalDevices failed, vr %d.\n", vr);
+ goto done;
+ }
+
+ for (device_idx = 0; device_idx < device_count; ++device_idx)
+ {
+ memset(&id, 0, sizeof(id));
+ id.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES;
+ properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
+ properties2.pNext = &id;
+
+ pvkGetPhysicalDeviceProperties2KHR(vk_physical_devices[device_idx], &properties2);
+
+ if (!(adapter = malloc(sizeof(*adapter))))
+ {
+ status = STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ adapter->handle = desc->pAdapters[device_idx].hAdapter;
+ adapter->vk_device = vk_physical_devices[device_idx];
+ list_add_tail(&x11_d3dkmt_adapters, &adapter->entry);
+
+ if (get_vulkan_luid_from_uuid((const GUID *)id.deviceUUID, &luid))
+ {
+ memcpy(&desc->pAdapters[device_idx].AdapterLuid, &luid, sizeof(LUID));
+ }
+ else
+ {
+ WARN("get_vulkan_luid_from_uuid failed, AdapterLuid will remain empty.\n");
+ memset(&desc->pAdapters[device_idx].AdapterLuid, 0, sizeof(LUID));
+ }
+
+ desc->pAdapters[device_idx].NumOfSources = 1;
+ desc->pAdapters[device_idx].bPrecisePresentRegionsPreferred = FALSE;
+ }
+
+ status = STATUS_SUCCESS;
+
+done:
+ desc->NumAdapters = device_count;
+ if (d3dkmt_vk_instance && list_empty(&x11_d3dkmt_adapters))
+ {
+ vulkan_funcs->p_vkDestroyInstance(d3dkmt_vk_instance, NULL);
+ d3dkmt_vk_instance = NULL;
+ }
+ pthread_mutex_unlock(&d3dkmt_mutex);
+ free(vk_physical_devices);
+ return status;
+}
+
/* Find the Vulkan device UUID corresponding to a LUID */
static BOOL get_vulkan_uuid_from_luid( const LUID *luid, GUID *uuid )
{
diff --git a/dlls/winex11.drv/xrender.c b/dlls/winex11.drv/xrender.c
index 7472391..7e605f9 100644
--- a/dlls/winex11.drv/xrender.c
+++ b/dlls/winex11.drv/xrender.c
@@ -2236,6 +2236,7 @@ static const struct gdi_dc_funcs xrender_funcs =
NULL, /* pUnrealizePalette */
NULL, /* pD3DKMTCheckVidPnExclusiveOwnership */
NULL, /* pD3DKMTCloseAdapter */
+ NULL, /* pD3DKMTEnumAdapters2 */
NULL, /* pD3DKMTOpenAdapterFromLuid */
NULL, /* pD3DKMTQueryVideoMemoryInfo */
NULL, /* pD3DKMTSetVidPnSourceOwner */
diff --git a/dlls/wow64win/gdi.c b/dlls/wow64win/gdi.c
index 36af173..993580c 100644
--- a/dlls/wow64win/gdi.c
+++ b/dlls/wow64win/gdi.c
@@ -507,6 +507,28 @@ NTSTATUS WINAPI wow64_NtGdiDdDDIDestroyDevice( UINT *args )
return NtGdiDdDDIDestroyDevice( desc );
}
+NTSTATUS WINAPI wow64_NtGdiDdDDIEnumAdapters2( UINT *args )
+{
+ struct
+ {
+ ULONG NumAdapters;
+ ULONG pAdapters;
+ } *desc32 = get_ptr( &args );
+ D3DKMT_ENUMADAPTERS2 desc;
+ NTSTATUS status;
+
+ if (!desc32) return STATUS_INVALID_PARAMETER;
+
+ desc.NumAdapters = desc32->NumAdapters;
+ desc.pAdapters = UlongToPtr( desc32->pAdapters );
+
+ status = NtGdiDdDDIEnumAdapters2( &desc );
+
+ desc32->NumAdapters = desc.NumAdapters;
+
+ return status;
+}
+
NTSTATUS WINAPI wow64_NtGdiDdDDIEscape( UINT *args )
{
const struct
diff --git a/include/ddk/d3dkmthk.h b/include/ddk/d3dkmthk.h
index 2d30bdd..918a4ad 100644
--- a/include/ddk/d3dkmthk.h
+++ b/include/ddk/d3dkmthk.h
@@ -785,6 +785,7 @@ NTSTATUS WINAPI D3DKMTCreateDCFromMemory(D3DKMT_CREATEDCFROMMEMORY *desc);
NTSTATUS WINAPI D3DKMTDestroyDCFromMemory(const D3DKMT_DESTROYDCFROMMEMORY *desc);
NTSTATUS WINAPI D3DKMTDestroyDevice(const D3DKMT_DESTROYDEVICE *desc);
NTSTATUS WINAPI D3DKMTEscape( const D3DKMT_ESCAPE *desc );
+NTSTATUS WINAPI D3DKMTEnumAdapters2(D3DKMT_ENUMADAPTERS2 *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 c2cb192..5097353 100644
--- a/include/ntgdi.h
+++ b/include/ntgdi.h
@@ -481,6 +481,7 @@ W32KAPI NTSTATUS WINAPI NtGdiDdDDICreateDCFromMemory( D3DKMT_CREATEDCFROMMEMORY
W32KAPI NTSTATUS WINAPI NtGdiDdDDICreateDevice( D3DKMT_CREATEDEVICE *desc );
W32KAPI NTSTATUS WINAPI NtGdiDdDDIDestroyDCFromMemory( const D3DKMT_DESTROYDCFROMMEMORY *desc );
W32KAPI NTSTATUS WINAPI NtGdiDdDDIDestroyDevice( const D3DKMT_DESTROYDEVICE *desc );
+W32KAPI NTSTATUS WINAPI NtGdiDdDDIEnumAdapters2( D3DKMT_ENUMADAPTERS2 *desc );
W32KAPI NTSTATUS WINAPI NtGdiDdDDIEscape( const D3DKMT_ESCAPE *desc );
W32KAPI NTSTATUS WINAPI NtGdiDdDDIOpenAdapterFromHdc( D3DKMT_OPENADAPTERFROMHDC *desc );
W32KAPI NTSTATUS WINAPI NtGdiDdDDIOpenAdapterFromDeviceName( D3DKMT_OPENADAPTERFROMDEVICENAME *desc );
diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h
index 5689e8c..0c3c919 100644
--- a/include/wine/gdi_driver.h
+++ b/include/wine/gdi_driver.h
@@ -168,6 +168,7 @@ struct gdi_dc_funcs
BOOL (*pUnrealizePalette)(HPALETTE);
NTSTATUS (*pD3DKMTCheckVidPnExclusiveOwnership)(const D3DKMT_CHECKVIDPNEXCLUSIVEOWNERSHIP *);
NTSTATUS (*pD3DKMTCloseAdapter)(const D3DKMT_CLOSEADAPTER *);
+ NTSTATUS (*pD3DKMTEnumAdapters2)(D3DKMT_ENUMADAPTERS2 *);
NTSTATUS (*pD3DKMTOpenAdapterFromLuid)(D3DKMT_OPENADAPTERFROMLUID *);
NTSTATUS (*pD3DKMTQueryVideoMemoryInfo)(D3DKMT_QUERYVIDEOMEMORYINFO *);
NTSTATUS (*pD3DKMTSetVidPnSourceOwner)(const D3DKMT_SETVIDPNSOURCEOWNER *);
commit 078cdc32a3c1c7cf95f213159d4a97b98b04789b
Author: Krzysztof Bogacki <krzysztof.bogacki@leancode.pl>
Date: Tue Dec 19 23:57:14 2023 +0100
win32u: Allow faking HAGS in QueryAdapterInfo.
diff --git a/dlls/win32u/driver.c b/dlls/win32u/driver.c
index 3f7b9e4..2bc7c37 100644
--- a/dlls/win32u/driver.c
+++ b/dlls/win32u/driver.c
@@ -1691,16 +1691,49 @@ NTSTATUS WINAPI NtGdiDdDDIDestroyDevice( const D3DKMT_DESTROYDEVICE *desc )
return status;
}
+static BOOL check_hags_enabled( void )
+{
+ const char *winehags = getenv( "WINEHAGS" );
+ return winehags && *winehags != '0';
+}
+
/******************************************************************************
* NtGdiDdDDIQueryAdapterInfo (win32u.@)
*/
NTSTATUS WINAPI NtGdiDdDDIQueryAdapterInfo( D3DKMT_QUERYADAPTERINFO *desc )
{
+ D3DKMT_WDDM_2_7_CAPS *d3dkmt_wddm_2_7_caps;
+
if (!desc)
return STATUS_INVALID_PARAMETER;
- FIXME("desc %p, type %d stub\n", desc, desc->Type);
- return STATUS_NOT_IMPLEMENTED;
+ TRACE("desc %p, type %d\n", desc, desc->Type);
+
+ switch (desc->Type)
+ {
+ case KMTQAITYPE_WDDM_2_7_CAPS:
+ if (!desc->pPrivateDriverData || desc->PrivateDriverDataSize != sizeof(D3DKMT_WDDM_2_7_CAPS))
+ return STATUS_INVALID_PARAMETER;
+
+ d3dkmt_wddm_2_7_caps = desc->pPrivateDriverData;
+ d3dkmt_wddm_2_7_caps->HwSchSupported = 1;
+ d3dkmt_wddm_2_7_caps->HwSchEnabled = 0;
+ d3dkmt_wddm_2_7_caps->HwSchEnabledByDefault = 0;
+ d3dkmt_wddm_2_7_caps->IndependentVidPnVSyncControl = 0;
+
+ if (check_hags_enabled())
+ {
+ d3dkmt_wddm_2_7_caps->HwSchEnabled = 1;
+ d3dkmt_wddm_2_7_caps->HwSchEnabledByDefault = 1;
+ }
+ break;
+
+ default:
+ FIXME("type %d not supported\n", desc->Type);
+ return STATUS_NOT_IMPLEMENTED;
+ }
+
+ return STATUS_SUCCESS;
}
/******************************************************************************
diff --git a/include/ddk/d3dkmthk.h b/include/ddk/d3dkmthk.h
index 918a4ad..4b2c5a7 100644
--- a/include/ddk/d3dkmthk.h
+++ b/include/ddk/d3dkmthk.h
@@ -773,6 +773,22 @@ typedef struct _D3DKMT_ENUMADAPTERS2
D3DKMT_ADAPTERINFO *pAdapters;
} D3DKMT_ENUMADAPTERS2;
+typedef struct _D3DKMT_WDDM_2_7_CAPS
+{
+ union
+ {
+ struct
+ {
+ UINT HwSchSupported : 1;
+ UINT HwSchEnabled : 1;
+ UINT HwSchEnabledByDefault : 1;
+ UINT IndependentVidPnVSyncControl : 1;
+ UINT Reserved : 28;
+ };
+ UINT Value;
+ };
+} D3DKMT_WDDM_2_7_CAPS;
+
#ifdef __cplusplus
extern "C"
{
@oscarbg
Copy link

oscarbg commented Mar 24, 2024

correct 002 patch for 9.5+:

diff --git a/dlls/win32u/d3dkmt.c b/dlls/win32u/d3dkmt.c
index f4d695ac0cb..c489601e147 100644
--- a/dlls/win32u/d3dkmt.c
+++ b/dlls/win32u/d3dkmt.c
@@ -223,15 +223,48 @@ NTSTATUS WINAPI NtGdiDdDDIDestroyDevice( const D3DKMT_DESTROYDEVICE *desc )
     return STATUS_SUCCESS;
 }
 
+static BOOL check_hags_enabled( void )
+{
+    const char *winehags = getenv( "WINEHAGS" );
+    return winehags && *winehags != '0';
+}
+
 /******************************************************************************
  *           NtGdiDdDDIQueryAdapterInfo    (win32u.@)
  */
 NTSTATUS WINAPI NtGdiDdDDIQueryAdapterInfo( D3DKMT_QUERYADAPTERINFO *desc )
 {
+    D3DKMT_WDDM_2_7_CAPS *d3dkmt_wddm_2_7_caps;
+
     if (!desc) return STATUS_INVALID_PARAMETER;
 
-    FIXME( "desc %p, type %d stub\n", desc, desc->Type );
-    return STATUS_NOT_IMPLEMENTED;
+    TRACE("desc %p, type %d\n", desc, desc->Type);
+
+    switch (desc->Type)
+    {
+        case KMTQAITYPE_WDDM_2_7_CAPS:
+            if (!desc->pPrivateDriverData || desc->PrivateDriverDataSize != sizeof(D3DKMT_WDDM_2_7_CAPS))
+                return STATUS_INVALID_PARAMETER;
+
+            d3dkmt_wddm_2_7_caps = desc->pPrivateDriverData;
+            d3dkmt_wddm_2_7_caps->HwSchSupported = 1;
+            d3dkmt_wddm_2_7_caps->HwSchEnabled = 0;
+            d3dkmt_wddm_2_7_caps->HwSchEnabledByDefault = 0;
+            d3dkmt_wddm_2_7_caps->IndependentVidPnVSyncControl = 0;
+
+            if (check_hags_enabled())
+            {
+                d3dkmt_wddm_2_7_caps->HwSchEnabled = 1;
+                d3dkmt_wddm_2_7_caps->HwSchEnabledByDefault = 1;
+            }
+            break;
+
+        default:
+            FIXME("type %d not supported\n", desc->Type);
+            return STATUS_NOT_IMPLEMENTED;
+    }
+
+    return STATUS_SUCCESS;
 }
 
 /******************************************************************************
diff --git a/include/ddk/d3dkmthk.h b/include/ddk/d3dkmthk.h
index 918a4ad..4b2c5a7 100644
--- a/include/ddk/d3dkmthk.h
+++ b/include/ddk/d3dkmthk.h
@@ -773,6 +773,22 @@ typedef struct _D3DKMT_ENUMADAPTERS2
   D3DKMT_ADAPTERINFO *pAdapters;
 } D3DKMT_ENUMADAPTERS2;
 
+typedef struct _D3DKMT_WDDM_2_7_CAPS
+{
+  union
+  {
+    struct
+    {
+      UINT HwSchSupported               :  1;
+      UINT HwSchEnabled                 :  1;
+      UINT HwSchEnabledByDefault        :  1;
+      UINT IndependentVidPnVSyncControl :  1;
+      UINT Reserved                     : 28;
+    };
+    UINT Value;
+  };
+} D3DKMT_WDDM_2_7_CAPS;
+
 #ifdef __cplusplus
 extern "C"
 {

@Saancreed
Copy link
Author

@oscarbg Does my diff from ValveSoftware/Proton#7361 (comment) not apply anymore?

@oscarbg
Copy link

oscarbg commented Mar 24, 2024

it's the same patch!.. wasn't aware of it.. I redid the same work as you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment