Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
June 2022
- 68 participants
- 3274 messages
[PATCH v3 3/4] winex11.drv: Merge settings.c into display.c.
by Rémi Bernon
From: Rémi Bernon <rbernon(a)codeweavers.com>
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/winex11.drv/Makefile.in | 1 -
dlls/winex11.drv/display.c | 962 +++++++++++++++++++++++++++++++++
dlls/winex11.drv/settings.c | 999 -----------------------------------
3 files changed, 962 insertions(+), 1000 deletions(-)
delete mode 100644 dlls/winex11.drv/settings.c
diff --git a/dlls/winex11.drv/Makefile.in b/dlls/winex11.drv/Makefile.in
index 3c653902ef2..e79c691b4d5 100644
--- a/dlls/winex11.drv/Makefile.in
+++ b/dlls/winex11.drv/Makefile.in
@@ -22,7 +22,6 @@ C_SRCS = \
opengl.c \
palette.c \
pen.c \
- settings.c \
systray.c \
vulkan.c \
window.c \
diff --git a/dlls/winex11.drv/display.c b/dlls/winex11.drv/display.c
index 510cb9dcee6..dec9d0afba8 100644
--- a/dlls/winex11.drv/display.c
+++ b/dlls/winex11.drv/display.c
@@ -30,6 +30,968 @@ WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
static struct x11drv_display_device_handler host_handler;
struct x11drv_display_device_handler desktop_handler;
+static struct x11drv_settings_handler settings_handler;
+
+struct x11drv_display_setting
+{
+ ULONG_PTR id;
+ BOOL placed;
+ RECT new_rect;
+ RECT desired_rect;
+ DEVMODEW desired_mode;
+};
+
+struct x11drv_display_depth
+{
+ struct list entry;
+ ULONG_PTR display_id;
+ DWORD depth;
+};
+
+/* Display device emulated depth list, protected by modes_section */
+static struct list x11drv_display_depth_list = LIST_INIT(x11drv_display_depth_list);
+
+/* All Windows drivers seen so far either support 32 bit depths, or 24 bit depths, but never both. So if we have
+ * a 32 bit framebuffer, report 32 bit bpps, otherwise 24 bit ones.
+ */
+static const unsigned int depths_24[] = {8, 16, 24};
+static const unsigned int depths_32[] = {8, 16, 32};
+const unsigned int *depths;
+
+/* Cached display modes for a device, protected by modes_section */
+static WCHAR cached_device_name[CCHDEVICENAME];
+static DWORD cached_flags;
+static DEVMODEW *cached_modes;
+static UINT cached_mode_count;
+
+static pthread_mutex_t settings_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+void X11DRV_Settings_SetHandler(const struct x11drv_settings_handler *new_handler)
+{
+ if (new_handler->priority > settings_handler.priority)
+ {
+ settings_handler = *new_handler;
+ TRACE("Display settings are now handled by: %s.\n", settings_handler.name);
+ }
+}
+
+/***********************************************************************
+ * Default handlers if resolution switching is not enabled
+ *
+ */
+static BOOL nores_get_id(const WCHAR *device_name, ULONG_PTR *id)
+{
+ WCHAR primary_adapter[CCHDEVICENAME];
+
+ if (!get_primary_adapter( primary_adapter ))
+ return FALSE;
+
+ *id = !wcsicmp( device_name, primary_adapter ) ? 1 : 0;
+ return TRUE;
+}
+
+static BOOL nores_get_modes(ULONG_PTR id, DWORD flags, DEVMODEW **new_modes, UINT *mode_count)
+{
+ RECT primary = get_host_primary_monitor_rect();
+ DEVMODEW *modes;
+
+ modes = calloc(1, sizeof(*modes));
+ if (!modes)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
+
+ modes[0].dmSize = sizeof(*modes);
+ modes[0].dmDriverExtra = 0;
+ modes[0].dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT |
+ DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY;
+ modes[0].dmDisplayOrientation = DMDO_DEFAULT;
+ modes[0].dmBitsPerPel = screen_bpp;
+ modes[0].dmPelsWidth = primary.right;
+ modes[0].dmPelsHeight = primary.bottom;
+ modes[0].dmDisplayFlags = 0;
+ modes[0].dmDisplayFrequency = 60;
+
+ *new_modes = modes;
+ *mode_count = 1;
+ return TRUE;
+}
+
+static void nores_free_modes(DEVMODEW *modes)
+{
+ free(modes);
+}
+
+static BOOL nores_get_current_mode(ULONG_PTR id, DEVMODEW *mode)
+{
+ RECT primary = get_host_primary_monitor_rect();
+
+ mode->dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT |
+ DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY | DM_POSITION;
+ mode->dmDisplayOrientation = DMDO_DEFAULT;
+ mode->dmDisplayFlags = 0;
+ mode->dmPosition.x = 0;
+ mode->dmPosition.y = 0;
+
+ if (id != 1)
+ {
+ FIXME("Non-primary adapters are unsupported.\n");
+ mode->dmBitsPerPel = 0;
+ mode->dmPelsWidth = 0;
+ mode->dmPelsHeight = 0;
+ mode->dmDisplayFrequency = 0;
+ return TRUE;
+ }
+
+ mode->dmBitsPerPel = screen_bpp;
+ mode->dmPelsWidth = primary.right;
+ mode->dmPelsHeight = primary.bottom;
+ mode->dmDisplayFrequency = 60;
+ return TRUE;
+}
+
+static LONG nores_set_current_mode(ULONG_PTR id, DEVMODEW *mode)
+{
+ WARN("NoRes settings handler, ignoring mode change request.\n");
+ return DISP_CHANGE_SUCCESSFUL;
+}
+
+/* default handler only gets the current X desktop resolution */
+void X11DRV_Settings_Init(void)
+{
+ struct x11drv_settings_handler nores_handler;
+
+ depths = screen_bpp == 32 ? depths_32 : depths_24;
+
+ nores_handler.name = "NoRes";
+ nores_handler.priority = 1;
+ nores_handler.get_id = nores_get_id;
+ nores_handler.get_modes = nores_get_modes;
+ nores_handler.free_modes = nores_free_modes;
+ nores_handler.get_current_mode = nores_get_current_mode;
+ nores_handler.set_current_mode = nores_set_current_mode;
+ X11DRV_Settings_SetHandler(&nores_handler);
+}
+
+/* Initialize registry display settings when new display devices are added */
+void init_registry_display_settings(void)
+{
+ DEVMODEW dm = {.dmSize = sizeof(dm)};
+ DISPLAY_DEVICEW dd = {sizeof(dd)};
+ UNICODE_STRING device_name;
+ DWORD i = 0;
+ LONG ret;
+
+ while (!NtUserEnumDisplayDevices( NULL, i++, &dd, 0 ))
+ {
+ RtlInitUnicodeString( &device_name, dd.DeviceName );
+
+ /* Skip if the device already has registry display settings */
+ if (NtUserEnumDisplaySettings( &device_name, ENUM_REGISTRY_SETTINGS, &dm, 0 ))
+ continue;
+
+ if (!NtUserEnumDisplaySettings( &device_name, ENUM_CURRENT_SETTINGS, &dm, 0 ))
+ {
+ ERR("Failed to query current display settings for %s.\n", wine_dbgstr_w(dd.DeviceName));
+ continue;
+ }
+
+ TRACE("Device %s current display mode %ux%u %ubits %uHz at %d,%d.\n",
+ wine_dbgstr_w(dd.DeviceName), dm.dmPelsWidth, dm.dmPelsHeight, dm.dmBitsPerPel,
+ dm.dmDisplayFrequency, dm.dmPosition.x, dm.dmPosition.y);
+
+ ret = NtUserChangeDisplaySettings( &device_name, &dm, NULL,
+ CDS_GLOBAL | CDS_NORESET | CDS_UPDATEREGISTRY, NULL );
+ if (ret != DISP_CHANGE_SUCCESSFUL)
+ ERR("Failed to save registry display settings for %s, returned %d.\n",
+ wine_dbgstr_w(dd.DeviceName), ret);
+ }
+}
+
+static HKEY get_display_device_reg_key( const WCHAR *device_name )
+{
+ static const WCHAR display[] = {'\\','\\','.','\\','D','I','S','P','L','A','Y'};
+ static const WCHAR video_key[] = {
+ '\\','R','e','g','i','s','t','r','y',
+ '\\','M','a','c','h','i','n','e',
+ '\\','H','A','R','D','W','A','R','E',
+ '\\','D','E','V','I','C','E','M','A','P',
+ '\\','V','I','D','E','O'};
+ static const WCHAR current_config_key[] = {
+ '\\','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',
+ '\\','H','a','r','d','w','a','r','e',' ','P','r','o','f','i','l','e','s',
+ '\\','C','u','r','r','e','n','t'};
+ WCHAR value_name[MAX_PATH], buffer[4096], *end_ptr;
+ KEY_VALUE_PARTIAL_INFORMATION *value = (void *)buffer;
+ DWORD adapter_index, size;
+ char adapter_name[100];
+ HKEY hkey;
+
+ /* Device name has to be \\.\DISPLAY%d */
+ if (wcsnicmp( device_name, display, ARRAY_SIZE(display) ))
+ return FALSE;
+
+ /* Parse \\.\DISPLAY* */
+ adapter_index = wcstol( device_name + ARRAY_SIZE(display), &end_ptr, 10 ) - 1;
+ if (*end_ptr)
+ return FALSE;
+
+ /* Open \Device\Video* in HKLM\HARDWARE\DEVICEMAP\VIDEO\ */
+ if (!(hkey = reg_open_key( NULL, video_key, sizeof(video_key) ))) return FALSE;
+ sprintf( adapter_name, "\\Device\\Video%d", adapter_index );
+ asciiz_to_unicode( value_name, adapter_name );
+ size = query_reg_value( hkey, value_name, value, sizeof(buffer) );
+ NtClose( hkey );
+ if (!size || value->Type != REG_SZ) return FALSE;
+
+ /* Replace \Registry\Machine\ prefix with HKEY_CURRENT_CONFIG */
+ memmove( buffer + ARRAYSIZE(current_config_key), (const WCHAR *)value->Data + 17,
+ size - 17 * sizeof(WCHAR) );
+ memcpy( buffer, current_config_key, sizeof(current_config_key) );
+ TRACE( "display device %s registry settings key %s.\n", wine_dbgstr_w(device_name),
+ wine_dbgstr_w(buffer) );
+ return reg_open_key( NULL, buffer, lstrlenW(buffer) * sizeof(WCHAR) );
+}
+
+static BOOL query_display_setting( HKEY hkey, const char *name, DWORD *ret )
+{
+ char buffer[1024];
+ WCHAR nameW[128];
+ KEY_VALUE_PARTIAL_INFORMATION *value = (void *)buffer;
+
+ asciiz_to_unicode( nameW, name );
+ if (query_reg_value( hkey, nameW, value, sizeof(buffer) ) != sizeof(DWORD) ||
+ value->Type != REG_DWORD)
+ return FALSE;
+
+ *ret = *(DWORD *)value->Data;
+ return TRUE;
+}
+
+static BOOL read_registry_settings(const WCHAR *device_name, DEVMODEW *dm)
+{
+ HANDLE mutex;
+ HKEY hkey;
+ BOOL ret = TRUE;
+
+ dm->dmFields = 0;
+
+ mutex = get_display_device_init_mutex();
+ if (!(hkey = get_display_device_reg_key( device_name )))
+ {
+ release_display_device_init_mutex(mutex);
+ return FALSE;
+ }
+
+ ret &= query_display_setting( hkey, "DefaultSettings.BitsPerPel", &dm->dmBitsPerPel );
+ dm->dmFields |= DM_BITSPERPEL;
+ ret &= query_display_setting( hkey, "DefaultSettings.XResolution", &dm->dmPelsWidth );
+ dm->dmFields |= DM_PELSWIDTH;
+ ret &= query_display_setting( hkey, "DefaultSettings.YResolution", &dm->dmPelsHeight );
+ dm->dmFields |= DM_PELSHEIGHT;
+ ret &= query_display_setting( hkey, "DefaultSettings.VRefresh", &dm->dmDisplayFrequency );
+ dm->dmFields |= DM_DISPLAYFREQUENCY;
+ ret &= query_display_setting( hkey, "DefaultSettings.Flags", &dm->dmDisplayFlags );
+ dm->dmFields |= DM_DISPLAYFLAGS;
+ ret &= query_display_setting( hkey, "DefaultSettings.XPanning", (DWORD *)&dm->dmPosition.x );
+ ret &= query_display_setting( hkey, "DefaultSettings.YPanning", (DWORD *)&dm->dmPosition.y );
+ dm->dmFields |= DM_POSITION;
+ ret &= query_display_setting( hkey, "DefaultSettings.Orientation", &dm->dmDisplayOrientation );
+ dm->dmFields |= DM_DISPLAYORIENTATION;
+ ret &= query_display_setting( hkey, "DefaultSettings.FixedOutput", &dm->dmDisplayFixedOutput );
+
+ NtClose( hkey );
+ release_display_device_init_mutex(mutex);
+ return ret;
+}
+
+static BOOL set_setting_value( HKEY hkey, const char *name, DWORD val )
+{
+ WCHAR nameW[128];
+ UNICODE_STRING str = { asciiz_to_unicode( nameW, name ) - sizeof(WCHAR), sizeof(nameW), nameW };
+ return !NtSetValueKey( hkey, &str, 0, REG_DWORD, &val, sizeof(val) );
+}
+
+static BOOL write_registry_settings(const WCHAR *device_name, const DEVMODEW *dm)
+{
+ HANDLE mutex;
+ HKEY hkey;
+ BOOL ret = TRUE;
+
+ mutex = get_display_device_init_mutex();
+ if (!(hkey = get_display_device_reg_key( device_name )))
+ {
+ release_display_device_init_mutex(mutex);
+ return FALSE;
+ }
+
+ ret &= set_setting_value( hkey, "DefaultSettings.BitsPerPel", dm->dmBitsPerPel );
+ ret &= set_setting_value( hkey, "DefaultSettings.XResolution", dm->dmPelsWidth );
+ ret &= set_setting_value( hkey, "DefaultSettings.YResolution", dm->dmPelsHeight );
+ ret &= set_setting_value( hkey, "DefaultSettings.VRefresh", dm->dmDisplayFrequency );
+ ret &= set_setting_value( hkey, "DefaultSettings.Flags", dm->dmDisplayFlags );
+ ret &= set_setting_value( hkey, "DefaultSettings.XPanning", dm->dmPosition.x );
+ ret &= set_setting_value( hkey, "DefaultSettings.YPanning", dm->dmPosition.y );
+ ret &= set_setting_value( hkey, "DefaultSettings.Orientation", dm->dmDisplayOrientation );
+ ret &= set_setting_value( hkey, "DefaultSettings.FixedOutput", dm->dmDisplayFixedOutput );
+
+ NtClose( hkey );
+ release_display_device_init_mutex(mutex);
+ return ret;
+}
+
+BOOL get_primary_adapter(WCHAR *name)
+{
+ DISPLAY_DEVICEW dd;
+ DWORD i;
+
+ dd.cb = sizeof(dd);
+ for (i = 0; !NtUserEnumDisplayDevices( NULL, i, &dd, 0 ); ++i)
+ {
+ if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
+ {
+ lstrcpyW(name, dd.DeviceName);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static int mode_compare(const void *p1, const void *p2)
+{
+ DWORD a_width, a_height, b_width, b_height;
+ const DEVMODEW *a = p1, *b = p2;
+
+ /* Use the width and height in landscape mode for comparison */
+ if (a->dmDisplayOrientation == DMDO_DEFAULT || a->dmDisplayOrientation == DMDO_180)
+ {
+ a_width = a->dmPelsWidth;
+ a_height = a->dmPelsHeight;
+ }
+ else
+ {
+ a_width = a->dmPelsHeight;
+ a_height = a->dmPelsWidth;
+ }
+
+ if (b->dmDisplayOrientation == DMDO_DEFAULT || b->dmDisplayOrientation == DMDO_180)
+ {
+ b_width = b->dmPelsWidth;
+ b_height = b->dmPelsHeight;
+ }
+ else
+ {
+ b_width = b->dmPelsHeight;
+ b_height = b->dmPelsWidth;
+ }
+
+ /* Depth in descending order */
+ if (a->dmBitsPerPel != b->dmBitsPerPel)
+ return b->dmBitsPerPel - a->dmBitsPerPel;
+
+ /* Width in ascending order */
+ if (a_width != b_width)
+ return a_width - b_width;
+
+ /* Height in ascending order */
+ if (a_height != b_height)
+ return a_height - b_height;
+
+ /* Frequency in descending order */
+ if (a->dmDisplayFrequency != b->dmDisplayFrequency)
+ return b->dmDisplayFrequency - a->dmDisplayFrequency;
+
+ /* Orientation in ascending order */
+ return a->dmDisplayOrientation - b->dmDisplayOrientation;
+}
+
+static void set_display_depth(ULONG_PTR display_id, DWORD depth)
+{
+ struct x11drv_display_depth *display_depth;
+
+ pthread_mutex_lock( &settings_mutex );
+ LIST_FOR_EACH_ENTRY(display_depth, &x11drv_display_depth_list, struct x11drv_display_depth, entry)
+ {
+ if (display_depth->display_id == display_id)
+ {
+ display_depth->depth = depth;
+ pthread_mutex_unlock( &settings_mutex );
+ return;
+ }
+ }
+
+ display_depth = malloc(sizeof(*display_depth));
+ if (!display_depth)
+ {
+ ERR("Failed to allocate memory.\n");
+ pthread_mutex_unlock( &settings_mutex );
+ return;
+ }
+
+ display_depth->display_id = display_id;
+ display_depth->depth = depth;
+ list_add_head(&x11drv_display_depth_list, &display_depth->entry);
+ pthread_mutex_unlock( &settings_mutex );
+}
+
+static DWORD get_display_depth(ULONG_PTR display_id)
+{
+ struct x11drv_display_depth *display_depth;
+ DWORD depth;
+
+ pthread_mutex_lock( &settings_mutex );
+ LIST_FOR_EACH_ENTRY(display_depth, &x11drv_display_depth_list, struct x11drv_display_depth, entry)
+ {
+ if (display_depth->display_id == display_id)
+ {
+ depth = display_depth->depth;
+ pthread_mutex_unlock( &settings_mutex );
+ return depth;
+ }
+ }
+ pthread_mutex_unlock( &settings_mutex );
+ return screen_bpp;
+}
+
+/***********************************************************************
+ * EnumDisplaySettingsEx (X11DRV.@)
+ *
+ */
+BOOL X11DRV_EnumDisplaySettingsEx( LPCWSTR name, DWORD n, LPDEVMODEW devmode, DWORD flags)
+{
+ static const WCHAR dev_name[CCHDEVICENAME] =
+ { 'W','i','n','e',' ','X','1','1',' ','d','r','i','v','e','r',0 };
+ DEVMODEW *modes;
+ UINT mode_count;
+ ULONG_PTR id;
+
+ if (n == ENUM_REGISTRY_SETTINGS)
+ {
+ if (!read_registry_settings(name, devmode))
+ {
+ ERR("Failed to get %s registry display settings.\n", wine_dbgstr_w(name));
+ return FALSE;
+ }
+ goto done;
+ }
+
+ if (n == ENUM_CURRENT_SETTINGS)
+ {
+ if (!settings_handler.get_id(name, &id) || !settings_handler.get_current_mode(id, devmode))
+ {
+ ERR("Failed to get %s current display settings.\n", wine_dbgstr_w(name));
+ return FALSE;
+ }
+
+ if (!is_detached_mode(devmode))
+ devmode->dmBitsPerPel = get_display_depth(id);
+
+ goto done;
+ }
+
+ pthread_mutex_lock( &settings_mutex );
+ if (n == 0 || wcsicmp(cached_device_name, name) || cached_flags != flags)
+ {
+ if (!settings_handler.get_id(name, &id) || !settings_handler.get_modes(id, flags, &modes, &mode_count))
+ {
+ ERR("Failed to get %s supported display modes.\n", wine_dbgstr_w(name));
+ pthread_mutex_unlock( &settings_mutex );
+ return FALSE;
+ }
+
+ qsort(modes, mode_count, sizeof(*modes) + modes[0].dmDriverExtra, mode_compare);
+
+ if (cached_modes)
+ settings_handler.free_modes(cached_modes);
+ lstrcpyW(cached_device_name, name);
+ cached_flags = flags;
+ cached_modes = modes;
+ cached_mode_count = mode_count;
+ }
+
+ if (n >= cached_mode_count)
+ {
+ pthread_mutex_unlock( &settings_mutex );
+ WARN("handler:%s device:%s mode index:%#x not found.\n", settings_handler.name, wine_dbgstr_w(name), n);
+ SetLastError(ERROR_NO_MORE_FILES);
+ return FALSE;
+ }
+
+ memcpy(devmode, (BYTE *)cached_modes + (sizeof(*cached_modes) + cached_modes[0].dmDriverExtra) * n, sizeof(*devmode));
+ pthread_mutex_unlock( &settings_mutex );
+
+done:
+ /* Set generic fields */
+ devmode->dmSize = FIELD_OFFSET(DEVMODEW, dmICMMethod);
+ devmode->dmDriverExtra = 0;
+ devmode->dmSpecVersion = DM_SPECVERSION;
+ devmode->dmDriverVersion = DM_SPECVERSION;
+ lstrcpyW(devmode->dmDeviceName, dev_name);
+ return TRUE;
+}
+
+BOOL is_detached_mode(const DEVMODEW *mode)
+{
+ return mode->dmFields & DM_POSITION &&
+ mode->dmFields & DM_PELSWIDTH &&
+ mode->dmFields & DM_PELSHEIGHT &&
+ mode->dmPelsWidth == 0 &&
+ mode->dmPelsHeight == 0;
+}
+
+/* Get the full display mode with all the necessary fields set.
+ * Return NULL on failure. Caller should call free_full_mode() to free the returned mode. */
+static DEVMODEW *get_full_mode(ULONG_PTR id, DEVMODEW *dev_mode)
+{
+ DEVMODEW *modes, *full_mode, *found_mode = NULL;
+ UINT mode_count, mode_idx;
+
+ if (is_detached_mode(dev_mode))
+ return dev_mode;
+
+ if (!settings_handler.get_modes(id, EDS_ROTATEDMODE, &modes, &mode_count))
+ return NULL;
+
+ qsort(modes, mode_count, sizeof(*modes) + modes[0].dmDriverExtra, mode_compare);
+ for (mode_idx = 0; mode_idx < mode_count; ++mode_idx)
+ {
+ found_mode = (DEVMODEW *)((BYTE *)modes + (sizeof(*modes) + modes[0].dmDriverExtra) * mode_idx);
+
+ if (dev_mode->dmFields & DM_BITSPERPEL &&
+ dev_mode->dmBitsPerPel &&
+ found_mode->dmBitsPerPel != dev_mode->dmBitsPerPel)
+ continue;
+ if (dev_mode->dmFields & DM_PELSWIDTH && found_mode->dmPelsWidth != dev_mode->dmPelsWidth)
+ continue;
+ if (dev_mode->dmFields & DM_PELSHEIGHT && found_mode->dmPelsHeight != dev_mode->dmPelsHeight)
+ continue;
+ if (dev_mode->dmFields & DM_DISPLAYFREQUENCY &&
+ dev_mode->dmDisplayFrequency &&
+ found_mode->dmDisplayFrequency &&
+ dev_mode->dmDisplayFrequency != 1 &&
+ dev_mode->dmDisplayFrequency != found_mode->dmDisplayFrequency)
+ continue;
+ if (dev_mode->dmFields & DM_DISPLAYORIENTATION &&
+ found_mode->dmDisplayOrientation != dev_mode->dmDisplayOrientation)
+ continue;
+
+ break;
+ }
+
+ if (!found_mode || mode_idx == mode_count)
+ {
+ settings_handler.free_modes(modes);
+ return NULL;
+ }
+
+ if (!(full_mode = malloc(sizeof(*found_mode) + found_mode->dmDriverExtra)))
+ {
+ settings_handler.free_modes(modes);
+ return NULL;
+ }
+
+ memcpy(full_mode, found_mode, sizeof(*found_mode) + found_mode->dmDriverExtra);
+ settings_handler.free_modes(modes);
+
+ full_mode->dmFields |= DM_POSITION;
+ full_mode->dmPosition = dev_mode->dmPosition;
+ return full_mode;
+}
+
+static void free_full_mode(DEVMODEW *mode)
+{
+ if (!is_detached_mode(mode))
+ free(mode);
+}
+
+static LONG get_display_settings(struct x11drv_display_setting **new_displays,
+ INT *new_display_count, const WCHAR *dev_name, DEVMODEW *dev_mode)
+{
+ struct x11drv_display_setting *displays;
+ DEVMODEW registry_mode, current_mode;
+ INT display_idx, display_count = 0;
+ DISPLAY_DEVICEW display_device;
+ LONG ret = DISP_CHANGE_FAILED;
+ UNICODE_STRING device_name;
+
+ display_device.cb = sizeof(display_device);
+ for (display_idx = 0; !NtUserEnumDisplayDevices( NULL, display_idx, &display_device, 0 ); ++display_idx)
+ ++display_count;
+
+ displays = calloc(display_count, sizeof(*displays));
+ if (!displays)
+ goto done;
+
+ for (display_idx = 0; display_idx < display_count; ++display_idx)
+ {
+ if (NtUserEnumDisplayDevices( NULL, display_idx, &display_device, 0 ))
+ goto done;
+
+ if (!settings_handler.get_id(display_device.DeviceName, &displays[display_idx].id))
+ {
+ ret = DISP_CHANGE_BADPARAM;
+ goto done;
+ }
+
+ RtlInitUnicodeString( &device_name, display_device.DeviceName );
+
+ if (!dev_mode)
+ {
+ memset(®istry_mode, 0, sizeof(registry_mode));
+ registry_mode.dmSize = sizeof(registry_mode);
+ if (!NtUserEnumDisplaySettings( &device_name, ENUM_REGISTRY_SETTINGS, ®istry_mode, 0 ))
+ goto done;
+
+ displays[display_idx].desired_mode = registry_mode;
+ }
+ else if (!wcsicmp(dev_name, display_device.DeviceName))
+ {
+ displays[display_idx].desired_mode = *dev_mode;
+ if (!(dev_mode->dmFields & DM_POSITION))
+ {
+ memset(¤t_mode, 0, sizeof(current_mode));
+ current_mode.dmSize = sizeof(current_mode);
+ if (!NtUserEnumDisplaySettings( &device_name, ENUM_CURRENT_SETTINGS, ¤t_mode, 0 ))
+ goto done;
+
+ displays[display_idx].desired_mode.dmFields |= DM_POSITION;
+ displays[display_idx].desired_mode.dmPosition = current_mode.dmPosition;
+ }
+ }
+ else
+ {
+ memset(¤t_mode, 0, sizeof(current_mode));
+ current_mode.dmSize = sizeof(current_mode);
+ if (!NtUserEnumDisplaySettings( &device_name, ENUM_CURRENT_SETTINGS, ¤t_mode, 0 ))
+ goto done;
+
+ displays[display_idx].desired_mode = current_mode;
+ }
+
+ SetRect(&displays[display_idx].desired_rect,
+ displays[display_idx].desired_mode.dmPosition.x,
+ displays[display_idx].desired_mode.dmPosition.y,
+ displays[display_idx].desired_mode.dmPosition.x + displays[display_idx].desired_mode.dmPelsWidth,
+ displays[display_idx].desired_mode.dmPosition.y + displays[display_idx].desired_mode.dmPelsHeight);
+ lstrcpyW(displays[display_idx].desired_mode.dmDeviceName, display_device.DeviceName);
+ }
+
+ *new_displays = displays;
+ *new_display_count = display_count;
+ return DISP_CHANGE_SUCCESSFUL;
+
+done:
+ free(displays);
+ return ret;
+}
+
+static INT offset_length(POINT offset)
+{
+ return offset.x * offset.x + offset.y * offset.y;
+}
+
+/* Check if a rect overlaps with placed display rects */
+static BOOL overlap_placed_displays(const RECT *rect, const struct x11drv_display_setting *displays, INT display_count)
+{
+ INT display_idx;
+ RECT intersect;
+
+ for (display_idx = 0; display_idx < display_count; ++display_idx)
+ {
+ if (displays[display_idx].placed &&
+ intersect_rect(&intersect, &displays[display_idx].new_rect, rect))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/* Get the offset with minimum length to place a display next to the placed displays with no spacing and overlaps */
+static POINT get_placement_offset(const struct x11drv_display_setting *displays, INT display_count, INT placing_idx)
+{
+ POINT points[8], left_top, offset, min_offset = {0, 0};
+ INT display_idx, point_idx, point_count, vertex_idx;
+ BOOL has_placed = FALSE, first = TRUE;
+ INT width, height;
+ RECT rect;
+
+ /* If the display to be placed is detached, no offset is needed to place it */
+ if (IsRectEmpty(&displays[placing_idx].desired_rect))
+ return min_offset;
+
+ /* If there is no placed and attached display, place this display as it is */
+ for (display_idx = 0; display_idx < display_count; ++display_idx)
+ {
+ if (displays[display_idx].placed && !IsRectEmpty(&displays[display_idx].new_rect))
+ {
+ has_placed = TRUE;
+ break;
+ }
+ }
+
+ if (!has_placed)
+ return min_offset;
+
+ /* Try to place this display with each of its four vertices at every vertex of the placed
+ * displays and see which combination has the minimum offset length */
+ width = displays[placing_idx].desired_rect.right - displays[placing_idx].desired_rect.left;
+ height = displays[placing_idx].desired_rect.bottom - displays[placing_idx].desired_rect.top;
+
+ for (display_idx = 0; display_idx < display_count; ++display_idx)
+ {
+ if (!displays[display_idx].placed || IsRectEmpty(&displays[display_idx].new_rect))
+ continue;
+
+ /* Get four vertices of the placed display rectangle */
+ points[0].x = displays[display_idx].new_rect.left;
+ points[0].y = displays[display_idx].new_rect.top;
+ points[1].x = displays[display_idx].new_rect.left;
+ points[1].y = displays[display_idx].new_rect.bottom;
+ points[2].x = displays[display_idx].new_rect.right;
+ points[2].y = displays[display_idx].new_rect.top;
+ points[3].x = displays[display_idx].new_rect.right;
+ points[3].y = displays[display_idx].new_rect.bottom;
+ point_count = 4;
+
+ /* Intersected points when moving the display to be placed horizontally */
+ if (displays[placing_idx].desired_rect.bottom >= displays[display_idx].new_rect.top &&
+ displays[placing_idx].desired_rect.top <= displays[display_idx].new_rect.bottom)
+ {
+ points[point_count].x = displays[display_idx].new_rect.left;
+ points[point_count++].y = displays[placing_idx].desired_rect.top;
+ points[point_count].x = displays[display_idx].new_rect.right;
+ points[point_count++].y = displays[placing_idx].desired_rect.top;
+ }
+ /* Intersected points when moving the display to be placed vertically */
+ if (displays[placing_idx].desired_rect.left <= displays[display_idx].new_rect.right &&
+ displays[placing_idx].desired_rect.right >= displays[display_idx].new_rect.left)
+ {
+ points[point_count].x = displays[placing_idx].desired_rect.left;
+ points[point_count++].y = displays[display_idx].new_rect.top;
+ points[point_count].x = displays[placing_idx].desired_rect.left;
+ points[point_count++].y = displays[display_idx].new_rect.bottom;
+ }
+
+ /* Try moving each vertex of the display rectangle to each points */
+ for (point_idx = 0; point_idx < point_count; ++point_idx)
+ {
+ for (vertex_idx = 0; vertex_idx < 4; ++vertex_idx)
+ {
+ switch (vertex_idx)
+ {
+ /* Move the bottom right vertex to the point */
+ case 0:
+ left_top.x = points[point_idx].x - width;
+ left_top.y = points[point_idx].y - height;
+ break;
+ /* Move the bottom left vertex to the point */
+ case 1:
+ left_top.x = points[point_idx].x;
+ left_top.y = points[point_idx].y - height;
+ break;
+ /* Move the top right vertex to the point */
+ case 2:
+ left_top.x = points[point_idx].x - width;
+ left_top.y = points[point_idx].y;
+ break;
+ /* Move the top left vertex to the point */
+ case 3:
+ left_top.x = points[point_idx].x;
+ left_top.y = points[point_idx].y;
+ break;
+ }
+
+ offset.x = left_top.x - displays[placing_idx].desired_rect.left;
+ offset.y = left_top.y - displays[placing_idx].desired_rect.top;
+ rect = displays[placing_idx].desired_rect;
+ OffsetRect(&rect, offset.x, offset.y);
+ if (!overlap_placed_displays(&rect, displays, display_count))
+ {
+ if (first)
+ {
+ min_offset = offset;
+ first = FALSE;
+ continue;
+ }
+
+ if (offset_length(offset) < offset_length(min_offset))
+ min_offset = offset;
+ }
+ }
+ }
+ }
+
+ return min_offset;
+}
+
+static void place_all_displays(struct x11drv_display_setting *displays, INT display_count)
+{
+ INT left_most = INT_MAX, top_most = INT_MAX;
+ INT placing_idx, display_idx;
+ POINT min_offset, offset;
+
+ /* Place all displays with no extra space between them and no overlapping */
+ while (1)
+ {
+ /* Place the unplaced display with the minimum offset length first */
+ placing_idx = -1;
+ for (display_idx = 0; display_idx < display_count; ++display_idx)
+ {
+ if (displays[display_idx].placed)
+ continue;
+
+ offset = get_placement_offset(displays, display_count, display_idx);
+ if (placing_idx == -1 || offset_length(offset) < offset_length(min_offset))
+ {
+ min_offset = offset;
+ placing_idx = display_idx;
+ }
+ }
+
+ /* If all displays are placed */
+ if (placing_idx == -1)
+ break;
+
+ displays[placing_idx].new_rect = displays[placing_idx].desired_rect;
+ OffsetRect(&displays[placing_idx].new_rect, min_offset.x, min_offset.y);
+ displays[placing_idx].placed = TRUE;
+ }
+
+ for (display_idx = 0; display_idx < display_count; ++display_idx)
+ {
+ displays[display_idx].desired_mode.dmPosition.x = displays[display_idx].new_rect.left;
+ displays[display_idx].desired_mode.dmPosition.y = displays[display_idx].new_rect.top;
+ left_most = min(left_most, displays[display_idx].new_rect.left);
+ top_most = min(top_most, displays[display_idx].new_rect.top);
+ }
+
+ /* Convert virtual screen coordinates to root coordinates */
+ for (display_idx = 0; display_idx < display_count; ++display_idx)
+ {
+ displays[display_idx].desired_mode.dmPosition.x -= left_most;
+ displays[display_idx].desired_mode.dmPosition.y -= top_most;
+ }
+}
+
+static LONG apply_display_settings(struct x11drv_display_setting *displays, INT display_count, BOOL do_attach)
+{
+ DEVMODEW *full_mode;
+ BOOL attached_mode;
+ INT display_idx;
+ LONG ret;
+
+ for (display_idx = 0; display_idx < display_count; ++display_idx)
+ {
+ attached_mode = !is_detached_mode(&displays[display_idx].desired_mode);
+ if ((attached_mode && !do_attach) || (!attached_mode && do_attach))
+ continue;
+
+ full_mode = get_full_mode(displays[display_idx].id, &displays[display_idx].desired_mode);
+ if (!full_mode)
+ return DISP_CHANGE_BADMODE;
+
+ TRACE("handler:%s changing %s to position:(%d,%d) resolution:%ux%u frequency:%uHz "
+ "depth:%ubits orientation:%#x.\n", settings_handler.name,
+ wine_dbgstr_w(displays[display_idx].desired_mode.dmDeviceName),
+ full_mode->dmPosition.x, full_mode->dmPosition.y, full_mode->dmPelsWidth,
+ full_mode->dmPelsHeight, full_mode->dmDisplayFrequency, full_mode->dmBitsPerPel,
+ full_mode->dmDisplayOrientation);
+
+ ret = settings_handler.set_current_mode(displays[display_idx].id, full_mode);
+ if (attached_mode && ret == DISP_CHANGE_SUCCESSFUL)
+ set_display_depth(displays[display_idx].id, full_mode->dmBitsPerPel);
+ free_full_mode(full_mode);
+ if (ret != DISP_CHANGE_SUCCESSFUL)
+ return ret;
+ }
+
+ return DISP_CHANGE_SUCCESSFUL;
+}
+
+static BOOL all_detached_settings(const struct x11drv_display_setting *displays, INT display_count)
+{
+ INT display_idx;
+
+ for (display_idx = 0; display_idx < display_count; ++display_idx)
+ {
+ if (!is_detached_mode(&displays[display_idx].desired_mode))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/***********************************************************************
+ * ChangeDisplaySettingsEx (X11DRV.@)
+ *
+ */
+LONG X11DRV_ChangeDisplaySettingsEx( LPCWSTR devname, LPDEVMODEW devmode,
+ HWND hwnd, DWORD flags, LPVOID lpvoid )
+{
+ struct x11drv_display_setting *displays;
+ INT display_idx, display_count;
+ DEVMODEW *full_mode;
+ LONG ret;
+
+ ret = get_display_settings(&displays, &display_count, devname, devmode);
+ if (ret != DISP_CHANGE_SUCCESSFUL)
+ return ret;
+
+ if (flags & CDS_UPDATEREGISTRY && devname && devmode)
+ {
+ for (display_idx = 0; display_idx < display_count; ++display_idx)
+ {
+ if (!wcsicmp(displays[display_idx].desired_mode.dmDeviceName, devname))
+ {
+ full_mode = get_full_mode(displays[display_idx].id, &displays[display_idx].desired_mode);
+ if (!full_mode)
+ {
+ free(displays);
+ return DISP_CHANGE_BADMODE;
+ }
+
+ if (!write_registry_settings(devname, full_mode))
+ {
+ ERR("Failed to write %s display settings to registry.\n", wine_dbgstr_w(devname));
+ free_full_mode(full_mode);
+ free(displays);
+ return DISP_CHANGE_NOTUPDATED;
+ }
+
+ free_full_mode(full_mode);
+ break;
+ }
+ }
+ }
+
+ if (flags & (CDS_TEST | CDS_NORESET))
+ {
+ free(displays);
+ return DISP_CHANGE_SUCCESSFUL;
+ }
+
+ if (all_detached_settings(displays, display_count))
+ {
+ WARN("Detaching all displays is not permitted.\n");
+ free(displays);
+ return DISP_CHANGE_SUCCESSFUL;
+ }
+
+ place_all_displays(displays, display_count);
+
+ /* Detach displays first to free up CRTCs */
+ ret = apply_display_settings(displays, display_count, FALSE);
+ if (ret == DISP_CHANGE_SUCCESSFUL)
+ ret = apply_display_settings(displays, display_count, TRUE);
+ if (ret == DISP_CHANGE_SUCCESSFUL)
+ X11DRV_DisplayDevices_Update(TRUE);
+ free(displays);
+ return ret;
+}
HANDLE get_display_device_init_mutex(void)
{
diff --git a/dlls/winex11.drv/settings.c b/dlls/winex11.drv/settings.c
deleted file mode 100644
index 06cf0df4482..00000000000
--- a/dlls/winex11.drv/settings.c
+++ /dev/null
@@ -1,999 +0,0 @@
-/*
- * Wine X11drv display settings functions
- *
- * Copyright 2003 Alexander James Pasadyn
- * Copyright 2020 Zhiyi Zhang for CodeWeavers
- *
- * 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
- */
-
-#if 0
-#pragma makedep unix
-#endif
-
-#include "config.h"
-#include <stdlib.h>
-
-#include "x11drv.h"
-
-#include "windef.h"
-#include "winreg.h"
-#include "wingdi.h"
-#include "wine/debug.h"
-
-WINE_DEFAULT_DEBUG_CHANNEL(x11settings);
-
-static struct x11drv_settings_handler settings_handler;
-
-struct x11drv_display_setting
-{
- ULONG_PTR id;
- BOOL placed;
- RECT new_rect;
- RECT desired_rect;
- DEVMODEW desired_mode;
-};
-
-struct x11drv_display_depth
-{
- struct list entry;
- ULONG_PTR display_id;
- DWORD depth;
-};
-
-/* Display device emulated depth list, protected by modes_section */
-static struct list x11drv_display_depth_list = LIST_INIT(x11drv_display_depth_list);
-
-/* All Windows drivers seen so far either support 32 bit depths, or 24 bit depths, but never both. So if we have
- * a 32 bit framebuffer, report 32 bit bpps, otherwise 24 bit ones.
- */
-static const unsigned int depths_24[] = {8, 16, 24};
-static const unsigned int depths_32[] = {8, 16, 32};
-const unsigned int *depths;
-
-/* Cached display modes for a device, protected by modes_section */
-static WCHAR cached_device_name[CCHDEVICENAME];
-static DWORD cached_flags;
-static DEVMODEW *cached_modes;
-static UINT cached_mode_count;
-
-static pthread_mutex_t settings_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-void X11DRV_Settings_SetHandler(const struct x11drv_settings_handler *new_handler)
-{
- if (new_handler->priority > settings_handler.priority)
- {
- settings_handler = *new_handler;
- TRACE("Display settings are now handled by: %s.\n", settings_handler.name);
- }
-}
-
-/***********************************************************************
- * Default handlers if resolution switching is not enabled
- *
- */
-static BOOL nores_get_id(const WCHAR *device_name, ULONG_PTR *id)
-{
- WCHAR primary_adapter[CCHDEVICENAME];
-
- if (!get_primary_adapter( primary_adapter ))
- return FALSE;
-
- *id = !wcsicmp( device_name, primary_adapter ) ? 1 : 0;
- return TRUE;
-}
-
-static BOOL nores_get_modes(ULONG_PTR id, DWORD flags, DEVMODEW **new_modes, UINT *mode_count)
-{
- RECT primary = get_host_primary_monitor_rect();
- DEVMODEW *modes;
-
- modes = calloc(1, sizeof(*modes));
- if (!modes)
- {
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- return FALSE;
- }
-
- modes[0].dmSize = sizeof(*modes);
- modes[0].dmDriverExtra = 0;
- modes[0].dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT |
- DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY;
- modes[0].dmDisplayOrientation = DMDO_DEFAULT;
- modes[0].dmBitsPerPel = screen_bpp;
- modes[0].dmPelsWidth = primary.right;
- modes[0].dmPelsHeight = primary.bottom;
- modes[0].dmDisplayFlags = 0;
- modes[0].dmDisplayFrequency = 60;
-
- *new_modes = modes;
- *mode_count = 1;
- return TRUE;
-}
-
-static void nores_free_modes(DEVMODEW *modes)
-{
- free(modes);
-}
-
-static BOOL nores_get_current_mode(ULONG_PTR id, DEVMODEW *mode)
-{
- RECT primary = get_host_primary_monitor_rect();
-
- mode->dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT |
- DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY | DM_POSITION;
- mode->dmDisplayOrientation = DMDO_DEFAULT;
- mode->dmDisplayFlags = 0;
- mode->dmPosition.x = 0;
- mode->dmPosition.y = 0;
-
- if (id != 1)
- {
- FIXME("Non-primary adapters are unsupported.\n");
- mode->dmBitsPerPel = 0;
- mode->dmPelsWidth = 0;
- mode->dmPelsHeight = 0;
- mode->dmDisplayFrequency = 0;
- return TRUE;
- }
-
- mode->dmBitsPerPel = screen_bpp;
- mode->dmPelsWidth = primary.right;
- mode->dmPelsHeight = primary.bottom;
- mode->dmDisplayFrequency = 60;
- return TRUE;
-}
-
-static LONG nores_set_current_mode(ULONG_PTR id, DEVMODEW *mode)
-{
- WARN("NoRes settings handler, ignoring mode change request.\n");
- return DISP_CHANGE_SUCCESSFUL;
-}
-
-/* default handler only gets the current X desktop resolution */
-void X11DRV_Settings_Init(void)
-{
- struct x11drv_settings_handler nores_handler;
-
- depths = screen_bpp == 32 ? depths_32 : depths_24;
-
- nores_handler.name = "NoRes";
- nores_handler.priority = 1;
- nores_handler.get_id = nores_get_id;
- nores_handler.get_modes = nores_get_modes;
- nores_handler.free_modes = nores_free_modes;
- nores_handler.get_current_mode = nores_get_current_mode;
- nores_handler.set_current_mode = nores_set_current_mode;
- X11DRV_Settings_SetHandler(&nores_handler);
-}
-
-/* Initialize registry display settings when new display devices are added */
-void init_registry_display_settings(void)
-{
- DEVMODEW dm = {.dmSize = sizeof(dm)};
- DISPLAY_DEVICEW dd = {sizeof(dd)};
- UNICODE_STRING device_name;
- DWORD i = 0;
- LONG ret;
-
- while (!NtUserEnumDisplayDevices( NULL, i++, &dd, 0 ))
- {
- RtlInitUnicodeString( &device_name, dd.DeviceName );
-
- /* Skip if the device already has registry display settings */
- if (NtUserEnumDisplaySettings( &device_name, ENUM_REGISTRY_SETTINGS, &dm, 0 ))
- continue;
-
- if (!NtUserEnumDisplaySettings( &device_name, ENUM_CURRENT_SETTINGS, &dm, 0 ))
- {
- ERR("Failed to query current display settings for %s.\n", wine_dbgstr_w(dd.DeviceName));
- continue;
- }
-
- TRACE("Device %s current display mode %ux%u %ubits %uHz at %d,%d.\n",
- wine_dbgstr_w(dd.DeviceName), dm.dmPelsWidth, dm.dmPelsHeight, dm.dmBitsPerPel,
- dm.dmDisplayFrequency, dm.dmPosition.x, dm.dmPosition.y);
-
- ret = NtUserChangeDisplaySettings( &device_name, &dm, NULL,
- CDS_GLOBAL | CDS_NORESET | CDS_UPDATEREGISTRY, NULL );
- if (ret != DISP_CHANGE_SUCCESSFUL)
- ERR("Failed to save registry display settings for %s, returned %d.\n",
- wine_dbgstr_w(dd.DeviceName), ret);
- }
-}
-
-static HKEY get_display_device_reg_key( const WCHAR *device_name )
-{
- static const WCHAR display[] = {'\\','\\','.','\\','D','I','S','P','L','A','Y'};
- static const WCHAR video_key[] = {
- '\\','R','e','g','i','s','t','r','y',
- '\\','M','a','c','h','i','n','e',
- '\\','H','A','R','D','W','A','R','E',
- '\\','D','E','V','I','C','E','M','A','P',
- '\\','V','I','D','E','O'};
- static const WCHAR current_config_key[] = {
- '\\','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',
- '\\','H','a','r','d','w','a','r','e',' ','P','r','o','f','i','l','e','s',
- '\\','C','u','r','r','e','n','t'};
- WCHAR value_name[MAX_PATH], buffer[4096], *end_ptr;
- KEY_VALUE_PARTIAL_INFORMATION *value = (void *)buffer;
- DWORD adapter_index, size;
- char adapter_name[100];
- HKEY hkey;
-
- /* Device name has to be \\.\DISPLAY%d */
- if (wcsnicmp( device_name, display, ARRAY_SIZE(display) ))
- return FALSE;
-
- /* Parse \\.\DISPLAY* */
- adapter_index = wcstol( device_name + ARRAY_SIZE(display), &end_ptr, 10 ) - 1;
- if (*end_ptr)
- return FALSE;
-
- /* Open \Device\Video* in HKLM\HARDWARE\DEVICEMAP\VIDEO\ */
- if (!(hkey = reg_open_key( NULL, video_key, sizeof(video_key) ))) return FALSE;
- sprintf( adapter_name, "\\Device\\Video%d", adapter_index );
- asciiz_to_unicode( value_name, adapter_name );
- size = query_reg_value( hkey, value_name, value, sizeof(buffer) );
- NtClose( hkey );
- if (!size || value->Type != REG_SZ) return FALSE;
-
- /* Replace \Registry\Machine\ prefix with HKEY_CURRENT_CONFIG */
- memmove( buffer + ARRAYSIZE(current_config_key), (const WCHAR *)value->Data + 17,
- size - 17 * sizeof(WCHAR) );
- memcpy( buffer, current_config_key, sizeof(current_config_key) );
- TRACE( "display device %s registry settings key %s.\n", wine_dbgstr_w(device_name),
- wine_dbgstr_w(buffer) );
- return reg_open_key( NULL, buffer, lstrlenW(buffer) * sizeof(WCHAR) );
-}
-
-static BOOL query_display_setting( HKEY hkey, const char *name, DWORD *ret )
-{
- char buffer[1024];
- WCHAR nameW[128];
- KEY_VALUE_PARTIAL_INFORMATION *value = (void *)buffer;
-
- asciiz_to_unicode( nameW, name );
- if (query_reg_value( hkey, nameW, value, sizeof(buffer) ) != sizeof(DWORD) ||
- value->Type != REG_DWORD)
- return FALSE;
-
- *ret = *(DWORD *)value->Data;
- return TRUE;
-}
-
-static BOOL read_registry_settings(const WCHAR *device_name, DEVMODEW *dm)
-{
- HANDLE mutex;
- HKEY hkey;
- BOOL ret = TRUE;
-
- dm->dmFields = 0;
-
- mutex = get_display_device_init_mutex();
- if (!(hkey = get_display_device_reg_key( device_name )))
- {
- release_display_device_init_mutex(mutex);
- return FALSE;
- }
-
- ret &= query_display_setting( hkey, "DefaultSettings.BitsPerPel", &dm->dmBitsPerPel );
- dm->dmFields |= DM_BITSPERPEL;
- ret &= query_display_setting( hkey, "DefaultSettings.XResolution", &dm->dmPelsWidth );
- dm->dmFields |= DM_PELSWIDTH;
- ret &= query_display_setting( hkey, "DefaultSettings.YResolution", &dm->dmPelsHeight );
- dm->dmFields |= DM_PELSHEIGHT;
- ret &= query_display_setting( hkey, "DefaultSettings.VRefresh", &dm->dmDisplayFrequency );
- dm->dmFields |= DM_DISPLAYFREQUENCY;
- ret &= query_display_setting( hkey, "DefaultSettings.Flags", &dm->dmDisplayFlags );
- dm->dmFields |= DM_DISPLAYFLAGS;
- ret &= query_display_setting( hkey, "DefaultSettings.XPanning", (DWORD *)&dm->dmPosition.x );
- ret &= query_display_setting( hkey, "DefaultSettings.YPanning", (DWORD *)&dm->dmPosition.y );
- dm->dmFields |= DM_POSITION;
- ret &= query_display_setting( hkey, "DefaultSettings.Orientation", &dm->dmDisplayOrientation );
- dm->dmFields |= DM_DISPLAYORIENTATION;
- ret &= query_display_setting( hkey, "DefaultSettings.FixedOutput", &dm->dmDisplayFixedOutput );
-
- NtClose( hkey );
- release_display_device_init_mutex(mutex);
- return ret;
-}
-
-static BOOL set_setting_value( HKEY hkey, const char *name, DWORD val )
-{
- WCHAR nameW[128];
- UNICODE_STRING str = { asciiz_to_unicode( nameW, name ) - sizeof(WCHAR), sizeof(nameW), nameW };
- return !NtSetValueKey( hkey, &str, 0, REG_DWORD, &val, sizeof(val) );
-}
-
-static BOOL write_registry_settings(const WCHAR *device_name, const DEVMODEW *dm)
-{
- HANDLE mutex;
- HKEY hkey;
- BOOL ret = TRUE;
-
- mutex = get_display_device_init_mutex();
- if (!(hkey = get_display_device_reg_key( device_name )))
- {
- release_display_device_init_mutex(mutex);
- return FALSE;
- }
-
- ret &= set_setting_value( hkey, "DefaultSettings.BitsPerPel", dm->dmBitsPerPel );
- ret &= set_setting_value( hkey, "DefaultSettings.XResolution", dm->dmPelsWidth );
- ret &= set_setting_value( hkey, "DefaultSettings.YResolution", dm->dmPelsHeight );
- ret &= set_setting_value( hkey, "DefaultSettings.VRefresh", dm->dmDisplayFrequency );
- ret &= set_setting_value( hkey, "DefaultSettings.Flags", dm->dmDisplayFlags );
- ret &= set_setting_value( hkey, "DefaultSettings.XPanning", dm->dmPosition.x );
- ret &= set_setting_value( hkey, "DefaultSettings.YPanning", dm->dmPosition.y );
- ret &= set_setting_value( hkey, "DefaultSettings.Orientation", dm->dmDisplayOrientation );
- ret &= set_setting_value( hkey, "DefaultSettings.FixedOutput", dm->dmDisplayFixedOutput );
-
- NtClose( hkey );
- release_display_device_init_mutex(mutex);
- return ret;
-}
-
-BOOL get_primary_adapter(WCHAR *name)
-{
- DISPLAY_DEVICEW dd;
- DWORD i;
-
- dd.cb = sizeof(dd);
- for (i = 0; !NtUserEnumDisplayDevices( NULL, i, &dd, 0 ); ++i)
- {
- if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
- {
- lstrcpyW(name, dd.DeviceName);
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-static int mode_compare(const void *p1, const void *p2)
-{
- DWORD a_width, a_height, b_width, b_height;
- const DEVMODEW *a = p1, *b = p2;
-
- /* Use the width and height in landscape mode for comparison */
- if (a->dmDisplayOrientation == DMDO_DEFAULT || a->dmDisplayOrientation == DMDO_180)
- {
- a_width = a->dmPelsWidth;
- a_height = a->dmPelsHeight;
- }
- else
- {
- a_width = a->dmPelsHeight;
- a_height = a->dmPelsWidth;
- }
-
- if (b->dmDisplayOrientation == DMDO_DEFAULT || b->dmDisplayOrientation == DMDO_180)
- {
- b_width = b->dmPelsWidth;
- b_height = b->dmPelsHeight;
- }
- else
- {
- b_width = b->dmPelsHeight;
- b_height = b->dmPelsWidth;
- }
-
- /* Depth in descending order */
- if (a->dmBitsPerPel != b->dmBitsPerPel)
- return b->dmBitsPerPel - a->dmBitsPerPel;
-
- /* Width in ascending order */
- if (a_width != b_width)
- return a_width - b_width;
-
- /* Height in ascending order */
- if (a_height != b_height)
- return a_height - b_height;
-
- /* Frequency in descending order */
- if (a->dmDisplayFrequency != b->dmDisplayFrequency)
- return b->dmDisplayFrequency - a->dmDisplayFrequency;
-
- /* Orientation in ascending order */
- return a->dmDisplayOrientation - b->dmDisplayOrientation;
-}
-
-static void set_display_depth(ULONG_PTR display_id, DWORD depth)
-{
- struct x11drv_display_depth *display_depth;
-
- pthread_mutex_lock( &settings_mutex );
- LIST_FOR_EACH_ENTRY(display_depth, &x11drv_display_depth_list, struct x11drv_display_depth, entry)
- {
- if (display_depth->display_id == display_id)
- {
- display_depth->depth = depth;
- pthread_mutex_unlock( &settings_mutex );
- return;
- }
- }
-
- display_depth = malloc(sizeof(*display_depth));
- if (!display_depth)
- {
- ERR("Failed to allocate memory.\n");
- pthread_mutex_unlock( &settings_mutex );
- return;
- }
-
- display_depth->display_id = display_id;
- display_depth->depth = depth;
- list_add_head(&x11drv_display_depth_list, &display_depth->entry);
- pthread_mutex_unlock( &settings_mutex );
-}
-
-static DWORD get_display_depth(ULONG_PTR display_id)
-{
- struct x11drv_display_depth *display_depth;
- DWORD depth;
-
- pthread_mutex_lock( &settings_mutex );
- LIST_FOR_EACH_ENTRY(display_depth, &x11drv_display_depth_list, struct x11drv_display_depth, entry)
- {
- if (display_depth->display_id == display_id)
- {
- depth = display_depth->depth;
- pthread_mutex_unlock( &settings_mutex );
- return depth;
- }
- }
- pthread_mutex_unlock( &settings_mutex );
- return screen_bpp;
-}
-
-/***********************************************************************
- * EnumDisplaySettingsEx (X11DRV.@)
- *
- */
-BOOL X11DRV_EnumDisplaySettingsEx( LPCWSTR name, DWORD n, LPDEVMODEW devmode, DWORD flags)
-{
- static const WCHAR dev_name[CCHDEVICENAME] =
- { 'W','i','n','e',' ','X','1','1',' ','d','r','i','v','e','r',0 };
- DEVMODEW *modes;
- UINT mode_count;
- ULONG_PTR id;
-
- if (n == ENUM_REGISTRY_SETTINGS)
- {
- if (!read_registry_settings(name, devmode))
- {
- ERR("Failed to get %s registry display settings.\n", wine_dbgstr_w(name));
- return FALSE;
- }
- goto done;
- }
-
- if (n == ENUM_CURRENT_SETTINGS)
- {
- if (!settings_handler.get_id(name, &id) || !settings_handler.get_current_mode(id, devmode))
- {
- ERR("Failed to get %s current display settings.\n", wine_dbgstr_w(name));
- return FALSE;
- }
-
- if (!is_detached_mode(devmode))
- devmode->dmBitsPerPel = get_display_depth(id);
-
- goto done;
- }
-
- pthread_mutex_lock( &settings_mutex );
- if (n == 0 || wcsicmp(cached_device_name, name) || cached_flags != flags)
- {
- if (!settings_handler.get_id(name, &id) || !settings_handler.get_modes(id, flags, &modes, &mode_count))
- {
- ERR("Failed to get %s supported display modes.\n", wine_dbgstr_w(name));
- pthread_mutex_unlock( &settings_mutex );
- return FALSE;
- }
-
- qsort(modes, mode_count, sizeof(*modes) + modes[0].dmDriverExtra, mode_compare);
-
- if (cached_modes)
- settings_handler.free_modes(cached_modes);
- lstrcpyW(cached_device_name, name);
- cached_flags = flags;
- cached_modes = modes;
- cached_mode_count = mode_count;
- }
-
- if (n >= cached_mode_count)
- {
- pthread_mutex_unlock( &settings_mutex );
- WARN("handler:%s device:%s mode index:%#x not found.\n", settings_handler.name, wine_dbgstr_w(name), n);
- SetLastError(ERROR_NO_MORE_FILES);
- return FALSE;
- }
-
- memcpy(devmode, (BYTE *)cached_modes + (sizeof(*cached_modes) + cached_modes[0].dmDriverExtra) * n, sizeof(*devmode));
- pthread_mutex_unlock( &settings_mutex );
-
-done:
- /* Set generic fields */
- devmode->dmSize = FIELD_OFFSET(DEVMODEW, dmICMMethod);
- devmode->dmDriverExtra = 0;
- devmode->dmSpecVersion = DM_SPECVERSION;
- devmode->dmDriverVersion = DM_SPECVERSION;
- lstrcpyW(devmode->dmDeviceName, dev_name);
- return TRUE;
-}
-
-BOOL is_detached_mode(const DEVMODEW *mode)
-{
- return mode->dmFields & DM_POSITION &&
- mode->dmFields & DM_PELSWIDTH &&
- mode->dmFields & DM_PELSHEIGHT &&
- mode->dmPelsWidth == 0 &&
- mode->dmPelsHeight == 0;
-}
-
-/* Get the full display mode with all the necessary fields set.
- * Return NULL on failure. Caller should call free_full_mode() to free the returned mode. */
-static DEVMODEW *get_full_mode(ULONG_PTR id, DEVMODEW *dev_mode)
-{
- DEVMODEW *modes, *full_mode, *found_mode = NULL;
- UINT mode_count, mode_idx;
-
- if (is_detached_mode(dev_mode))
- return dev_mode;
-
- if (!settings_handler.get_modes(id, EDS_ROTATEDMODE, &modes, &mode_count))
- return NULL;
-
- qsort(modes, mode_count, sizeof(*modes) + modes[0].dmDriverExtra, mode_compare);
- for (mode_idx = 0; mode_idx < mode_count; ++mode_idx)
- {
- found_mode = (DEVMODEW *)((BYTE *)modes + (sizeof(*modes) + modes[0].dmDriverExtra) * mode_idx);
-
- if (dev_mode->dmFields & DM_BITSPERPEL &&
- dev_mode->dmBitsPerPel &&
- found_mode->dmBitsPerPel != dev_mode->dmBitsPerPel)
- continue;
- if (dev_mode->dmFields & DM_PELSWIDTH && found_mode->dmPelsWidth != dev_mode->dmPelsWidth)
- continue;
- if (dev_mode->dmFields & DM_PELSHEIGHT && found_mode->dmPelsHeight != dev_mode->dmPelsHeight)
- continue;
- if (dev_mode->dmFields & DM_DISPLAYFREQUENCY &&
- dev_mode->dmDisplayFrequency &&
- found_mode->dmDisplayFrequency &&
- dev_mode->dmDisplayFrequency != 1 &&
- dev_mode->dmDisplayFrequency != found_mode->dmDisplayFrequency)
- continue;
- if (dev_mode->dmFields & DM_DISPLAYORIENTATION &&
- found_mode->dmDisplayOrientation != dev_mode->dmDisplayOrientation)
- continue;
-
- break;
- }
-
- if (!found_mode || mode_idx == mode_count)
- {
- settings_handler.free_modes(modes);
- return NULL;
- }
-
- if (!(full_mode = malloc(sizeof(*found_mode) + found_mode->dmDriverExtra)))
- {
- settings_handler.free_modes(modes);
- return NULL;
- }
-
- memcpy(full_mode, found_mode, sizeof(*found_mode) + found_mode->dmDriverExtra);
- settings_handler.free_modes(modes);
-
- full_mode->dmFields |= DM_POSITION;
- full_mode->dmPosition = dev_mode->dmPosition;
- return full_mode;
-}
-
-static void free_full_mode(DEVMODEW *mode)
-{
- if (!is_detached_mode(mode))
- free(mode);
-}
-
-static LONG get_display_settings(struct x11drv_display_setting **new_displays,
- INT *new_display_count, const WCHAR *dev_name, DEVMODEW *dev_mode)
-{
- struct x11drv_display_setting *displays;
- DEVMODEW registry_mode, current_mode;
- INT display_idx, display_count = 0;
- DISPLAY_DEVICEW display_device;
- LONG ret = DISP_CHANGE_FAILED;
- UNICODE_STRING device_name;
-
- display_device.cb = sizeof(display_device);
- for (display_idx = 0; !NtUserEnumDisplayDevices( NULL, display_idx, &display_device, 0 ); ++display_idx)
- ++display_count;
-
- displays = calloc(display_count, sizeof(*displays));
- if (!displays)
- goto done;
-
- for (display_idx = 0; display_idx < display_count; ++display_idx)
- {
- if (NtUserEnumDisplayDevices( NULL, display_idx, &display_device, 0 ))
- goto done;
-
- if (!settings_handler.get_id(display_device.DeviceName, &displays[display_idx].id))
- {
- ret = DISP_CHANGE_BADPARAM;
- goto done;
- }
-
- RtlInitUnicodeString( &device_name, display_device.DeviceName );
-
- if (!dev_mode)
- {
- memset(®istry_mode, 0, sizeof(registry_mode));
- registry_mode.dmSize = sizeof(registry_mode);
- if (!NtUserEnumDisplaySettings( &device_name, ENUM_REGISTRY_SETTINGS, ®istry_mode, 0 ))
- goto done;
-
- displays[display_idx].desired_mode = registry_mode;
- }
- else if (!wcsicmp(dev_name, display_device.DeviceName))
- {
- displays[display_idx].desired_mode = *dev_mode;
- if (!(dev_mode->dmFields & DM_POSITION))
- {
- memset(¤t_mode, 0, sizeof(current_mode));
- current_mode.dmSize = sizeof(current_mode);
- if (!NtUserEnumDisplaySettings( &device_name, ENUM_CURRENT_SETTINGS, ¤t_mode, 0 ))
- goto done;
-
- displays[display_idx].desired_mode.dmFields |= DM_POSITION;
- displays[display_idx].desired_mode.dmPosition = current_mode.dmPosition;
- }
- }
- else
- {
- memset(¤t_mode, 0, sizeof(current_mode));
- current_mode.dmSize = sizeof(current_mode);
- if (!NtUserEnumDisplaySettings( &device_name, ENUM_CURRENT_SETTINGS, ¤t_mode, 0 ))
- goto done;
-
- displays[display_idx].desired_mode = current_mode;
- }
-
- SetRect(&displays[display_idx].desired_rect,
- displays[display_idx].desired_mode.dmPosition.x,
- displays[display_idx].desired_mode.dmPosition.y,
- displays[display_idx].desired_mode.dmPosition.x + displays[display_idx].desired_mode.dmPelsWidth,
- displays[display_idx].desired_mode.dmPosition.y + displays[display_idx].desired_mode.dmPelsHeight);
- lstrcpyW(displays[display_idx].desired_mode.dmDeviceName, display_device.DeviceName);
- }
-
- *new_displays = displays;
- *new_display_count = display_count;
- return DISP_CHANGE_SUCCESSFUL;
-
-done:
- free(displays);
- return ret;
-}
-
-static INT offset_length(POINT offset)
-{
- return offset.x * offset.x + offset.y * offset.y;
-}
-
-/* Check if a rect overlaps with placed display rects */
-static BOOL overlap_placed_displays(const RECT *rect, const struct x11drv_display_setting *displays, INT display_count)
-{
- INT display_idx;
- RECT intersect;
-
- for (display_idx = 0; display_idx < display_count; ++display_idx)
- {
- if (displays[display_idx].placed &&
- intersect_rect(&intersect, &displays[display_idx].new_rect, rect))
- return TRUE;
- }
- return FALSE;
-}
-
-/* Get the offset with minimum length to place a display next to the placed displays with no spacing and overlaps */
-static POINT get_placement_offset(const struct x11drv_display_setting *displays, INT display_count, INT placing_idx)
-{
- POINT points[8], left_top, offset, min_offset = {0, 0};
- INT display_idx, point_idx, point_count, vertex_idx;
- BOOL has_placed = FALSE, first = TRUE;
- INT width, height;
- RECT rect;
-
- /* If the display to be placed is detached, no offset is needed to place it */
- if (IsRectEmpty(&displays[placing_idx].desired_rect))
- return min_offset;
-
- /* If there is no placed and attached display, place this display as it is */
- for (display_idx = 0; display_idx < display_count; ++display_idx)
- {
- if (displays[display_idx].placed && !IsRectEmpty(&displays[display_idx].new_rect))
- {
- has_placed = TRUE;
- break;
- }
- }
-
- if (!has_placed)
- return min_offset;
-
- /* Try to place this display with each of its four vertices at every vertex of the placed
- * displays and see which combination has the minimum offset length */
- width = displays[placing_idx].desired_rect.right - displays[placing_idx].desired_rect.left;
- height = displays[placing_idx].desired_rect.bottom - displays[placing_idx].desired_rect.top;
-
- for (display_idx = 0; display_idx < display_count; ++display_idx)
- {
- if (!displays[display_idx].placed || IsRectEmpty(&displays[display_idx].new_rect))
- continue;
-
- /* Get four vertices of the placed display rectangle */
- points[0].x = displays[display_idx].new_rect.left;
- points[0].y = displays[display_idx].new_rect.top;
- points[1].x = displays[display_idx].new_rect.left;
- points[1].y = displays[display_idx].new_rect.bottom;
- points[2].x = displays[display_idx].new_rect.right;
- points[2].y = displays[display_idx].new_rect.top;
- points[3].x = displays[display_idx].new_rect.right;
- points[3].y = displays[display_idx].new_rect.bottom;
- point_count = 4;
-
- /* Intersected points when moving the display to be placed horizontally */
- if (displays[placing_idx].desired_rect.bottom >= displays[display_idx].new_rect.top &&
- displays[placing_idx].desired_rect.top <= displays[display_idx].new_rect.bottom)
- {
- points[point_count].x = displays[display_idx].new_rect.left;
- points[point_count++].y = displays[placing_idx].desired_rect.top;
- points[point_count].x = displays[display_idx].new_rect.right;
- points[point_count++].y = displays[placing_idx].desired_rect.top;
- }
- /* Intersected points when moving the display to be placed vertically */
- if (displays[placing_idx].desired_rect.left <= displays[display_idx].new_rect.right &&
- displays[placing_idx].desired_rect.right >= displays[display_idx].new_rect.left)
- {
- points[point_count].x = displays[placing_idx].desired_rect.left;
- points[point_count++].y = displays[display_idx].new_rect.top;
- points[point_count].x = displays[placing_idx].desired_rect.left;
- points[point_count++].y = displays[display_idx].new_rect.bottom;
- }
-
- /* Try moving each vertex of the display rectangle to each points */
- for (point_idx = 0; point_idx < point_count; ++point_idx)
- {
- for (vertex_idx = 0; vertex_idx < 4; ++vertex_idx)
- {
- switch (vertex_idx)
- {
- /* Move the bottom right vertex to the point */
- case 0:
- left_top.x = points[point_idx].x - width;
- left_top.y = points[point_idx].y - height;
- break;
- /* Move the bottom left vertex to the point */
- case 1:
- left_top.x = points[point_idx].x;
- left_top.y = points[point_idx].y - height;
- break;
- /* Move the top right vertex to the point */
- case 2:
- left_top.x = points[point_idx].x - width;
- left_top.y = points[point_idx].y;
- break;
- /* Move the top left vertex to the point */
- case 3:
- left_top.x = points[point_idx].x;
- left_top.y = points[point_idx].y;
- break;
- }
-
- offset.x = left_top.x - displays[placing_idx].desired_rect.left;
- offset.y = left_top.y - displays[placing_idx].desired_rect.top;
- rect = displays[placing_idx].desired_rect;
- OffsetRect(&rect, offset.x, offset.y);
- if (!overlap_placed_displays(&rect, displays, display_count))
- {
- if (first)
- {
- min_offset = offset;
- first = FALSE;
- continue;
- }
-
- if (offset_length(offset) < offset_length(min_offset))
- min_offset = offset;
- }
- }
- }
- }
-
- return min_offset;
-}
-
-static void place_all_displays(struct x11drv_display_setting *displays, INT display_count)
-{
- INT left_most = INT_MAX, top_most = INT_MAX;
- INT placing_idx, display_idx;
- POINT min_offset, offset;
-
- /* Place all displays with no extra space between them and no overlapping */
- while (1)
- {
- /* Place the unplaced display with the minimum offset length first */
- placing_idx = -1;
- for (display_idx = 0; display_idx < display_count; ++display_idx)
- {
- if (displays[display_idx].placed)
- continue;
-
- offset = get_placement_offset(displays, display_count, display_idx);
- if (placing_idx == -1 || offset_length(offset) < offset_length(min_offset))
- {
- min_offset = offset;
- placing_idx = display_idx;
- }
- }
-
- /* If all displays are placed */
- if (placing_idx == -1)
- break;
-
- displays[placing_idx].new_rect = displays[placing_idx].desired_rect;
- OffsetRect(&displays[placing_idx].new_rect, min_offset.x, min_offset.y);
- displays[placing_idx].placed = TRUE;
- }
-
- for (display_idx = 0; display_idx < display_count; ++display_idx)
- {
- displays[display_idx].desired_mode.dmPosition.x = displays[display_idx].new_rect.left;
- displays[display_idx].desired_mode.dmPosition.y = displays[display_idx].new_rect.top;
- left_most = min(left_most, displays[display_idx].new_rect.left);
- top_most = min(top_most, displays[display_idx].new_rect.top);
- }
-
- /* Convert virtual screen coordinates to root coordinates */
- for (display_idx = 0; display_idx < display_count; ++display_idx)
- {
- displays[display_idx].desired_mode.dmPosition.x -= left_most;
- displays[display_idx].desired_mode.dmPosition.y -= top_most;
- }
-}
-
-static LONG apply_display_settings(struct x11drv_display_setting *displays, INT display_count, BOOL do_attach)
-{
- DEVMODEW *full_mode;
- BOOL attached_mode;
- INT display_idx;
- LONG ret;
-
- for (display_idx = 0; display_idx < display_count; ++display_idx)
- {
- attached_mode = !is_detached_mode(&displays[display_idx].desired_mode);
- if ((attached_mode && !do_attach) || (!attached_mode && do_attach))
- continue;
-
- full_mode = get_full_mode(displays[display_idx].id, &displays[display_idx].desired_mode);
- if (!full_mode)
- return DISP_CHANGE_BADMODE;
-
- TRACE("handler:%s changing %s to position:(%d,%d) resolution:%ux%u frequency:%uHz "
- "depth:%ubits orientation:%#x.\n", settings_handler.name,
- wine_dbgstr_w(displays[display_idx].desired_mode.dmDeviceName),
- full_mode->dmPosition.x, full_mode->dmPosition.y, full_mode->dmPelsWidth,
- full_mode->dmPelsHeight, full_mode->dmDisplayFrequency, full_mode->dmBitsPerPel,
- full_mode->dmDisplayOrientation);
-
- ret = settings_handler.set_current_mode(displays[display_idx].id, full_mode);
- if (attached_mode && ret == DISP_CHANGE_SUCCESSFUL)
- set_display_depth(displays[display_idx].id, full_mode->dmBitsPerPel);
- free_full_mode(full_mode);
- if (ret != DISP_CHANGE_SUCCESSFUL)
- return ret;
- }
-
- return DISP_CHANGE_SUCCESSFUL;
-}
-
-static BOOL all_detached_settings(const struct x11drv_display_setting *displays, INT display_count)
-{
- INT display_idx;
-
- for (display_idx = 0; display_idx < display_count; ++display_idx)
- {
- if (!is_detached_mode(&displays[display_idx].desired_mode))
- return FALSE;
- }
-
- return TRUE;
-}
-
-/***********************************************************************
- * ChangeDisplaySettingsEx (X11DRV.@)
- *
- */
-LONG X11DRV_ChangeDisplaySettingsEx( LPCWSTR devname, LPDEVMODEW devmode,
- HWND hwnd, DWORD flags, LPVOID lpvoid )
-{
- struct x11drv_display_setting *displays;
- INT display_idx, display_count;
- DEVMODEW *full_mode;
- LONG ret;
-
- ret = get_display_settings(&displays, &display_count, devname, devmode);
- if (ret != DISP_CHANGE_SUCCESSFUL)
- return ret;
-
- if (flags & CDS_UPDATEREGISTRY && devname && devmode)
- {
- for (display_idx = 0; display_idx < display_count; ++display_idx)
- {
- if (!wcsicmp(displays[display_idx].desired_mode.dmDeviceName, devname))
- {
- full_mode = get_full_mode(displays[display_idx].id, &displays[display_idx].desired_mode);
- if (!full_mode)
- {
- free(displays);
- return DISP_CHANGE_BADMODE;
- }
-
- if (!write_registry_settings(devname, full_mode))
- {
- ERR("Failed to write %s display settings to registry.\n", wine_dbgstr_w(devname));
- free_full_mode(full_mode);
- free(displays);
- return DISP_CHANGE_NOTUPDATED;
- }
-
- free_full_mode(full_mode);
- break;
- }
- }
- }
-
- if (flags & (CDS_TEST | CDS_NORESET))
- {
- free(displays);
- return DISP_CHANGE_SUCCESSFUL;
- }
-
- if (all_detached_settings(displays, display_count))
- {
- WARN("Detaching all displays is not permitted.\n");
- free(displays);
- return DISP_CHANGE_SUCCESSFUL;
- }
-
- place_all_displays(displays, display_count);
-
- /* Detach displays first to free up CRTCs */
- ret = apply_display_settings(displays, display_count, FALSE);
- if (ret == DISP_CHANGE_SUCCESSFUL)
- ret = apply_display_settings(displays, display_count, TRUE);
- if (ret == DISP_CHANGE_SUCCESSFUL)
- X11DRV_DisplayDevices_Update(TRUE);
- free(displays);
- return ret;
-}
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/322
June 30, 2022
[PATCH v3 2/4] winex11.drv: Use nameless structs and unions in settings.c.
by Rémi Bernon
From: Rémi Bernon <rbernon(a)codeweavers.com>
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/winex11.drv/settings.c | 69 ++++++++++++++++++-------------------
1 file changed, 33 insertions(+), 36 deletions(-)
diff --git a/dlls/winex11.drv/settings.c b/dlls/winex11.drv/settings.c
index 0f9c4c876de..06cf0df4482 100644
--- a/dlls/winex11.drv/settings.c
+++ b/dlls/winex11.drv/settings.c
@@ -26,9 +26,6 @@
#include "config.h"
#include <stdlib.h>
-#define NONAMELESSUNION
-#define NONAMELESSSTRUCT
-
#include "x11drv.h"
#include "windef.h"
@@ -114,11 +111,11 @@ static BOOL nores_get_modes(ULONG_PTR id, DWORD flags, DEVMODEW **new_modes, UIN
modes[0].dmDriverExtra = 0;
modes[0].dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT |
DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY;
- modes[0].u1.s2.dmDisplayOrientation = DMDO_DEFAULT;
+ modes[0].dmDisplayOrientation = DMDO_DEFAULT;
modes[0].dmBitsPerPel = screen_bpp;
modes[0].dmPelsWidth = primary.right;
modes[0].dmPelsHeight = primary.bottom;
- modes[0].u2.dmDisplayFlags = 0;
+ modes[0].dmDisplayFlags = 0;
modes[0].dmDisplayFrequency = 60;
*new_modes = modes;
@@ -137,10 +134,10 @@ static BOOL nores_get_current_mode(ULONG_PTR id, DEVMODEW *mode)
mode->dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT |
DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY | DM_POSITION;
- mode->u1.s2.dmDisplayOrientation = DMDO_DEFAULT;
- mode->u2.dmDisplayFlags = 0;
- mode->u1.s2.dmPosition.x = 0;
- mode->u1.s2.dmPosition.y = 0;
+ mode->dmDisplayOrientation = DMDO_DEFAULT;
+ mode->dmDisplayFlags = 0;
+ mode->dmPosition.x = 0;
+ mode->dmPosition.y = 0;
if (id != 1)
{
@@ -207,7 +204,7 @@ void init_registry_display_settings(void)
TRACE("Device %s current display mode %ux%u %ubits %uHz at %d,%d.\n",
wine_dbgstr_w(dd.DeviceName), dm.dmPelsWidth, dm.dmPelsHeight, dm.dmBitsPerPel,
- dm.dmDisplayFrequency, dm.u1.s2.dmPosition.x, dm.u1.s2.dmPosition.y);
+ dm.dmDisplayFrequency, dm.dmPosition.x, dm.dmPosition.y);
ret = NtUserChangeDisplaySettings( &device_name, &dm, NULL,
CDS_GLOBAL | CDS_NORESET | CDS_UPDATEREGISTRY, NULL );
@@ -303,14 +300,14 @@ static BOOL read_registry_settings(const WCHAR *device_name, DEVMODEW *dm)
dm->dmFields |= DM_PELSHEIGHT;
ret &= query_display_setting( hkey, "DefaultSettings.VRefresh", &dm->dmDisplayFrequency );
dm->dmFields |= DM_DISPLAYFREQUENCY;
- ret &= query_display_setting( hkey, "DefaultSettings.Flags", &dm->u2.dmDisplayFlags );
+ ret &= query_display_setting( hkey, "DefaultSettings.Flags", &dm->dmDisplayFlags );
dm->dmFields |= DM_DISPLAYFLAGS;
- ret &= query_display_setting( hkey, "DefaultSettings.XPanning", (DWORD *)&dm->u1.s2.dmPosition.x );
- ret &= query_display_setting( hkey, "DefaultSettings.YPanning", (DWORD *)&dm->u1.s2.dmPosition.y );
+ ret &= query_display_setting( hkey, "DefaultSettings.XPanning", (DWORD *)&dm->dmPosition.x );
+ ret &= query_display_setting( hkey, "DefaultSettings.YPanning", (DWORD *)&dm->dmPosition.y );
dm->dmFields |= DM_POSITION;
- ret &= query_display_setting( hkey, "DefaultSettings.Orientation", &dm->u1.s2.dmDisplayOrientation );
+ ret &= query_display_setting( hkey, "DefaultSettings.Orientation", &dm->dmDisplayOrientation );
dm->dmFields |= DM_DISPLAYORIENTATION;
- ret &= query_display_setting( hkey, "DefaultSettings.FixedOutput", &dm->u1.s2.dmDisplayFixedOutput );
+ ret &= query_display_setting( hkey, "DefaultSettings.FixedOutput", &dm->dmDisplayFixedOutput );
NtClose( hkey );
release_display_device_init_mutex(mutex);
@@ -341,11 +338,11 @@ static BOOL write_registry_settings(const WCHAR *device_name, const DEVMODEW *dm
ret &= set_setting_value( hkey, "DefaultSettings.XResolution", dm->dmPelsWidth );
ret &= set_setting_value( hkey, "DefaultSettings.YResolution", dm->dmPelsHeight );
ret &= set_setting_value( hkey, "DefaultSettings.VRefresh", dm->dmDisplayFrequency );
- ret &= set_setting_value( hkey, "DefaultSettings.Flags", dm->u2.dmDisplayFlags );
- ret &= set_setting_value( hkey, "DefaultSettings.XPanning", dm->u1.s2.dmPosition.x );
- ret &= set_setting_value( hkey, "DefaultSettings.YPanning", dm->u1.s2.dmPosition.y );
- ret &= set_setting_value( hkey, "DefaultSettings.Orientation", dm->u1.s2.dmDisplayOrientation );
- ret &= set_setting_value( hkey, "DefaultSettings.FixedOutput", dm->u1.s2.dmDisplayFixedOutput );
+ ret &= set_setting_value( hkey, "DefaultSettings.Flags", dm->dmDisplayFlags );
+ ret &= set_setting_value( hkey, "DefaultSettings.XPanning", dm->dmPosition.x );
+ ret &= set_setting_value( hkey, "DefaultSettings.YPanning", dm->dmPosition.y );
+ ret &= set_setting_value( hkey, "DefaultSettings.Orientation", dm->dmDisplayOrientation );
+ ret &= set_setting_value( hkey, "DefaultSettings.FixedOutput", dm->dmDisplayFixedOutput );
NtClose( hkey );
release_display_device_init_mutex(mutex);
@@ -376,7 +373,7 @@ static int mode_compare(const void *p1, const void *p2)
const DEVMODEW *a = p1, *b = p2;
/* Use the width and height in landscape mode for comparison */
- if (a->u1.s2.dmDisplayOrientation == DMDO_DEFAULT || a->u1.s2.dmDisplayOrientation == DMDO_180)
+ if (a->dmDisplayOrientation == DMDO_DEFAULT || a->dmDisplayOrientation == DMDO_180)
{
a_width = a->dmPelsWidth;
a_height = a->dmPelsHeight;
@@ -387,7 +384,7 @@ static int mode_compare(const void *p1, const void *p2)
a_height = a->dmPelsWidth;
}
- if (b->u1.s2.dmDisplayOrientation == DMDO_DEFAULT || b->u1.s2.dmDisplayOrientation == DMDO_180)
+ if (b->dmDisplayOrientation == DMDO_DEFAULT || b->dmDisplayOrientation == DMDO_180)
{
b_width = b->dmPelsWidth;
b_height = b->dmPelsHeight;
@@ -415,7 +412,7 @@ static int mode_compare(const void *p1, const void *p2)
return b->dmDisplayFrequency - a->dmDisplayFrequency;
/* Orientation in ascending order */
- return a->u1.s2.dmDisplayOrientation - b->u1.s2.dmDisplayOrientation;
+ return a->dmDisplayOrientation - b->dmDisplayOrientation;
}
static void set_display_depth(ULONG_PTR display_id, DWORD depth)
@@ -585,7 +582,7 @@ static DEVMODEW *get_full_mode(ULONG_PTR id, DEVMODEW *dev_mode)
dev_mode->dmDisplayFrequency != found_mode->dmDisplayFrequency)
continue;
if (dev_mode->dmFields & DM_DISPLAYORIENTATION &&
- found_mode->u1.s2.dmDisplayOrientation != dev_mode->u1.s2.dmDisplayOrientation)
+ found_mode->dmDisplayOrientation != dev_mode->dmDisplayOrientation)
continue;
break;
@@ -607,7 +604,7 @@ static DEVMODEW *get_full_mode(ULONG_PTR id, DEVMODEW *dev_mode)
settings_handler.free_modes(modes);
full_mode->dmFields |= DM_POSITION;
- full_mode->u1.s2.dmPosition = dev_mode->u1.s2.dmPosition;
+ full_mode->dmPosition = dev_mode->dmPosition;
return full_mode;
}
@@ -668,7 +665,7 @@ static LONG get_display_settings(struct x11drv_display_setting **new_displays,
goto done;
displays[display_idx].desired_mode.dmFields |= DM_POSITION;
- displays[display_idx].desired_mode.u1.s2.dmPosition = current_mode.u1.s2.dmPosition;
+ displays[display_idx].desired_mode.dmPosition = current_mode.dmPosition;
}
}
else
@@ -682,10 +679,10 @@ static LONG get_display_settings(struct x11drv_display_setting **new_displays,
}
SetRect(&displays[display_idx].desired_rect,
- displays[display_idx].desired_mode.u1.s2.dmPosition.x,
- displays[display_idx].desired_mode.u1.s2.dmPosition.y,
- displays[display_idx].desired_mode.u1.s2.dmPosition.x + displays[display_idx].desired_mode.dmPelsWidth,
- displays[display_idx].desired_mode.u1.s2.dmPosition.y + displays[display_idx].desired_mode.dmPelsHeight);
+ displays[display_idx].desired_mode.dmPosition.x,
+ displays[display_idx].desired_mode.dmPosition.y,
+ displays[display_idx].desired_mode.dmPosition.x + displays[display_idx].desired_mode.dmPelsWidth,
+ displays[display_idx].desired_mode.dmPosition.y + displays[display_idx].desired_mode.dmPelsHeight);
lstrcpyW(displays[display_idx].desired_mode.dmDeviceName, display_device.DeviceName);
}
@@ -871,8 +868,8 @@ static void place_all_displays(struct x11drv_display_setting *displays, INT disp
for (display_idx = 0; display_idx < display_count; ++display_idx)
{
- displays[display_idx].desired_mode.u1.s2.dmPosition.x = displays[display_idx].new_rect.left;
- displays[display_idx].desired_mode.u1.s2.dmPosition.y = displays[display_idx].new_rect.top;
+ displays[display_idx].desired_mode.dmPosition.x = displays[display_idx].new_rect.left;
+ displays[display_idx].desired_mode.dmPosition.y = displays[display_idx].new_rect.top;
left_most = min(left_most, displays[display_idx].new_rect.left);
top_most = min(top_most, displays[display_idx].new_rect.top);
}
@@ -880,8 +877,8 @@ static void place_all_displays(struct x11drv_display_setting *displays, INT disp
/* Convert virtual screen coordinates to root coordinates */
for (display_idx = 0; display_idx < display_count; ++display_idx)
{
- displays[display_idx].desired_mode.u1.s2.dmPosition.x -= left_most;
- displays[display_idx].desired_mode.u1.s2.dmPosition.y -= top_most;
+ displays[display_idx].desired_mode.dmPosition.x -= left_most;
+ displays[display_idx].desired_mode.dmPosition.y -= top_most;
}
}
@@ -905,9 +902,9 @@ static LONG apply_display_settings(struct x11drv_display_setting *displays, INT
TRACE("handler:%s changing %s to position:(%d,%d) resolution:%ux%u frequency:%uHz "
"depth:%ubits orientation:%#x.\n", settings_handler.name,
wine_dbgstr_w(displays[display_idx].desired_mode.dmDeviceName),
- full_mode->u1.s2.dmPosition.x, full_mode->u1.s2.dmPosition.y, full_mode->dmPelsWidth,
+ full_mode->dmPosition.x, full_mode->dmPosition.y, full_mode->dmPelsWidth,
full_mode->dmPelsHeight, full_mode->dmDisplayFrequency, full_mode->dmBitsPerPel,
- full_mode->u1.s2.dmDisplayOrientation);
+ full_mode->dmDisplayOrientation);
ret = settings_handler.set_current_mode(displays[display_idx].id, full_mode);
if (attached_mode && ret == DISP_CHANGE_SUCCESSFUL)
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/322
June 30, 2022
[PATCH v3 1/4] winex11.drv: Rename display settings handlers to settings_handler.
by Rémi Bernon
From: Rémi Bernon <rbernon(a)codeweavers.com>
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/winex11.drv/settings.c | 32 ++++++++++++++++----------------
1 file changed, 16 insertions(+), 16 deletions(-)
diff --git a/dlls/winex11.drv/settings.c b/dlls/winex11.drv/settings.c
index e7e353b33ad..0f9c4c876de 100644
--- a/dlls/winex11.drv/settings.c
+++ b/dlls/winex11.drv/settings.c
@@ -38,6 +38,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(x11settings);
+static struct x11drv_settings_handler settings_handler;
+
struct x11drv_display_setting
{
ULONG_PTR id;
@@ -64,8 +66,6 @@ static const unsigned int depths_24[] = {8, 16, 24};
static const unsigned int depths_32[] = {8, 16, 32};
const unsigned int *depths;
-static struct x11drv_settings_handler handler;
-
/* Cached display modes for a device, protected by modes_section */
static WCHAR cached_device_name[CCHDEVICENAME];
static DWORD cached_flags;
@@ -76,10 +76,10 @@ static pthread_mutex_t settings_mutex = PTHREAD_MUTEX_INITIALIZER;
void X11DRV_Settings_SetHandler(const struct x11drv_settings_handler *new_handler)
{
- if (new_handler->priority > handler.priority)
+ if (new_handler->priority > settings_handler.priority)
{
- handler = *new_handler;
- TRACE("Display settings are now handled by: %s.\n", handler.name);
+ settings_handler = *new_handler;
+ TRACE("Display settings are now handled by: %s.\n", settings_handler.name);
}
}
@@ -490,7 +490,7 @@ BOOL X11DRV_EnumDisplaySettingsEx( LPCWSTR name, DWORD n, LPDEVMODEW devmode, DW
if (n == ENUM_CURRENT_SETTINGS)
{
- if (!handler.get_id(name, &id) || !handler.get_current_mode(id, devmode))
+ if (!settings_handler.get_id(name, &id) || !settings_handler.get_current_mode(id, devmode))
{
ERR("Failed to get %s current display settings.\n", wine_dbgstr_w(name));
return FALSE;
@@ -505,7 +505,7 @@ BOOL X11DRV_EnumDisplaySettingsEx( LPCWSTR name, DWORD n, LPDEVMODEW devmode, DW
pthread_mutex_lock( &settings_mutex );
if (n == 0 || wcsicmp(cached_device_name, name) || cached_flags != flags)
{
- if (!handler.get_id(name, &id) || !handler.get_modes(id, flags, &modes, &mode_count))
+ if (!settings_handler.get_id(name, &id) || !settings_handler.get_modes(id, flags, &modes, &mode_count))
{
ERR("Failed to get %s supported display modes.\n", wine_dbgstr_w(name));
pthread_mutex_unlock( &settings_mutex );
@@ -515,7 +515,7 @@ BOOL X11DRV_EnumDisplaySettingsEx( LPCWSTR name, DWORD n, LPDEVMODEW devmode, DW
qsort(modes, mode_count, sizeof(*modes) + modes[0].dmDriverExtra, mode_compare);
if (cached_modes)
- handler.free_modes(cached_modes);
+ settings_handler.free_modes(cached_modes);
lstrcpyW(cached_device_name, name);
cached_flags = flags;
cached_modes = modes;
@@ -525,7 +525,7 @@ BOOL X11DRV_EnumDisplaySettingsEx( LPCWSTR name, DWORD n, LPDEVMODEW devmode, DW
if (n >= cached_mode_count)
{
pthread_mutex_unlock( &settings_mutex );
- WARN("handler:%s device:%s mode index:%#x not found.\n", handler.name, wine_dbgstr_w(name), n);
+ WARN("handler:%s device:%s mode index:%#x not found.\n", settings_handler.name, wine_dbgstr_w(name), n);
SetLastError(ERROR_NO_MORE_FILES);
return FALSE;
}
@@ -562,7 +562,7 @@ static DEVMODEW *get_full_mode(ULONG_PTR id, DEVMODEW *dev_mode)
if (is_detached_mode(dev_mode))
return dev_mode;
- if (!handler.get_modes(id, EDS_ROTATEDMODE, &modes, &mode_count))
+ if (!settings_handler.get_modes(id, EDS_ROTATEDMODE, &modes, &mode_count))
return NULL;
qsort(modes, mode_count, sizeof(*modes) + modes[0].dmDriverExtra, mode_compare);
@@ -593,18 +593,18 @@ static DEVMODEW *get_full_mode(ULONG_PTR id, DEVMODEW *dev_mode)
if (!found_mode || mode_idx == mode_count)
{
- handler.free_modes(modes);
+ settings_handler.free_modes(modes);
return NULL;
}
if (!(full_mode = malloc(sizeof(*found_mode) + found_mode->dmDriverExtra)))
{
- handler.free_modes(modes);
+ settings_handler.free_modes(modes);
return NULL;
}
memcpy(full_mode, found_mode, sizeof(*found_mode) + found_mode->dmDriverExtra);
- handler.free_modes(modes);
+ settings_handler.free_modes(modes);
full_mode->dmFields |= DM_POSITION;
full_mode->u1.s2.dmPosition = dev_mode->u1.s2.dmPosition;
@@ -640,7 +640,7 @@ static LONG get_display_settings(struct x11drv_display_setting **new_displays,
if (NtUserEnumDisplayDevices( NULL, display_idx, &display_device, 0 ))
goto done;
- if (!handler.get_id(display_device.DeviceName, &displays[display_idx].id))
+ if (!settings_handler.get_id(display_device.DeviceName, &displays[display_idx].id))
{
ret = DISP_CHANGE_BADPARAM;
goto done;
@@ -903,13 +903,13 @@ static LONG apply_display_settings(struct x11drv_display_setting *displays, INT
return DISP_CHANGE_BADMODE;
TRACE("handler:%s changing %s to position:(%d,%d) resolution:%ux%u frequency:%uHz "
- "depth:%ubits orientation:%#x.\n", handler.name,
+ "depth:%ubits orientation:%#x.\n", settings_handler.name,
wine_dbgstr_w(displays[display_idx].desired_mode.dmDeviceName),
full_mode->u1.s2.dmPosition.x, full_mode->u1.s2.dmPosition.y, full_mode->dmPelsWidth,
full_mode->dmPelsHeight, full_mode->dmDisplayFrequency, full_mode->dmBitsPerPel,
full_mode->u1.s2.dmDisplayOrientation);
- ret = handler.set_current_mode(displays[display_idx].id, full_mode);
+ ret = settings_handler.set_current_mode(displays[display_idx].id, full_mode);
if (attached_mode && ret == DISP_CHANGE_SUCCESSFUL)
set_display_depth(displays[display_idx].id, full_mode->dmBitsPerPel);
free_full_mode(full_mode);
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/322
June 30, 2022
[PATCH v3 0/4] MR322: winex11.drv: Preparation for nulldrv display modes.
by Rémi Bernon
The idea is to have a `add_mode` manager callback and enumerate adapter modes when updating display devices. Then the modes would be read from the registry and cached with the adapters and monitors, allowing us to move more things to win32u.
This MR is a preparation towards that, moving the `winex11` settings handler to display.c, and making sure we do not enumerate display modes before they have been initialized or while the list is being built.
--
v3: winex11.drv: Avoid requesting current mode in X11DRV_desktop_get_modes.
winex11.drv: Merge settings.c into display.c.
winex11.drv: Use nameless structs and unions in settings.c.
winex11.drv: Rename display settings handlers to settings_handler.
https://gitlab.winehq.org/wine/wine/-/merge_requests/322
June 30, 2022
Re: [PATCH v2 0/4] MR322: winex11.drv: Preparation for nulldrv display modes.
by Rémi Bernon
On Thu Jun 30 07:13:30 2022 +0000, Zhiyi Zhang wrote:
> There is already an open_hkcu_key() in x11drv_main.c
Ah indeed, I thought there probably was but I looked for `reg_open_hkcu_key` as there's a few around already and it didn't match. It's slightly different for some reason...
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/322#note_3009
June 30, 2022
[PATCH 1/1] winex11.drv: Use a global Vulkan instance in X11DRV_D3DKMTOpenAdapterFromLuid().
by Zhiyi Zhang
From: Zhiyi Zhang <zzhang(a)codeweavers.com>
This avoids opening multiple Vulkan instances when multiple D3D kernel mode adapters are open.
Some tests that leak reference to D3D adapters crash because of out of memory errors before this
patch.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53201
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53231
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53235
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/winex11.drv/x11drv_main.c | 62 ++++++++++++++++++++--------------
1 file changed, 36 insertions(+), 26 deletions(-)
diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c
index dc987ae70a2..4e908f2918b 100644
--- a/dlls/winex11.drv/x11drv_main.c
+++ b/dlls/winex11.drv/x11drv_main.c
@@ -107,7 +107,6 @@ static pthread_mutex_t error_mutex = PTHREAD_MUTEX_INITIALIZER;
struct x11_d3dkmt_adapter
{
D3DKMT_HANDLE handle; /* Kernel mode graphics adapter handle */
- VkInstance vk_instance; /* Vulkan instance */
VkPhysicalDevice vk_device; /* Vulkan physical device */
struct list entry; /* List entry */
};
@@ -120,6 +119,7 @@ struct d3dkmt_vidpn_source
struct list entry; /* List entry */
};
+static VkInstance d3dkmt_vk_instance; /* Vulkan instance for D3DKMT functions */
static struct list x11_d3dkmt_adapters = LIST_INIT( x11_d3dkmt_adapters );
static struct list d3dkmt_vidpn_sources = LIST_INIT( d3dkmt_vidpn_sources ); /* VidPN source information list */
@@ -862,12 +862,17 @@ NTSTATUS CDECL X11DRV_D3DKMTCloseAdapter( const D3DKMT_CLOSEADAPTER *desc )
{
if (adapter->handle == desc->hAdapter)
{
- vulkan_funcs->p_vkDestroyInstance(adapter->vk_instance, NULL);
list_remove(&adapter->entry);
free(adapter);
break;
}
}
+
+ if (list_empty(&x11_d3dkmt_adapters))
+ {
+ vulkan_funcs->p_vkDestroyInstance(d3dkmt_vk_instance, NULL);
+ d3dkmt_vk_instance = NULL;
+ }
pthread_mutex_unlock(&d3dkmt_mutex);
return STATUS_SUCCESS;
}
@@ -1134,7 +1139,6 @@ NTSTATUS CDECL X11DRV_D3DKMTOpenAdapterFromLuid( D3DKMT_OPENADAPTERFROMLUID *des
struct x11_d3dkmt_adapter *adapter;
VkInstanceCreateInfo create_info;
VkPhysicalDeviceIDProperties id;
- VkInstance vk_instance = NULL;
VkResult vr;
GUID uuid;
@@ -1152,30 +1156,35 @@ NTSTATUS CDECL X11DRV_D3DKMTOpenAdapterFromLuid( D3DKMT_OPENADAPTERFROMLUID *des
return STATUS_UNSUCCESSFUL;
}
- 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;
+ pthread_mutex_lock(&d3dkmt_mutex);
- vr = vulkan_funcs->p_vkCreateInstance(&create_info, NULL, &vk_instance);
- if (vr != VK_SUCCESS)
+ if (!d3dkmt_vk_instance)
{
- WARN("Failed to create a Vulkan instance, vr %d.\n", vr);
- goto done;
+ 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(vk_instance, #f))) \
- { \
- WARN("Failed to load " #f ".\n"); \
- 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(vk_instance, &device_count, NULL);
+ 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);
@@ -1185,7 +1194,7 @@ NTSTATUS CDECL X11DRV_D3DKMTOpenAdapterFromLuid( D3DKMT_OPENADAPTERFROMLUID *des
if (!(vk_physical_devices = calloc(device_count, sizeof(*vk_physical_devices))))
goto done;
- vr = pvkEnumeratePhysicalDevices(vk_instance, &device_count, vk_physical_devices);
+ vr = pvkEnumeratePhysicalDevices(d3dkmt_vk_instance, &device_count, vk_physical_devices);
if (vr != VK_SUCCESS)
{
WARN("vkEnumeratePhysicalDevices failed, vr %d.\n", vr);
@@ -1210,19 +1219,20 @@ NTSTATUS CDECL X11DRV_D3DKMTOpenAdapterFromLuid( D3DKMT_OPENADAPTERFROMLUID *des
}
adapter->handle = desc->hAdapter;
- adapter->vk_instance = vk_instance;
adapter->vk_device = vk_physical_devices[device_idx];
- pthread_mutex_lock(&d3dkmt_mutex);
list_add_head(&x11_d3dkmt_adapters, &adapter->entry);
- pthread_mutex_unlock(&d3dkmt_mutex);
- free(vk_physical_devices);
- return STATUS_SUCCESS;
+ status = STATUS_SUCCESS;
+ break;
}
done:
+ 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);
- if (vk_instance)
- vulkan_funcs->p_vkDestroyInstance(vk_instance, NULL);
return status;
}
@@ -1253,7 +1263,7 @@ NTSTATUS CDECL X11DRV_D3DKMTQueryVideoMemoryInfo( D3DKMT_QUERYVIDEOMEMORYINFO *d
if (adapter->handle != desc->hAdapter)
continue;
- if (!(pvkGetPhysicalDeviceMemoryProperties2KHR = (void *)vulkan_funcs->p_vkGetInstanceProcAddr(adapter->vk_instance, "vkGetPhysicalDeviceMemoryProperties2KHR")))
+ if (!(pvkGetPhysicalDeviceMemoryProperties2KHR = (void *)vulkan_funcs->p_vkGetInstanceProcAddr(d3dkmt_vk_instance, "vkGetPhysicalDeviceMemoryProperties2KHR")))
{
WARN("Failed to load vkGetPhysicalDeviceMemoryProperties2KHR.\n");
status = STATUS_UNSUCCESSFUL;
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/346
June 30, 2022
[PATCH 0/1] MR346: winex11.drv: Use a global Vulkan instance in X11DRV_D3DKMTOpenAdapterFromLuid().
by Zhiyi Zhang (@zhiyi)
This avoids opening multiple Vulkan instances when multiple D3D kernel mode adapters are open.
Some tests that leak reference to D3D adapters crash because of out of memory errors before this
patch.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53201
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53231
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53235
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/346
June 30, 2022
[PATCH v2 4/4] mfplat/tests: Fix resource leaks.
by Zhiyi Zhang
From: Zhiyi Zhang <zzhang(a)codeweavers.com>
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53235
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/mfplat/tests/mfplat.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
index 48f7a444add..deed2408a41 100644
--- a/dlls/mfplat/tests/mfplat.c
+++ b/dlls/mfplat/tests/mfplat.c
@@ -6639,11 +6639,12 @@ static void test_MFCreateDXSurfaceBuffer(void)
IMF2DBuffer2_Release(_2dbuffer2);
IMFMediaBuffer_Release(buffer);
+ IDirect3DDevice9_Release(device);
done:
if (backbuffer)
IDirect3DSurface9_Release(backbuffer);
- IDirect3D9_Release(d3d);
+ ok(!IDirect3D9_Release(d3d), "Unexpected refcount.\n");
DestroyWindow(window);
}
@@ -7618,6 +7619,8 @@ static void test_sample_allocator_d3d9(void)
IMFVideoSampleAllocator_Release(allocator);
IMFMediaType_Release(video_type);
+ IDirect3DDeviceManager9_Release(d3d9_manager);
+ IDirect3DDevice9_Release(d3d9_device);
done:
IDirect3D9_Release(d3d9);
@@ -7725,6 +7728,7 @@ static void test_sample_allocator_d3d11(void)
hr = IMFMediaBuffer_Unlock(buffer);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ IMFMediaBuffer_Release(buffer);
IMFSample_Release(sample);
IMFVideoSampleAllocator_Release(allocator);
@@ -7867,7 +7871,7 @@ static void test_sample_allocator_d3d11(void)
static void test_sample_allocator_d3d12(void)
{
- IMFVideoSampleAllocator *allocator;
+ IMFVideoSampleAllocator *allocator = NULL;
D3D12_HEAP_PROPERTIES heap_props;
IMFDXGIDeviceManager *manager;
D3D12_HEAP_FLAGS heap_flags;
@@ -7955,11 +7959,12 @@ static void test_sample_allocator_d3d12(void)
ID3D12Resource_Release(resource);
IMFDXGIBuffer_Release(dxgi_buffer);
+ IMFMediaBuffer_Release(buffer);
IMFSample_Release(sample);
- IMFVideoSampleAllocator_Release(allocator);
-
done:
+ if (allocator)
+ IMFVideoSampleAllocator_Release(allocator);
IMFDXGIDeviceManager_Release(manager);
ID3D12Device_Release(device);
}
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/345
June 30, 2022
[PATCH v2 3/4] d2d1/tests: Fix resource leaks.
by Zhiyi Zhang
From: Zhiyi Zhang <zzhang(a)codeweavers.com>
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53231
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/d2d1/tests/d2d1.c | 18 +++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)
diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c
index 6ba4d8cec59..960d4480747 100644
--- a/dlls/d2d1/tests/d2d1.c
+++ b/dlls/d2d1/tests/d2d1.c
@@ -1168,7 +1168,8 @@ static void release_test_context_(unsigned int line, struct d2d1_test_context *c
IDXGISurface_Release(ctx->surface);
IDXGISwapChain_Release(ctx->swapchain);
DestroyWindow(ctx->window);
- IDXGIDevice_Release(ctx->device);
+ ref = IDXGIDevice_Release(ctx->device);
+ ok_(__FILE__, line)(!ref, "Device has %lu references left.\n", ref);
}
#define init_test_context(ctx, d3d11) init_test_context_(__LINE__, ctx, d3d11)
@@ -5182,16 +5183,17 @@ static void test_shared_bitmap(BOOL d3d11)
todo_wine_if(i == 2 || i == 3 || i == 5 || i == 6)
ok(hr == bitmap_format_tests[i].hr, "%u: Got unexpected hr %#lx.\n", i, hr);
- if (SUCCEEDED(bitmap_format_tests[i].hr))
+ if (SUCCEEDED(hr) && hr == bitmap_format_tests[i].hr)
{
pixel_format = ID2D1Bitmap_GetPixelFormat(bitmap2);
ok(pixel_format.format == bitmap_format_tests[i].result.format, "%u: unexpected pixel format %#x.\n",
i, pixel_format.format);
ok(pixel_format.alphaMode == bitmap_format_tests[i].result.alphaMode, "%u: unexpected alpha mode %d.\n",
i, pixel_format.alphaMode);
+ }
+ if (SUCCEEDED(hr))
ID2D1Bitmap_Release(bitmap2);
- }
}
}
@@ -5723,6 +5725,8 @@ static void test_draw_text_layout(BOOL d3d11)
IDWriteRenderingParams_Release(rendering_params);
}
+ ID2D1SolidColorBrush_Release(brush2);
+ ID2D1SolidColorBrush_Release(brush);
IDWriteTextFormat_Release(text_format);
IDWriteTextLayout_Release(text_layout);
IDWriteFactory_Release(dwrite_factory);
@@ -8899,7 +8903,7 @@ static void test_bitmap_surface(BOOL d3d11)
todo_wine_if(bitmap_format_tests[i].hr == WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT)
ok(hr == bitmap_format_tests[i].hr, "%u: Got unexpected hr %#lx.\n", i, hr);
- if (SUCCEEDED(bitmap_format_tests[i].hr))
+ if (SUCCEEDED(hr) && hr == bitmap_format_tests[i].hr)
{
pixel_format = ID2D1Bitmap1_GetPixelFormat(bitmap);
@@ -8907,9 +8911,10 @@ static void test_bitmap_surface(BOOL d3d11)
i, pixel_format.format);
ok(pixel_format.alphaMode == bitmap_format_tests[i].result.alphaMode, "%u: unexpected alpha mode %d.\n",
i, pixel_format.alphaMode);
+ }
+ if (SUCCEEDED(hr))
ID2D1Bitmap1_Release(bitmap);
- }
}
/* A8 surface */
@@ -8943,6 +8948,7 @@ static void test_bitmap_surface(BOOL d3d11)
ID2D1DeviceContext_SetTarget(device_context, (ID2D1Image *)bitmap);
ID2D1DeviceContext_GetTarget(device_context, &target);
ok(target == (ID2D1Image *)bitmap, "Unexpected target.\n");
+ ID2D1Image_Release(target);
check_rt_bitmap_surface((ID2D1RenderTarget *)device_context, TRUE, D2D1_BITMAP_OPTIONS_NONE);
@@ -9036,6 +9042,7 @@ static void test_bitmap_surface(BOOL d3d11)
hr = ID2D1Factory1_CreateWicBitmapRenderTarget(factory, wic_bitmap, &rt_desc, &rt);
ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+ IWICBitmap_Release(wic_bitmap);
check_rt_bitmap_surface(rt, FALSE, D2D1_BITMAP_OPTIONS_NONE);
ID2D1RenderTarget_Release(rt);
@@ -9423,6 +9430,7 @@ static void test_command_list(BOOL d3d11)
{
ID2D1DeviceContext_Release(device_context);
ID2D1Factory1_Release(factory);
+ release_test_context(&ctx);
return;
}
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/345
June 30, 2022
[PATCH v2 2/4] evr/tests: Fix resource leaks.
by Zhiyi Zhang
From: Zhiyi Zhang <zzhang(a)codeweavers.com>
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53201
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/evr/tests/evr.c | 35 +++++++++++++++++++++++++----------
1 file changed, 25 insertions(+), 10 deletions(-)
diff --git a/dlls/evr/tests/evr.c b/dlls/evr/tests/evr.c
index fa9ad2a0b35..37bb55739d3 100644
--- a/dlls/evr/tests/evr.c
+++ b/dlls/evr/tests/evr.c
@@ -1061,10 +1061,11 @@ static void test_surface_sample(void)
ok(flags == 0x123, "Unexpected flags %#lx.\n", flags);
IMFSample_Release(sample);
-
-done:
if (backbuffer)
IDirect3DSurface9_Release(backbuffer);
+ ok(!IDirect3DDevice9_Release(device), "Unexpected refcount.\n");
+
+done:
DestroyWindow(window);
}
@@ -1455,6 +1456,7 @@ static void test_default_presenter(void)
hr = MFGetService((IUnknown *)presenter, &MR_VIDEO_ACCELERATION_SERVICE, &IID_IDirect3DDeviceManager9, (void **)&dm);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ IDirect3DDeviceManager9_Release(dm);
hr = IMFVideoPresenter_QueryInterface(presenter, &IID_IMFVideoDisplayControl, (void **)&display_control);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
@@ -1484,6 +1486,7 @@ static void test_default_presenter(void)
hr = IMFVideoDisplayControl_GetVideoWindow(display_control, &hwnd2);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
ok(hwnd2 == hwnd, "Unexpected window %p.\n", hwnd2);
+ IMFVideoDisplayControl_Release(display_control);
/* Rate support. */
hr = IMFVideoPresenter_QueryInterface(presenter, &IID_IMFRateSupport, (void **)&rate_support);
@@ -1511,7 +1514,7 @@ static void test_default_presenter(void)
IMFRateSupport_Release(rate_support);
- IMFVideoPresenter_Release(presenter);
+ ok(!IMFVideoPresenter_Release(presenter), "Unexpected refcount.\n");
DestroyWindow(hwnd);
}
@@ -1697,7 +1700,10 @@ static void test_MFCreateVideoSampleAllocator(void)
if (!(device = create_device(window)))
{
skip("Failed to create a D3D device, skipping tests.\n");
- goto done;
+ IMFMediaType_Release(video_type);
+ IMFMediaType_Release(media_type);
+ DestroyWindow(window);
+ return;
}
hr = DXVA2CreateDirect3DDeviceManager9(&token, &manager);
@@ -1735,14 +1741,13 @@ static void test_MFCreateVideoSampleAllocator(void)
hr = IMFMediaBuffer_Unlock(buffer);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ IMFMediaBuffer_Release(buffer);
IMFSample_Release(sample);
-
IMFVideoSampleAllocator_Release(allocator);
-
+ IMFMediaType_Release(video_type);
IMFMediaType_Release(media_type);
IDirect3DDeviceManager9_Release(manager);
IDirect3DDevice9_Release(device);
-done:
DestroyWindow(window);
}
@@ -2067,6 +2072,7 @@ static void test_presenter_native_video_size(void)
hr = IMFVideoPresenter_QueryInterface(presenter, &IID_IMFTopologyServiceLookupClient, (void **)&lookup_client);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ IMFTopologyServiceLookupClient_Release(lookup_client);
hr = IMFVideoPresenter_QueryInterface(presenter, &IID_IMFVideoDisplayControl, (void **)&display_control);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
@@ -2141,6 +2147,7 @@ static void test_presenter_native_video_size(void)
ok((ratio.cx == 4 && ratio.cy == 3) || broken(!memcmp(&ratio, &size, sizeof(ratio))) /* < Win10 */,
"Unexpected ratio %lu x %lu.\n", ratio.cx, ratio.cy);
+ IMFTopologyServiceLookupClient_Release(lookup_client);
IMFMediaType_Release(video_type);
IMFVideoDisplayControl_Release(display_control);
IMFVideoPresenter_Release(presenter);
@@ -2259,7 +2266,8 @@ static void test_presenter_video_window(void)
hr = IDirect3DDeviceManager9_CloseDeviceHandle(dm, hdevice);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
- IMFVideoDisplayControl_Release(display_control);
+ IDirect3DDeviceManager9_Release(dm);
+ ok(!IMFVideoDisplayControl_Release(display_control), "Unexpected refcount.\n");
DestroyWindow(window);
}
@@ -2420,6 +2428,7 @@ static void test_presenter_media_type(void)
hr = IMFTopologyServiceLookupClient_InitServicePointers(lookup_client, &host.IMFTopologyServiceLookup_iface);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ IMFTopologyServiceLookupClient_Release(lookup_client);
hr = IMFVideoDisplayControl_SetVideoWindow(display_control, window);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
@@ -2431,6 +2440,7 @@ static void test_presenter_media_type(void)
hr = IMFTransform_SetInputType(mixer, 0, input_type, 0);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ IMFMediaType_Release(input_type);
hr = IMFVideoPresenter_ProcessMessage(presenter, MFVP_MESSAGE_INVALIDATEMEDIATYPE, 0);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
@@ -2463,6 +2473,8 @@ static void test_presenter_media_type(void)
IMFVideoDisplayControl_Release(display_control);
IMFVideoPresenter_Release(presenter);
IMFTransform_Release(mixer);
+ IDirect3DDeviceManager9_Release(manager);
+ IDirect3DDevice9_Release(device);
done:
DestroyWindow(window);
@@ -2949,6 +2961,7 @@ static void test_mixer_samples(void)
ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
IMFDesiredSample_Clear(desired);
+ IMFDesiredSample_Release(desired);
hr = IMFTransform_ProcessInput(mixer, 0, NULL, 0);
ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
@@ -3045,8 +3058,8 @@ static void test_mixer_samples(void)
IMFVideoProcessor_Release(processor);
IMFTransform_Release(mixer);
- IDirect3DDevice9_Release(device);
IDirect3DDeviceManager9_Release(manager);
+ ok(!IDirect3DDevice9_Release(device), "Unexpected refcount.\n");
done:
DestroyWindow(window);
@@ -3120,9 +3133,11 @@ static void test_mixer_render(void)
hr = IMFTransform_QueryInterface(mixer, &IID_IMFVideoProcessor, (void **)&processor);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ IMFVideoProcessor_Release(processor);
hr = IMFTransform_QueryInterface(mixer, &IID_IMFVideoMixerControl, (void **)&mixer_control);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ IMFVideoMixerControl_Release(mixer_control);
/* Configure device and media types. */
hr = DXVA2CreateDirect3DDeviceManager9(&token, &manager);
@@ -3197,8 +3212,8 @@ static void test_mixer_render(void)
IDirect3DSurface9_Release(surface);
IMFTransform_Release(mixer);
- IDirect3DDevice9_Release(device);
IDirect3DDeviceManager9_Release(manager);
+ ok(!IDirect3DDevice9_Release(device), "Unexpected refcount.\n");
done:
DestroyWindow(window);
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/345
June 30, 2022