-- v3: win32u: Read and cache adapter modes from the registry. win32u: Introduce new add_mode device manager callback. winemac.drv: Introduce new display_mode_to_devmode helper. winex11.drv: Set desktop settings handler before updating display devices.
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/desktop.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/dlls/winex11.drv/desktop.c b/dlls/winex11.drv/desktop.c index 162b524d504..3e589f9d940 100644 --- a/dlls/winex11.drv/desktop.c +++ b/dlls/winex11.drv/desktop.c @@ -335,6 +335,16 @@ void X11DRV_init_desktop( Window win, unsigned int width, unsigned int height ) max_width = primary_rect.right; max_height = primary_rect.bottom;
+ /* Initialize virtual desktop display settings handler */ + settings_handler.name = "Virtual Desktop"; + settings_handler.priority = 1000; + settings_handler.get_id = X11DRV_desktop_get_id; + settings_handler.get_modes = X11DRV_desktop_get_modes; + settings_handler.free_modes = X11DRV_desktop_free_modes; + settings_handler.get_current_mode = X11DRV_desktop_get_current_mode; + settings_handler.set_current_mode = X11DRV_desktop_set_current_mode; + X11DRV_Settings_SetHandler( &settings_handler ); + /* Initialize virtual desktop mode display device handler */ desktop_handler.name = "Virtual Desktop"; desktop_handler.get_gpus = X11DRV_desktop_get_gpus; @@ -346,16 +356,6 @@ void X11DRV_init_desktop( Window win, unsigned int width, unsigned int height ) desktop_handler.register_event_handlers = NULL; TRACE("Display device functions are now handled by: Virtual Desktop\n"); X11DRV_DisplayDevices_Init( TRUE ); - - /* Initialize virtual desktop display settings handler */ - settings_handler.name = "Virtual Desktop"; - settings_handler.priority = 1000; - settings_handler.get_id = X11DRV_desktop_get_id; - settings_handler.get_modes = X11DRV_desktop_get_modes; - settings_handler.free_modes = X11DRV_desktop_free_modes; - settings_handler.get_current_mode = X11DRV_desktop_get_current_mode; - settings_handler.set_current_mode = X11DRV_desktop_set_current_mode; - X11DRV_Settings_SetHandler( &settings_handler ); }
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/winemac.drv/display.c | 136 ++++++++++++++++++++----------------- 1 file changed, 73 insertions(+), 63 deletions(-)
diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c index a217a3fc422..d2f221fdbd1 100644 --- a/dlls/winemac.drv/display.c +++ b/dlls/winemac.drv/display.c @@ -61,6 +61,78 @@ static pthread_mutex_t modes_mutex = PTHREAD_MUTEX_INITIALIZER; static BOOL inited_original_display_mode;
+static int display_mode_bits_per_pixel(CGDisplayModeRef display_mode) +{ + CFStringRef pixel_encoding; + int bits_per_pixel = 0; + + pixel_encoding = CGDisplayModeCopyPixelEncoding(display_mode); + if (pixel_encoding) + { + if (CFEqual(pixel_encoding, CFSTR(kIO32BitFloatPixels))) + bits_per_pixel = 128; + else if (CFEqual(pixel_encoding, CFSTR(kIO16BitFloatPixels))) + bits_per_pixel = 64; + else if (CFEqual(pixel_encoding, CFSTR(kIO64BitDirectPixels))) + bits_per_pixel = 64; + else if (CFEqual(pixel_encoding, CFSTR(kIO30BitDirectPixels))) + bits_per_pixel = 30; + else if (CFEqual(pixel_encoding, CFSTR(IO32BitDirectPixels))) + bits_per_pixel = 32; + else if (CFEqual(pixel_encoding, CFSTR(IO16BitDirectPixels))) + bits_per_pixel = 16; + else if (CFEqual(pixel_encoding, CFSTR(IO8BitIndexedPixels))) + bits_per_pixel = 8; + else if (CFEqual(pixel_encoding, CFSTR(IO4BitIndexedPixels))) + bits_per_pixel = 4; + else if (CFEqual(pixel_encoding, CFSTR(IO2BitIndexedPixels))) + bits_per_pixel = 2; + else if (CFEqual(pixel_encoding, CFSTR(IO1BitIndexedPixels))) + bits_per_pixel = 1; + + CFRelease(pixel_encoding); + } + + return bits_per_pixel; +} + + +static void display_mode_to_devmode(CGDirectDisplayID display_id, CGDisplayModeRef display_mode, DEVMODEW *devmode) +{ + uint32_t io_flags; + double rotation; + + rotation = CGDisplayRotation(display_id); + devmode->dmDisplayOrientation = ((int)((rotation / 90) + 0.5)) % 4; + devmode->dmFields |= DM_DISPLAYORIENTATION; + + io_flags = CGDisplayModeGetIOFlags(display_mode); + if (io_flags & kDisplayModeStretchedFlag) + devmode->dmDisplayFixedOutput = DMDFO_STRETCH; + else + devmode->dmDisplayFixedOutput = DMDFO_CENTER; + devmode->dmFields |= DM_DISPLAYFIXEDOUTPUT; + + devmode->dmBitsPerPel = display_mode_bits_per_pixel(display_mode); + if (devmode->dmBitsPerPel) + devmode->dmFields |= DM_BITSPERPEL; + + devmode->dmPelsWidth = CGDisplayModeGetWidth(display_mode); + devmode->dmPelsHeight = CGDisplayModeGetHeight(display_mode); + devmode->dmFields |= DM_PELSWIDTH | DM_PELSHEIGHT; + + devmode->dmDisplayFlags = 0; + if (io_flags & kDisplayModeInterlacedFlag) + devmode->dmDisplayFlags |= DM_INTERLACED; + devmode->dmFields |= DM_DISPLAYFLAGS; + + devmode->dmDisplayFrequency = CGDisplayModeGetRefreshRate(display_mode); + if (!devmode->dmDisplayFrequency) + devmode->dmDisplayFrequency = 60; + devmode->dmFields |= DM_DISPLAYFREQUENCY; +} + + static BOOL set_setting_value(HKEY hkey, const char *name, DWORD val) { WCHAR nameW[128]; @@ -321,42 +393,6 @@ static BOOL display_mode_matches_descriptor(CGDisplayModeRef mode, const struct }
-static int display_mode_bits_per_pixel(CGDisplayModeRef display_mode) -{ - CFStringRef pixel_encoding; - int bits_per_pixel = 0; - - pixel_encoding = CGDisplayModeCopyPixelEncoding(display_mode); - if (pixel_encoding) - { - if (CFEqual(pixel_encoding, CFSTR(kIO32BitFloatPixels))) - bits_per_pixel = 128; - else if (CFEqual(pixel_encoding, CFSTR(kIO16BitFloatPixels))) - bits_per_pixel = 64; - else if (CFEqual(pixel_encoding, CFSTR(kIO64BitDirectPixels))) - bits_per_pixel = 64; - else if (CFEqual(pixel_encoding, CFSTR(kIO30BitDirectPixels))) - bits_per_pixel = 30; - else if (CFEqual(pixel_encoding, CFSTR(IO32BitDirectPixels))) - bits_per_pixel = 32; - else if (CFEqual(pixel_encoding, CFSTR(IO16BitDirectPixels))) - bits_per_pixel = 16; - else if (CFEqual(pixel_encoding, CFSTR(IO8BitIndexedPixels))) - bits_per_pixel = 8; - else if (CFEqual(pixel_encoding, CFSTR(IO4BitIndexedPixels))) - bits_per_pixel = 4; - else if (CFEqual(pixel_encoding, CFSTR(IO2BitIndexedPixels))) - bits_per_pixel = 2; - else if (CFEqual(pixel_encoding, CFSTR(IO1BitIndexedPixels))) - bits_per_pixel = 1; - - CFRelease(pixel_encoding); - } - - return bits_per_pixel; -} - - static int get_default_bpp(void) { int ret; @@ -893,8 +929,6 @@ BOOL macdrv_EnumDisplaySettingsEx(LPCWSTR devname, DWORD mode, DEVMODEW *devmode CGDisplayModeRef display_mode; int display_mode_bpp; BOOL synthesized = FALSE; - double rotation; - uint32_t io_flags;
TRACE("%s, %u, %p + %hu, %08x\n", debugstr_w(devname), mode, devmode, devmode->dmSize, flags);
@@ -1004,23 +1038,10 @@ BOOL macdrv_EnumDisplaySettingsEx(LPCWSTR devname, DWORD mode, DEVMODEW *devmode devmode->dmPosition.y = 0; devmode->dmFields |= DM_POSITION;
- rotation = CGDisplayRotation(displays[0].displayID); - devmode->dmDisplayOrientation = ((int)((rotation / 90) + 0.5)) % 4; - devmode->dmFields |= DM_DISPLAYORIENTATION; - - io_flags = CGDisplayModeGetIOFlags(display_mode); - if (io_flags & kDisplayModeStretchedFlag) - devmode->dmDisplayFixedOutput = DMDFO_STRETCH; - else - devmode->dmDisplayFixedOutput = DMDFO_CENTER; - devmode->dmFields |= DM_DISPLAYFIXEDOUTPUT; - + display_mode_to_devmode(displays[0].displayID, display_mode, devmode); devmode->dmBitsPerPel = display_mode_bpp; if (devmode->dmBitsPerPel) devmode->dmFields |= DM_BITSPERPEL; - - devmode->dmPelsWidth = CGDisplayModeGetWidth(display_mode); - devmode->dmPelsHeight = CGDisplayModeGetHeight(display_mode); if (retina_enabled) { struct display_mode_descriptor* desc = create_original_display_mode_descriptor(displays[0].displayID); @@ -1031,17 +1052,6 @@ BOOL macdrv_EnumDisplaySettingsEx(LPCWSTR devname, DWORD mode, DEVMODEW *devmode } free_display_mode_descriptor(desc); } - devmode->dmFields |= DM_PELSWIDTH | DM_PELSHEIGHT; - - devmode->dmDisplayFlags = 0; - if (io_flags & kDisplayModeInterlacedFlag) - devmode->dmDisplayFlags |= DM_INTERLACED; - devmode->dmFields |= DM_DISPLAYFLAGS; - - devmode->dmDisplayFrequency = CGDisplayModeGetRefreshRate(display_mode); - if (!devmode->dmDisplayFrequency) - devmode->dmDisplayFrequency = 60; - devmode->dmFields |= DM_DISPLAYFREQUENCY;
CFRelease(display_mode); macdrv_free_displays(displays);
From: R��mi Bernon rbernon@codeweavers.com
And use it to enumerate display modes in winex11 and wineandroid. --- dlls/win32u/sysparams.c | 106 +++++++++++++++++++++++++++++------- dlls/wineandroid.drv/init.c | 6 ++ dlls/winemac.drv/display.c | 87 ++++++++++++++++++++++++++++- dlls/winex11.drv/display.c | 16 ++++++ include/wine/gdi_driver.h | 1 + 5 files changed, 195 insertions(+), 21 deletions(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 9580452b50f..0b7e7aefd61 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -178,6 +178,8 @@ static const WCHAR x_panningW[] = {'X','P','a','n','n','i','n','g',0}; static const WCHAR y_panningW[] = {'Y','P','a','n','n','i','n','g',0}; static const WCHAR orientationW[] = {'O','r','i','e','n','t','a','t','i','o','n',0}; static const WCHAR fixed_outputW[] = {'F','i','x','e','d','O','u','t','p','u','t',0}; +static const WCHAR driver_extraW[] = {'D','r','i','v','e','r','E','x','t','r','a',0}; +static const WCHAR mode_countW[] = {'M','o','d','e','C','o','u','n','t',0};
static const char guid_devclass_displayA[] = "{4D36E968-E325-11CE-BFC1-08002BE10318}"; static const WCHAR guid_devclass_displayW[] = @@ -420,19 +422,20 @@ static void release_display_device_init_mutex( HANDLE mutex ) NtClose( mutex ); }
-static BOOL write_adapter_mode( HKEY adapter_key, const DEVMODEW *mode ) +static BOOL write_adapter_mode( HKEY adapter_key, DWORD index, const DEVMODEW *mode ) { - static const WCHAR default_settingsW[] = {'D','e','f','a','u','l','t','S','e','t','t','i','n','g','s','.',0}; WCHAR bufferW[MAX_PATH]; + char buffer[MAX_PATH]; + HKEY hkey; + BOOL ret;
-#define set_mode_field( name, field, flag ) \ - do \ - { \ - lstrcpyW( bufferW, default_settingsW ); \ - lstrcatW( bufferW, (name) ); \ - if (!set_reg_value( adapter_key, bufferW, REG_DWORD, &mode->field, sizeof(mode->field) )) \ - return FALSE; \ - } while (0) + sprintf( buffer, "Modes\%08X", index ); + if (!(hkey = reg_create_key( adapter_key, bufferW, asciiz_to_unicode( bufferW, buffer ) - sizeof(WCHAR), + REG_OPTION_VOLATILE, NULL ))) + return FALSE; + +#define set_mode_field( name, field, flag ) \ + if (!(ret = set_reg_value( hkey, (name), REG_DWORD, &mode->field, sizeof(mode->field) ))) goto done;
set_mode_field( bits_per_pelW, dmBitsPerPel, DM_BITSPERPEL ); set_mode_field( x_resolutionW, dmPelsWidth, DM_PELSWIDTH ); @@ -443,26 +446,34 @@ static BOOL write_adapter_mode( HKEY adapter_key, const DEVMODEW *mode ) set_mode_field( fixed_outputW, dmDisplayFixedOutput, DM_DISPLAYFIXEDOUTPUT ); set_mode_field( x_panningW, dmPosition.x, DM_POSITION ); set_mode_field( y_panningW, dmPosition.y, DM_POSITION ); + ret = set_reg_value( hkey, driver_extraW, REG_BINARY, mode + 1, mode->dmDriverExtra );
#undef set_mode_field
- return TRUE; +done: + NtClose( hkey ); + return ret; }
-static BOOL read_adapter_mode( HKEY adapter_key, DEVMODEW *mode ) +static BOOL read_adapter_mode( HKEY adapter_key, DWORD index, DEVMODEW *mode ) { - static const WCHAR default_settingsW[] = {'D','e','f','a','u','l','t','S','e','t','t','i','n','g','s','.',0}; char value_buf[offsetof(KEY_VALUE_PARTIAL_INFORMATION, Data[sizeof(DWORD)])]; KEY_VALUE_PARTIAL_INFORMATION *value = (void *)value_buf; WCHAR bufferW[MAX_PATH]; + char buffer[MAX_PATH]; + HKEY hkey; + BOOL ret; + + sprintf( buffer, "Modes\%08X", index ); + if (!(hkey = reg_open_key( adapter_key, bufferW, asciiz_to_unicode( bufferW, buffer ) - sizeof(WCHAR) ))) + return FALSE;
#define query_mode_field( name, field, flag ) \ do \ { \ - lstrcpyW( bufferW, default_settingsW ); \ - lstrcatW( bufferW, (name) ); \ - if (!query_reg_value( adapter_key, bufferW, value, sizeof(value_buf) ) || \ - value->Type != REG_DWORD) return FALSE; \ + ret = query_reg_value( hkey, (name), value, sizeof(value_buf) ) && \ + value->Type == REG_DWORD; \ + if (!ret) goto done; \ mode->field = *(const DWORD *)value->Data; \ mode->dmFields |= (flag); \ } while (0) @@ -479,6 +490,13 @@ static BOOL read_adapter_mode( HKEY adapter_key, DEVMODEW *mode )
#undef query_mode_field
+ ret = query_reg_value( hkey, driver_extraW, value, sizeof(value_buf) ) && + value->Type == REG_BINARY; + if (ret && value->DataLength <= mode->dmDriverExtra) + memcpy( mode + 1, value->Data, mode->dmDriverExtra ); + +done: + NtClose( hkey ); return TRUE; }
@@ -494,7 +512,7 @@ static BOOL read_registry_settings( const WCHAR *adapter_path, DEVMODEW *mode ) else if (!(hkey = reg_open_key( config_key, adapter_path, lstrlenW( adapter_path ) * sizeof(WCHAR) ))) ret = FALSE; else { - ret = read_adapter_mode( hkey, mode ); + ret = read_adapter_mode( hkey, ENUM_REGISTRY_SETTINGS, mode ); NtClose( hkey ); }
@@ -514,7 +532,7 @@ static BOOL write_registry_settings( const WCHAR *adapter_path, const DEVMODEW * if (!(hkey = reg_open_key( config_key, adapter_path, lstrlenW( adapter_path ) * sizeof(WCHAR) ))) ret = FALSE; else { - ret = write_adapter_mode( hkey, mode ); + ret = write_adapter_mode( hkey, ENUM_REGISTRY_SETTINGS, mode ); NtClose( hkey ); }
@@ -909,6 +927,8 @@ struct device_manager_ctx unsigned int video_count; unsigned int monitor_count; unsigned int output_count; + unsigned int mode_count; + unsigned int driver_extra; HANDLE mutex; WCHAR gpuid[128]; WCHAR gpu_guid[64]; @@ -998,6 +1018,8 @@ static void add_gpu( const struct gdi_gpu *gpu, void *param ) gpu_index = ctx->gpu_count++; ctx->adapter_count = 0; ctx->monitor_count = 0; + ctx->mode_count = 0; + ctx->driver_extra = 0;
if (!enum_key && !(enum_key = reg_create_key( NULL, enum_keyW, sizeof(enum_keyW), 0, NULL ))) return; @@ -1127,6 +1149,8 @@ static void add_adapter( const struct gdi_adapter *adapter, void *param ) adapter_index = ctx->adapter_count++; video_index = ctx->video_count++; ctx->monitor_count = 0; + ctx->mode_count = 0; + ctx->driver_extra = 0;
len = asciiz_to_unicode( bufferW, "\Registry\Machine\System\CurrentControlSet\" "Control\Video\" ) / sizeof(WCHAR) - 1; @@ -1282,11 +1306,36 @@ static void add_monitor( const struct gdi_monitor *monitor, void *param ) if (hkey) NtClose( hkey ); }
+static void add_mode( const DEVMODEW *mode, void *param ) +{ + struct device_manager_ctx *ctx = param; + + if (!ctx->adapter_count) + { + static const struct gdi_adapter default_adapter = + { + .state_flags = DISPLAY_DEVICE_ATTACHED_TO_DESKTOP | DISPLAY_DEVICE_PRIMARY_DEVICE | DISPLAY_DEVICE_VGA_COMPATIBLE, + }; + TRACE( "adding default fake adapter\n" ); + add_adapter( &default_adapter, ctx ); + } + + if (write_adapter_mode( ctx->adapter_key, ctx->mode_count, mode )) + { + ctx->driver_extra = max( ctx->driver_extra, mode->dmDriverExtra ); + set_reg_value( ctx->adapter_key, driver_extraW, REG_DWORD, &ctx->driver_extra, sizeof(ctx->driver_extra) ); + + ctx->mode_count++; + set_reg_value( ctx->adapter_key, mode_countW, REG_DWORD, &ctx->mode_count, sizeof(ctx->mode_count) ); + } +} + static const struct gdi_device_manager device_manager = { add_gpu, add_adapter, add_monitor, + add_mode, };
static void release_display_manager_ctx( struct device_manager_ctx *ctx ) @@ -1431,22 +1480,39 @@ static BOOL update_display_cache(void)
if (!user_driver->pUpdateDisplayDevices( &device_manager, TRUE, &ctx )) { + static const DEVMODEW modes[] = + { + { .dmFields = DM_DISPLAYORIENTATION|DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT|DM_DISPLAYFLAGS|DM_DISPLAYFREQUENCY|DM_POSITION, + .dmBitsPerPel = 32, .dmPelsWidth = 640, .dmPelsHeight = 480, .dmDisplayFrequency = 60, }, + { .dmFields = DM_DISPLAYORIENTATION|DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT|DM_DISPLAYFLAGS|DM_DISPLAYFREQUENCY|DM_POSITION, + .dmBitsPerPel = 32, .dmPelsWidth = 800, .dmPelsHeight = 600, .dmDisplayFrequency = 60, }, + { .dmFields = DM_DISPLAYORIENTATION|DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT|DM_DISPLAYFLAGS|DM_DISPLAYFREQUENCY|DM_POSITION, + .dmBitsPerPel = 32, .dmPelsWidth = 1024, .dmPelsHeight = 768, .dmDisplayFrequency = 60, }, + { .dmFields = DM_DISPLAYORIENTATION|DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT|DM_DISPLAYFLAGS|DM_DISPLAYFREQUENCY|DM_POSITION, + .dmBitsPerPel = 16, .dmPelsWidth = 640, .dmPelsHeight = 480, .dmDisplayFrequency = 60, }, + { .dmFields = DM_DISPLAYORIENTATION|DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT|DM_DISPLAYFLAGS|DM_DISPLAYFREQUENCY|DM_POSITION, + .dmBitsPerPel = 16, .dmPelsWidth = 800, .dmPelsHeight = 600, .dmDisplayFrequency = 60, }, + { .dmFields = DM_DISPLAYORIENTATION|DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT|DM_DISPLAYFLAGS|DM_DISPLAYFREQUENCY|DM_POSITION, + .dmBitsPerPel = 16, .dmPelsWidth = 1024, .dmPelsHeight = 768, .dmDisplayFrequency = 60, }, + }; static const struct gdi_gpu gpu; static const struct gdi_adapter adapter = { .state_flags = DISPLAY_DEVICE_ATTACHED_TO_DESKTOP | DISPLAY_DEVICE_PRIMARY_DEVICE | DISPLAY_DEVICE_VGA_COMPATIBLE, }; - DEVMODEW mode = {.dmPelsWidth = 1024, .dmPelsHeight = 768}; + DEVMODEW mode = modes[2]; struct gdi_monitor monitor = { .state_flags = DISPLAY_DEVICE_ACTIVE | DISPLAY_DEVICE_ATTACHED, .rc_monitor = {.right = mode.dmPelsWidth, .bottom = mode.dmPelsHeight}, .rc_work = {.right = mode.dmPelsWidth, .bottom = mode.dmPelsHeight}, }; + UINT i;
add_gpu( &gpu, &ctx ); add_adapter( &adapter, &ctx ); add_monitor( &monitor, &ctx ); + for (i = 0; i < ARRAY_SIZE(modes); ++i) add_mode( modes + i, &ctx ); } release_display_manager_ctx( &ctx );
diff --git a/dlls/wineandroid.drv/init.c b/dlls/wineandroid.drv/init.c index a82932bf65f..e23f2b62f7e 100644 --- a/dlls/wineandroid.drv/init.c +++ b/dlls/wineandroid.drv/init.c @@ -288,9 +288,15 @@ BOOL ANDROID_UpdateDisplayDevices( const struct gdi_device_manager *device_manag .rc_work = monitor_rc_work, .state_flags = DISPLAY_DEVICE_ACTIVE | DISPLAY_DEVICE_ATTACHED, }; + const DEVMODEW mode = + { + .dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY, + .dmBitsPerPel = screen_bpp, .dmPelsWidth = screen_width, .dmPelsHeight = screen_height, .dmDisplayFrequency = 60, + }; device_manager->add_gpu( &gpu, param ); device_manager->add_adapter( &adapter, param ); device_manager->add_monitor( &gdi_monitor, param ); + device_manager->add_mode( &mode, param ); force_display_devices_refresh = FALSE; }
diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c index d2f221fdbd1..7e7f1da9391 100644 --- a/dlls/winemac.drv/display.c +++ b/dlls/winemac.drv/display.c @@ -918,6 +918,77 @@ better: return ret; }
+ +static DEVMODEW *display_get_modes(CGDirectDisplayID display_id, int *modes_count) +{ + int default_bpp = get_default_bpp(), synth_count = 0, count, i; + BOOL modes_has_8bpp = FALSE, modes_has_16bpp = FALSE; + struct display_mode_descriptor *desc; + DEVMODEW *devmodes; + CFArrayRef modes; + + modes = copy_display_modes(display_id, TRUE); + if (!modes) + return NULL; + + count = CFArrayGetCount(modes); + for (i = 0; i < count && !(modes_has_8bpp && modes_has_16bpp); i++) + { + CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(modes, i); + int bpp = display_mode_bits_per_pixel(mode); + if (bpp == 8) + modes_has_8bpp = TRUE; + else if (bpp == 16) + modes_has_16bpp = TRUE; + } + + if (!(devmodes = calloc(count * 3, sizeof(DEVMODEW)))) + { + CFRelease(modes); + return NULL; + } + + for (i = 0; i < count; i++) + { + CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(modes, i); + display_mode_to_devmode(display_id, mode, devmodes + i); + } + + for (i = 0; !modes_has_16bpp && i < count; i++) + { + /* We only synthesize modes from those having the default bpp. */ + if (devmodes[i].dmBitsPerPel != default_bpp) continue; + devmodes[count + synth_count] = devmodes[i]; + devmodes[count + synth_count].dmBitsPerPel = 16; + synth_count++; + } + + for (i = 0; !modes_has_8bpp && i < count; i++) + { + /* We only synthesize modes from those having the default bpp. */ + if (devmodes[i].dmBitsPerPel != default_bpp) continue; + devmodes[count + synth_count] = devmodes[i]; + devmodes[count + synth_count].dmBitsPerPel = 8; + synth_count++; + } + + desc = create_original_display_mode_descriptor(display_id); + for (i = 0; i < count; i++) + { + CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(modes, i); + if (retina_enabled && display_mode_matches_descriptor(mode, desc)) + { + devmodes[i].dmPelsWidth *= 2; + devmodes[i].dmPelsHeight *= 2; + } + } + free_display_mode_descriptor(desc); + + CFRelease(modes); + *modes_count = count + synth_count; + return devmodes; +} + /*********************************************************************** * EnumDisplaySettingsEx (MACDRV.@) * @@ -1301,7 +1372,8 @@ BOOL macdrv_UpdateDisplayDevices( const struct gdi_device_manager *device_manage struct macdrv_adapter *adapters, *adapter; struct macdrv_monitor *monitors, *monitor; struct macdrv_gpu *gpus, *gpu; - INT gpu_count, adapter_count, monitor_count; + INT gpu_count, adapter_count, monitor_count, mode_count; + DEVMODEW *mode, *modes; DWORD len;
if (!force && !force_display_devices_refresh) return TRUE; @@ -1359,6 +1431,19 @@ BOOL macdrv_UpdateDisplayDevices( const struct gdi_device_manager *device_manage device_manager->add_monitor( &gdi_monitor, param ); }
+ if (!(modes = display_get_modes(adapter->id, &mode_count))) break; + TRACE("adapter: %#x, mode count: %d\n", adapter->id, mode_count); + + /* Initialize modes */ + for (mode = modes; mode < modes + mode_count; mode++) + { + TRACE("mode: %dx%dx%dbpp @%d Hz, %sstretched %sinterlaced\n", mode->dmPelsWidth, mode->dmPelsHeight, + mode->dmBitsPerPel, mode->dmDisplayFrequency, + mode->dmDisplayFixedOutput == DMDFO_STRETCH ? "" : "un", + mode->dmDisplayFlags & DM_INTERLACED ? "" : "non-"); + device_manager->add_mode( mode, param ); + } + macdrv_free_monitors(monitors); }
diff --git a/dlls/winex11.drv/display.c b/dlls/winex11.drv/display.c index cbf1e7f70cd..174411c7915 100644 --- a/dlls/winex11.drv/display.c +++ b/dlls/winex11.drv/display.c @@ -1026,6 +1026,8 @@ BOOL X11DRV_UpdateDisplayDevices( const struct gdi_device_manager *device_manage struct gdi_gpu *gpus; INT gpu_count, adapter_count, monitor_count; INT gpu, adapter, monitor; + DEVMODEW *modes, *mode; + DWORD mode_count;
if (!force && !force_display_devices_refresh) return TRUE; force_display_devices_refresh = FALSE; @@ -1060,6 +1062,20 @@ BOOL X11DRV_UpdateDisplayDevices( const struct gdi_device_manager *device_manage }
handler->free_monitors(monitors, monitor_count); + + if (!settings_handler.get_modes( adapters[adapter].id, EDS_ROTATEDMODE, &modes, &mode_count )) + continue; + + qsort( modes, mode_count, sizeof(*modes) + modes[0].dmDriverExtra, mode_compare ); + + for (mode = modes; mode_count; mode_count--) + { + TRACE( "mode: %p\n", mode ); + device_manager->add_mode( mode, param ); + mode = (DEVMODEW *)((char *)mode + sizeof(*modes) + modes[0].dmDriverExtra); + } + + settings_handler.free_modes( modes ); }
handler->free_adapters(adapters); diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h index 77ccc431e51..9acfaf1f65f 100644 --- a/include/wine/gdi_driver.h +++ b/include/wine/gdi_driver.h @@ -266,6 +266,7 @@ struct gdi_device_manager void (*add_gpu)( const struct gdi_gpu *gpu, void *param ); void (*add_adapter)( const struct gdi_adapter *adapter, void *param ); void (*add_monitor)( const struct gdi_monitor *monitor, void *param ); + void (*add_mode)( const DEVMODEW *mode, void *param ); };
struct tagUPDATELAYEREDWINDOWINFO;
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/win32u/sysparams.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 0b7e7aefd61..820de2743cf 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -203,6 +203,8 @@ static const WCHAR guid_devinterface_monitorW[] = {'{','E','6','F','0','7','B','5','F','-','E','E','9','7','-','4','A','9','0','-', 'B','0','7','6','-','3','3','F','5','7','B','F','4','E','A','A','7','}',0};
+#define NEXT_DEVMODEW(mode) ((DEVMODEW *)((char *)((mode) + 1) + (mode)->dmDriverExtra)) + /* Cached display device information */ struct display_device { @@ -220,6 +222,8 @@ struct adapter struct display_device dev; unsigned int id; const WCHAR *config_key; + unsigned int mode_count; + DEVMODEW *modes; };
struct monitor @@ -545,8 +549,9 @@ static BOOL read_display_adapter_settings( unsigned int index, struct adapter *i char buffer[4096]; KEY_VALUE_PARTIAL_INFORMATION *value = (void *)buffer; WCHAR *value_str = (WCHAR *)value->Data; + DWORD i, driver_extra = 0, size; + DEVMODEW *mode; HKEY hkey; - DWORD size;
if (!enum_key && !(enum_key = reg_open_key( NULL, enum_keyW, sizeof(enum_keyW) ))) return FALSE; @@ -585,10 +590,28 @@ static BOOL read_display_adapter_settings( unsigned int index, struct adapter *i /* Interface name */ info->dev.interface_name[0] = 0;
+ /* ModeCount / DriverExtra */ + if (query_reg_value( hkey, mode_countW, value, sizeof(buffer) ) && value->Type == REG_DWORD) + info->mode_count = *(const DWORD *)value->Data; + if (query_reg_value( hkey, driver_extraW, value, sizeof(buffer) ) && value->Type == REG_DWORD) + driver_extra = *(const DWORD *)value->Data; + + /* Modes */ + if ((info->modes = calloc( info->mode_count, sizeof(DEVMODEW) + driver_extra ))) + { + for (i = 0, mode = info->modes; i < info->mode_count; i++) + { + mode->dmDriverExtra = driver_extra; + if (!read_adapter_mode( hkey, i, mode )) break; + mode = NEXT_DEVMODEW(mode); + } + info->mode_count = i; + } + /* DeviceID */ size = query_reg_value( hkey, gpu_idW, value, sizeof(buffer) ); NtClose( hkey ); - if (!size || value->Type != REG_SZ) return FALSE; + if (!size || value->Type != REG_SZ || !info->mode_count || !info->modes) return FALSE;
if (!(hkey = reg_open_key( enum_key, value_str, value->DataLength - sizeof(WCHAR) ))) return FALSE; @@ -1375,6 +1398,7 @@ static void clear_display_devices(void) { adapter = LIST_ENTRY( list_head( &adapters ), struct adapter, entry ); list_remove( &adapter->entry ); + free( adapter->modes ); free( adapter ); } } @@ -1413,6 +1437,7 @@ static BOOL update_display_cache_from_registry(void)
if (!read_display_adapter_settings( adapter_id, adapter )) { + free( adapter->modes ); free( adapter ); break; }
On Mon Jul 25 08:36:16 2022 +0000, R��mi Bernon wrote:
changed this line in [version 3 of the diff](/wine/wine/-/merge_requests/406/diffs?diff_id=5870&start_sha=033e023f6ed9db06d88b8664f027df1ce4ccf8ad#d1968e8c429ee8f293c300a3b265157c4161beb0_965_961)
Thanks, it should be doing the right thing now.
This merge request was approved by Huw Davies.
Zhiyi Zhang (@zhiyi) commented about dlls/win32u/sysparams.c:
- struct device_manager_ctx *ctx = param;
- if (!ctx->adapter_count)
- {
static const struct gdi_adapter default_adapter =
{
.state_flags = DISPLAY_DEVICE_ATTACHED_TO_DESKTOP | DISPLAY_DEVICE_PRIMARY_DEVICE | DISPLAY_DEVICE_VGA_COMPATIBLE,
};
TRACE( "adding default fake adapter\n" );
add_adapter( &default_adapter, ctx );
- }
- if (write_adapter_mode( ctx->adapter_key, ctx->mode_count, mode ))
- {
ctx->driver_extra = max( ctx->driver_extra, mode->dmDriverExtra );
set_reg_value( ctx->adapter_key, driver_extraW, REG_DWORD, &ctx->driver_extra, sizeof(ctx->driver_extra) );
dmDriverExtra should be a fixed value for all modes. So you don't need to call max() and save it to the registry every time.
Zhiyi Zhang (@zhiyi) commented about dlls/win32u/sysparams.c:
if (!user_driver->pUpdateDisplayDevices( &device_manager, TRUE, &ctx )) {
static const DEVMODEW modes[] =
{
{ .dmFields = DM_DISPLAYORIENTATION|DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT|DM_DISPLAYFLAGS|DM_DISPLAYFREQUENCY|DM_POSITION,
The DM_POSITION flag is only used for the current mode. For available modes, they have no position obviously. Add a space before and after the |. And is it really necessary to add 6 modes? Not that there is anything wrong with it.
Zhiyi Zhang (@zhiyi) commented about dlls/win32u/sysparams.c:
{ .dmFields = DM_DISPLAYORIENTATION|DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT|DM_DISPLAYFLAGS|DM_DISPLAYFREQUENCY|DM_POSITION,
.dmBitsPerPel = 32, .dmPelsWidth = 1024, .dmPelsHeight = 768, .dmDisplayFrequency = 60, },
{ .dmFields = DM_DISPLAYORIENTATION|DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT|DM_DISPLAYFLAGS|DM_DISPLAYFREQUENCY|DM_POSITION,
.dmBitsPerPel = 16, .dmPelsWidth = 640, .dmPelsHeight = 480, .dmDisplayFrequency = 60, },
{ .dmFields = DM_DISPLAYORIENTATION|DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT|DM_DISPLAYFLAGS|DM_DISPLAYFREQUENCY|DM_POSITION,
.dmBitsPerPel = 16, .dmPelsWidth = 800, .dmPelsHeight = 600, .dmDisplayFrequency = 60, },
{ .dmFields = DM_DISPLAYORIENTATION|DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT|DM_DISPLAYFLAGS|DM_DISPLAYFREQUENCY|DM_POSITION,
.dmBitsPerPel = 16, .dmPelsWidth = 1024, .dmPelsHeight = 768, .dmDisplayFrequency = 60, },
}; static const struct gdi_gpu gpu; static const struct gdi_adapter adapter = { .state_flags = DISPLAY_DEVICE_ATTACHED_TO_DESKTOP | DISPLAY_DEVICE_PRIMARY_DEVICE | DISPLAY_DEVICE_VGA_COMPATIBLE, };
DEVMODEW mode = {.dmPelsWidth = 1024, .dmPelsHeight = 768};
DEVMODEW mode = modes[2];
Use pointer.
Zhiyi Zhang (@zhiyi) commented about dlls/winemac.drv/display.c:
- {
/* We only synthesize modes from those having the default bpp. */
if (devmodes[i].dmBitsPerPel != default_bpp) continue;
devmodes[count + synth_count] = devmodes[i];
devmodes[count + synth_count].dmBitsPerPel = 8;
synth_count++;
- }
- desc = create_original_display_mode_descriptor(display_id);
- for (i = 0; i < count; i++)
- {
CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(modes, i);
if (retina_enabled && display_mode_matches_descriptor(mode, desc))
{
devmodes[i].dmPelsWidth *= 2;
devmodes[i].dmPelsHeight *= 2;
Shouldn't you apply the scaling to fake 16bit and 8bit modes?
On Wed Jul 27 08:24:06 2022 +0000, Zhiyi Zhang wrote:
Shouldn't you apply the scaling to fake 16bit and 8bit modes?
I wasn't completely sure about that, but looking again at the logic in macdrv_EnumDisplaySettingsEx I think you're right. I'll update it.