From 709d7dd7227f1ff86b440425721b219e63da7a2d Mon Sep 17 00:00:00 2001 From: Guido Günther Date: Tue, 3 Jul 2018 17:52:13 +0200 Subject: rootston: Handle modeline parameter This allows to pass custom modes. --- rootston/config.c | 59 +++++++++++++++++++++++++++++++++++++++++++ rootston/output.c | 12 +++++++++ rootston/rootston.ini.example | 7 +++++ 3 files changed, 78 insertions(+) (limited to 'rootston') diff --git a/rootston/config.c b/rootston/config.c index 9a4d77fd..7ef5e629 100644 --- a/rootston/config.c +++ b/rootston/config.c @@ -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); } diff --git a/rootston/output.c b/rootston/output.c index 353d431f..fda2fe89 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -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), @@ -841,6 +842,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); } diff --git a/rootston/rootston.ini.example b/rootston/rootston.ini.example index 556cbefb..bb0efa44 100644 --- a/rootston/rootston.ini.example +++ b/rootston/rootston.ini.example @@ -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 -- cgit v1.2.3 From 60a83e99f4dc930d7d4ed5999f49967a72b7df32 Mon Sep 17 00:00:00 2001 From: Guido Günther Date: Sat, 7 Jul 2018 14:45:43 +0200 Subject: rootston: use wl_list_empty instead of wl_list_length > 0 --- rootston/output.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'rootston') diff --git a/rootston/output.c b/rootston/output.c index fda2fe89..bf671d6b 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -806,7 +806,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); -- cgit v1.2.3