diff --git a/dlls/winex11.drv/desktop.c b/dlls/winex11.drv/desktop.c index b517e44e150..71b3a0a5a27 100644 --- a/dlls/winex11.drv/desktop.c +++ b/dlls/winex11.drv/desktop.c @@ -265,6 +265,8 @@ static BOOL X11DRV_desktop_get_monitors( ULONG_PTR adapter_id, struct x11drv_mon SetRect( &monitor->rc_work, 0, 0, desktop_width, desktop_height ); query_desktop_work_area( &monitor->rc_work ); monitor->state_flags = DISPLAY_DEVICE_ATTACHED; + monitor->edid_len = 0; + monitor->edid = NULL; if (desktop_width && desktop_height) monitor->state_flags |= DISPLAY_DEVICE_ACTIVE; @@ -273,7 +275,7 @@ static BOOL X11DRV_desktop_get_monitors( ULONG_PTR adapter_id, struct x11drv_mon return TRUE; } -static void X11DRV_desktop_free_monitors( struct x11drv_monitor *monitors ) +static void X11DRV_desktop_free_monitors( struct x11drv_monitor *monitors, int count ) { heap_free( monitors ); } diff --git a/dlls/winex11.drv/display.c b/dlls/winex11.drv/display.c index b3ff213ae89..ca81f169f9f 100644 --- a/dlls/winex11.drv/display.c +++ b/dlls/winex11.drv/display.c @@ -109,6 +109,8 @@ static const WCHAR monitor_hardware_idW[] = { 'M','O','N','I','T','O','R','\\', 'D','e','f','a','u','l','t','_','M','o','n','i','t','o','r',0,0}; static const WCHAR driver_date_fmtW[] = {'%','u','-','%','u','-','%','u',0}; +static const WCHAR edidW[] = {'E','D','I','D',0}; +static const WCHAR bad_edidW[] = {'B','A','D','_','E','D','I','D',0}; static struct x11drv_display_device_handler host_handler; struct x11drv_display_device_handler desktop_handler; @@ -257,7 +259,7 @@ RECT get_host_primary_monitor_rect(void) if (gpus) host_handler.free_gpus(gpus); if (adapters) host_handler.free_adapters(adapters); - if (monitors) host_handler.free_monitors(monitors); + if (monitors) host_handler.free_monitors(monitors, monitor_count); return rect; } @@ -611,6 +613,13 @@ static BOOL X11DRV_InitMonitor(HDEVINFO devinfo, const struct x11drv_monitor *mo DEVPROP_TYPE_UINT32, (const BYTE *)&output_id, sizeof(output_id), 0)) goto done; + hkey = SetupDiCreateDevRegKeyW(devinfo, &device_data, DICS_FLAG_GLOBAL, 0, DIREG_DEV, NULL, NULL); + if (monitor->edid) + RegSetValueExW(hkey, edidW, 0, REG_BINARY, monitor->edid, monitor->edid_len); + else + RegSetValueExW(hkey, bad_edidW, 0, REG_BINARY, NULL, 0); + RegCloseKey(hkey); + /* Create driver key */ hkey = SetupDiCreateDevRegKeyW(devinfo, &device_data, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL); RegCloseKey(hkey); @@ -768,7 +777,7 @@ void X11DRV_DisplayDevices_Init(BOOL force) goto done; } - handler->free_monitors(monitors); + handler->free_monitors(monitors, monitor_count); monitors = NULL; video_index++; } @@ -788,5 +797,5 @@ done: if (adapters) handler->free_adapters(adapters); if (monitors) - handler->free_monitors(monitors); + handler->free_monitors(monitors, monitor_count); } diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index afa06561aaa..5ed2fcf73fb 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -413,6 +413,7 @@ enum x11drv_atoms FIRST_XATOM = XA_LAST_PREDEFINED + 1, XATOM_CLIPBOARD = FIRST_XATOM, XATOM_COMPOUND_TEXT, + XATOM_EDID, XATOM_INCR, XATOM_MANAGER, XATOM_MULTIPLE, @@ -751,6 +752,9 @@ struct x11drv_monitor RECT rc_work; /* StateFlags in DISPLAY_DEVICE struct */ DWORD state_flags; + /* Extended Device Identification Data */ + unsigned long edid_len; + unsigned char *edid; }; /* Required functions for display device registry initialization */ @@ -786,7 +790,7 @@ struct x11drv_display_device_handler void (*free_adapters)(struct x11drv_adapter *adapters); /* free_monitors will be called to free a monitor list from get_monitors */ - void (*free_monitors)(struct x11drv_monitor *monitors); + void (*free_monitors)(struct x11drv_monitor *monitors, int count); /* register_event_handlers will be called to register event handlers. * This function pointer is optional and can be NULL when driver doesn't support it */ diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c index 2fac560556b..e8b273d055e 100644 --- a/dlls/winex11.drv/x11drv_main.c +++ b/dlls/winex11.drv/x11drv_main.c @@ -138,6 +138,7 @@ static const char * const atom_names[NB_XATOMS - FIRST_XATOM] = { "CLIPBOARD", "COMPOUND_TEXT", + "EDID", "INCR", "MANAGER", "MULTIPLE", diff --git a/dlls/winex11.drv/xinerama.c b/dlls/winex11.drv/xinerama.c index c9863482534..0e1e07669c2 100644 --- a/dlls/winex11.drv/xinerama.c +++ b/dlls/winex11.drv/xinerama.c @@ -244,6 +244,8 @@ static BOOL xinerama_get_monitors( ULONG_PTR adapter_id, struct x11drv_monitor * monitor[index].rc_work = monitors[i].rcWork; /* Xinerama only reports monitors already attached */ monitor[index].state_flags = DISPLAY_DEVICE_ATTACHED; + monitor[index].edid_len = 0; + monitor[index].edid = NULL; if (!IsRectEmpty( &monitors[i].rcMonitor )) monitor[index].state_flags |= DISPLAY_DEVICE_ACTIVE; @@ -256,7 +258,7 @@ static BOOL xinerama_get_monitors( ULONG_PTR adapter_id, struct x11drv_monitor * return TRUE; } -static void xinerama_free_monitors( struct x11drv_monitor *monitors ) +static void xinerama_free_monitors( struct x11drv_monitor *monitors, int count ) { heap_free( monitors ); } diff --git a/dlls/winex11.drv/xrandr.c b/dlls/winex11.drv/xrandr.c index e7adcec0f2e..8faece9023a 100644 --- a/dlls/winex11.drv/xrandr.c +++ b/dlls/winex11.drv/xrandr.c @@ -68,6 +68,7 @@ MAKE_FUNCPTR(XRRFreeOutputInfo) MAKE_FUNCPTR(XRRFreeScreenResources) MAKE_FUNCPTR(XRRGetCrtcInfo) MAKE_FUNCPTR(XRRGetOutputInfo) +MAKE_FUNCPTR(XRRGetOutputProperty) MAKE_FUNCPTR(XRRGetScreenResources) MAKE_FUNCPTR(XRRGetScreenResourcesCurrent) MAKE_FUNCPTR(XRRGetScreenSizeRange) @@ -112,6 +113,7 @@ static int load_xrandr(void) LOAD_FUNCPTR(XRRFreeScreenResources); LOAD_FUNCPTR(XRRGetCrtcInfo); LOAD_FUNCPTR(XRRGetOutputInfo); + LOAD_FUNCPTR(XRRGetOutputProperty); LOAD_FUNCPTR(XRRGetScreenResources); LOAD_FUNCPTR(XRRGetScreenResourcesCurrent); LOAD_FUNCPTR(XRRGetScreenSizeRange); @@ -466,6 +468,24 @@ static void get_screen_size( XRRScreenResources *resources, unsigned int *width, } } +static void get_edid( RROutput output, unsigned char **prop, unsigned long *len ) +{ + int result, actual_format; + unsigned long bytes_after; + Atom actual_type; + + result = pXRRGetOutputProperty( gdi_display, output, x11drv_atom(EDID), 0, 128, FALSE, FALSE, + AnyPropertyType, &actual_type, &actual_format, len, + &bytes_after, prop ); + + if (result != Success) + { + WARN("Could not retrieve EDID property for output %#lx.\n", output); + *prop = NULL; + *len = 0; + } +} + static void set_screen_size( int width, int height ) { int screen = default_visual.screen; @@ -1036,6 +1056,7 @@ static BOOL xrandr14_get_monitors( ULONG_PTR adapter_id, struct x11drv_monitor * { lstrcpyW( monitors[monitor_count].name, generic_nonpnp_monitorW ); monitors[monitor_count].state_flags = DISPLAY_DEVICE_ATTACHED; + get_edid( adapter_id, &monitors[monitor_count].edid, &monitors[monitor_count].edid_len ); monitor_count = 1; } /* Active monitors, need to find other monitors with the same coordinates as mirrored */ @@ -1091,6 +1112,9 @@ static BOOL xrandr14_get_monitors( ULONG_PTR adapter_id, struct x11drv_monitor * if (is_crtc_primary( primary_rect, crtc_info )) primary_index = monitor_count; + + get_edid( screen_resources->outputs[i], &monitors[monitor_count].edid, + &monitors[monitor_count].edid_len ); monitor_count++; } @@ -1131,14 +1155,26 @@ done: pXRRFreeOutputInfo( enum_output_info ); if (!ret) { + for (i = 0; i < monitor_count; i++) + { + if (monitors[i].edid) + XFree( monitors[i].edid ); + } heap_free( monitors ); ERR("Failed to get monitors\n"); } return ret; } -static void xrandr14_free_monitors( struct x11drv_monitor *monitors ) +static void xrandr14_free_monitors( struct x11drv_monitor *monitors, int count ) { + int i; + + for (i = 0; i < count; i++) + { + if (monitors[i].edid) + XFree( monitors[i].edid ); + } heap_free( monitors ); }