@ -1157,6 +1157,143 @@ static struct wlr_drm_crtc *connector_get_current_crtc(
return NULL ;
}
static void connect_drm_connector ( struct wlr_drm_connector * wlr_conn ,
const drmModeConnector * drm_conn ) {
struct wlr_drm_backend * drm = wlr_conn - > backend ;
wlr_log ( WLR_DEBUG , " Current CRTC: %d " ,
wlr_conn - > crtc ? ( int ) wlr_conn - > crtc - > id : - 1 ) ;
wlr_output_init ( & wlr_conn - > output , & drm - > backend , & output_impl ,
drm - > display ) ;
wlr_output_set_name ( & wlr_conn - > output , wlr_conn - > name ) ;
wlr_conn - > output . phys_width = drm_conn - > mmWidth ;
wlr_conn - > output . phys_height = drm_conn - > mmHeight ;
wlr_log ( WLR_INFO , " Physical size: % " PRId32 " x% " PRId32 ,
wlr_conn - > output . phys_width , wlr_conn - > output . phys_height ) ;
wlr_conn - > output . subpixel = subpixel_map [ drm_conn - > subpixel ] ;
get_drm_connector_props ( drm - > fd , wlr_conn - > id , & wlr_conn - > props ) ;
uint64_t non_desktop ;
if ( get_drm_prop ( drm - > fd , wlr_conn - > id ,
wlr_conn - > props . non_desktop , & non_desktop ) ) {
if ( non_desktop = = 1 ) {
wlr_log ( WLR_INFO , " Non-desktop connector " ) ;
}
wlr_conn - > output . non_desktop = non_desktop ;
}
wlr_conn - > max_bpc = 0 ;
if ( wlr_conn - > props . max_bpc ! = 0 ) {
if ( ! introspect_drm_prop_range ( drm - > fd , wlr_conn - > props . max_bpc ,
NULL , & wlr_conn - > max_bpc ) ) {
wlr_log ( WLR_ERROR , " Failed to introspect 'max bpc' property " ) ;
}
}
size_t edid_len = 0 ;
uint8_t * edid = get_drm_prop_blob ( drm - > fd ,
wlr_conn - > id , wlr_conn - > props . edid , & edid_len ) ;
parse_edid ( wlr_conn , edid_len , edid ) ;
free ( edid ) ;
char * subconnector = NULL ;
if ( wlr_conn - > props . subconnector ) {
subconnector = get_drm_prop_enum ( drm - > fd ,
wlr_conn - > id , wlr_conn - > props . subconnector ) ;
}
if ( subconnector & & strcmp ( subconnector , " Native " ) = = 0 ) {
free ( subconnector ) ;
subconnector = NULL ;
}
struct wlr_output * output = & wlr_conn - > output ;
char description [ 128 ] ;
snprintf ( description , sizeof ( description ) , " %s %s%s%s (%s%s%s) " ,
output - > make , output - > model ,
output - > serial ? " " : " " ,
output - > serial ? output - > serial : " " ,
output - > name ,
subconnector ? " via " : " " ,
subconnector ? subconnector : " " ) ;
wlr_output_set_description ( output , description ) ;
free ( subconnector ) ;
// Before iterating on the conn's modes, get the current KMS mode
// in use from the connector's CRTC.
drmModeModeInfo * current_modeinfo = NULL ;
if ( wlr_conn - > crtc ! = NULL ) {
if ( wlr_conn - > crtc - > props . mode_id = = 0 ) {
// Use the legacy drm interface.
if ( wlr_conn - > crtc - > legacy_crtc - > mode_valid ) {
current_modeinfo = & wlr_conn - > crtc - > legacy_crtc - > mode ;
}
} else {
// Use the modern atomic drm interface.
size_t modeinfo_size = 0 ;
current_modeinfo = get_drm_prop_blob ( drm - > fd , wlr_conn - > crtc - > id ,
wlr_conn - > crtc - > props . mode_id , & modeinfo_size ) ;
assert ( modeinfo_size = = sizeof ( drmModeModeInfo ) ) ;
}
}
wlr_log ( WLR_INFO , " Detected modes: " ) ;
for ( int i = 0 ; i < drm_conn - > count_modes ; + + i ) {
if ( drm_conn - > modes [ i ] . flags & DRM_MODE_FLAG_INTERLACE ) {
continue ;
}
struct wlr_drm_mode * mode = drm_mode_create ( & drm_conn - > modes [ i ] ) ;
if ( ! mode ) {
wlr_log_errno ( WLR_ERROR , " Allocation failed " ) ;
continue ;
}
// If this is the current mode set on the conn's crtc,
// then set it as the conn's output current mode.
if ( current_modeinfo ! = NULL & & memcmp ( & mode - > drm_mode ,
current_modeinfo , sizeof ( * current_modeinfo ) ) = = 0 ) {
// Update width, height, refresh, transform_matrix and current_mode
// of this connector's output.
wlr_output_update_mode ( & wlr_conn - > output , & mode - > wlr_mode ) ;
uint64_t mode_id = 0 ;
get_drm_prop ( drm - > fd , wlr_conn - > crtc - > id ,
wlr_conn - > crtc - > props . mode_id , & mode_id ) ;
wlr_conn - > crtc - > mode_id = mode_id ;
}
wlr_log ( WLR_INFO , " % " PRId32 " x% " PRId32 " @% " PRId32 " %s " ,
mode - > wlr_mode . width , mode - > wlr_mode . height ,
mode - > wlr_mode . refresh ,
mode - > wlr_mode . preferred ? " (preferred) " : " " ) ;
wl_list_insert ( wlr_conn - > output . modes . prev , & mode - > wlr_mode . link ) ;
}
if ( wlr_conn - > crtc ! = NULL & & wlr_conn - > crtc - > props . mode_id ! = 0 ) {
// free() the modeinfo pointer, but only
// if not using the legacy API.
free ( current_modeinfo ) ;
}
wlr_conn - > possible_crtcs =
drmModeConnectorGetPossibleCrtcs ( drm - > fd , drm_conn ) ;
if ( wlr_conn - > possible_crtcs = = 0 ) {
wlr_drm_conn_log ( wlr_conn , WLR_ERROR , " No CRTC possible " ) ;
}
wlr_output_update_enabled ( & wlr_conn - > output , wlr_conn - > crtc ! = NULL ) ;
wlr_conn - > status = DRM_MODE_CONNECTED ;
}
static void disconnect_drm_connector ( struct wlr_drm_connector * conn ) ;
void scan_drm_connectors ( struct wlr_drm_backend * drm ,
@ -1261,137 +1398,7 @@ void scan_drm_connectors(struct wlr_drm_backend *drm,
if ( wlr_conn - > status = = DRM_MODE_DISCONNECTED & &
drm_conn - > connection = = DRM_MODE_CONNECTED ) {
wlr_log ( WLR_INFO , " '%s' connected " , wlr_conn - > name ) ;
wlr_log ( WLR_DEBUG , " Current CRTC: %d " ,
wlr_conn - > crtc ? ( int ) wlr_conn - > crtc - > id : - 1 ) ;
wlr_output_init ( & wlr_conn - > output , & drm - > backend , & output_impl ,
drm - > display ) ;
wlr_output_set_name ( & wlr_conn - > output , wlr_conn - > name ) ;
wlr_conn - > output . phys_width = drm_conn - > mmWidth ;
wlr_conn - > output . phys_height = drm_conn - > mmHeight ;
wlr_log ( WLR_INFO , " Physical size: % " PRId32 " x% " PRId32 ,
wlr_conn - > output . phys_width , wlr_conn - > output . phys_height ) ;
wlr_conn - > output . subpixel = subpixel_map [ drm_conn - > subpixel ] ;
get_drm_connector_props ( drm - > fd , wlr_conn - > id , & wlr_conn - > props ) ;
uint64_t non_desktop ;
if ( get_drm_prop ( drm - > fd , wlr_conn - > id ,
wlr_conn - > props . non_desktop , & non_desktop ) ) {
if ( non_desktop = = 1 ) {
wlr_log ( WLR_INFO , " Non-desktop connector " ) ;
}
wlr_conn - > output . non_desktop = non_desktop ;
}
wlr_conn - > max_bpc = 0 ;
if ( wlr_conn - > props . max_bpc ! = 0 ) {
if ( ! introspect_drm_prop_range ( drm - > fd , wlr_conn - > props . max_bpc ,
NULL , & wlr_conn - > max_bpc ) ) {
wlr_log ( WLR_ERROR , " Failed to introspect 'max bpc' property " ) ;
}
}
size_t edid_len = 0 ;
uint8_t * edid = get_drm_prop_blob ( drm - > fd ,
wlr_conn - > id , wlr_conn - > props . edid , & edid_len ) ;
parse_edid ( wlr_conn , edid_len , edid ) ;
free ( edid ) ;
char * subconnector = NULL ;
if ( wlr_conn - > props . subconnector ) {
subconnector = get_drm_prop_enum ( drm - > fd ,
wlr_conn - > id , wlr_conn - > props . subconnector ) ;
}
if ( subconnector & & strcmp ( subconnector , " Native " ) = = 0 ) {
free ( subconnector ) ;
subconnector = NULL ;
}
struct wlr_output * output = & wlr_conn - > output ;
char description [ 128 ] ;
snprintf ( description , sizeof ( description ) , " %s %s%s%s (%s%s%s) " ,
output - > make , output - > model ,
output - > serial ? " " : " " ,
output - > serial ? output - > serial : " " ,
output - > name ,
subconnector ? " via " : " " ,
subconnector ? subconnector : " " ) ;
wlr_output_set_description ( output , description ) ;
free ( subconnector ) ;
// Before iterating on the conn's modes, get the current KMS mode
// in use from the connector's CRTC.
drmModeModeInfo * current_modeinfo = NULL ;
if ( wlr_conn - > crtc ! = NULL ) {
if ( wlr_conn - > crtc - > props . mode_id = = 0 ) {
// Use the legacy drm interface.
if ( wlr_conn - > crtc - > legacy_crtc - > mode_valid ) {
current_modeinfo = & wlr_conn - > crtc - > legacy_crtc - > mode ;
}
} else {
// Use the modern atomic drm interface.
size_t modeinfo_size = 0 ;
current_modeinfo = get_drm_prop_blob ( drm - > fd , wlr_conn - > crtc - > id ,
wlr_conn - > crtc - > props . mode_id , & modeinfo_size ) ;
assert ( modeinfo_size = = sizeof ( drmModeModeInfo ) ) ;
}
}
wlr_log ( WLR_INFO , " Detected modes: " ) ;
for ( int i = 0 ; i < drm_conn - > count_modes ; + + i ) {
if ( drm_conn - > modes [ i ] . flags & DRM_MODE_FLAG_INTERLACE ) {
continue ;
}
struct wlr_drm_mode * mode = drm_mode_create ( & drm_conn - > modes [ i ] ) ;
if ( ! mode ) {
wlr_log_errno ( WLR_ERROR , " Allocation failed " ) ;
continue ;
}
// If this is the current mode set on the conn's crtc,
// then set it as the conn's output current mode.
if ( current_modeinfo ! = NULL & & memcmp ( & mode - > drm_mode ,
current_modeinfo , sizeof ( * current_modeinfo ) ) = = 0 ) {
// Update width, height, refresh, transform_matrix and current_mode
// of this connector's output.
wlr_output_update_mode ( & wlr_conn - > output , & mode - > wlr_mode ) ;
uint64_t mode_id = 0 ;
get_drm_prop ( drm - > fd , wlr_conn - > crtc - > id ,
wlr_conn - > crtc - > props . mode_id , & mode_id ) ;
wlr_conn - > crtc - > mode_id = mode_id ;
}
wlr_log ( WLR_INFO , " % " PRId32 " x% " PRId32 " @% " PRId32 " %s " ,
mode - > wlr_mode . width , mode - > wlr_mode . height ,
mode - > wlr_mode . refresh ,
mode - > wlr_mode . preferred ? " (preferred) " : " " ) ;
wl_list_insert ( wlr_conn - > output . modes . prev , & mode - > wlr_mode . link ) ;
}
if ( wlr_conn - > crtc ! = NULL & & wlr_conn - > crtc - > props . mode_id ! = 0 ) {
// free() the modeinfo pointer, but only
// if not using the legacy API.
free ( current_modeinfo ) ;
}
wlr_conn - > possible_crtcs =
drmModeConnectorGetPossibleCrtcs ( drm - > fd , drm_conn ) ;
if ( wlr_conn - > possible_crtcs = = 0 ) {
wlr_drm_conn_log ( wlr_conn , WLR_ERROR , " No CRTC possible " ) ;
}
wlr_output_update_enabled ( & wlr_conn - > output , wlr_conn - > crtc ! = NULL ) ;
wlr_conn - > status = DRM_MODE_CONNECTED ;
connect_drm_connector ( wlr_conn , drm_conn ) ;
new_outputs [ new_outputs_len + + ] = wlr_conn ;
} else if ( wlr_conn - > status = = DRM_MODE_CONNECTED & &
drm_conn - > connection ! = DRM_MODE_CONNECTED ) {