diff --git a/compositor/main.c b/compositor/main.c index 0cc11a5e..38df77f6 100644 --- a/compositor/main.c +++ b/compositor/main.c @@ -1087,48 +1087,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) @@ -1153,6 +1111,65 @@ 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"); + free(modeline); + 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) @@ -1178,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 8319d7cf..491f171f 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) + if (connector_get_current_mode(output->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); - 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: + drmModeFreeCrtc(output->original_crtc); + output->original_crtc = NULL; + + 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; + + 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,33 +2418,157 @@ 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); - b->crtc_allocator &= ~(1 << output->crtc_id); - b->connector_allocator &= ~(1 << output->connector_id); - free(output); - free(config.modeline); + drmModeFreeProperty(output->dpms_prop); 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); + } + + 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); +} + +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); + + b->crtc_allocator &= ~(1 << output->crtc_id); + b->connector_allocator &= ~(1 << output->connector_id); + + 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); + + if (output->page_flip_pending) { + output->disable_pending = 1; + 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 a Weston output structure + * + * Given a DRM connector, create a matching drm_output structure and add it + * to Weston's output list. It also takes ownership of the connector, which + * is released when output is destroyed. + * + * @param b Weston backend 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; + + b->crtc_allocator |= (1 << output->crtc_id); + b->connector_allocator |= (1 << output->connector_id); + + weston_output_init_pending(&output->base, b->compositor); + weston_compositor_add_pending_output(&output->base, b->compositor); + + return 0; +} + static void create_sprites(struct drm_backend *b) { @@ -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,17 @@ 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; + } else { + drmModeFreeConnector(connector); } - - 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 +2700,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 +2725,13 @@ 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); + } else { + drmModeFreeConnector(connector); } - drmModeFreeConnector(connector); } drmModeFreeResources(resources); @@ -2695,6 +2746,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 +3139,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 +3154,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 +3175,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 +3297,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 1266031f..8f89a2b3 100644 --- a/libweston/compositor-drm.h +++ b/libweston/compositor-drm.h @@ -29,12 +29,13 @@ #define WESTON_COMPOSITOR_DRM_H #include "compositor.h" +#include "plugin-registry.h" #ifdef __cplusplus extern "C" { #endif -#define WESTON_DRM_BACKEND_CONFIG_VERSION 1 +#define WESTON_DRM_BACKEND_CONFIG_VERSION 2 struct libinput_device; @@ -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