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

Giulio Camuffo giuliocamuffo at gmail.com
Sat Jun 27 04:07:44 PDT 2015


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/main.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 31a2f45..b8f7823 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 =				\
 	$(AM_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 =				\
 	$(AM_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 =			\
 	$(AM_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) $(AM_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 =			\
 	$(AM_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 =				\
 	$(AM_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 150d1fb..5e7a758 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -4544,6 +4544,43 @@ fail:
 	return NULL;
 }
 
+/** 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
+ * ::weston_backend_config.
+ * 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)
 {
@@ -4734,7 +4771,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 faaacc2..781653e 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 *
@@ -1553,8 +1570,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/main.c b/src/main.c
index a2ed2b4..d629c58 100644
--- a/src/main.c
+++ b/src/main.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;
 
@@ -629,6 +639,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"))
+		return init_wayland_backend(compositor, backend, argc, argv, config);
+	else if (strstr(backend, "x11-backend.so"))
+		return init_x11_backend(compositor, backend, argc, argv, config);
+	else if (strstr(backend, "drm-backend.so"))
+		return init_drm_backend(compositor, backend, argc, argv, config);
+	else if (strstr(backend, "fbdev-backend.so"))
+		return init_fbdev_backend(compositor, backend, argc, argv, config);
+	else if (strstr(backend, "headless-backend.so"))
+		return init_headless_backend(compositor, backend, argc, argv, config);
+	else if (strstr(backend, "rpi-backend.so"))
+		return init_rpi_backend(compositor, backend, argc, argv, config);
+	else if (strstr(backend, "rdp-backend.so"))
+		return init_rdp_backend(compositor, backend, argc, argv, config);
+
+	return -1;
+}
+
 int main(int argc, char *argv[])
 {
 	int ret = EXIT_FAILURE;
@@ -636,9 +1217,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;
@@ -723,11 +1301,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;
@@ -735,12 +1309,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;
-- 
2.4.4



More information about the wayland-devel mailing list