mirror of
				https://gitlab.freedesktop.org/wlroots/wlroots.git
				synced 2025-10-29 05:40:12 -04:00 
			
		
		
		
	Merge pull request #1095 from agx/output-add-mode
Allow to add additional modes to outputs
This commit is contained in:
		
						commit
						be54278207
					
				
					 6 changed files with 117 additions and 1 deletions
				
			
		|  | @ -566,6 +566,33 @@ error_conn: | |||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| bool wlr_drm_connector_add_mode(struct wlr_output *output, | ||||
| 		const drmModeModeInfo *modeinfo) { | ||||
| 	struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output; | ||||
| 
 | ||||
| 	assert(modeinfo); | ||||
| 	if (modeinfo->type != DRM_MODE_TYPE_USERDEF) { | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	struct wlr_drm_mode *mode = calloc(1, sizeof(*mode)); | ||||
| 	if (!mode) { | ||||
| 		return false; | ||||
| 	} | ||||
| 	memcpy(&mode->drm_mode, modeinfo, sizeof(*modeinfo)); | ||||
| 
 | ||||
| 	mode->wlr_mode.width = mode->drm_mode.hdisplay; | ||||
| 	mode->wlr_mode.height = mode->drm_mode.vdisplay; | ||||
| 	mode->wlr_mode.refresh = mode->drm_mode.vrefresh; | ||||
| 
 | ||||
| 	wlr_log(L_INFO, "Registered custom mode " | ||||
| 			"%"PRId32"x%"PRId32"@%"PRId32, | ||||
| 			mode->wlr_mode.width, mode->wlr_mode.height, | ||||
| 			mode->wlr_mode.refresh); | ||||
| 	wl_list_insert(&conn->output.modes, &mode->wlr_mode.link); | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| static void drm_connector_transform(struct wlr_output *output, | ||||
| 		enum wl_output_transform transform) { | ||||
| 	output->transform = transform; | ||||
|  |  | |||
|  | @ -143,5 +143,9 @@ void restore_drm_outputs(struct wlr_drm_backend *drm); | |||
| void scan_drm_connectors(struct wlr_drm_backend *state); | ||||
| int handle_drm_event(int fd, uint32_t mask, void *data); | ||||
| void enable_drm_connector(struct wlr_output *output, bool enable); | ||||
| /**
 | ||||
|  * Add mode to the list of available modes | ||||
|  */ | ||||
| bool wlr_drm_connector_add_mode(struct wlr_output *output, const drmModeModeInfo *mode); | ||||
| 
 | ||||
| #endif | ||||
|  |  | |||
|  | @ -1,11 +1,17 @@ | |||
| #ifndef ROOTSTON_CONFIG_H | ||||
| #define ROOTSTON_CONFIG_H | ||||
| 
 | ||||
| #include <xf86drmMode.h> | ||||
| #include <wlr/types/wlr_input_device.h> | ||||
| #include <wlr/types/wlr_output_layout.h> | ||||
| 
 | ||||
| #define ROOTS_CONFIG_DEFAULT_SEAT_NAME "seat0" | ||||
| 
 | ||||
| struct roots_output_mode_config { | ||||
| 	drmModeModeInfo info; | ||||
| 	struct wl_list link; | ||||
| }; | ||||
| 
 | ||||
| struct roots_output_config { | ||||
| 	char *name; | ||||
| 	bool enable; | ||||
|  | @ -17,6 +23,7 @@ struct roots_output_config { | |||
| 		int width, height; | ||||
| 		float refresh_rate; | ||||
| 	} mode; | ||||
| 	struct wl_list modes; | ||||
| }; | ||||
| 
 | ||||
| struct roots_device_config { | ||||
|  |  | |||
|  | @ -116,6 +116,51 @@ static uint32_t parse_modifier(const char *symname) { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| static bool parse_modeline(const char *s, drmModeModeInfo *mode) { | ||||
| 	char hsync[16]; | ||||
| 	char vsync[16]; | ||||
| 	float fclock; | ||||
| 
 | ||||
| 	mode->type = DRM_MODE_TYPE_USERDEF; | ||||
| 
 | ||||
| 	if (sscanf(s, "%f %hd %hd %hd %hd %hd %hd %hd %hd %15s %15s", | ||||
| 		   &fclock, | ||||
| 		   &mode->hdisplay, | ||||
| 		   &mode->hsync_start, | ||||
| 		   &mode->hsync_end, | ||||
| 		   &mode->htotal, | ||||
| 		   &mode->vdisplay, | ||||
| 		   &mode->vsync_start, | ||||
| 		   &mode->vsync_end, | ||||
| 		   &mode->vtotal, hsync, vsync) != 11) { | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	mode->clock = fclock * 1000; | ||||
| 	mode->vrefresh = mode->clock * 1000.0 * 1000.0 | ||||
| 		/ mode->htotal / mode->vtotal; | ||||
| 	if (strcasecmp(hsync, "+hsync") == 0) { | ||||
| 		mode->flags |= DRM_MODE_FLAG_PHSYNC; | ||||
| 	} else if (strcasecmp(hsync, "-hsync") == 0) { | ||||
| 		mode->flags |= DRM_MODE_FLAG_NHSYNC; | ||||
| 	} else { | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	if (strcasecmp(vsync, "+vsync") == 0) { | ||||
| 		mode->flags |= DRM_MODE_FLAG_PVSYNC; | ||||
| 	} else if (strcasecmp(vsync, "-vsync") == 0) { | ||||
| 		mode->flags |= DRM_MODE_FLAG_NVSYNC; | ||||
| 	} else { | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	snprintf(mode->name, sizeof(mode->name), "%dx%d@%d", | ||||
| 		 mode->hdisplay, mode->vdisplay, mode->vrefresh / 1000); | ||||
| 
 | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| void add_binding_config(struct wl_list *bindings, const char* combination, | ||||
| 		const char* command) { | ||||
| 	struct roots_binding_config *bc = | ||||
|  | @ -269,6 +314,7 @@ static int config_ini_handler(void *user, const char *section, const char *name, | |||
| 			oc->transform = WL_OUTPUT_TRANSFORM_NORMAL; | ||||
| 			oc->scale = 1; | ||||
| 			oc->enable = true; | ||||
| 			wl_list_init(&oc->modes); | ||||
| 			wl_list_insert(&config->outputs, &oc->link); | ||||
| 		} | ||||
| 
 | ||||
|  | @ -322,6 +368,15 @@ static int config_ini_handler(void *user, const char *section, const char *name, | |||
| 			wlr_log(L_DEBUG, "Configured output %s with mode %dx%d@%f", | ||||
| 					oc->name, oc->mode.width, oc->mode.height, | ||||
| 					oc->mode.refresh_rate); | ||||
| 		} else if (strcmp(name, "modeline") == 0) { | ||||
| 			struct roots_output_mode_config *mode = calloc(1, sizeof(*mode)); | ||||
| 
 | ||||
| 			if (parse_modeline(value, &mode->info)) { | ||||
| 				wl_list_insert(&oc->modes, &mode->link); | ||||
| 			} else { | ||||
| 				free(mode); | ||||
| 				wlr_log(L_ERROR, "Invalid modeline: %s", value); | ||||
| 			} | ||||
| 		} | ||||
| 	} else if (strncmp(cursor_prefix, section, strlen(cursor_prefix)) == 0) { | ||||
| 		const char *seat_name = section + strlen(cursor_prefix); | ||||
|  | @ -459,6 +514,10 @@ struct roots_config *roots_config_create_from_args(int argc, char *argv[]) { | |||
| void roots_config_destroy(struct roots_config *config) { | ||||
| 	struct roots_output_config *oc, *otmp = NULL; | ||||
| 	wl_list_for_each_safe(oc, otmp, &config->outputs, link) { | ||||
| 		struct roots_output_mode_config *omc, *omctmp = NULL; | ||||
| 		wl_list_for_each_safe(omc, omctmp, &oc->modes, link) { | ||||
| 			free(omc); | ||||
| 		} | ||||
| 		free(oc->name); | ||||
| 		free(oc); | ||||
| 	} | ||||
|  |  | |||
|  | @ -16,6 +16,7 @@ | |||
| #include "rootston/layers.h" | ||||
| #include "rootston/output.h" | ||||
| #include "rootston/server.h" | ||||
| #include "backend/drm/drm.h" | ||||
| 
 | ||||
| /**
 | ||||
|  * Rotate a child's position relative to a parent. The parent size is (pw, ph), | ||||
|  | @ -821,7 +822,7 @@ void handle_new_output(struct wl_listener *listener, void *data) { | |||
| 		wlr_output->model, wlr_output->serial, wlr_output->phys_width, | ||||
| 		wlr_output->phys_height); | ||||
| 
 | ||||
| 	if (wl_list_length(&wlr_output->modes) > 0) { | ||||
| 	if (!wl_list_empty(&wlr_output->modes)) { | ||||
| 		struct wlr_output_mode *mode = | ||||
| 			wl_container_of((&wlr_output->modes)->prev, mode, link); | ||||
| 		wlr_output_set_mode(wlr_output, mode); | ||||
|  | @ -857,6 +858,17 @@ void handle_new_output(struct wl_listener *listener, void *data) { | |||
| 		roots_config_get_output(config, wlr_output); | ||||
| 	if (output_config) { | ||||
| 		if (output_config->enable) { | ||||
| 			struct roots_output_mode_config *mode_config; | ||||
| 
 | ||||
| 			if (wlr_output_is_drm(wlr_output)) { | ||||
| 				wl_list_for_each(mode_config, &output_config->modes, link) { | ||||
| 					wlr_drm_connector_add_mode(wlr_output, &mode_config->info); | ||||
| 				} | ||||
| 			} else { | ||||
| 				if (!wl_list_empty(&output_config->modes)) { | ||||
| 					wlr_log(L_ERROR, "Can only add modes for DRM backend"); | ||||
| 				} | ||||
| 			} | ||||
| 			if (output_config->mode.width) { | ||||
| 				set_mode(wlr_output, output_config); | ||||
| 			} | ||||
|  |  | |||
|  | @ -19,6 +19,13 @@ y = 0 | |||
| #                                              and rotate by specified angle | ||||
| rotate = 90 | ||||
| 
 | ||||
| # Additional video mode to add | ||||
| # Format is generated by cvt and is documented in x.org.conf(5) | ||||
| modeline = 87.25 720 776 848  976 1440 1443 1453 1493 -hsync +vsync | ||||
| modeline = 65.13 768 816 896 1024 1024 1025 1028 1060 -HSync +VSync | ||||
| # Select one of the above modes | ||||
| mode = 768x1024 | ||||
| 
 | ||||
| [cursor] | ||||
| # Restrict cursor movements to single output | ||||
| map-to-output = VGA-1 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Drew DeVault
						Drew DeVault