[PATCH 04/10] weston: Port DRM backend to new output handling API
Armin Krezović
krezovic.armin at gmail.com
Fri Aug 12 11:48:01 UTC 2016
On 12.08.2016 13:28, Quentin Glidic wrote:
> On 11/08/2016 17:33, 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().
>>
>> Signed-off-by: Armin Krezović <krezovic.armin at gmail.com>
>> ---
>> compositor/main.c | 103 ++++++-----
>> libweston/compositor-drm.c | 429 +++++++++++++++++++++++++--------------------
>> libweston/compositor-drm.h | 42 +++--
>> 3 files changed, 327 insertions(+), 247 deletions(-)
>>
>> diff --git a/compositor/main.c b/compositor/main.c
>> index c5d8e81..8be8717 100644
>> --- a/compositor/main.c
>> +++ b/compositor/main.c
>> @@ -1105,48 +1105,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;
>
> We can remove that value from the enum I think. Or do we use it anywhere else?
>
>
>> - }
>> -
>> - 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)
>> @@ -1171,6 +1129,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");
>> + 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)
>> @@ -1196,12 +1212,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..76c1314 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,34 +2418,144 @@ 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);
>> - }
>> -
>> - drmModeFreeCrtc(output->original_crtc);
>
> Why did you remove this drmModeFreeCrtc? You moved code, but the drmModeGetCrtc is still in this same function.
>
>
Oops, good catch.
>> b->crtc_allocator &= ~(1 << output->crtc_id);
>> b->connector_allocator &= ~(1 << output->connector_id);
>> - free(output);
>> - free(config.modeline);
>> +
>> + drmModeFreeProperty(output->dpms_prop);
>
> Is that a side effect? Did drmModeFreeCrtc take care of this?
>
> With these “fixed”:
> Reviewed-by: Quentin Glidic <sardemff7+git at sardemff7.net>
>
Not really, no. output_disable still runs them both.
> Cheers,
>
>
>>
>> return -1;
>> }
>>
>> static void
>> +drm_output_destroy(struct weston_output *base)
>> +{
>> + struct drm_output *output = to_drm_output(base);
>> +
>> + if (output->page_flip_pending) {
>> + output->destroy_pending = 1;
>> + weston_log("destroy output while page flip pending\n");
>> + return;
>> + }
>> +
>> + weston_output_destroy(&output->base);
>> +
>> + drmModeFreeConnector(output->connector);
>> +
>> + if (output->backlight)
>> + backlight_destroy(output->backlight);
>> +
>> + free(output);
>> +}
>> +
>> +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);
>> + drmModeCrtcPtr origcrtc;
>> +
>> + if (output->page_flip_pending) {
>> + output->disable_pending = 1;
>> + weston_log("disable output while page flip pending\n");
>> + return -1;
>> + }
>> +
>> + if (output->base.initialized) {
>> + origcrtc = output->original_crtc;
>> +
>> + 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);
>> +
>> + 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);
>> +
>> + 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;
>> +
>> + weston_output_init_pending(&output->base, b->compositor);
>> +
>> + return 0;
>> +}
>> +
>> +static void
>> create_sprites(struct drm_backend *b)
>> {
>> struct drm_sprite *sprite;
>> @@ -2578,7 +2631,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 +2662,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 +2684,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 +2709,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 +2728,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 +3121,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 +3136,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 +3157,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 +3279,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..05eb5da 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,14 @@ 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 modeline to be used by the output. Refer to the documentation
>> + * of WESTON_DRM_BACKEND_OUTPUT_PREFERRED for details. */
>> + 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 +67,25 @@ 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;
>> + 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 +126,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
>>
>
>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 855 bytes
Desc: OpenPGP digital signature
URL: <https://lists.freedesktop.org/archives/wayland-devel/attachments/20160812/93c89bee/attachment-0001.sig>
More information about the wayland-devel
mailing list