[PATCH weston 04/12 v2] weston: Port DRM backend to new output handling API
Quentin Glidic
sardemff7+wayland at sardemff7.net
Tue Aug 16 10:38:21 UTC 2016
On 14/08/2016 17:28, Armin Krezović wrote:
> This is a complete port of the DRM backend that uses
> recently added output handling API for output
> configuration.
>
> Output can be configured at runtime by passing the
> necessary configuration parameters, which can be
> filled in manually or obtained from the configuration
> file using previously added functionality. It is
> required that the scale and transform values are set
> using the previously added functionality.
>
> After everything has been set, output needs to be
> enabled manually using weston_output_enable().
>
> v2:
>
> - Added missing drmModeFreeCrtc() to drm_output_enable()
> cleanup list in case of failure.
> - Split drm_backend_disable() into drm_backend_deinit()
> to accomodate for changes in the first patch in the
> series. Moved restoring original crtc to
> drm_output_destroy().
>
> Signed-off-by: Armin Krezović <krezovic.armin at gmail.com>
> ---
> compositor/main.c | 103 ++++++-----
> libweston/compositor-drm.c | 439 ++++++++++++++++++++++++++-------------------
> libweston/compositor-drm.h | 48 +++--
> 3 files changed, 344 insertions(+), 246 deletions(-)
>
> diff --git a/compositor/main.c b/compositor/main.c
> index 905d71f..b0d21ea 100644
> --- a/compositor/main.c
> +++ b/compositor/main.c
> @@ -1088,48 +1088,6 @@ wet_configure_windowed_output_from_config(struct weston_output *output,
> return 0;
> }
>
> -static enum weston_drm_backend_output_mode
> -drm_configure_output(struct weston_compositor *c,
> - bool use_current_mode,
> - const char *name,
> - struct weston_drm_backend_output_config *config)
> -{
> - struct weston_config *wc = wet_get_config(c);
> - struct weston_config_section *section;
> - char *s;
> - int scale;
> - enum weston_drm_backend_output_mode mode =
> - WESTON_DRM_BACKEND_OUTPUT_PREFERRED;
> -
> - section = weston_config_get_section(wc, "output", "name", name);
> - weston_config_section_get_string(section, "mode", &s, "preferred");
> - if (strcmp(s, "off") == 0) {
> - free(s);
> - return WESTON_DRM_BACKEND_OUTPUT_OFF;
> - }
> -
> - if (use_current_mode || strcmp(s, "current") == 0) {
> - mode = WESTON_DRM_BACKEND_OUTPUT_CURRENT;
> - } else if (strcmp(s, "preferred") != 0) {
> - config->modeline = s;
> - s = NULL;
> - }
> - free(s);
> -
> - weston_config_section_get_int(section, "scale", &scale, 1);
> - config->base.scale = scale >= 1 ? 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->gbm_format, NULL);
> - weston_config_section_get_string(section, "seat", &config->seat, "");
> - return mode;
> -}
> -
> static void
> configure_input_device(struct weston_compositor *compositor,
> struct libinput_device *device)
> @@ -1154,6 +1112,64 @@ configure_input_device(struct weston_compositor *compositor,
> }
> }
>
> +static void
> +drm_backend_output_configure(struct wl_listener *listener, void *data)
> +{
> + struct weston_output *output = data;
> + struct weston_config *wc = wet_get_config(output->compositor);
> + struct weston_config_section *section;
> + const struct weston_drm_output_api *api = weston_drm_output_get_api(output->compositor);
> + enum weston_drm_backend_output_mode mode =
> + WESTON_DRM_BACKEND_OUTPUT_PREFERRED;
> +
> + char *s;
> + char *modeline = NULL;
> + char *gbm_format = NULL;
> + char *seat = NULL;
> +
> + if (!api) {
> + weston_log("Cannot use weston_drm_output_api.\n");
> + return;
> + }
> +
> + section = weston_config_get_section(wc, "output", "name", output->name);
> + weston_config_section_get_string(section, "mode", &s, "preferred");
> +
> + if (strcmp(s, "off") == 0) {
> + weston_output_disable(output);
> + free(s);
> + return;
> + } else if (strcmp(s, "current") == 0) {
> + mode = WESTON_DRM_BACKEND_OUTPUT_CURRENT;
> + } else if (strcmp(s, "preferred") != 0) {
> + modeline = s;
> + s = NULL;
> + }
> + free(s);
> +
> + if (api->set_mode(output, mode, modeline) < 0) {
> + weston_log("Cannot configure an output using weston_drm_output_api.\n");
Needs a free(modeline); here.
I’ll pass on the deep review of this one this time. :-)
Cheers,
> + return;
> + }
> + free(modeline);
> +
> + wet_output_set_scale(output, section, 1, 0);
> + wet_output_set_transform(output, section, WL_OUTPUT_TRANSFORM_NORMAL, UINT32_MAX);
> +
> + weston_config_section_get_string(section,
> + "gbm-format", &gbm_format, NULL);
> +
> + api->set_gbm_format(output, gbm_format);
> + free(gbm_format);
> +
> + weston_config_section_get_string(section, "seat", &seat, "");
> +
> + api->set_seat(output, seat);
> + free(seat);
> +
> + weston_output_enable(output);
> +}
> +
> static int
> load_drm_backend(struct weston_compositor *c,
> int *argc, char **argv, struct weston_config *wc)
> @@ -1179,12 +1195,13 @@ load_drm_backend(struct weston_compositor *c,
>
> config.base.struct_version = WESTON_DRM_BACKEND_CONFIG_VERSION;
> config.base.struct_size = sizeof(struct weston_drm_backend_config);
> - config.configure_output = drm_configure_output;
> config.configure_device = configure_input_device;
>
> ret = weston_compositor_load_backend(c, WESTON_BACKEND_DRM,
> &config.base);
>
> + wet_set_pending_output_handler(c, drm_backend_output_configure);
> +
> free(config.gbm_format);
> free(config.seat_id);
>
> diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c
> index 5c9bfd9..adba13c 100644
> --- a/libweston/compositor-drm.c
> +++ b/libweston/compositor-drm.c
> @@ -122,16 +122,6 @@ struct drm_backend {
> int32_t cursor_width;
> int32_t cursor_height;
>
> - /** Callback used to configure the outputs.
> - *
> - * This function will be called by the backend when a new DRM
> - * output needs to be configured.
> - */
> - enum weston_drm_backend_output_mode
> - (*configure_output)(struct weston_compositor *compositor,
> - bool use_current_mode,
> - const char *name,
> - struct weston_drm_backend_output_config *output_config);
> bool use_current_mode;
> };
>
> @@ -161,7 +151,8 @@ struct drm_edid {
> };
>
> struct drm_output {
> - struct weston_output base;
> + struct weston_output base;
> + drmModeConnector *connector;
>
> uint32_t crtc_id;
> int pipe;
> @@ -176,6 +167,7 @@ struct drm_output {
> int vblank_pending;
> int page_flip_pending;
> int destroy_pending;
> + int disable_pending;
>
> struct gbm_surface *gbm_surface;
> struct gbm_bo *gbm_cursor_bo[2];
> @@ -681,7 +673,7 @@ drm_output_repaint(struct weston_output *output_base,
> struct drm_mode *mode;
> int ret = 0;
>
> - if (output->destroy_pending)
> + if (output->disable_pending || output->destroy_pending)
> return -1;
>
> if (!output->next)
> @@ -787,7 +779,7 @@ drm_output_start_repaint_loop(struct weston_output *output_base)
> .request.signal = 0,
> };
>
> - if (output->destroy_pending)
> + if (output->disable_pending || output->destroy_pending)
> return;
>
> if (!output->current) {
> @@ -877,7 +869,7 @@ vblank_handler(int fd, unsigned int frame, unsigned int sec, unsigned int usec,
> }
>
> static void
> -drm_output_destroy(struct weston_output *output_base);
> +drm_output_destroy(struct weston_output *base);
>
> static void
> page_flip_handler(int fd, unsigned int frame,
> @@ -904,6 +896,8 @@ page_flip_handler(int fd, unsigned int frame,
>
> if (output->destroy_pending)
> drm_output_destroy(&output->base);
> + else if (output->disable_pending)
> + weston_output_disable(&output->base);
> else if (!output->vblank_pending) {
> ts.tv_sec = sec;
> ts.tv_nsec = usec * 1000;
> @@ -1344,51 +1338,6 @@ drm_assign_planes(struct weston_output *output_base)
> static void
> drm_output_fini_pixman(struct drm_output *output);
>
> -static void
> -drm_output_destroy(struct weston_output *output_base)
> -{
> - struct drm_output *output = to_drm_output(output_base);
> - struct drm_backend *b = to_drm_backend(output->base.compositor);
> - drmModeCrtcPtr origcrtc = output->original_crtc;
> -
> - if (output->page_flip_pending) {
> - output->destroy_pending = 1;
> - weston_log("destroy output while page flip pending\n");
> - return;
> - }
> -
> - if (output->backlight)
> - backlight_destroy(output->backlight);
> -
> - drmModeFreeProperty(output->dpms_prop);
> -
> - /* Turn off hardware cursor */
> - drmModeSetCursor(b->drm.fd, output->crtc_id, 0, 0, 0);
> -
> - /* Restore original CRTC state */
> - drmModeSetCrtc(b->drm.fd, origcrtc->crtc_id, origcrtc->buffer_id,
> - origcrtc->x, origcrtc->y,
> - &output->connector_id, 1, &origcrtc->mode);
> - drmModeFreeCrtc(origcrtc);
> -
> - b->crtc_allocator &= ~(1 << output->crtc_id);
> - b->connector_allocator &= ~(1 << output->connector_id);
> -
> - if (b->use_pixman) {
> - drm_output_fini_pixman(output);
> - } else {
> - gl_renderer->output_destroy(output_base);
> - gbm_surface_destroy(output->gbm_surface);
> - }
> -
> - weston_plane_release(&output->fb_plane);
> - weston_plane_release(&output->cursor_plane);
> -
> - weston_output_destroy(&output->base);
> -
> - free(output);
> -}
> -
> /**
> * Find the closest-matching mode for a given target
> *
> @@ -2239,7 +2188,7 @@ static struct drm_mode *
> drm_output_choose_initial_mode(struct drm_backend *backend,
> struct drm_output *output,
> enum weston_drm_backend_output_mode mode,
> - struct weston_drm_backend_output_config *config,
> + const char *modeline,
> const drmModeModeInfo *current_mode)
> {
> struct drm_mode *preferred = NULL;
> @@ -2247,21 +2196,21 @@ drm_output_choose_initial_mode(struct drm_backend *backend,
> struct drm_mode *configured = NULL;
> struct drm_mode *best = NULL;
> struct drm_mode *drm_mode;
> - drmModeModeInfo modeline;
> + drmModeModeInfo drm_modeline;
> int32_t width = 0;
> int32_t height = 0;
>
> - if (mode == WESTON_DRM_BACKEND_OUTPUT_PREFERRED && config->modeline) {
> - if (sscanf(config->modeline, "%dx%d", &width, &height) != 2) {
> + if (mode == WESTON_DRM_BACKEND_OUTPUT_PREFERRED && modeline) {
> + if (sscanf(modeline, "%dx%d", &width, &height) != 2) {
> width = -1;
>
> - if (parse_modeline(config->modeline, &modeline) == 0) {
> - configured = drm_output_add_mode(output, &modeline);
> + if (parse_modeline(modeline, &drm_modeline) == 0) {
> + configured = drm_output_add_mode(output, &drm_modeline);
> if (!configured)
> return NULL;
> } else {
> weston_log("Invalid modeline \"%s\" for output %s\n",
> - config->modeline, output->base.name);
> + modeline, output->base.name);
> }
> }
> }
> @@ -2330,109 +2279,104 @@ connector_get_current_mode(drmModeConnector *connector, int drm_fd,
> return 0;
> }
>
> -/**
> - * Create and configure a Weston output structure
> - *
> - * Given a DRM connector, create a matching drm_output structure and add it
> - * to Weston's output list.
> - *
> - * @param b Weston backend structure structure
> - * @param resources DRM resources for this device
> - * @param connector DRM connector to use for this new output
> - * @param x Horizontal offset to use into global co-ordinate space
> - * @param y Vertical offset to use into global co-ordinate space
> - * @param drm_device udev device pointer
> - * @returns 0 on success, or -1 on failure
> - */
> static int
> -create_output_for_connector(struct drm_backend *b,
> - drmModeRes *resources,
> - drmModeConnector *connector,
> - int x, int y, struct udev_device *drm_device)
> +drm_output_set_mode(struct weston_output *base,
> + enum weston_drm_backend_output_mode mode,
> + const char *modeline)
> {
> - struct drm_output *output;
> - struct drm_mode *drm_mode, *next, *current;
> - struct weston_mode *m;
> + struct drm_output *output = to_drm_output(base);
> + struct drm_backend *b = to_drm_backend(base->compositor);
>
> + struct drm_mode *drm_mode, *next, *current;
> drmModeModeInfo crtc_mode;
> int i;
> - enum weston_drm_backend_output_mode mode;
> - struct weston_drm_backend_output_config config = {{ 0 }};
> -
> - i = find_crtc_for_connector(b, resources, connector);
> - if (i < 0) {
> - weston_log("No usable crtc/encoder pair for connector.\n");
> - return -1;
> - }
>
> - output = zalloc(sizeof *output);
> - if (output == NULL)
> - return -1;
> -
> - output->base.subpixel = drm_subpixel_to_wayland(connector->subpixel);
> - output->base.name = make_connector_name(connector);
> output->base.make = "unknown";
> output->base.model = "unknown";
> output->base.serial_number = "unknown";
> wl_list_init(&output->base.mode_list);
>
> - mode = b->configure_output(b->compositor, b->use_current_mode,
> - output->base.name, &config);
> - if (parse_gbm_format(config.gbm_format, b->gbm_format, &output->gbm_format) == -1)
> - output->gbm_format = b->gbm_format;
> -
> - setup_output_seat_constraint(b, &output->base,
> - config.seat ? config.seat : "");
> - free(config.seat);
> -
> - output->crtc_id = resources->crtcs[i];
> - output->pipe = i;
> - b->crtc_allocator |= (1 << output->crtc_id);
> - output->connector_id = connector->connector_id;
> - b->connector_allocator |= (1 << output->connector_id);
> -
> - output->original_crtc = drmModeGetCrtc(b->drm.fd, output->crtc_id);
> - output->dpms_prop = drm_get_prop(b->drm.fd, connector, "DPMS");
> -
> - if (connector_get_current_mode(connector, b->drm.fd, &crtc_mode) < 0)
> - goto err_free;
> -
> - for (i = 0; i < connector->count_modes; i++) {
> - drm_mode = drm_output_add_mode(output, &connector->modes[i]);
> + for (i = 0; i < output->connector->count_modes; i++) {
> + drm_mode = drm_output_add_mode(output, &output->connector->modes[i]);
> if (!drm_mode)
> goto err_free;
> }
>
> - if (mode == WESTON_DRM_BACKEND_OUTPUT_OFF) {
> - weston_log("Disabling output %s\n", output->base.name);
> - drmModeSetCrtc(b->drm.fd, output->crtc_id,
> - 0, 0, 0, 0, 0, NULL);
> + if (connector_get_current_mode(output->connector, b->drm.fd, &crtc_mode) < 0)
> goto err_free;
> - }
>
> - current = drm_output_choose_initial_mode(b, output, mode, &config,
> - &crtc_mode);
> + current = drm_output_choose_initial_mode(b, output, mode, modeline, &crtc_mode);
> if (!current)
> goto err_free;
> +
> output->base.current_mode = ¤t->base;
> output->base.current_mode->flags |= WL_OUTPUT_MODE_CURRENT;
>
> - weston_output_init(&output->base, b->compositor, x, y,
> - connector->mmWidth, connector->mmHeight,
> - config.base.transform, config.base.scale);
> + /* Set native_ fields, so weston_output_mode_switch_to_native() works */
> + output->base.native_mode = output->base.current_mode;
> + output->base.native_scale = output->base.current_scale;
> +
> + output->base.mm_width = output->connector->mmWidth;
> + output->base.mm_height = output->connector->mmHeight;
> +
> + return 0;
> +
> +err_free:
> + wl_list_for_each_safe(drm_mode, next, &output->base.mode_list,
> + base.link) {
> + wl_list_remove(&drm_mode->base.link);
> + free(drm_mode);
> + }
> +
> + return -1;
> +}
> +
> +static void
> +drm_output_set_gbm_format(struct weston_output *base,
> + const char *gbm_format)
> +{
> + struct drm_output *output = to_drm_output(base);
> + struct drm_backend *b = to_drm_backend(base->compositor);
> +
> + if (parse_gbm_format(gbm_format, b->gbm_format, &output->gbm_format) == -1)
> + output->gbm_format = b->gbm_format;
> +}
> +
> +static void
> +drm_output_set_seat(struct weston_output *base,
> + const char *seat)
> +{
> + struct drm_output *output = to_drm_output(base);
> + struct drm_backend *b = to_drm_backend(base->compositor);
> +
> + setup_output_seat_constraint(b, &output->base,
> + seat ? seat : "");
> +}
> +
> +static int
> +drm_output_enable(struct weston_output *base)
> +{
> + struct drm_output *output = to_drm_output(base);
> + struct drm_backend *b = to_drm_backend(base->compositor);
> +
> + struct weston_mode *m;
> +
> + b->crtc_allocator |= (1 << output->crtc_id);
> + b->connector_allocator |= (1 << output->connector_id);
> +
> + output->original_crtc = drmModeGetCrtc(b->drm.fd, output->crtc_id);
> + output->dpms_prop = drm_get_prop(b->drm.fd, output->connector, "DPMS");
>
> if (b->use_pixman) {
> if (drm_output_init_pixman(output, b) < 0) {
> weston_log("Failed to init output pixman state\n");
> - goto err_output;
> + goto err_free;
> }
> } else if (drm_output_init_egl(output, b) < 0) {
> weston_log("Failed to init output gl state\n");
> - goto err_output;
> + goto err_free;
> }
>
> - output->backlight = backlight_init(drm_device,
> - connector->connector_type);
> if (output->backlight) {
> weston_log("Initialized backlight, device %s\n",
> output->backlight->path);
> @@ -2442,15 +2386,8 @@ create_output_for_connector(struct drm_backend *b,
> weston_log("Failed to initialize backlight\n");
> }
>
> - weston_compositor_add_output(b->compositor, &output->base);
> -
> - find_and_parse_output_edid(b, output, connector);
> - if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
> - output->base.connection_internal = 1;
> -
> output->base.start_repaint_loop = drm_output_start_repaint_loop;
> output->base.repaint = drm_output_repaint;
> - output->base.destroy = drm_output_destroy;
> output->base.assign_planes = drm_assign_planes;
> output->base.set_dpms = drm_set_dpms;
> output->base.switch_mode = drm_output_switch_mode;
> @@ -2458,6 +2395,12 @@ create_output_for_connector(struct drm_backend *b,
> output->base.gamma_size = output->original_crtc->gamma_size;
> output->base.set_gamma = drm_output_set_gamma;
>
> + output->base.subpixel = drm_subpixel_to_wayland(output->connector->subpixel);
> +
> + find_and_parse_output_edid(b, output, output->connector);
> + if (output->connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
> + output->base.connection_internal = 1;
> +
> weston_plane_init(&output->cursor_plane, b->compositor,
> INT32_MIN, INT32_MIN);
> weston_plane_init(&output->fb_plane, b->compositor, 0, 0);
> @@ -2475,31 +2418,155 @@ create_output_for_connector(struct drm_backend *b,
> ", preferred" : "",
> m->flags & WL_OUTPUT_MODE_CURRENT ?
> ", current" : "",
> - connector->count_modes == 0 ?
> + output->connector->count_modes == 0 ?
> ", built-in" : "");
>
> - /* Set native_ fields, so weston_output_mode_switch_to_native() works */
> - output->base.native_mode = output->base.current_mode;
> - output->base.native_scale = output->base.current_scale;
> -
> return 0;
>
> -err_output:
> - weston_output_destroy(&output->base);
> err_free:
> - wl_list_for_each_safe(drm_mode, next, &output->base.mode_list,
> - base.link) {
> - wl_list_remove(&drm_mode->base.link);
> - free(drm_mode);
> + drmModeFreeProperty(output->dpms_prop);
> + drmModeFreeCrtc(output->original_crtc);
> +
> + b->connector_allocator &= ~(1 << output->connector_id);
> + b->crtc_allocator &= ~(1 << output->crtc_id);
> +
> + return -1;
> +}
> +
> +static void
> +drm_output_deinit(struct weston_output *base)
> +{
> + struct drm_output *output = to_drm_output(base);
> + struct drm_backend *b = to_drm_backend(base->compositor);
> +
> + if (b->use_pixman) {
> + drm_output_fini_pixman(output);
> + } else {
> + gl_renderer->output_destroy(&output->base);
> + gbm_surface_destroy(output->gbm_surface);
> }
>
> - drmModeFreeCrtc(output->original_crtc);
> + weston_plane_release(&output->fb_plane);
> + weston_plane_release(&output->cursor_plane);
> +
> + drmModeFreeProperty(output->dpms_prop);
> +
> + /* Turn off hardware cursor */
> + drmModeSetCursor(b->drm.fd, output->crtc_id, 0, 0, 0);
> +
> b->crtc_allocator &= ~(1 << output->crtc_id);
> b->connector_allocator &= ~(1 << output->connector_id);
> +}
> +
> +static void
> +drm_output_destroy(struct weston_output *base)
> +{
> + struct drm_output *output = to_drm_output(base);
> + struct drm_backend *b = to_drm_backend(base->compositor);
> + drmModeCrtcPtr origcrtc = output->original_crtc;
> +
> + if (output->page_flip_pending) {
> + output->destroy_pending = 1;
> + weston_log("destroy output while page flip pending\n");
> + return;
> + }
> +
> + if (output->base.enabled)
> + drm_output_deinit(&output->base);
> +
> + if (origcrtc) {
> + /* Restore original CRTC state */
> + drmModeSetCrtc(b->drm.fd, origcrtc->crtc_id, origcrtc->buffer_id,
> + origcrtc->x, origcrtc->y,
> + &output->connector_id, 1, &origcrtc->mode);
> + drmModeFreeCrtc(origcrtc);
> + }
> +
> + weston_output_destroy(&output->base);
> +
> + drmModeFreeConnector(output->connector);
> +
> + if (output->backlight)
> + backlight_destroy(output->backlight);
> +
> free(output);
> - free(config.modeline);
> +}
>
> - return -1;
> +static int
> +drm_output_disable(struct weston_output *base)
> +{
> + struct drm_output *output = to_drm_output(base);
> + struct drm_backend *b = to_drm_backend(base->compositor);
> +
> + if (output->page_flip_pending) {
> + output->disable_pending = 1;
> + weston_log("disable output while page flip pending\n");
> + return -1;
> + }
> +
> + if (output->base.enabled)
> + drm_output_deinit(&output->base);
> +
> + output->disable_pending = 0;
> +
> + weston_log("Disabling output %s\n", output->base.name);
> + drmModeSetCrtc(b->drm.fd, output->crtc_id,
> + 0, 0, 0, 0, 0, NULL);
> +
> + return 0;
> +}
> +
> +/**
> + * Create and configure a Weston output structure
> + *
> + * Given a DRM connector, create a matching drm_output structure and add it
> + * to Weston's output list.
> + *
> + * @param b Weston backend structure structure
> + * @param resources DRM resources for this device
> + * @param connector DRM connector to use for this new output
> + * @param drm_device udev device pointer
> + * @returns 0 on success, or -1 on failure
> + */
> +static int
> +create_output_for_connector(struct drm_backend *b,
> + drmModeRes *resources,
> + drmModeConnector *connector,
> + struct udev_device *drm_device)
> +{
> + struct drm_output *output;
> + int i;
> +
> + i = find_crtc_for_connector(b, resources, connector);
> + if (i < 0) {
> + weston_log("No usable crtc/encoder pair for connector.\n");
> + return -1;
> + }
> +
> + output = zalloc(sizeof *output);
> + if (output == NULL)
> + return -1;
> +
> + output->connector = connector;
> + output->crtc_id = resources->crtcs[i];
> + output->pipe = i;
> + output->connector_id = connector->connector_id;
> +
> + output->backlight = backlight_init(drm_device,
> + connector->connector_type);
> +
> + output->base.enable = drm_output_enable;
> + output->base.destroy = drm_output_destroy;
> + output->base.disable = drm_output_disable;
> + output->base.name = make_connector_name(connector);
> +
> + output->destroy_pending = 0;
> + output->disable_pending = 0;
> + output->original_crtc = NULL;
> +
> + weston_output_init_pending(&output->base, b->compositor);
> +
> + return 0;
> }
>
> static void
> @@ -2578,7 +2645,6 @@ create_outputs(struct drm_backend *b, uint32_t option_connector,
> drmModeConnector *connector;
> drmModeRes *resources;
> int i;
> - int x = 0, y = 0;
>
> resources = drmModeGetResources(b->drm.fd);
> if (!resources) {
> @@ -2610,21 +2676,15 @@ create_outputs(struct drm_backend *b, uint32_t option_connector,
> (option_connector == 0 ||
> connector->connector_id == option_connector)) {
> if (create_output_for_connector(b, resources,
> - connector, x, y,
> - drm_device) < 0) {
> + connector, drm_device) < 0) {
> drmModeFreeConnector(connector);
> continue;
> }
> -
> - x += container_of(b->compositor->output_list.prev,
> - struct weston_output,
> - link)->width;
> }
> -
> - drmModeFreeConnector(connector);
> }
>
> - if (wl_list_empty(&b->compositor->output_list))
> + if (wl_list_empty(&b->compositor->output_list) &&
> + wl_list_empty(&b->compositor->pending_output_list))
> weston_log("No currently active connector found.\n");
>
> drmModeFreeResources(resources);
> @@ -2638,7 +2698,6 @@ update_outputs(struct drm_backend *b, struct udev_device *drm_device)
> drmModeConnector *connector;
> drmModeRes *resources;
> struct drm_output *output, *next;
> - int x = 0, y = 0;
> uint32_t connected = 0, disconnects = 0;
> int i;
>
> @@ -2664,23 +2723,11 @@ update_outputs(struct drm_backend *b, struct udev_device *drm_device)
> connected |= (1 << connector_id);
>
> if (!(b->connector_allocator & (1 << connector_id))) {
> - struct weston_output *last =
> - container_of(b->compositor->output_list.prev,
> - struct weston_output, link);
> -
> - /* XXX: not yet needed, we die with 0 outputs */
> - if (!wl_list_empty(&b->compositor->output_list))
> - x = last->x + last->width;
> - else
> - x = 0;
> - y = 0;
> create_output_for_connector(b, resources,
> - connector, x, y,
> - drm_device);
> + connector, drm_device);
> weston_log("connector %d connected\n", connector_id);
>
> }
> - drmModeFreeConnector(connector);
> }
> drmModeFreeResources(resources);
>
> @@ -2695,6 +2742,16 @@ update_outputs(struct drm_backend *b, struct udev_device *drm_device)
> drm_output_destroy(&output->base);
> }
> }
> +
> + wl_list_for_each_safe(output, next, &b->compositor->pending_output_list,
> + base.link) {
> + if (disconnects & (1 << output->connector_id)) {
> + disconnects &= ~(1 << output->connector_id);
> + weston_log("connector %d disconnected\n",
> + output->connector_id);
> + drm_output_destroy(&output->base);
> + }
> + }
> }
> }
>
> @@ -3078,6 +3135,12 @@ renderer_switch_binding(struct weston_keyboard *keyboard, uint32_t time,
> switch_to_gl_renderer(b);
> }
>
> +static const struct weston_drm_output_api api = {
> + drm_output_set_mode,
> + drm_output_set_gbm_format,
> + drm_output_set_seat,
> +};
> +
> static struct drm_backend *
> drm_backend_create(struct weston_compositor *compositor,
> struct weston_drm_backend_config *config)
> @@ -3087,6 +3150,7 @@ drm_backend_create(struct weston_compositor *compositor,
> struct wl_event_loop *loop;
> const char *path;
> const char *seat_id = default_seat;
> + int ret;
>
> weston_log("initializing drm backend\n");
>
> @@ -3107,7 +3171,6 @@ drm_backend_create(struct weston_compositor *compositor,
> b->sprites_are_broken = 1;
> b->compositor = compositor;
> b->use_pixman = config->use_pixman;
> - b->configure_output = config->configure_output;
> b->use_current_mode = config->use_current_mode;
>
> if (parse_gbm_format(config->gbm_format, GBM_FORMAT_XRGB8888, &b->gbm_format) < 0)
> @@ -3230,6 +3293,14 @@ drm_backend_create(struct weston_compositor *compositor,
>
> compositor->backend = &b->base;
>
> + ret = weston_plugin_api_register(compositor, WESTON_DRM_OUTPUT_API_NAME,
> + &api, sizeof(api));
> +
> + if (ret < 0) {
> + weston_log("Failed to register output API.\n");
> + goto err_udev_monitor;
> + }
> +
> return b;
>
> err_udev_monitor:
> diff --git a/libweston/compositor-drm.h b/libweston/compositor-drm.h
> index 1266031..bc3bf17 100644
> --- a/libweston/compositor-drm.h
> +++ b/libweston/compositor-drm.h
> @@ -29,6 +29,7 @@
> #define WESTON_COMPOSITOR_DRM_H
>
> #include "compositor.h"
> +#include "plugin-registry.h"
>
> #ifdef __cplusplus
> extern "C" {
> @@ -51,8 +52,17 @@ enum weston_drm_backend_output_mode {
> WESTON_DRM_BACKEND_OUTPUT_PREFERRED,
> };
>
> -struct weston_drm_backend_output_config {
> - struct weston_backend_output_config base;
> +#define WESTON_DRM_OUTPUT_API_NAME "weston_drm_output_api_v1"
> +
> +struct weston_drm_output_api {
> + /** The mode to be used by the output. Refer to the documentation
> + * of WESTON_DRM_BACKEND_OUTPUT_PREFERRED for details.
> + *
> + * Returns 0 on success, -1 on failure.
> + */
> + int (*set_mode)(struct weston_output *output,
> + enum weston_drm_backend_output_mode mode,
> + const char *modeline);
>
> /** The pixel format to be used by the output. Valid values are:
> * - NULL - The format set at backend creation time will be used;
> @@ -60,15 +70,26 @@ struct weston_drm_backend_output_config {
> * - "rgb565"
> * - "xrgb2101010"
> */
> - char *gbm_format;
> + void (*set_gbm_format)(struct weston_output *output,
> + const char *gbm_format);
> +
> /** The seat to be used by the output. Set to NULL to use the
> - * default seat. */
> - char *seat;
> - /** The modeline to be used by the output. Refer to the documentation
> - * of WESTON_DRM_BACKEND_OUTPUT_PREFERRED for details. */
> - char *modeline;
> + * default seat.
> + */
> + void (*set_seat)(struct weston_output *output,
> + const char *seat);
> };
>
> +static inline const struct weston_drm_output_api *
> +weston_drm_output_get_api(struct weston_compositor *compositor)
> +{
> + const void *api;
> + api = weston_plugin_api_get(compositor, WESTON_DRM_OUTPUT_API_NAME,
> + sizeof(struct weston_drm_output_api));
> +
> + return (const struct weston_drm_output_api *)api;
> +}
> +
> /** The backend configuration struct.
> *
> * weston_drm_backend_config contains the configuration used by a DRM
> @@ -109,17 +130,6 @@ struct weston_drm_backend_config {
> */
> char *gbm_format;
>
> - /** Callback used to configure the outputs.
> - *
> - * This function will be called by the backend when a new DRM
> - * output needs to be configured.
> - */
> - enum weston_drm_backend_output_mode
> - (*configure_output)(struct weston_compositor *compositor,
> - bool use_current_mode,
> - const char *name,
> - struct weston_drm_backend_output_config *output_config);
> -
> /** Callback used to configure input devices.
> *
> * This function will be called by the backend when a new input device
>
--
Quentin “Sardem FF7” Glidic
More information about the wayland-devel
mailing list