[PATCH weston 04/11] make the backends compositor-neutral

Jon A. Cruz jonc at osg.samsung.com
Tue Jun 23 18:05:22 PDT 2015


Just a few minor low-level items in this feedback...

On 06/22/2015 01:02 PM, Giulio Camuffo wrote:
> The backends used to have lots of code dealing with weston specific configs.
> To allow them to be used by other compositors with their own configurations
> remove all the usage of weston_config from the backends code and move it
> in weston.c. The backends are now initialized with the new
> weston_compositor_init_backend() function which takes a pointer to a
> weston_backend_config struct. Each backend now installs one header where
> a subclass of weston_backend_config is defined, and the compositor creates
> an instance of the backend-specific config struct and passes it to
> weston_compositor_init_backend().
> This means that the compositor now needs to know about all the backends
> to be able to instantiate them, but no backend specific API such as xcb
> or libdrm leaks through, so there are no new dependencies for the compositor.
> 
> A backend may now set a vfunc pointer to create a new compositor. Not all do
> though, and use instead a callback function to configure a new output
> that comes from below the compositor, instead of above it.
> ---
>  Makefile.am               |  21 ++
>  src/compositor-drm.c      | 163 +++++--------
>  src/compositor-drm.h      |  77 ++++++
>  src/compositor-fbdev.c    |  66 ++---
>  src/compositor-fbdev.h    |  58 +++++
>  src/compositor-headless.c |  81 +++----
>  src/compositor-headless.h |  47 ++++
>  src/compositor-rdp.c      |  57 +----
>  src/compositor-rdp.h      |  54 +++++
>  src/compositor-rpi.c      |  50 ++--
>  src/compositor-rpi.h      |  51 ++++
>  src/compositor-wayland.c  | 222 ++++-------------
>  src/compositor-wayland.h  |  58 +++++
>  src/compositor-x11.c      | 166 ++++---------
>  src/compositor-x11.h      |  55 +++++
>  src/compositor.c          |  40 +++-
>  src/compositor.h          |  20 +-
>  src/weston.c              | 599 ++++++++++++++++++++++++++++++++++++++++++++--
>  18 files changed, 1283 insertions(+), 602 deletions(-)
>  create mode 100644 src/compositor-drm.h
>  create mode 100644 src/compositor-fbdev.h
>  create mode 100644 src/compositor-headless.h
>  create mode 100644 src/compositor-rdp.h
>  create mode 100644 src/compositor-rpi.h
>  create mode 100644 src/compositor-wayland.h
>  create mode 100644 src/compositor-x11.h
> 
> diff --git a/Makefile.am b/Makefile.am
> index fa90853..29430e3 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -72,6 +72,13 @@ weston_SOURCES =					\
>  	src/log.c					\
>  	src/compositor.c				\
>  	src/compositor.h				\
> +	src/compositor-x11.h				\
> +	src/compositor-wayland.h			\
> +	src/compositor-drm.h				\
> +	src/compositor-headless.h			\
> +	src/compositor-fbdev.h				\
> +	src/compositor-rdp.h				\
> +	src/compositor-rpi.h				\
>  	src/input.c					\
>  	src/data-device.c				\
>  	src/screenshooter.c				\
> @@ -188,6 +195,13 @@ westonincludedir = $(includedir)/weston
>  westoninclude_HEADERS =				\
>  	src/version.h				\
>  	src/compositor.h			\
> +	src/compositor-x11.h			\
> +	src/compositor-wayland.h		\
> +	src/compositor-drm.h			\
> +	src/compositor-headless.h		\
> +	src/compositor-fbdev.h			\
> +	src/compositor-rdp.h			\
> +	src/compositor-rpi.h			\
>  	src/timeline-object.h			\
>  	shared/matrix.h				\
>  	shared/config-parser.h			\
> @@ -224,6 +238,7 @@ x11_backend_la_CFLAGS =				\
>  	$(GCC_CFLAGS)
>  x11_backend_la_SOURCES = 			\
>  	src/compositor-x11.c			\
> +	src/compositor-x11.h			\
>  	shared/helpers.h
>  endif
>  
> @@ -251,6 +266,7 @@ drm_backend_la_CFLAGS =				\
>  	$(GCC_CFLAGS)
>  drm_backend_la_SOURCES =			\
>  	src/compositor-drm.c			\
> +	src/compositor-drm.h			\
>  	$(INPUT_BACKEND_SOURCES)		\
>  	shared/helpers.h			\
>  	src/libbacklight.c			\
> @@ -279,6 +295,7 @@ wayland_backend_la_CFLAGS =			\
>  	$(GCC_CFLAGS)
>  wayland_backend_la_SOURCES = 			\
>  	src/compositor-wayland.c		\
> +	src/compositor-wayland.h		\
>  	shared/helpers.h
>  nodist_wayland_backend_la_SOURCES =			\
>  	protocol/fullscreen-shell-protocol.c		\
> @@ -306,6 +323,7 @@ rpi_backend_la_CFLAGS =				\
>  	$(RPI_BCM_HOST_CFLAGS)
>  rpi_backend_la_SOURCES =			\
>  	src/compositor-rpi.c			\
> +	src/compositor-rpi.h			\
>  	src/rpi-renderer.c			\
>  	src/rpi-renderer.h			\
>  	src/rpi-bcm-stubs.h			\
> @@ -326,6 +344,7 @@ headless_backend_la_LIBADD = $(COMPOSITOR_LIBS) libshared.la
>  headless_backend_la_CFLAGS = $(COMPOSITOR_CFLAGS) $(GCC_CFLAGS)
>  headless_backend_la_SOURCES = 			\
>  	src/compositor-headless.c		\
> +	src/compositor-headless.h		\
>  	shared/helpers.h
>  endif
>  
> @@ -346,6 +365,7 @@ fbdev_backend_la_CFLAGS =			\
>  	$(GCC_CFLAGS)
>  fbdev_backend_la_SOURCES =			\
>  	src/compositor-fbdev.c			\
> +	src/compositor-fbdev.h			\
>  	shared/helpers.h			\
>  	$(INPUT_BACKEND_SOURCES)
>  endif
> @@ -362,6 +382,7 @@ rdp_backend_la_CFLAGS =				\
>  	$(GCC_CFLAGS)
>  rdp_backend_la_SOURCES = 			\
>  	src/compositor-rdp.c			\
> +	src/compositor-rdp.h			\
>  	shared/helpers.h
>  endif
>  
> diff --git a/src/compositor-drm.c b/src/compositor-drm.c
> index 4302f40..8f34521 100644
> --- a/src/compositor-drm.c
> +++ b/src/compositor-drm.c
> @@ -49,6 +49,7 @@
>  #include "shared/helpers.h"
>  #include "libbacklight.h"
>  #include "compositor.h"
> +#include "compositor-drm.h"
>  #include "gl-renderer.h"
>  #include "pixman-renderer.h"
>  #include "libinput-seat.h"
> @@ -72,15 +73,8 @@
>  #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 weston_drm_backend_modeline {
> +	drmModeModeInfo mode;
>  };
>  
>  struct drm_backend {
> @@ -105,6 +99,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
> @@ -128,6 +123,12 @@ struct drm_backend {
>  
>  	uint32_t cursor_width;
>  	uint32_t cursor_height;
> +
> +	void (*configure_output)(struct weston_compositor *compositor,
> +				 const char *name,
> +				 struct weston_drm_backend_output_config *config,
> +				 int (*parse_modeline)(const char *s,
> +				   struct weston_drm_backend_modeline *modeline));
>  };
>  
>  struct drm_mode {
> @@ -216,13 +217,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";
> @@ -1890,8 +1884,9 @@ find_and_parse_output_edid(struct drm_backend *b,
>  
>  
>  static int
> -parse_modeline(const char *s, drmModeModeInfo *mode)
> +parse_modeline(const char *s, struct weston_drm_backend_modeline *modeline)
>  {
> +	drmModeModeInfo *mode = &modeline->mode;
>  	char hsync[16];
>  	char vsync[16];
>  	float fclock;
> @@ -1952,16 +1947,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)
> @@ -1975,8 +1964,6 @@ get_gbm_format_from_section(struct weston_config_section *section,
>  		ret = -1;
>  	}
>  
> -	free(s);
> -
>  	return ret;
>  }
>  
> @@ -1989,15 +1976,14 @@ create_output_for_connector(struct drm_backend *b,
>  	struct drm_output *output;
>  	struct drm_mode *drm_mode, *next, *preferred, *current, *configured, *best;
>  	struct weston_mode *m;
> -	struct weston_config_section *section;
>  	drmModeEncoder *encoder;
> -	drmModeModeInfo crtc_mode, modeline;
> +	drmModeModeInfo crtc_mode;
>  	drmModeCrtc *crtc;
> -	int i, width, height, scale;
> -	char name[32], *s;
> +	int i;
> +	char name[32];
>  	const char *type_name;
> -	enum output_config config;
> -	uint32_t transform;
> +	struct weston_drm_backend_modeline modeline;
> +	struct weston_drm_backend_output_config config = { 0 };
>  
>  	i = find_crtc_for_connector(b, resources, connector);
>  	if (i < 0) {
> @@ -2022,42 +2008,15 @@ create_output_for_connector(struct drm_backend *b,
>  	snprintf(name, 32, "%s%d", type_name, connector->connector_type_id);
>  	output->base.name = strdup(name);
>  
> -	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)
> +	config.modeline = &modeline;
> +	b->configure_output(b->compositor, output->base.name,
> +			    &config, &parse_modeline);
> +	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;
> @@ -2088,7 +2047,7 @@ 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);
> @@ -2101,9 +2060,9 @@ create_output_for_connector(struct drm_backend *b,
>  	best = NULL;
>  
>  	wl_list_for_each_reverse(drm_mode, &output->base.mode_list, base.link) {
> -		if (config == 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(&crtc_mode, &drm_mode->mode_info, sizeof crtc_mode))
>  			current = drm_mode;
> @@ -2112,8 +2071,8 @@ create_output_for_connector(struct drm_backend *b,
>  		best = drm_mode;
>  	}
>  
> -	if (config == OUTPUT_CONFIG_MODELINE) {
> -		configured = drm_output_add_mode(output, &modeline);
> +	if (config.type == WESTON_DRM_BACKEND_OUTPUT_TYPE_MODELINE) {
> +		configured = drm_output_add_mode(output, &config.modeline->mode);
>  		if (!configured)
>  			goto err_free;
>  	}
> @@ -2124,10 +2083,10 @@ create_output_for_connector(struct drm_backend *b,
>  			goto err_free;
>  	}
>  
> -	if (config == OUTPUT_CONFIG_CURRENT)
> +	if (config.type == WESTON_DRM_BACKEND_OUTPUT_TYPE_CURRENT)
>  		configured = current;
>  
> -	if (option_current_mode && current)
> +	if (b->option_current_mode && current)
>  		output->base.current_mode = &current->base;
>  	else if (configured)
>  		output->base.current_mode = &configured->base;
> @@ -2147,7 +2106,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) {
> @@ -2807,16 +2766,14 @@ renderer_switch_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
>  
>  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");
>  
> @@ -2836,18 +2793,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");
> @@ -2863,7 +2820,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;
> @@ -2889,6 +2846,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;
>  
> @@ -2901,12 +2859,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;
>  	}
> @@ -2975,31 +2933,20 @@ 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)
> +backend_init(struct weston_compositor *compositor,
> +	     struct weston_backend_config *base)
>  {
>  	struct drm_backend *b;
> -	struct drm_parameters param = { 0, };
> -
> -	const struct weston_option drm_options[] = {
> -		{ WESTON_OPTION_INTEGER, "connector", 0, &param.connector },
> -		{ WESTON_OPTION_STRING, "seat", 0, &param.seat_id },
> -		{ WESTON_OPTION_INTEGER, "tty", 0, &param.tty },
> -		{ WESTON_OPTION_BOOLEAN, "current-mode", 0, &option_current_mode },
> -		{ WESTON_OPTION_BOOLEAN, "use-pixman", 0, &param.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 *)base;
>  
> -	b = drm_backend_create(compositor, &param, 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..5c5a3f9
> --- /dev/null
> +++ b/src/compositor-drm.h
> @@ -0,0 +1,77 @@
> +/*
> + * 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
> +};
> +
> +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,
> +				 int (*parse_modeline)(const char *s,
> +				   struct weston_drm_backend_modeline *modeline));
> +};
> +
> +#ifdef  __cplusplus
> +}
> +#endif
> +
> +#endif
> diff --git a/src/compositor-fbdev.c b/src/compositor-fbdev.c
> index 7117bc5..c0833ca 100644
> --- a/src/compositor-fbdev.c
> +++ b/src/compositor-fbdev.c
> @@ -44,6 +44,7 @@
>  
>  #include "shared/helpers.h"
>  #include "compositor.h"
> +#include "compositor-fbdev.h"
>  #include "launcher-util.h"
>  #include "pixman-renderer.h"
>  #include "libinput-seat.h"
> @@ -59,6 +60,10 @@ struct fbdev_backend {
>  	struct udev_input input;
>  	int use_pixman;
>  	struct wl_listener session_listener;
> +
> +	void (*configure_output)(struct weston_compositor *compositor,
> +				 const char *name,
> +				 struct weston_fbdev_backend_output_config *config);
>  };
>  
>  struct fbdev_screeninfo {
> @@ -95,12 +100,6 @@ struct fbdev_output {
>  	uint8_t depth;
>  };
>  
> -struct fbdev_parameters {
> -	int tty;
> -	char *device;
> -	int use_gl;
> -};
> -
>  struct gl_renderer_interface *gl_renderer;
>  
>  static const char default_seat[] = "seat0";
> @@ -486,13 +485,12 @@ fbdev_output_create(struct fbdev_backend *backend,
>                      const char *device)
>  {
>  	struct fbdev_output *output;
> -	struct weston_config_section *section;
>  	int fb_fd;
>  	int width, height;
>  	unsigned int bytes_per_pixel;
>  	struct wl_event_loop *loop;
>  	uint32_t config_transform;
> -	char *s;
> +	struct weston_fbdev_backend_output_config config = { 0 };
>  
>  	weston_log("Creating fbdev output.\n");
>  
> @@ -537,14 +535,9 @@ fbdev_output_create(struct fbdev_backend *backend,
>  	output->base.model = output->fb_info.id;
>  	output->base.name = strdup("fbdev");
>  
> -	section = weston_config_get_section(backend->compositor->config,
> -					    "output", "name",
> -					    output->base.name);
> -	weston_config_section_get_string(section, "transform", &s, "normal");
> -	if (weston_parse_transform(s, &config_transform) < 0)
> -		weston_log("Invalid transform \"%s\" for output %s\n",
> -			   s, output->base.name);
> -	free(s);
> +	backend->configure_output(backend->compositor,
> +				  output->base.name, &config);
> +	config_transform = config.base.transform;
>  
>  	weston_output_init(&output->base, backend->compositor,
>  	                   0, 0, output->fb_info.width_mm,
> @@ -811,12 +804,12 @@ switch_vt_binding(struct weston_seat *seat, uint32_t time, uint32_t key, void *d
>  }
>  
>  static struct fbdev_backend *
> -fbdev_backend_create(struct weston_compositor *compositor, int *argc, char *argv[],
> -                     struct weston_config *config,
> -                     struct fbdev_parameters *param)
> +fbdev_backend_create(struct weston_compositor *compositor,
> +                     struct weston_fbdev_backend_config *config)
>  {
>  	struct fbdev_backend *backend;
>  	const char *seat_id = default_seat;
> +	const char *device = "/dev/fb0";
>  	uint32_t key;
>  
>  	weston_log("initializing fbdev backend\n");
> @@ -841,7 +834,7 @@ fbdev_backend_create(struct weston_compositor *compositor, int *argc, char *argv
>  	wl_signal_add(&compositor->session_signal,
>  		      &backend->session_listener);
>  	compositor->launcher =
> -		weston_launcher_connect(compositor, param->tty, "seat0", false);
> +		weston_launcher_connect(compositor, config->tty, "seat0", false);
>  	if (!compositor->launcher) {
>  		weston_log("fatal: fbdev backend should be run "
>  			   "using weston-launch binary or as root\n");
> @@ -850,9 +843,11 @@ fbdev_backend_create(struct weston_compositor *compositor, int *argc, char *argv
>  
>  	backend->base.destroy = fbdev_backend_destroy;
>  	backend->base.restore = fbdev_restore;
> +	backend->base.create_output = NULL;
>  
>  	backend->prev_state = WESTON_COMPOSITOR_ACTIVE;
> -	backend->use_pixman = !param->use_gl;
> +	backend->use_pixman = !config->use_gl;
> +	backend->configure_output = config->configure_output;
>  
>  	for (key = KEY_F1; key < KEY_F9; key++)
>  		weston_compositor_add_key_binding(compositor, key,
> @@ -879,7 +874,9 @@ fbdev_backend_create(struct weston_compositor *compositor, int *argc, char *argv
>  		}
>  	}
>  
> -	if (fbdev_output_create(backend, param->device) < 0)
> +	if (config->device)
> +		device = config->device;
> +	if (fbdev_output_create(backend, device) < 0)
>  		goto out_pixman;
>  
>  	udev_input_init(&backend->input, compositor, backend->udev, seat_id);
> @@ -904,27 +901,14 @@ out_compositor:
>  }
>  
>  WL_EXPORT int
> -backend_init(struct weston_compositor *compositor, int *argc, char *argv[],
> -	     struct weston_config *config)
> +backend_init(struct weston_compositor *compositor,
> +	     struct weston_backend_config *base)
>  {
> +	struct weston_fbdev_backend_config *config =
> +				(struct weston_fbdev_backend_config *)base;
>  	struct fbdev_backend *b;
> -	/* TODO: Ideally, available frame buffers should be enumerated using
> -	 * udev, rather than passing a device node in as a parameter. */
> -	struct fbdev_parameters param = {
> -		.tty = 0, /* default to current tty */
> -		.device = "/dev/fb0", /* default frame buffer */
> -		.use_gl = 0,
> -	};
> -
> -	const struct weston_option fbdev_options[] = {
> -		{ WESTON_OPTION_INTEGER, "tty", 0, &param.tty },
> -		{ WESTON_OPTION_STRING, "device", 0, &param.device },
> -		{ WESTON_OPTION_BOOLEAN, "use-gl", 0, &param.use_gl },
> -	};
> -
> -	parse_options(fbdev_options, ARRAY_LENGTH(fbdev_options), argc, argv);
> -
> -	b = fbdev_backend_create(compositor, argc, argv, config, &param);
> +
> +	b = fbdev_backend_create(compositor, config);
>  	if (b == NULL)
>  		return -1;
>  	return 0;
> diff --git a/src/compositor-fbdev.h b/src/compositor-fbdev.h
> new file mode 100644
> index 0000000..736d56c
> --- /dev/null
> +++ b/src/compositor-fbdev.h
> @@ -0,0 +1,58 @@
> +/*
> + * Copyright © 2008-2011 Kristian Høgsberg
> + * Copyright © 2011 Intel Corporation
> + * Copyright © 2012 Raspberry Pi Foundation
> + * Copyright © 2013 Philip Withnall
> + * 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_FBDEV_H
> +#define WESTON_COMPOSITOR_FBDEV_H
> +
> +#ifdef  __cplusplus
> +extern "C" {
> +#endif
> +
> +#include "compositor.h"
> +
> +struct weston_fbdev_backend_output_config {
> +	struct weston_backend_output_config base;
> +};
> +
> +struct weston_fbdev_backend_config {
> +	struct weston_backend_config base;
> +
> +	int tty;
> +	bool use_gl;
> +	const char *device;
> +	void (*configure_output)(struct weston_compositor *compositor,
> +				 const char *name,
> +				 struct weston_fbdev_backend_output_config *config);
> +};
> +
> +#ifdef  __cplusplus
> +}
> +#endif
> +
> +#endif
> diff --git a/src/compositor-headless.c b/src/compositor-headless.c
> index b1be3a0..f768bf3 100644
> --- a/src/compositor-headless.c
> +++ b/src/compositor-headless.c
> @@ -33,6 +33,7 @@
>  
>  #include "shared/helpers.h"
>  #include "compositor.h"
> +#include "compositor-headless.h"
>  #include "pixman-renderer.h"
>  #include "presentation_timing-server-protocol.h"
>  
> @@ -51,13 +52,6 @@ struct headless_output {
>  	pixman_image_t *image;
>  };
>  
> -struct headless_parameters {
> -	int width;
> -	int height;
> -	int use_pixman;
> -	uint32_t transform;
> -};
> -
>  static void
>  headless_output_start_repaint_loop(struct weston_output *output)
>  {
> @@ -118,9 +112,9 @@ headless_output_destroy(struct weston_output *output_base)
>  	return;
>  }
>  
> -static int
> +static struct headless_output *
>  headless_backend_create_output(struct headless_backend *b,
> -			       struct headless_parameters *param)
> +			       struct weston_backend_output_config *config)
>  {
>  	struct weston_compositor *c = b->compositor;
>  	struct headless_output *output;
> @@ -128,19 +122,19 @@ headless_backend_create_output(struct headless_backend *b,
>  
>  	output = zalloc(sizeof *output);
>  	if (output == NULL)
> -		return -1;
> +		return NULL;
>  
>  	output->mode.flags =
>  		WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
> -	output->mode.width = param->width;
> -	output->mode.height = param->height;
> +	output->mode.width = config->width;
> +	output->mode.height = config->height;
>  	output->mode.refresh = 60000;
>  	wl_list_init(&output->base.mode_list);
>  	wl_list_insert(&output->base.mode_list, &output->mode.link);
>  
>  	output->base.current_mode = &output->mode;
> -	weston_output_init(&output->base, c, 0, 0, param->width,
> -			   param->height, param->transform, 1);
> +	weston_output_init(&output->base, c, 0, 0, output->mode.width,
> +			   output->mode.height, config->transform, 1);
>  
>  	output->base.make = "weston";
>  	output->base.model = "headless";
> @@ -158,18 +152,19 @@ headless_backend_create_output(struct headless_backend *b,
>  	output->base.switch_mode = NULL;
>  
>  	if (b->use_pixman) {
> -		output->image_buf = malloc(param->width * param->height * 4);
> +		output->image_buf = malloc(output->mode.width *
> +					   output->mode.height * 4);
>  		if (!output->image_buf)
> -			return -1;
> +			return NULL;
>  
>  		output->image = pixman_image_create_bits(PIXMAN_x8r8g8b8,
> -							 param->width,
> -							 param->height,
> +							 output->mode.width,
> +							 output->mode.height,
>  							 output->image_buf,
> -							 param->width * 4);
> +							 config->width * 4);
>  
>  		if (pixman_renderer_output_create(&output->base) < 0)
> -			return -1;
> +			return NULL;
>  
>  		pixman_renderer_output_set_buffer(&output->base,
>  						  output->image);
> @@ -177,7 +172,7 @@ headless_backend_create_output(struct headless_backend *b,
>  
>  	weston_compositor_add_output(c, &output->base);
>  
> -	return 0;
> +	return output;
>  }
>  
>  static int
> @@ -215,10 +210,18 @@ headless_destroy(struct weston_compositor *ec)
>  	free(b);
>  }
>  
> +static struct weston_output *
> +headless_create_output(struct weston_compositor *ec, const char *name,
> +		       struct weston_backend_output_config *config)
> +{
> +	struct headless_backend *b = (struct headless_backend *) ec->backend;
> +	struct headless_output *o = headless_backend_create_output(b, config);
> +	return &o->base;
> +}
> +
>  static struct headless_backend *
>  headless_backend_create(struct weston_compositor *compositor,
> -			struct headless_parameters *param,
> -			const char *display_name)
> +			struct weston_headless_backend_config *config)
>  {
>  	struct headless_backend *b;
>  
> @@ -235,13 +238,12 @@ headless_backend_create(struct weston_compositor *compositor,
>  
>  	b->base.destroy = headless_destroy;
>  	b->base.restore = headless_restore;
> +	b->base.create_output = headless_create_output;
>  
> -	b->use_pixman = param->use_pixman;
> +	b->use_pixman = config->use_pixman;
>  	if (b->use_pixman) {
>  		pixman_renderer_init(compositor);
>  	}
> -	if (headless_backend_create_output(b, param) < 0)
> -		goto err_input;
>  
>  	if (!b->use_pixman && noop_renderer_init(compositor) < 0)
>  		goto err_input;
> @@ -258,32 +260,13 @@ err_free:
>  
>  WL_EXPORT int
>  backend_init(struct weston_compositor *compositor,
> -	     int *argc, char *argv[],
> -	     struct weston_config *config)
> +	     struct weston_backend_config *base)
>  {
> -	int width = 1024, height = 640;
> -	char *display_name = NULL;
> -	struct headless_parameters param = { 0, };
> -	const char *transform = "normal";
> +	struct weston_headless_backend_config *config =
> +				(struct weston_headless_backend_config *)base;
>  	struct headless_backend *b;
>  
> -	const struct weston_option headless_options[] = {
> -		{ WESTON_OPTION_INTEGER, "width", 0, &width },
> -		{ WESTON_OPTION_INTEGER, "height", 0, &height },
> -		{ WESTON_OPTION_BOOLEAN, "use-pixman", 0, &param.use_pixman },
> -		{ WESTON_OPTION_STRING, "transform", 0, &transform },
> -	};
> -
> -	parse_options(headless_options,
> -		      ARRAY_LENGTH(headless_options), argc, argv);
> -
> -	param.width = width;
> -	param.height = height;
> -
> -	if (weston_parse_transform(transform, &param.transform) < 0)
> -		weston_log("Invalid transform \"%s\"\n", transform);
> -
> -	b = headless_backend_create(compositor, &param, display_name);
> +	b = headless_backend_create(compositor, config);
>  	if (b == NULL)
>  		return -1;
>  	return 0;
> diff --git a/src/compositor-headless.h b/src/compositor-headless.h
> new file mode 100644
> index 0000000..757c430
> --- /dev/null
> +++ b/src/compositor-headless.h
> @@ -0,0 +1,47 @@
> +/*
> + * Copyright © 2010-2011 Benjamin Franzke
> + * Copyright © 2012 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_HEADLESS_H
> +#define WESTON_COMPOSITOR_HEADLESS_H
> +
> +#ifdef  __cplusplus
> +extern "C" {
> +#endif
> +
> +#include "compositor.h"
> +
> +struct weston_headless_backend_config {
> +	struct weston_backend_config base;
> +
> +	bool use_pixman;
> +};
> +
> +#ifdef  __cplusplus
> +}
> +#endif
> +
> +#endif
> diff --git a/src/compositor-rdp.c b/src/compositor-rdp.c
> index 86c5b2a..b8c0c31 100644
> --- a/src/compositor-rdp.c
> +++ b/src/compositor-rdp.c
> @@ -67,24 +67,13 @@
>  
>  #include "shared/helpers.h"
>  #include "compositor.h"
> +#include "compositor-rdp.h"
>  #include "pixman-renderer.h"
>  
>  #define MAX_FREERDP_FDS 32
>  #define DEFAULT_AXIS_STEP_DISTANCE wl_fixed_from_int(10)
>  #define RDP_MODE_FREQ 60 * 1000
>  
> -struct rdp_backend_config {
> -	int width;
> -	int height;
> -	char *bind_address;
> -	int port;
> -	char *rdp_key;
> -	char *server_cert;
> -	char *server_key;
> -	int env_socket;
> -	int no_clients_resize;
> -};
> -
>  struct rdp_output;
>  
>  struct rdp_backend {
> @@ -138,19 +127,6 @@ struct rdp_peer_context {
>  typedef struct rdp_peer_context RdpPeerContext;
>  
>  static void
> -rdp_backend_config_init(struct rdp_backend_config *config) {
> -	config->width = 640;
> -	config->height = 480;
> -	config->bind_address = NULL;
> -	config->port = 3389;
> -	config->rdp_key = NULL;
> -	config->server_cert = NULL;
> -	config->server_key = NULL;
> -	config->env_socket = 0;
> -	config->no_clients_resize = 0;
> -}
> -
> -static void
>  rdp_peer_refresh_rfx(pixman_region32_t *damage, pixman_image_t *image, freerdp_peer *peer)
>  {
>  	int width, height, nrects, i;
> @@ -1160,8 +1136,7 @@ rdp_incoming_peer(freerdp_listener *instance, freerdp_peer *client)
>  
>  static struct rdp_backend *
>  rdp_backend_create(struct weston_compositor *compositor,
> -		   struct rdp_backend_config *config,
> -		   int *argc, char *argv[], struct weston_config *wconfig)
> +		   struct weston_rdp_backend_config *config)
>  {
>  	struct rdp_backend *b;
>  	char *fd_str;
> @@ -1174,6 +1149,7 @@ rdp_backend_create(struct weston_compositor *compositor,
>  	b->compositor = compositor;
>  	b->base.destroy = rdp_destroy;
>  	b->base.restore = rdp_restore;
> +	b->base.create_output = NULL;
>  	b->rdp_key = config->rdp_key ? strdup(config->rdp_key) : NULL;
>  	b->no_clients_resize = config->no_clients_resize;
>  
> @@ -1243,37 +1219,24 @@ err_free_strings:
>  }
>  
>  WL_EXPORT int
> -backend_init(struct weston_compositor *compositor, int *argc, char *argv[],
> -	     struct weston_config *wconfig)
> +backend_init(struct weston_compositor *compositor,
> +	     struct weston_backend_config *base)
>  {
>  	struct rdp_backend *b;
> -	struct rdp_backend_config config;
> -	rdp_backend_config_init(&config);
> +	struct weston_rdp_backend_config *config =
> +				(struct weston_rdp_backend_config *)base;
>  	int major, minor, revision;
>  
>  	freerdp_get_version(&major, &minor, &revision);
>  	weston_log("using FreeRDP version %d.%d.%d\n", major, minor, revision);
>  
> -	const struct weston_option rdp_options[] = {
> -		{ WESTON_OPTION_BOOLEAN, "env-socket", 0, &config.env_socket },
> -		{ WESTON_OPTION_INTEGER, "width", 0, &config.width },
> -		{ WESTON_OPTION_INTEGER, "height", 0, &config.height },
> -		{ WESTON_OPTION_STRING,  "address", 0, &config.bind_address },
> -		{ WESTON_OPTION_INTEGER, "port", 0, &config.port },
> -		{ WESTON_OPTION_BOOLEAN, "no-clients-resize", 0, &config.no_clients_resize },
> -		{ WESTON_OPTION_STRING,  "rdp4-key", 0, &config.rdp_key },
> -		{ WESTON_OPTION_STRING,  "rdp-tls-cert", 0, &config.server_cert },
> -		{ WESTON_OPTION_STRING,  "rdp-tls-key", 0, &config.server_key }
> -	};
> -
> -	parse_options(rdp_options, ARRAY_LENGTH(rdp_options), argc, argv);
> -	if (!config.rdp_key && (!config.server_cert || !config.server_key)) {
> +	if (!config->rdp_key && (!config->server_cert || !config->server_key)) {
>  		weston_log("the RDP compositor requires keys and an optional certificate for RDP or TLS security ("
>  				"--rdp4-key or --rdp-tls-cert/--rdp-tls-key)\n");
> -		return NULL;
> +		return -1;
>  	}
>  
> -	b = rdp_backend_create(compositor, &config, argc, argv, wconfig);
> +	b = rdp_backend_create(compositor, config);
>  	if (b == NULL)
>  		return -1;
>  	return 0;
> diff --git a/src/compositor-rdp.h b/src/compositor-rdp.h
> new file mode 100644
> index 0000000..8d3e568
> --- /dev/null
> +++ b/src/compositor-rdp.h
> @@ -0,0 +1,54 @@
> +/*
> + * Copyright © 2013 Hardening <rdp.effort at gmail.com>
> + * 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_RDP_H
> +#define WESTON_COMPOSITOR_RDP_H
> +
> +#ifdef  __cplusplus
> +extern "C" {
> +#endif
> +
> +#include "compositor.h"
> +
> +struct weston_rdp_backend_config {
> +	struct weston_backend_config base;
> +
> +	int width;
> +	int height;
> +	const char *bind_address;
> +	int port;
> +	const char *rdp_key;
> +	const char *server_cert;
> +	const char *server_key;
> +	int env_socket;
> +	int no_clients_resize;
> +};
> +
> +#ifdef  __cplusplus
> +}
> +#endif
> +
> +#endif
> diff --git a/src/compositor-rpi.c b/src/compositor-rpi.c
> index 14bd76b..c2bffe5 100644
> --- a/src/compositor-rpi.c
> +++ b/src/compositor-rpi.c
> @@ -48,6 +48,7 @@
>  
>  #include "shared/helpers.h"
>  #include "compositor.h"
> +#include "compositor-rpi.h"
>  #include "rpi-renderer.h"
>  #include "launcher-util.h"
>  #include "libinput-seat.h"
> @@ -455,17 +456,12 @@ switch_vt_binding(struct weston_seat *seat, uint32_t time, uint32_t key, void *d
>  	weston_launcher_activate_vt(compositor->launcher, key - KEY_F1 + 1);
>  }
>  
> -struct rpi_parameters {
> -	int tty;
> -	struct rpi_renderer_parameters renderer;
> -	uint32_t output_transform;
> -};
> -
>  static struct rpi_backend *
>  rpi_backend_create(struct weston_compositor *compositor,
> -		   struct rpi_parameters *param)
> +		   struct weston_rpi_backend_config *config)
>  {
>  	struct rpi_backend *backend;
> +	struct rpi_renderer_parameters renderer_params;
>  	uint32_t key;
>  
>  	weston_log("initializing Raspberry Pi backend\n");
> @@ -488,7 +484,7 @@ rpi_backend_create(struct weston_compositor *compositor,
>  	wl_signal_add(&compositor->session_signal,
>  		      &backend->session_listener);
>  	compositor->launcher =
> -		weston_launcher_connect(compositor, param->tty, "seat0", false);
> +		weston_launcher_connect(compositor, config->tty, "seat0", false);
>  	if (!compositor->launcher) {
>  		weston_log("Failed to initialize tty.\n");
>  		goto out_udev;
> @@ -496,9 +492,10 @@ rpi_backend_create(struct weston_compositor *compositor,
>  
>  	backend->base.destroy = rpi_backend_destroy;
>  	backend->base.restore = rpi_restore;
> +	backend->base.create_output = NULL;
>  
>  	backend->prev_state = WESTON_COMPOSITOR_ACTIVE;
> -	backend->single_buffer = param->renderer.single_buffer;
> +	backend->single_buffer = config->single_buffer;
>  
>  	weston_log("Dispmanx planes are %s buffered.\n",
>  		   backend->single_buffer ? "single" : "double");
> @@ -517,10 +514,12 @@ rpi_backend_create(struct weston_compositor *compositor,
>  	 */
>  	bcm_host_init();
>  
> -	if (rpi_renderer_create(compositor, &param->renderer) < 0)
> +	renderer_params.single_buffer = config->single_buffer;
> +	renderer_params.opaque_regions = config->opaque_regions;
> +	if (rpi_renderer_create(compositor, &renderer_params) < 0)
>  		goto out_launcher;
>  
> -	if (rpi_output_create(backend, param->output_transform) < 0)
> +	if (rpi_output_create(backend, config->output_transform) < 0)
>  		goto out_renderer;
>  
>  	if (udev_input_init(&backend->input,
> @@ -552,34 +551,13 @@ out_compositor:
>  
>  WL_EXPORT int
>  backend_init(struct weston_compositor *compositor,
> -	     int *argc, char *argv[],
> -	     struct weston_config *config)
> +	     struct weston_backend_config *base)
>  {
> -	const char *transform = "normal";
> +	struct weston_rpi_backend_config *config =
> +				(struct weston_rpi_backend_config *)base;
>  	struct rpi_backend *b;
>  
> -	struct rpi_parameters param = {
> -		.tty = 0, /* default to current tty */
> -		.renderer.single_buffer = 0,
> -		.output_transform = WL_OUTPUT_TRANSFORM_NORMAL,
> -		.renderer.opaque_regions = 0,
> -	};
> -
> -	const struct weston_option rpi_options[] = {
> -		{ WESTON_OPTION_INTEGER, "tty", 0, &param.tty },
> -		{ WESTON_OPTION_BOOLEAN, "single-buffer", 0,
> -		  &param.renderer.single_buffer },
> -		{ WESTON_OPTION_STRING, "transform", 0, &transform },
> -		{ WESTON_OPTION_BOOLEAN, "opaque-regions", 0,
> -		  &param.renderer.opaque_regions },
> -	};
> -
> -	parse_options(rpi_options, ARRAY_LENGTH(rpi_options), argc, argv);
> -
> -	if (weston_parse_transform(transform, &param.output_transform) < 0)
> -		weston_log("invalid transform \"%s\"\n", transform);
> -
> -	b = rpi_backend_create(compositor, &param);
> +	b = rpi_backend_create(compositor, config);
>  	if (b == NULL)
>  		return -1;
>  	return 0;
> diff --git a/src/compositor-rpi.h b/src/compositor-rpi.h
> new file mode 100644
> index 0000000..b3190c9
> --- /dev/null
> +++ b/src/compositor-rpi.h
> @@ -0,0 +1,51 @@
> +/*
> + * Copyright © 2008-2011 Kristian Høgsberg
> + * Copyright © 2011 Intel Corporation
> + * Copyright © 2012-2013 Raspberry Pi Foundation
> + * 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_RPI_H
> +#define WESTON_COMPOSITOR_RPI_H
> +
> +#ifdef  __cplusplus
> +extern "C" {
> +#endif
> +
> +#include "compositor.h"
> +
> +struct weston_rpi_backend_config {
> +	struct weston_backend_config base;
> +
> +	int tty;
> +	uint32_t output_transform;
> +	int single_buffer;
> +	int opaque_regions;
> +};
> +
> +#ifdef  __cplusplus
> +}
> +#endif
> +
> +#endif
> diff --git a/src/compositor-wayland.c b/src/compositor-wayland.c
> index 35f1de0..418a0bb 100644
> --- a/src/compositor-wayland.c
> +++ b/src/compositor-wayland.c
> @@ -40,6 +40,7 @@
>  #include <wayland-cursor.h>
>  
>  #include "compositor.h"
> +#include "compositor-wayland.h"
>  #include "gl-renderer.h"
>  #include "pixman-renderer.h"
>  #include "shared/helpers.h"
> @@ -49,8 +50,6 @@
>  #include "fullscreen-shell-client-protocol.h"
>  #include "presentation_timing-server-protocol.h"
>  
> -#define WINDOW_TITLE "Weston Compositor"
> -
>  struct wayland_backend {
>  	struct weston_backend base;
>  	struct weston_compositor *compositor;
> @@ -71,6 +70,7 @@ struct wayland_backend {
>  
>  	int use_pixman;
>  	int sprawl_across_outputs;
> +	char *window_title;
>  
>  	struct theme *theme;
>  	cairo_device_t *frame_device;
> @@ -759,14 +759,16 @@ wayland_output_set_windowed(struct wayland_output *output)
>  		return 0;
>  
>  	if (output->name) {
> -		tlen = strlen(output->name) + strlen(WINDOW_TITLE " - ");
> +		tlen = strlen(output->name) + strlen(b->window_title) +
> +		       strlen(" - ");
>  		title = malloc(tlen + 1);
>  		if (!title)
>  			return -1;
>  
> -		snprintf(title, tlen + 1, WINDOW_TITLE " - %s", output->name);
> +		snprintf(title, tlen + 1, "%s - %s", b->window_title,
> +						     output->name);
>  	} else {
> -		title = strdup(WINDOW_TITLE);
> +		title = strdup(b->window_title);
>  	}
>  
>  	if (!b->theme) {
> @@ -1083,65 +1085,6 @@ err_name:
>  }
>  
>  static struct wayland_output *
> -wayland_output_create_for_config(struct wayland_backend *b,
> -				 struct weston_config_section *config_section,
> -				 int option_width, int option_height,
> -				 int option_scale, int32_t x, int32_t y)
> -{
> -	struct wayland_output *output;
> -	char *mode, *t, *name, *str;
> -	int width, height, scale;
> -	uint32_t transform;
> -	unsigned int slen;
> -
> -	weston_config_section_get_string(config_section, "name", &name, NULL);
> -	if (name) {
> -		slen = strlen(name);
> -		slen += strlen(WINDOW_TITLE " - ");
> -		str = malloc(slen + 1);
> -		if (str)
> -			snprintf(str, slen + 1, WINDOW_TITLE " - %s", name);
> -		free(name);
> -		name = str;
> -	}
> -	if (!name)
> -		name = strdup(WINDOW_TITLE);
> -
> -	weston_config_section_get_string(config_section,
> -					 "mode", &mode, "1024x600");
> -	if (sscanf(mode, "%dx%d", &width, &height) != 2) {
> -		weston_log("Invalid mode \"%s\" for output %s\n",
> -			   mode, name);
> -		width = 1024;
> -		height = 640;
> -	}
> -	free(mode);
> -
> -	if (option_width)
> -		width = option_width;
> -	if (option_height)
> -		height = option_height;
> -
> -	weston_config_section_get_int(config_section, "scale", &scale, 1);
> -
> -	if (option_scale)
> -		scale = option_scale;
> -
> -	weston_config_section_get_string(config_section,
> -					 "transform", &t, "normal");
> -	if (weston_parse_transform(t, &transform) < 0)
> -		weston_log("Invalid transform \"%s\" for output %s\n",
> -			   t, name);
> -	free(t);
> -
> -	output = wayland_output_create(b, x, y, width, height, name, 0,
> -				       transform, scale);
> -	free(name);
> -
> -	return output;
> -}
> -
> -static struct wayland_output *
>  wayland_output_create_for_parent_output(struct wayland_backend *b,
>  					struct wayland_parent_output *poutput)
>  {
> @@ -1884,6 +1827,7 @@ wayland_destroy(struct weston_compositor *ec)
>  	if (b->parent.shm)
>  		wl_shm_destroy(b->parent.shm);
>  
> +	free(b->window_title);
>  	free(b);
>  }
>  
> @@ -1895,25 +1839,16 @@ static const char *left_ptrs[] = {
>  };
>  
>  static void
> -create_cursor(struct wayland_backend *b, struct weston_config *config)
> +create_cursor(struct wayland_backend *b, const char *theme, int size)
>  {
> -	struct weston_config_section *s;
> -	int size;
> -	char *theme = NULL;
>  	unsigned int i;
>  
> -	s = weston_config_get_section(config, "shell", NULL, NULL);
> -	weston_config_section_get_string(s, "cursor-theme", &theme, NULL);
> -	weston_config_section_get_int(s, "cursor-size", &size, 32);
> -
>  	b->cursor_theme = wl_cursor_theme_load(theme, size, b->parent.shm);
>  	if (!b->cursor_theme) {
>  		fprintf(stderr, "could not load cursor theme\n");
>  		return;
>  	}
>  
> -	free(theme);
> -
>  	b->cursor = NULL;
>  	for (i = 0; !b->cursor && i < ARRAY_LENGTH(left_ptrs); ++i)
>  		b->cursor = wl_cursor_theme_get_cursor(b->cursor_theme,
> @@ -1948,8 +1883,8 @@ fullscreen_binding(struct weston_seat *seat_base, uint32_t time, uint32_t key,
>  
>  static struct wayland_backend *
>  wayland_backend_create(struct weston_compositor *compositor, int use_pixman,
> -		       const char *display_name, int *argc, char *argv[],
> -		       struct weston_config *config)
> +		       const char *display_name,
> +		       const char *cursor_theme, int cursor_size)
>  {
>  	struct wayland_backend *b;
>  	struct wl_event_loop *loop;
> @@ -1975,7 +1910,7 @@ wayland_backend_create(struct weston_compositor *compositor, int use_pixman,
>  	wl_registry_add_listener(b->parent.registry, &registry_listener, b);
>  	wl_display_roundtrip(b->parent.wl_display);
>  
> -	create_cursor(b, config);
> +	create_cursor(b, cursor_theme, cursor_size);
>  
>  	b->use_pixman = use_pixman;
>  
> @@ -2032,67 +1967,47 @@ err_compositor:
>  	return NULL;
>  }
>  
> -static void
> -wayland_backend_destroy(struct wayland_backend *b)
> +static struct weston_output *
> +wayland_create_output(struct weston_compositor *c, const char *name,
> +		      struct weston_backend_output_config *base)
>  {
> -	struct weston_output *output, *next;
> -
> -	wl_list_for_each_safe(output, next, &b->compositor->output_list, link)
> -		wayland_output_destroy(output);
> +	struct wayland_backend *b = (struct wayland_backend *)c->backend;
> +	struct weston_wayland_backend_output_config *config =
> +			(struct weston_wayland_backend_output_config *)base;
> +	struct wayland_output *output;
>  
> -	b->compositor->renderer->destroy(b->compositor);
> -	wl_display_disconnect(b->parent.wl_display);
> +	output = wayland_output_create(b, 0, 0, config->base.width,
> +				       config->base.height,
> +				       name, config->fullscreen,
> +				       config->base.transform,
> +				       config->base.scale);
> +	if (!output)
> +		return NULL;
>  
> -	if (b->theme)
> -		theme_destroy(b->theme);
> -	if (b->frame_device)
> -		cairo_device_destroy(b->frame_device);
> -	wl_cursor_theme_destroy(b->cursor_theme);
> +	if (config->fullscreen)
> +		wayland_output_set_fullscreen(output, 0, 0, NULL);
> +	else
> +		wayland_output_set_windowed(output);
>  
> -	weston_compositor_shutdown(b->compositor);
> -	free(b);
> +	return &output->base;
>  }
>  
>  WL_EXPORT int
> -backend_init(struct weston_compositor *compositor, int *argc, char *argv[],
> -	     struct weston_config *config)
> +backend_init(struct weston_compositor *compositor,
> +	     struct weston_backend_config *base)
>  {
> +	struct weston_wayland_backend_config *config =
> +				(struct weston_wayland_backend_config *)base;
>  	struct wayland_backend *b;
> -	struct wayland_output *output;
>  	struct wayland_parent_output *poutput;
> -	struct weston_config_section *section;
> -	int x, count, width, height, scale, use_pixman, fullscreen, sprawl;
> -	const char *section_name, *display_name;
> -	char *name;
>  
> -	const struct weston_option wayland_options[] = {
> -		{ WESTON_OPTION_INTEGER, "width", 0, &width },
> -		{ WESTON_OPTION_INTEGER, "height", 0, &height },
> -		{ WESTON_OPTION_INTEGER, "scale", 0, &scale },
> -		{ WESTON_OPTION_STRING, "display", 0, &display_name },
> -		{ WESTON_OPTION_BOOLEAN, "use-pixman", 0, &use_pixman },
> -		{ WESTON_OPTION_INTEGER, "output-count", 0, &count },
> -		{ WESTON_OPTION_BOOLEAN, "fullscreen", 0, &fullscreen },
> -		{ WESTON_OPTION_BOOLEAN, "sprawl", 0, &sprawl },
> -	};
> -
> -	width = 0;
> -	height = 0;
> -	scale = 0;
> -	display_name = NULL;
> -	use_pixman = 0;
> -	count = 1;
> -	fullscreen = 0;
> -	sprawl = 0;
> -	parse_options(wayland_options,
> -		      ARRAY_LENGTH(wayland_options), argc, argv);
> -
> -	b = wayland_backend_create(compositor, use_pixman, display_name,
> -				   argc, argv, config);
> +	b = wayland_backend_create(compositor, config->use_pixman, config->display,
> +				   config->cursor_theme, config->cursor_size);
>  	if (!b)
>  		return -1;
>  
> -	if (sprawl || b->parent.fshell) {
> +	b->window_title = strdup(config->window_title);
> +	if (config->sprawl || b->parent.fshell) {
>  		b->sprawl_across_outputs = 1;
>  		wl_display_roundtrip(b->parent.wl_display);
>  
> @@ -2101,68 +2016,11 @@ backend_init(struct weston_compositor *compositor, int *argc, char *argv[],
>  
>  		return 0;
>  	}
> -
> -	if (fullscreen) {
> -		output = wayland_output_create(b, 0, 0, width, height,
> -					       NULL, 1, 0, 1);
> -		if (!output)
> -			goto err_outputs;
> -
> -		wayland_output_set_fullscreen(output, 0, 0, NULL);
> -		return 0;
> -	}
> -
> -	section = NULL;
> -	x = 0;
> -	while (weston_config_next_section(config, &section, &section_name)) {
> -		if (!section_name || strcmp(section_name, "output") != 0)
> -			continue;
> -		weston_config_section_get_string(section, "name", &name, NULL);
> -		if (name == NULL)
> -			continue;
> -
> -		if (name[0] != 'W' || name[1] != 'L') {
> -			free(name);
> -			continue;
> -		}
> -		free(name);
> -
> -		output = wayland_output_create_for_config(b, section, width,
> -							  height, scale, x, 0);
> -		if (!output)
> -			goto err_outputs;
> -		if (wayland_output_set_windowed(output))
> -			goto err_outputs;
> -
> -		x += output->base.width;
> -		--count;
> -	}
> -
> -	if (!width)
> -		width = 1024;
> -	if (!height)
> -		height = 640;
> -	if (!scale)
> -		scale = 1;
> -	while (count > 0) {
> -		output = wayland_output_create(b, x, 0, width, height,
> -					       NULL, 0, 0, scale);
> -		if (!output)
> -			goto err_outputs;
> -		if (wayland_output_set_windowed(output))
> -			goto err_outputs;
> -
> -		x += width;
> -		--count;
> -	}
> +	b->base.create_output = wayland_create_output;
>  
>  	weston_compositor_add_key_binding(compositor, KEY_F,
>  				          MODIFIER_CTRL | MODIFIER_ALT,
>  				          fullscreen_binding, b);
>  
>  	return 0;
> -
> -err_outputs:
> -	wayland_backend_destroy(b);
> -	return -1;
>  }
> diff --git a/src/compositor-wayland.h b/src/compositor-wayland.h
> new file mode 100644
> index 0000000..ebbcebb
> --- /dev/null
> +++ b/src/compositor-wayland.h
> @@ -0,0 +1,58 @@
> +/*
> + * Copyright © 2010-2011 Benjamin Franzke
> + * Copyright © 2013 Jason Ekstrand
> + * 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_WAYLAND_H
> +#define WESTON_COMPOSITOR_WAYLAND_H
> +
> +#ifdef  __cplusplus
> +extern "C" {
> +#endif
> +
> +#include "compositor.h"
> +
> +struct weston_wayland_backend_config {
> +	struct weston_backend_config base;
> +
> +	const char *display;
> +	bool use_pixman;
> +	bool sprawl;
> +	int cursor_size;
> +	const char *cursor_theme;
> +	const char *window_title;
> +};
> +
> +struct weston_wayland_backend_output_config {
> +	struct weston_backend_output_config base;
> +
> +	int fullscreen;
> +};
> +
> +#ifdef  __cplusplus
> +}
> +#endif
> +
> +#endif
> diff --git a/src/compositor-x11.c b/src/compositor-x11.c
> index 55c85ed..f3ccd17 100644
> --- a/src/compositor-x11.c
> +++ b/src/compositor-x11.c
> @@ -50,6 +50,7 @@
>  #include <xkbcommon/xkbcommon.h>
>  
>  #include "compositor.h"
> +#include "compositor-x11.h"
>  #include "gl-renderer.h"
>  #include "pixman-renderer.h"
>  #include "shared/config-parser.h"
> @@ -59,11 +60,6 @@
>  
>  #define DEFAULT_AXIS_STEP_DISTANCE wl_fixed_from_int(10)
>  
> -static int option_width;
> -static int option_height;
> -static int option_scale;
> -static int option_count;
> -
>  struct x11_backend {
>  	struct weston_backend	 base;
>  	struct weston_compositor *compositor;
> @@ -78,6 +74,7 @@ struct x11_backend {
>  	unsigned int		 has_xkb;
>  	uint8_t			 xkb_event_base;
>  	int			 use_pixman;
> +	bool			 no_input;
>  
>  	int			 has_net_wm_state_fullscreen;
>  
> @@ -762,7 +759,7 @@ x11_output_init_shm(struct x11_backend *b, struct x11_output *output,
>  static struct x11_output *
>  x11_backend_create_output(struct x11_backend *b, int x, int y,
>  			     int width, int height, int fullscreen,
> -			     int no_input, char *configured_name,
> +			     int no_input, const char *configured_name,
>  			     uint32_t transform, int32_t scale)
>  {
>  	static const char name[] = "Weston Compositor";
> @@ -1509,23 +1506,41 @@ init_gl_renderer(struct x11_backend *b)
>  
>  	return ret;
>  }
> +
> +static struct weston_output *
> +x11_create_output(struct weston_compositor *c, const char *name,
> +                  struct weston_backend_output_config *base)
> +{
> +	struct x11_backend *b = (struct x11_backend *)c->backend;
> +	struct weston_x11_backend_output_config *config =
> +			(struct weston_x11_backend_output_config *)base;
> +	struct x11_output *output;
> +
> +	if (!b->has_net_wm_state_fullscreen && config->fullscreen) {
> +		static bool warned = false;
> +		if (!warned) {
> +			weston_log("Can not fullscreen without window manager support"
> +				"(need _NET_WM_STATE_FULLSCREEN)\n");
> +			warned = true;
> +		}
> +		config->fullscreen = 0;
> +	}
> +	output = x11_backend_create_output(b, 0, 0, config->base.width,
> +					   config->base.height,
> +					   config->fullscreen, b->no_input,
> +					   name, config->base.transform,
> +					   config->base.scale);
> +	if (!output)
> +		return NULL;
> +	return &output->base;
> +}
> +
>  static struct x11_backend *
>  x11_backend_create(struct weston_compositor *compositor,
> -		   int fullscreen,
> -		   int no_input,
> -		   int use_pixman,
> -		   int *argc, char *argv[],
> -		   struct weston_config *config)
> +		   struct weston_x11_backend_config *config)
>  {
>  	struct x11_backend *b;
> -	struct x11_output *output;
> -	struct weston_config_section *section;
>  	xcb_screen_iterator_t s;
> -	int i, x = 0, output_count = 0;
> -	int width, height, scale, count;
> -	const char *section_name;
> -	char *name, *t, *mode;
> -	uint32_t transform;
>  
>  	weston_log("initializing x11 backend\n");
>  
> @@ -1554,14 +1569,9 @@ x11_backend_create(struct weston_compositor *compositor,
>  	x11_backend_get_resources(b);
>  	x11_backend_get_wm_info(b);
>  
> -	if (!b->has_net_wm_state_fullscreen && fullscreen) {
> -		weston_log("Can not fullscreen without window manager support"
> -			   "(need _NET_WM_STATE_FULLSCREEN)\n");
> -		fullscreen = 0;
> -	}
> -
> -	b->use_pixman = use_pixman;
> -	if (b->use_pixman) {
> +	b->use_pixman = config->use_pixman;
> +	b->no_input = config->no_input;
> +	if (config->use_pixman) {
>  		if (pixman_renderer_init(compositor) < 0) {
>  			weston_log("Failed to initialize pixman renderer for X11 backend\n");
>  			goto err_xdisplay;
> @@ -1570,86 +1580,17 @@ x11_backend_create(struct weston_compositor *compositor,
>  	else if (init_gl_renderer(b) < 0) {
>  		goto err_xdisplay;
>  	}
> -	weston_log("Using %s renderer\n", use_pixman ? "pixman" : "gl");
> +	weston_log("Using %s renderer\n", config->use_pixman ? "pixman" : "gl");
>  
>  	b->base.destroy = x11_destroy;
>  	b->base.restore = x11_restore;
> +	b->base.create_output = x11_create_output;
>  
> -	if (x11_input_create(b, no_input) < 0) {
> +	if (x11_input_create(b, config->no_input) < 0) {
>  		weston_log("Failed to create X11 input\n");
>  		goto err_renderer;
>  	}
>  
> -	width = option_width ? option_width : 1024;
> -	height = option_height ? option_height : 640;
> -	scale = option_scale ? option_scale : 1;
> -	count = option_count ? option_count : 1;
> -
> -	section = NULL;
> -	while (weston_config_next_section(config,
> -					  &section, &section_name)) {
> -		if (strcmp(section_name, "output") != 0)
> -			continue;
> -		weston_config_section_get_string(section, "name", &name, NULL);
> -		if (name == NULL || name[0] != 'X') {
> -			free(name);
> -			continue;
> -		}
> -
> -		weston_config_section_get_string(section,
> -						 "mode", &mode, "1024x600");
> -		if (sscanf(mode, "%dx%d", &width, &height) != 2) {
> -			weston_log("Invalid mode \"%s\" for output %s\n",
> -				   mode, name);
> -			width = 1024;
> -			height = 600;
> -		}
> -		free(mode);
> -
> -		if (option_width)
> -			width = option_width;
> -		if (option_height)
> -			height = option_height;
> -
> -		weston_config_section_get_int(section, "scale", &scale, 1);
> -		if (option_scale)
> -			scale = option_scale;
> -
> -		weston_config_section_get_string(section,
> -						 "transform", &t, "normal");
> -		if (weston_parse_transform(t, &transform) < 0)
> -			weston_log("Invalid transform \"%s\" for output %s\n",
> -				   t, name);
> -		free(t);
> -
> -		output = x11_backend_create_output(b, x, 0,
> -						   width, height,
> -						   fullscreen, no_input,
> -						   name, transform, scale);
> -		free(name);
> -		if (output == NULL) {
> -			weston_log("Failed to create configured x11 output\n");
> -			goto err_x11_input;
> -		}
> -
> -		x = pixman_region32_extents(&output->base.region)->x2;
> -
> -		output_count++;
> -		if (option_count && output_count >= option_count)
> -			break;
> -	}
> -
> -	for (i = output_count; i < count; i++) {
> -		output = x11_backend_create_output(b, x, 0, width, height,
> -						   fullscreen, no_input, NULL,
> -						   WL_OUTPUT_TRANSFORM_NORMAL, scale);
> -		if (output == NULL) {
> -			weston_log("Failed to create x11 output #%d\n", i);
> -			goto err_x11_input;
> -		}
> -		x = pixman_region32_extents(&output->base.region)->x2;
> -	}
> -
>  	b->xcb_source =
>  		wl_event_loop_add_fd(compositor->input_loop,
>  				     xcb_get_file_descriptor(b->conn),
> @@ -1660,8 +1601,6 @@ x11_backend_create(struct weston_compositor *compositor,
>  	compositor->backend = &b->base;
>  	return b;
>  
> -err_x11_input:
> -	x11_input_destroy(b);
>  err_renderer:
>  	compositor->renderer->destroy(compositor);
>  err_xdisplay:
> @@ -1672,31 +1611,14 @@ err_free:
>  }
>  
>  WL_EXPORT int
> -backend_init(struct weston_compositor *compositor, int *argc, char *argv[],
> -	     struct weston_config *config)
> +backend_init(struct weston_compositor *compositor,
> +	     struct weston_backend_config *base)
>  {
> +	struct weston_x11_backend_config *config =
> +			(struct weston_x11_backend_config *)base;
>  	struct x11_backend *b;
> -	int fullscreen = 0;
> -	int no_input = 0;
> -	int use_pixman = 0;
> -
> -	const struct weston_option x11_options[] = {
> -		{ WESTON_OPTION_INTEGER, "width", 0, &option_width },
> -		{ WESTON_OPTION_INTEGER, "height", 0, &option_height },
> -		{ WESTON_OPTION_INTEGER, "scale", 0, &option_scale },
> -		{ WESTON_OPTION_BOOLEAN, "fullscreen", 'f', &fullscreen },
> -		{ WESTON_OPTION_INTEGER, "output-count", 0, &option_count },
> -		{ WESTON_OPTION_BOOLEAN, "no-input", 0, &no_input },
> -		{ WESTON_OPTION_BOOLEAN, "use-pixman", 0, &use_pixman },
> -	};
> -
> -	parse_options(x11_options, ARRAY_LENGTH(x11_options), argc, argv);
>  
> -	b = x11_backend_create(compositor,
> -			       fullscreen,
> -			       no_input,
> -			       use_pixman,
> -			       argc, argv, config);
> +	b = x11_backend_create(compositor, config);
>  	if (b == NULL)
>  		return -1;
>  	return 0;
> diff --git a/src/compositor-x11.h b/src/compositor-x11.h
> new file mode 100644
> index 0000000..244de06
> --- /dev/null
> +++ b/src/compositor-x11.h
> @@ -0,0 +1,55 @@
> +/*
> + * Copyright © 2008-2011 Kristian Høgsberg
> + * Copyright © 2010-2011 Intel Corporation
> + * Copyright © 2013 Vasily Khoruzhick <anarsoul at gmail.com>
> + * 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_X11
> +#define WESTON_COMPOSITOR_X11
> +
> +#ifdef  __cplusplus
> +extern "C" {
> +#endif
> +
> +#include "compositor.h"
> +
> +struct weston_x11_backend_config {
> +	struct weston_backend_config base;
> +
> +	bool use_pixman;
> +	bool no_input;
> +};
> +
> +struct weston_x11_backend_output_config {
> +	struct weston_backend_output_config base;
> +
> +	int fullscreen;
> +};
> +
> +#ifdef  __cplusplus
> +}
> +#endif
> +
> +#endif
> diff --git a/src/compositor.c b/src/compositor.c
> index 6e111f1..b063265 100644
> --- a/src/compositor.c
> +++ b/src/compositor.c
> @@ -4544,6 +4544,43 @@ fail:
>  	return NULL;
>  }
>  

In general it's more expected to see the doxygen comment in the .h where
this is declared, not the .c where it is defined.

"\brief" not needed. Just end with a period (as is the case here) and
auto-brief of doxygen covers it.

> +/** \brief Init the backend for the given compositor.
> + *
> + * This function loads the passed \c backend with the given
> + * config on the given compositor. Returns 0 on success, -1
> + * on failure.
> + * \c backend can either be a full path to the backend plugin
> + * or a relative one, in which case the path is resolved
> + * based on libweston's install prefix.
> + * The backend configuration object must be a pointer to an
> + * object whose type is a backend specific subclass of
> + * \ref weston_backend_config.

Generally "\ref" is not needed. Doxygen will recognize globals and
structs when prefixed with '::' and functions when followed by '()'.
Following the "less is more" doxygen approach also helps with
integrating documentation from different areas.

So here, "subclass of ::weston_backend_config" most likely will suffice.

> + * After this function returns \c backend_config can be safely
> + * freed.
> + *
> + * \param c The compositor to load the backend on.
> + * \param backend The backend plugin to load.
> + * \param backend_config The configuration struct for the backend.
> + *
> + * \memberof weston_compositor
> + */
> +WL_EXPORT int
> +weston_compositor_init_backend(struct weston_compositor *c, const char *backend,
> +			       struct weston_backend_config *backend_config)
> +{
> +	int (*backend_init)(struct weston_compositor *c,
> +			    struct weston_backend_config *config);
> +
> +	backend_init = weston_load_module(backend,
> +					  "backend_init");
> +	if (!backend_init || backend_init(c, backend_config) < 0) {
> +		weston_log("fatal: failed to create compositor backend\n");
> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +
>  WL_EXPORT void
>  weston_compositor_shutdown(struct weston_compositor *ec)
>  {
> @@ -4733,7 +4770,8 @@ weston_compositor_destroy(struct weston_compositor *compositor)
>  
>  	weston_compositor_xkb_destroy(compositor);
>  
> -	compositor->backend->destroy(compositor);
> +	if (compositor->backend)
> +		compositor->backend->destroy(compositor);
>  	free(compositor);
>  }
>  
> diff --git a/src/compositor.h b/src/compositor.h
> index df2b563..a7a968b 100644
> --- a/src/compositor.h
> +++ b/src/compositor.h
> @@ -603,9 +603,23 @@ enum weston_capability {
>  	WESTON_CAP_VIEW_CLIP_MASK		= 0x0010,
>  };
>  
> +struct weston_backend_output_config {
> +	uint32_t transform;
> +	int32_t width;
> +	int32_t height;
> +	int scale;
> +};
> +
>  struct weston_backend {
>  	void (*destroy)(struct weston_compositor *ec);
>  	void (*restore)(struct weston_compositor *ec);
> +	struct weston_output *
> +		(*create_output)(struct weston_compositor *ec,
> +				 const char *name,
> +				 struct weston_backend_output_config *config);
> +};
> +
> +struct weston_backend_config {
>  };
>  
>  struct weston_compositor {
> @@ -1344,6 +1358,9 @@ void
>  weston_compositor_destroy(struct weston_compositor *ec);
>  struct weston_compositor *
>  weston_compositor_create(struct wl_display *display, void *user_data);
> +int
> +weston_compositor_init_backend(struct weston_compositor *c, const char *backend,
> +			       struct weston_backend_config *backend_config);
>  void
>  weston_compositor_exit(struct weston_compositor *ec);
>  void *
> @@ -1548,8 +1565,7 @@ noop_renderer_init(struct weston_compositor *ec);
>  
>  int
>  backend_init(struct weston_compositor *c,
> -	     int *argc, char *argv[],
> -	     struct weston_config *config);
> +             struct weston_backend_config *config);
>  int
>  module_init(struct weston_compositor *compositor,
>  	    int *argc, char *argv[]);
> diff --git a/src/weston.c b/src/weston.c
> index 404e5f8..aa5e74a 100644
> --- a/src/weston.c
> +++ b/src/weston.c
> @@ -47,6 +47,16 @@
>  #include "git-version.h"
>  #include "version.h"
>  
> +#include "compositor-wayland.h"
> +#include "compositor-x11.h"
> +#include "compositor-drm.h"
> +#include "compositor-fbdev.h"
> +#include "compositor-headless.h"
> +#include "compositor-rpi.h"
> +#include "compositor-rdp.h"
> +
> +#define WINDOW_TITLE "Weston Compositor"
> +
>  static struct wl_list child_process_list;
>  static struct weston_compositor *segv_compositor;
>  
> @@ -624,6 +634,577 @@ handle_exit(struct weston_compositor *c)
>  	wl_display_terminate(c->wl_display);
>  }
>  
> +static char *
> +create_config_for_output(struct weston_config_section *config_section,
> +				 int option_width, int option_height,
> +				 int option_scale,
> +				 struct weston_backend_output_config *config)
> +{
> +	char *mode, *t, *name, *str;
> +	int width, height, scale;
> +	uint32_t transform;
> +	unsigned int slen;
> +
> +	weston_config_section_get_string(config_section, "name", &name, NULL);
> +	if (name) {
> +		slen = strlen(name);
> +		slen += strlen(WINDOW_TITLE " - ");
> +		str = malloc(slen + 1);
> +		if (str)
> +			snprintf(str, slen + 1, WINDOW_TITLE " - %s", name);
> +		free(name);
> +		name = str;
> +	}
> +	if (!name)
> +		name = strdup(WINDOW_TITLE);
> +
> +	weston_config_section_get_string(config_section,
> +					 "mode", &mode, "1024x600");
> +	if (sscanf(mode, "%dx%d", &width, &height) != 2) {
> +		weston_log("Invalid mode \"%s\" for output %s\n",
> +			   mode, name);
> +		width = 1024;
> +		height = 640;
> +	}
> +	free(mode);
> +
> +	if (option_width)
> +		width = option_width;
> +	if (option_height)
> +		height = option_height;
> +
> +	weston_config_section_get_int(config_section, "scale", &scale, 1);
> +
> +	if (option_scale)
> +		scale = option_scale;
> +
> +	weston_config_section_get_string(config_section,
> +					 "transform", &t, "normal");
> +	if (weston_parse_transform(t, &transform) < 0)
> +		weston_log("Invalid transform \"%s\" for output %s\n",
> +			   t, name);
> +	free(t);
> +
> +	config->width = width;
> +	config->height = height;
> +	config->transform = transform;
> +	config->scale = scale;
> +	return name;
> +}
> +
> +static int
> +init_wayland_backend(struct weston_compositor *c, const char *backend,
> +		     int *argc, char **argv, struct weston_config *wc)
> +{
> +	struct weston_wayland_backend_config config = {
> +		.use_pixman = false,
> +		.sprawl = false,
> +		.display = NULL,
> +		.cursor_size = 32,
> +		.cursor_theme = NULL,
> +		.window_title = WINDOW_TITLE,
> +	};
> +	struct weston_config_section *section;
> +	int count = 0;
> +	int width = 1024, height = 640;
> +	int scale = 1;
> +	bool fullscreen = false;
> +	const char *section_name;
> +	char *cursor_theme = NULL;
> +	char *display_name = NULL;
> +	struct weston_output *output;
> +	char *name, *output_name;
> +	int x = 0;
> +	int i;
> +	int output_count = 0;
> +	int ret = 0;
> +
> +	const struct weston_option options[] = {
> +		{ WESTON_OPTION_INTEGER, "width", 0, &width },
> +		{ WESTON_OPTION_INTEGER, "height", 0, &height },
> +		{ WESTON_OPTION_INTEGER, "scale", 0, &scale },
> +		{ WESTON_OPTION_STRING, "display", 0, &display_name },
> +		{ WESTON_OPTION_BOOLEAN, "use-pixman", 0, &config.use_pixman },
> +		{ WESTON_OPTION_INTEGER, "output-count", 0, &count },
> +		{ WESTON_OPTION_BOOLEAN, "fullscreen", 0, &fullscreen },
> +		{ WESTON_OPTION_BOOLEAN, "sprawl", 0, &config.sprawl },
> +	};
> +
> +	parse_options(options, ARRAY_LENGTH(options), argc, argv);
> +
> +	section = weston_config_get_section(wc, "shell", NULL, NULL);
> +	weston_config_section_get_string(section, "cursor-theme",
> +					 &cursor_theme,
> +					 cursor_theme);
> +	weston_config_section_get_int(section, "cursor-size",
> +				      &config.cursor_size, config.cursor_size);
> +
> +	config.cursor_theme = cursor_theme;
> +	config.display = display_name;
> +
> +	if (weston_compositor_init_backend(c, backend, &config.base) < 0) {
> +		ret = -1;
> +		goto cleanup;
> +	}
> +
> +	if (!c->backend->create_output) {
> +		ret = -1;
> +		goto cleanup;
> +	}
> +
> +	if (fullscreen) {
> +		struct weston_wayland_backend_output_config output_config = {
> +			.base.width = width,
> +			.base.height = height,
> +			.base.scale = scale,
> +			.base.transform = WL_OUTPUT_TRANSFORM_NORMAL,
> +			.fullscreen = true,
> +		};
> +		output = c->backend->create_output(c, NULL, &output_config.base);
> +		goto cleanup;
> +	}
> +
> +	section = NULL;
> +	while (weston_config_next_section(wc,
> +					  &section, &section_name)) {
> +		if (strcmp(section_name, "output") != 0)
> +			continue;
> +		weston_config_section_get_string(section, "name", &name, NULL);
> +		if (name == NULL)
> +			continue;
> +
> +		if (name[0] == 'W' && name[1] == 'L') {
> +			struct weston_wayland_backend_output_config output_config;
> +			output_name = create_config_for_output(section, width,
> +							height, scale,
> +							&output_config.base);
> +			output_config.fullscreen = false;
> +			output = c->backend->create_output(c, name,
> +							   &output_config.base);
> +			free(output_name);
> +		} else {
> +			free(name);
> +			continue;
> +		}
> +		free(name);
> +
> +		if (!output) {
> +			ret = -1;
> +			goto cleanup;
> +		}
> +
> +		weston_output_move(output, x, 0);
> +		x = pixman_region32_extents(&output->region)->x2;
> +
> +		output_count++;
> +		if (count && output_count >= count)
> +			break;
> +	}
> +
> +	if (!count)
> +		count = 1;
> +	for (i = output_count; i < count; i++) {
> +		struct weston_wayland_backend_output_config output_config = {
> +			.base.width = width,
> +			.base.height = height,
> +			.base.scale = scale,
> +			.base.transform = WL_OUTPUT_TRANSFORM_NORMAL,
> +			.fullscreen = false,
> +		};
> +		output = c->backend->create_output(c, NULL, &output_config.base);
> +		if (output == NULL) {
> +			ret = -1;
> +			goto cleanup;
> +		}
> +		weston_output_move(output, x, 0);
> +		x = pixman_region32_extents(&output->region)->x2;
> +	}
> +
> +cleanup:
> +	free(cursor_theme);
> +	free(display_name);
> +	return ret;
> +}
> +
> +static int
> +init_x11_backend(struct weston_compositor *c, const char *backend,
> +		 int *argc, char **argv, struct weston_config *wc)
> +{
> +	struct weston_x11_backend_config config = {
> +		.use_pixman = false,
> +		.no_input = false,
> +	};
> +	struct weston_config_section *section;
> +	int count = 0;
> +	int width = 640, height = 480;
> +	int scale = 1;
> +	bool fullscreen = false;
> +	const char *section_name;
> +	struct weston_output *output;
> +	char *name, *output_name;
> +	int x = 0;
> +	int i;
> +	int output_count = 0;
> +	int ret = 0;
> +
> +	const struct weston_option options[] = {
> +		{ WESTON_OPTION_INTEGER, "width", 0, &width },
> +		{ WESTON_OPTION_INTEGER, "height", 0, &height },
> +		{ WESTON_OPTION_INTEGER, "scale", 0, &scale },
> +		{ WESTON_OPTION_BOOLEAN, "use-pixman", 0, &config.use_pixman },
> +		{ WESTON_OPTION_INTEGER, "output-count", 0, &count },
> +		{ WESTON_OPTION_BOOLEAN, "fullscreen", 0, &fullscreen },
> +		{ WESTON_OPTION_BOOLEAN, "no-input", 0, &config.no_input },
> +	};
> +
> +	parse_options(options, ARRAY_LENGTH(options), argc, argv);
> +
> +	if (weston_compositor_init_backend(c, backend, &config.base) < 0) {
> +		ret = -1;
> +		goto cleanup;
> +	}
> +
> +	if (!c->backend->create_output) {
> +		ret = -1;
> +		goto cleanup;
> +	}
> +
> +	section = NULL;
> +	while (weston_config_next_section(wc,
> +					  &section, &section_name)) {
> +		if (strcmp(section_name, "output") != 0)
> +			continue;
> +		weston_config_section_get_string(section, "name", &name, NULL);
> +		if (name == NULL)
> +			continue;
> +
> +		if (name[0] == 'X') {
> +			struct weston_x11_backend_output_config output_config;
> +			output_name = create_config_for_output(section, width,
> +							height, scale,
> +							&output_config.base);
> +			output_config.fullscreen = false;
> +			output = c->backend->create_output(c, name,
> +							   &output_config.base);
> +			free(output_name);
> +		} else {
> +			free(name);
> +			continue;
> +		}
> +		free(name);
> +
> +		if (!output) {
> +			weston_log("Failed to create configured x11 output\n");
> +			ret = -1;
> +			goto cleanup;
> +		}
> +
> +		weston_output_move(output, x, 0);
> +		x = pixman_region32_extents(&output->region)->x2;
> +
> +		output_count++;
> +		if (count && output_count >= count)
> +			break;
> +	}
> +
> +	if (!count)
> +		count = 1;
> +	for (i = output_count; i < count; i++) {
> +		struct weston_x11_backend_output_config output_config = {
> +			.base.width = width,
> +			.base.height = height,
> +			.base.scale = scale,
> +			.base.transform = WL_OUTPUT_TRANSFORM_NORMAL,
> +			.fullscreen = false,
> +		};
> +		output = c->backend->create_output(c, NULL,
> +						   &output_config.base);
> +		if (output == NULL) {
> +			weston_log("Failed to create x11 output #%d\n", i);
> +			ret = -1;
> +			goto cleanup;
> +		}
> +		weston_output_move(output, x, 0);
> +		x = pixman_region32_extents(&output->region)->x2;
> +	}
> +
> +cleanup:
> +	return ret;
> +}
> +
> +static void
> +drm_configure_output(struct weston_compositor *c, const char *name,
> +		     struct weston_drm_backend_output_config *config,
> +		     int (*parse_modeline)(const char *s,
> +				struct weston_drm_backend_modeline *modeline))
> +{
> +	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 (weston_compositor_init_backend(c, backend, &config.base) < 0)
> +		ret = -1;
> +
> +	free(seat);
> +	free(format);
> +	return ret;
> +}
> +
> +static void
> +fbdev_configure_output(struct weston_compositor *c, const char *name,
> +		       struct weston_fbdev_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, "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);
> +}
> +
> +static int
> +init_fbdev_backend(struct weston_compositor *c, const char *backend,
> +		 int *argc, char **argv, struct weston_config *wc)
> +{
> +	struct weston_fbdev_backend_config config = {
> +		.use_gl = false,
> +		.device = NULL,
> +		.tty = 0,
> +		.configure_output = fbdev_configure_output,
> +	};
> +	int ret = 0;
> +	char *device = NULL;
> +
> +	/* TODO: Ideally, available frame buffers should be enumerated using
> +	 * udev, rather than passing a device node in as a parameter. */
> +	const struct weston_option options[] = {
> +		{ WESTON_OPTION_INTEGER, "tty", 0, &config.tty },
> +		{ WESTON_OPTION_STRING, "device", 0, &device },
> +		{ WESTON_OPTION_BOOLEAN, "use-gl", 0, &config.use_gl },
> +	};
> +
> +	parse_options(options, ARRAY_LENGTH(options), argc, argv);
> +
> +	config.device = device;
> +
> +	if (weston_compositor_init_backend(c, backend, &config.base) < 0)
> +		ret = -1;
> +
> +	free(device);
> +	return ret;
> +}
> +
> +static int
> +init_headless_backend(struct weston_compositor *c, const char *backend,
> +		     int *argc, char **argv, struct weston_config *wc)
> +{
> +	struct weston_headless_backend_config config = {
> +		.use_pixman = false,
> +	};
> +	int ret = 0;
> +	int width = 0;
> +	int height = 0;
> +	char *transform = 0;
> +
> +	const struct weston_option options[] = {
> +		{ WESTON_OPTION_INTEGER, "width", 0, &width },
> +		{ WESTON_OPTION_INTEGER, "height", 0, &height },
> +		{ WESTON_OPTION_BOOLEAN, "use-pixman", 0, &config.use_pixman },
> +		{ WESTON_OPTION_STRING, "transform", 0, &transform },
> +	};
> +
> +	parse_options(options, ARRAY_LENGTH(options), argc, argv);
> +
> +	if (weston_compositor_init_backend(c, backend, &config.base) < 0) {
> +		ret = -1;
> +		goto cleanup;
> +	}
> +
> +	if (c->backend->create_output) {
> +		struct weston_backend_output_config output_config;
> +		output_config.width = width ? width: 1024;
> +		output_config.height = height ? height : 640;
> +		output_config.transform = WL_OUTPUT_TRANSFORM_NORMAL;
> +		if (transform &&
> +		    weston_parse_transform(transform, &output_config.transform) < 0)
> +			weston_log("Invalid transform \"%s\"\n", transform);
> +
> +		if (!c->backend->create_output(c, "headless", &output_config))
> +			ret = -1;
> +	} else {
> +		ret = -1;
> +	}
> +
> +cleanup:
> +	free(transform);
> +
> +	return ret;
> +}
> +
> +static int
> +init_rpi_backend(struct weston_compositor *c, const char *backend,
> +		 int *argc, char **argv, struct weston_config *wc)
> +{
> +	struct weston_rpi_backend_config config = {
> +		.tty = 0,
> +		.single_buffer = false,
> +		.opaque_regions = false,
> +		.output_transform = WL_OUTPUT_TRANSFORM_NORMAL,
> +	};
> +	char *transform = NULL;
> +	int ret = 0;
> +
> +	const struct weston_option options[] = {
> +		{ WESTON_OPTION_INTEGER, "tty", 0, &config.tty },
> +		{ WESTON_OPTION_BOOLEAN, "single-buffer", 0, &config.single_buffer },
> +		{ WESTON_OPTION_STRING, "transform", 0, &transform },
> +		{ WESTON_OPTION_BOOLEAN, "opaque-regions", 0, &config.opaque_regions },
> +	};
> +
> +	parse_options(options, ARRAY_LENGTH(options), argc, argv);
> +
> +	if (transform &&
> +	    weston_parse_transform(transform, &config.output_transform) < 0)
> +		weston_log("Invalid transform \"%s\"\n", transform);
> +
> +	if (weston_compositor_init_backend(c, backend, &config.base) < 0)
> +		ret = -1;
> +
> +	free(transform);
> +	return ret;
> +}
> +
> +static int
> +init_rdp_backend(struct weston_compositor *c, const char *backend,
> +		 int *argc, char **argv, struct weston_config *wc)
> +{
> +	struct weston_rdp_backend_config config = {
> +		.width = 640,
> +		.height = 480,
> +		.bind_address = NULL,
> +		.port = 3389,
> +		.rdp_key = NULL,
> +		.server_cert = NULL,
> +		.server_key = NULL,
> +		.env_socket = 0,
> +		.no_clients_resize = 0,
> +	};
> +	int ret = 0;
> +
> +	const struct weston_option options[] = {
> +		{ WESTON_OPTION_BOOLEAN, "env-socket", 0, &config.env_socket },
> +		{ WESTON_OPTION_INTEGER, "width", 0, &config.width },
> +		{ WESTON_OPTION_INTEGER, "height", 0, &config.height },
> +		{ WESTON_OPTION_STRING,  "address", 0, &config.bind_address },
> +		{ WESTON_OPTION_INTEGER, "port", 0, &config.port },
> +		{ WESTON_OPTION_BOOLEAN, "no-clients-resize", 0, &config.no_clients_resize },
> +		{ WESTON_OPTION_STRING,  "rdp4-key", 0, &config.rdp_key },
> +		{ WESTON_OPTION_STRING,  "rdp-tls-cert", 0, &config.server_cert },
> +		{ WESTON_OPTION_STRING,  "rdp-tls-key", 0, &config.server_key }
> +	};
> +
> +	parse_options(options, ARRAY_LENGTH(options), argc, argv);
> +
> +	if (weston_compositor_init_backend(c, backend, &config.base) < 0)
> +		ret = -1;
> +	return ret;
> +}
> +
> +static int
> +init_backend(struct weston_compositor *compositor, const char *backend,
> +	     int *argc, char **argv, struct weston_config *config)
> +{
> +	if (strstr(backend, "wayland-backend.so\0"))
> +		return init_wayland_backend(compositor, backend, argc, argv, config);
> +	else if (strstr(backend, "x11-backend.so\0"))
> +		return init_x11_backend(compositor, backend, argc, argv, config);
> +	else if (strstr(backend, "drm-backend.so\0"))
> +		return init_drm_backend(compositor, backend, argc, argv, config);
> +	else if (strstr(backend, "fbdev-backend.so\0"))
> +		return init_fbdev_backend(compositor, backend, argc, argv, config);
> +	else if (strstr(backend, "headless-backend.so\0"))
> +		return init_headless_backend(compositor, backend, argc, argv, config);
> +	else if (strstr(backend, "rpi-backend.so\0"))
> +		return init_rpi_backend(compositor, backend, argc, argv, config);
> +	else if (strstr(backend, "rdp-backend.so\0"))
> +		return init_rdp_backend(compositor, backend, argc, argv, config);


For these calls to strstr(), is there a reason to add the extra explicit
null chars of "\0"?


> +
> +	return -1;
> +}
> +
>  int main(int argc, char *argv[])
>  {
>  	int ret = EXIT_FAILURE;
> @@ -631,9 +1212,6 @@ int main(int argc, char *argv[])
>  	struct weston_compositor *ec;
>  	struct wl_event_source *signals[4];
>  	struct wl_event_loop *loop;
> -	int (*backend_init)(struct weston_compositor *c,
> -			    int *argc, char *argv[],
> -			    struct weston_config *config);
>  	int i, fd;
>  	char *backend = NULL;
>  	char *shell = NULL;
> @@ -718,11 +1296,7 @@ int main(int argc, char *argv[])
>  			backend = weston_choose_default_backend();
>  	}
>  
> -	backend_init = weston_load_module(backend, "backend_init");
> -	if (!backend_init)
> -		goto out_signals;
> -
> -	ec = weston_compositor_create(display, NULL);
> +	ec = weston_compositor_create(display, config);
>  	if (ec == NULL) {
>  		weston_log("fatal: failed to create compositor\n");
>  		goto out_signals;
> @@ -730,12 +1304,9 @@ int main(int argc, char *argv[])
>  
>  	ec->config = config;
>  	if (weston_compositor_init_config(ec, config) < 0)
> -		goto out_signals;
> -
> -	if (backend_init(ec, &argc, argv, config) < 0) {
> -		weston_log("fatal: failed to create compositor backend\n");
> -		goto out_signals;
> -	}
> +		goto out;
> +	if (init_backend(ec, backend, &argc, argv, config) < 0)
> +		goto out;
>  
>  	catch_signals();
>  	segv_compositor = ec;
> 

-- 
Jon A. Cruz - Senior Open Source Developer
Samsung Open Source Group
jonc at osg.samsung.com


More information about the wayland-devel mailing list