aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/rootston/config.h7
-rw-r--r--rootston/config.c59
-rw-r--r--rootston/output.c12
-rw-r--r--rootston/rootston.ini.example7
4 files changed, 85 insertions, 0 deletions
diff --git a/include/rootston/config.h b/include/rootston/config.h
index 97a8baab..86699c6a 100644
--- a/include/rootston/config.h
+++ b/include/rootston/config.h
@@ -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 {
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