From: Giulio Camuffo <giuliocamu...@gmail.com> --- Makefile.am | 3 + src/compositor-drm.c | 234 ++++++++++++++++----------------------------------- src/compositor-drm.h | 89 ++++++++++++++++++++ src/main.c | 127 +++++++++++++++++++++++++++- 4 files changed, 292 insertions(+), 161 deletions(-) create mode 100644 src/compositor-drm.h
diff --git a/Makefile.am b/Makefile.am index 76ab546..2f21930 100644 --- a/Makefile.am +++ b/Makefile.am @@ -72,6 +72,7 @@ weston_SOURCES = \ src/log.c \ src/compositor.c \ src/compositor.h \ + src/compositor-drm.h \ src/input.c \ src/data-device.c \ src/screenshooter.c \ @@ -188,6 +189,7 @@ westonincludedir = $(includedir)/weston westoninclude_HEADERS = \ src/version.h \ src/compositor.h \ + src/compositor-drm.h \ src/timeline-object.h \ shared/matrix.h \ shared/config-parser.h \ @@ -251,6 +253,7 @@ drm_backend_la_CFLAGS = \ $(AM_CFLAGS) drm_backend_la_SOURCES = \ src/compositor-drm.c \ + src/compositor-drm.h \ $(INPUT_BACKEND_SOURCES) \ shared/helpers.h \ shared/timespec-util.h \ diff --git a/src/compositor-drm.c b/src/compositor-drm.c index ce95d05..4c298fe 100644 --- a/src/compositor-drm.c +++ b/src/compositor-drm.c @@ -50,6 +50,7 @@ #include "shared/timespec-util.h" #include "libbacklight.h" #include "compositor.h" +#include "compositor-drm.h" #include "gl-renderer.h" #include "pixman-renderer.h" #include "libinput-seat.h" @@ -73,17 +74,6 @@ #define GBM_BO_USE_CURSOR GBM_BO_USE_CURSOR_64X64 #endif -static int option_current_mode = 0; - -enum output_config { - OUTPUT_CONFIG_INVALID = 0, - OUTPUT_CONFIG_OFF, - OUTPUT_CONFIG_PREFERRED, - OUTPUT_CONFIG_CURRENT, - OUTPUT_CONFIG_MODE, - OUTPUT_CONFIG_MODELINE -}; - struct drm_backend { struct weston_backend base; struct weston_compositor *compositor; @@ -106,6 +96,7 @@ struct drm_backend { uint32_t connector_allocator; struct wl_listener session_listener; uint32_t format; + bool option_current_mode; /* we need these parameters in order to not fail drmModeAddFB2() * due to out of bounds dimensions, and then mistakenly set @@ -129,6 +120,10 @@ struct drm_backend { int32_t cursor_width; int32_t cursor_height; + + void (*configure_output)(struct weston_compositor *compositor, + const char *name, + struct weston_drm_backend_output_config *config); }; struct drm_mode { @@ -219,13 +214,6 @@ struct drm_sprite { uint32_t formats[]; }; -struct drm_parameters { - int connector; - int tty; - int use_pixman; - const char *seat_id; -}; - static struct gl_renderer_interface *gl_renderer; static const char default_seat[] = "seat0"; @@ -2026,47 +2014,26 @@ find_and_parse_output_edid(struct drm_backend *b, -static int -parse_modeline(const char *s, drmModeModeInfo *mode) -{ - char hsync[16]; - char vsync[16]; - float fclock; - - mode->type = DRM_MODE_TYPE_USERDEF; - mode->hskew = 0; - mode->vscan = 0; - mode->vrefresh = 0; - mode->flags = 0; - - 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 -1; - - mode->clock = fclock * 1000; - if (strcmp(hsync, "+hsync") == 0) - mode->flags |= DRM_MODE_FLAG_PHSYNC; - else if (strcmp(hsync, "-hsync") == 0) - mode->flags |= DRM_MODE_FLAG_NHSYNC; - else - return -1; +static void +parse_modeline(struct weston_drm_backend_modeline *modeline, + drmModeModeInfo *drm_mode) +{ + drm_mode->type = DRM_MODE_TYPE_USERDEF; + drm_mode->hskew = 0; + drm_mode->vscan = 0; + drm_mode->vrefresh = 0; + drm_mode->flags = modeline->flags; + drm_mode->clock = modeline->clock; - if (strcmp(vsync, "+vsync") == 0) - mode->flags |= DRM_MODE_FLAG_PVSYNC; - else if (strcmp(vsync, "-vsync") == 0) - mode->flags |= DRM_MODE_FLAG_NVSYNC; - else - return -1; + drm_mode->hdisplay = modeline->hdisplay; + drm_mode->hsync_start = modeline->hsync_start; + drm_mode->hsync_end = modeline->hsync_end; + drm_mode->htotal = modeline->htotal; - return 0; + drm_mode->vdisplay = modeline->vdisplay; + drm_mode->vsync_start = modeline->vsync_start; + drm_mode->vsync_end = modeline->vsync_end; + drm_mode->vtotal = modeline->vtotal; } static void @@ -2093,16 +2060,10 @@ setup_output_seat_constraint(struct drm_backend *b, } static int -get_gbm_format_from_section(struct weston_config_section *section, - uint32_t default_value, - uint32_t *format) +parse_gbm_format(const char *s, uint32_t default_value, uint32_t *format) { - char *s; int ret = 0; - weston_config_section_get_string(section, - "gbm-format", &s, NULL); - if (s == NULL) *format = default_value; else if (strcmp(s, "xrgb8888") == 0) @@ -2116,8 +2077,6 @@ get_gbm_format_from_section(struct weston_config_section *section, ret = -1; } - free(s); - return ret; } @@ -2127,31 +2086,29 @@ get_gbm_format_from_section(struct weston_config_section *section, * Find the most suitable mode to use for initial setup (or reconfiguration on * hotplug etc) for a DRM output. * + * @param backend The DRM backend object * @param output DRM output to choose mode for - * @param kind Strategy and preference to use when choosing mode - * @param width Desired width for this output - * @param height Desired height for this output + * @param config Desired configuration for the output * @param current_mode Mode currently being displayed on this output - * @param modeline Manually-entered mode (may be NULL) * @returns A mode from the output's mode list, or NULL if none available */ static struct drm_mode * -drm_output_choose_initial_mode(struct drm_output *output, - enum output_config kind, - int width, int height, - const drmModeModeInfo *current_mode, - const drmModeModeInfo *modeline) +drm_output_choose_initial_mode(struct drm_backend *backend, + struct drm_output *output, + struct weston_drm_backend_output_config *config, + const drmModeModeInfo *current_mode) { struct drm_mode *preferred = NULL; struct drm_mode *current = NULL; struct drm_mode *configured = NULL; struct drm_mode *best = NULL; struct drm_mode *drm_mode; + drmModeModeInfo modeline; wl_list_for_each_reverse(drm_mode, &output->base.mode_list, base.link) { - if (kind == OUTPUT_CONFIG_MODE && - width == drm_mode->base.width && - height == drm_mode->base.height) + if (config->type == WESTON_DRM_BACKEND_OUTPUT_TYPE_MODE && + config->base.width == drm_mode->base.width && + config->base.height == drm_mode->base.height) configured = drm_mode; if (memcmp(¤t_mode, &drm_mode->mode_info, @@ -2164,8 +2121,9 @@ drm_output_choose_initial_mode(struct drm_output *output, best = drm_mode; } - if (kind == OUTPUT_CONFIG_MODELINE) { - configured = drm_output_add_mode(output, modeline); + if (config->type == WESTON_DRM_BACKEND_OUTPUT_TYPE_MODELINE) { + parse_modeline(&config->modeline, &modeline); + configured = drm_output_add_mode(output, &modeline); if (!configured) return NULL; } @@ -2176,10 +2134,10 @@ drm_output_choose_initial_mode(struct drm_output *output, return NULL; } - if (kind == OUTPUT_CONFIG_CURRENT) + if (config->type == WESTON_DRM_BACKEND_OUTPUT_TYPE_CURRENT) configured = current; - if (option_current_mode && current) + if (backend->option_current_mode && current) return current; if (configured) @@ -2245,12 +2203,9 @@ create_output_for_connector(struct drm_backend *b, struct drm_output *output; struct drm_mode *drm_mode, *next, *current; struct weston_mode *m; - struct weston_config_section *section; - drmModeModeInfo crtc_mode, modeline; - int i, width, height, scale; - char *s; - enum output_config config; - uint32_t transform; + drmModeModeInfo crtc_mode; + int i; + struct weston_drm_backend_output_config config; i = find_crtc_for_connector(b, resources, connector); if (i < 0) { @@ -2269,42 +2224,14 @@ create_output_for_connector(struct drm_backend *b, output->base.serial_number = "unknown"; wl_list_init(&output->base.mode_list); - section = weston_config_get_section(b->compositor->config, "output", "name", - output->base.name); - weston_config_section_get_string(section, "mode", &s, "preferred"); - if (strcmp(s, "off") == 0) - config = OUTPUT_CONFIG_OFF; - else if (strcmp(s, "preferred") == 0) - config = OUTPUT_CONFIG_PREFERRED; - else if (strcmp(s, "current") == 0) - config = OUTPUT_CONFIG_CURRENT; - else if (sscanf(s, "%dx%d", &width, &height) == 2) - config = OUTPUT_CONFIG_MODE; - else if (parse_modeline(s, &modeline) == 0) - config = OUTPUT_CONFIG_MODELINE; - else { - weston_log("Invalid mode \"%s\" for output %s\n", - s, output->base.name); - config = OUTPUT_CONFIG_PREFERRED; - } - free(s); - - weston_config_section_get_int(section, "scale", &scale, 1); - weston_config_section_get_string(section, "transform", &s, "normal"); - if (weston_parse_transform(s, &transform) < 0) - weston_log("Invalid transform \"%s\" for output %s\n", - s, output->base.name); - - free(s); - - if (get_gbm_format_from_section(section, - b->format, - &output->format) == -1) + b->configure_output(b->compositor, output->base.name, + &config); + if (parse_gbm_format(config.format, b->format, &output->format) == -1) output->format = b->format; - weston_config_section_get_string(section, "seat", &s, ""); - setup_output_seat_constraint(b, &output->base, s); - free(s); + setup_output_seat_constraint(b, &output->base, + config.seat ? config.seat : ""); + free(config.seat); output->crtc_id = resources->crtcs[i]; output->pipe = i; @@ -2324,16 +2251,15 @@ create_output_for_connector(struct drm_backend *b, goto err_free; } - if (config == OUTPUT_CONFIG_OFF) { + if (config.type == WESTON_DRM_BACKEND_OUTPUT_TYPE_OFF) { weston_log("Disabling output %s\n", output->base.name); drmModeSetCrtc(b->drm.fd, output->crtc_id, 0, 0, 0, 0, 0, NULL); goto err_free; } - current = drm_output_choose_initial_mode(output, config, - width, height, - &crtc_mode, &modeline); + current = drm_output_choose_initial_mode(b, output, &config, + &crtc_mode); if (!current) goto err_free; output->base.current_mode = ¤t->base; @@ -2341,7 +2267,7 @@ create_output_for_connector(struct drm_backend *b, weston_output_init(&output->base, b->compositor, x, y, connector->mmWidth, connector->mmHeight, - transform, scale); + config.base.transform, config.base.scale); if (b->use_pixman) { if (drm_output_init_pixman(output, b) < 0) { @@ -3008,16 +2934,14 @@ renderer_switch_binding(struct weston_keyboard *keyboard, uint32_t time, static struct drm_backend * drm_backend_create(struct weston_compositor *compositor, - struct drm_parameters *param, - int *argc, char *argv[], - struct weston_config *config) + struct weston_drm_backend_config *config) { struct drm_backend *b; - struct weston_config_section *section; struct udev_device *drm_device; struct wl_event_loop *loop; const char *path; uint32_t key; + const char *seat_id = default_seat; weston_log("initializing drm backend\n"); @@ -3037,18 +2961,18 @@ drm_backend_create(struct weston_compositor *compositor, b->sprites_are_broken = 1; b->cursors_are_broken = 1; b->compositor = compositor; + b->use_pixman = config->use_pixman; + b->configure_output = config->configure_output; + b->option_current_mode = config->default_current_mode; - section = weston_config_get_section(config, "core", NULL, NULL); - if (get_gbm_format_from_section(section, - GBM_FORMAT_XRGB8888, - &b->format) == -1) - goto err_base; - - b->use_pixman = param->use_pixman; + if (parse_gbm_format(config->format, GBM_FORMAT_XRGB8888, &b->format) < 0) + goto err_compositor; + if (config->seat_id) + seat_id = config->seat_id; /* Check if we run drm-backend using weston-launch */ - compositor->launcher = weston_launcher_connect(compositor, param->tty, - param->seat_id, true); + compositor->launcher = weston_launcher_connect(compositor, config->tty, + seat_id, true); if (compositor->launcher == NULL) { weston_log("fatal: drm backend should be run " "using weston-launch binary or as root\n"); @@ -3064,7 +2988,7 @@ drm_backend_create(struct weston_compositor *compositor, b->session_listener.notify = session_notify; wl_signal_add(&compositor->session_signal, &b->session_listener); - drm_device = find_primary_gpu(b, param->seat_id); + drm_device = find_primary_gpu(b, seat_id); if (drm_device == NULL) { weston_log("no drm device found\n"); goto err_udev; @@ -3090,6 +3014,7 @@ drm_backend_create(struct weston_compositor *compositor, b->base.destroy = drm_destroy; b->base.restore = drm_restore; + b->base.create_output = NULL; b->prev_state = WESTON_COMPOSITOR_ACTIVE; @@ -3102,12 +3027,12 @@ drm_backend_create(struct weston_compositor *compositor, create_sprites(b); if (udev_input_init(&b->input, - compositor, b->udev, param->seat_id) < 0) { + compositor, b->udev, seat_id) < 0) { weston_log("failed to create input devices\n"); goto err_sprite; } - if (create_outputs(b, param->connector, drm_device) < 0) { + if (create_outputs(b, config->connector, drm_device) < 0) { weston_log("failed to create output for %s\n", path); goto err_udev_input; } @@ -3175,32 +3100,21 @@ err_udev: udev_unref(b->udev); err_compositor: weston_compositor_shutdown(compositor); -err_base: + free(b); return NULL; } WL_EXPORT int backend_init(struct weston_compositor *compositor, int *argc, char *argv[], - struct weston_config *config, - struct weston_backend_config *config_base) + struct weston_config *wc, + struct weston_backend_config *config_base) { struct drm_backend *b; - struct drm_parameters param = { 0, }; - - const struct weston_option drm_options[] = { - { WESTON_OPTION_INTEGER, "connector", 0, ¶m.connector }, - { WESTON_OPTION_STRING, "seat", 0, ¶m.seat_id }, - { WESTON_OPTION_INTEGER, "tty", 0, ¶m.tty }, - { WESTON_OPTION_BOOLEAN, "current-mode", 0, &option_current_mode }, - { WESTON_OPTION_BOOLEAN, "use-pixman", 0, ¶m.use_pixman }, - }; - - param.seat_id = default_seat; - - parse_options(drm_options, ARRAY_LENGTH(drm_options), argc, argv); + struct weston_drm_backend_config *config = + (struct weston_drm_backend_config *)config_base; - b = drm_backend_create(compositor, ¶m, argc, argv, config); + b = drm_backend_create(compositor, config); if (b == NULL) return -1; return 0; diff --git a/src/compositor-drm.h b/src/compositor-drm.h new file mode 100644 index 0000000..b058ef3 --- /dev/null +++ b/src/compositor-drm.h @@ -0,0 +1,89 @@ +/* + * Copyright © 2008-2011 Kristian Høgsberg + * Copyright © 2011 Intel Corporation + * Copyright © 2015 Giulio Camuffo + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef WESTON_COMPOSITOR_DRM_H +#define WESTON_COMPOSITOR_DRM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "compositor.h" + +struct weston_drm_backend_modeline; + +enum weston_drm_backend_output_type { + WESTON_DRM_BACKEND_OUTPUT_TYPE_INVALID = 0, + WESTON_DRM_BACKEND_OUTPUT_TYPE_OFF, + WESTON_DRM_BACKEND_OUTPUT_TYPE_PREFERRED, + WESTON_DRM_BACKEND_OUTPUT_TYPE_CURRENT, + WESTON_DRM_BACKEND_OUTPUT_TYPE_MODE, + WESTON_DRM_BACKEND_OUTPUT_TYPE_MODELINE +}; + +enum weston_drm_backend_modeline_flags { + WESTON_DRM_BACKEND_MODELINE_FLAG_PHSYNC = (1 << 0), + WESTON_DRM_BACKEND_MODELINE_FLAG_NHSYNC = (1 << 1), + WESTON_DRM_BACKEND_MODELINE_FLAG_PVSYNC = (1 << 2), + WESTON_DRM_BACKEND_MODELINE_FLAG_NVSYNC = (1 << 3), +}; + +struct weston_drm_backend_modeline { + uint32_t flags; + uint32_t clock; + uint16_t hdisplay, hsync_start, hsync_end, htotal; + uint16_t vdisplay, vsync_start, vsync_end, vtotal; +}; + +struct weston_drm_backend_output_config { + struct weston_backend_output_config base; + + char *format; + char *seat; + enum weston_drm_backend_output_type type; + struct weston_drm_backend_modeline modeline; +}; + +struct weston_drm_backend_config { + struct weston_backend_config base; + + int connector; + int tty; + bool use_pixman; + const char *seat_id; + const char *format; + bool default_current_mode; + void (*configure_output)(struct weston_compositor *compositor, + const char *name, + struct weston_drm_backend_output_config *config); +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/main.c b/src/main.c index 19124a9..d861c60 100644 --- a/src/main.c +++ b/src/main.c @@ -47,6 +47,8 @@ #include "git-version.h" #include "version.h" +#include "compositor-drm.h" + static struct wl_list child_process_list; static struct weston_compositor *segv_compositor; @@ -664,12 +666,135 @@ init_backend_new(struct weston_compositor *compositor, const char *backend, } static int +parse_modeline(const char *s, struct weston_drm_backend_modeline *mode) +{ + char hsync[16]; + char vsync[16]; + float fclock; + + mode->flags = 0; + + 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 -1; + + mode->clock = fclock * 1000; + if (strcmp(hsync, "+hsync") == 0) + mode->flags |= WESTON_DRM_BACKEND_MODELINE_FLAG_PHSYNC; + else if (strcmp(hsync, "-hsync") == 0) + mode->flags |= WESTON_DRM_BACKEND_MODELINE_FLAG_NHSYNC; + else + return -1; + + if (strcmp(vsync, "+vsync") == 0) + mode->flags |= WESTON_DRM_BACKEND_MODELINE_FLAG_PVSYNC; + else if (strcmp(vsync, "-vsync") == 0) + mode->flags |= WESTON_DRM_BACKEND_MODELINE_FLAG_NVSYNC; + else + return -1; + + return 0; +} + +static void +drm_configure_output(struct weston_compositor *c, const char *name, + struct weston_drm_backend_output_config *config) +{ + struct weston_config *wc = weston_compositor_get_user_data(c); + struct weston_config_section *section; + char *s; + + section = weston_config_get_section(wc, "output", "name", name); + weston_config_section_get_string(section, "mode", &s, "preferred"); + if (strcmp(s, "off") == 0) + config->type = WESTON_DRM_BACKEND_OUTPUT_TYPE_OFF; + else if (strcmp(s, "preferred") == 0) + config->type = WESTON_DRM_BACKEND_OUTPUT_TYPE_PREFERRED; + else if (strcmp(s, "current") == 0) + config->type = WESTON_DRM_BACKEND_OUTPUT_TYPE_CURRENT; + else if (sscanf(s, "%dx%d", &config->base.width, + &config->base.height) == 2) + config->type = WESTON_DRM_BACKEND_OUTPUT_TYPE_MODE; + else if (parse_modeline(s, &config->modeline) == 0) + config->type = WESTON_DRM_BACKEND_OUTPUT_TYPE_MODELINE; + else { + weston_log("Invalid mode \"%s\" for output %s\n", + s, name); + config->type = WESTON_DRM_BACKEND_OUTPUT_TYPE_PREFERRED; + } + free(s); + + weston_config_section_get_int(section, "scale", &config->base.scale, 1); + weston_config_section_get_string(section, "transform", &s, "normal"); + if (weston_parse_transform(s, &config->base.transform) < 0) + weston_log("Invalid transform \"%s\" for output %s\n", + s, name); + free(s); + + weston_config_section_get_string(section, + "gbm-format", &config->format, NULL); + weston_config_section_get_string(section, "seat", &config->seat, ""); +} + +static int +init_drm_backend(struct weston_compositor *c, const char *backend, + int *argc, char **argv, struct weston_config *wc) +{ + struct weston_drm_backend_config config = { + .use_pixman = false, + .connector = 0, + .seat_id = NULL, + .format = NULL, + .tty = 0, + .default_current_mode = false, + .configure_output = drm_configure_output, + }; + struct weston_config_section *section; + char *format = NULL, *seat = NULL; + int ret = 0; + + const struct weston_option options[] = { + { WESTON_OPTION_INTEGER, "connector", 0, &config.connector }, + { WESTON_OPTION_STRING, "seat", 0, &seat }, + { WESTON_OPTION_INTEGER, "tty", 0, &config.tty }, + { WESTON_OPTION_BOOLEAN, "current-mode", 0, + &config.default_current_mode }, + { WESTON_OPTION_BOOLEAN, "use-pixman", 0, &config.use_pixman }, + }; + + parse_options(options, ARRAY_LENGTH(options), argc, argv); + + section = weston_config_get_section(wc, "core", NULL, NULL); + weston_config_section_get_string(section, + "gbm-format", &format, + format); + config.format = format; + config.seat_id = seat; + + if (init_backend_new(c, backend, &config.base) < 0) + ret = -1; + + free(seat); + free(format); + return ret; +} + +static int init_backend(struct weston_compositor *compositor, const char *backend, int *argc, char **argv, struct weston_config *config) { -#if 0 + if (strstr(backend, "drm-backend.so")) return init_drm_backend(compositor, backend, argc, argv, config); +#if 0 else if (strstr(backend, "wayland-backend.so")) return init_wayland_backend(compositor, backend, argc, argv, config); else if (strstr(backend, "x11-backend.so")) -- 2.4.6 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel