[PATCH weston 04/18] rpi: switch to rpi-renderer

ppaalanen at gmail.com ppaalanen at gmail.com
Wed May 22 08:03:07 PDT 2013


From: Pekka Paalanen <ppaalanen at gmail.com>

Replace the GL renderer with the new rpi-renderer on the Raspberry Pi
backend. This makes Weston on rpi not use EGL or GL anymore, at all.

The weston_plane feature is disabled, since the rpi-renderer does the
same, but better.

Add a command line option to select the output transform. It is not a
weston.ini option for now, since the rpi backend does not read the
configuration file yet. Hopefully that will be done later with some
shared code.

Add the rpi options to 'weston --help' output.

Signed-off-by: Pekka Paalanen <pekka.paalanen at collabora.co.uk>
---
 configure.ac         |   4 +-
 src/compositor-rpi.c | 171 +++++++++++++++++++++++++--------------------------
 src/compositor.c     |  10 +++
 3 files changed, 97 insertions(+), 88 deletions(-)

diff --git a/configure.ac b/configure.ac
index 93a6720..2aec1bb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -146,9 +146,9 @@ AC_ARG_ENABLE(rpi-compositor,
 	      AS_HELP_STRING([--disable-rpi-compositor],
 	                     [do not build the Raspberry Pi backend]),,
 	      enable_rpi_compositor=yes)
-AM_CONDITIONAL(ENABLE_RPI_COMPOSITOR, test "x$enable_rpi_compositor" = "xyes" -a "x$enable_egl" = "xyes")
+AM_CONDITIONAL(ENABLE_RPI_COMPOSITOR, test "x$enable_rpi_compositor" = "xyes")
 have_bcm_host="no"
-if test x$enable_rpi_compositor = xyes -a x$enable_egl = xyes; then
+if test "x$enable_rpi_compositor" = "xyes"; then
   AC_DEFINE([BUILD_RPI_COMPOSITOR], [1], [Build the compositor for Raspberry Pi])
   PKG_CHECK_MODULES(RPI_COMPOSITOR, [libudev >= 136 mtdev >= 1.1.0])
   PKG_CHECK_MODULES(RPI_BCM_HOST, [bcm_host],
diff --git a/src/compositor-rpi.c b/src/compositor-rpi.c
index 3cb2b56..f83e55c 100644
--- a/src/compositor-rpi.c
+++ b/src/compositor-rpi.c
@@ -1,7 +1,7 @@
 /*
  * Copyright © 2008-2011 Kristian Høgsberg
  * Copyright © 2011 Intel Corporation
- * Copyright © 2012 Raspberry Pi Foundation
+ * Copyright © 2012-2013 Raspberry Pi Foundation
  *
  * Permission to use, copy, modify, distribute, and sell this software and
  * its documentation for any purpose is hereby granted without fee, provided
@@ -44,7 +44,7 @@
 #endif
 
 #include "compositor.h"
-#include "gl-renderer.h"
+#include "rpi-renderer.h"
 #include "evdev.h"
 
 /*
@@ -148,8 +148,6 @@ struct rpi_output {
 	struct rpi_flippipe flippipe;
 
 	DISPMANX_DISPLAY_HANDLE_T display;
-	EGL_DISPMANX_WINDOW_T egl_window;
-	DISPMANX_ELEMENT_HANDLE_T egl_element;
 
 	struct wl_list element_list; /* struct rpi_element */
 	struct wl_list old_element_list; /* struct rpi_element */
@@ -910,9 +908,12 @@ rpi_output_repaint(struct weston_output *base, pixman_region32_t *damage)
 	DISPMANX_UPDATE_HANDLE_T update;
 	int layer = 10000;
 
-	DBG("%s\n", __func__);
+	DBG("frame update start\n");
 
-	update = vc_dispmanx_update_start(0);
+	/* Update priority higher than in rpi-renderer's
+	 * output destroy function, see rpi_output_destroy().
+	 */
+	update = vc_dispmanx_update_start(1);
 
 	/* update all live elements */
 	wl_list_for_each(element, &output->element_list, link) {
@@ -923,20 +924,16 @@ rpi_output_repaint(struct weston_output *base, pixman_region32_t *damage)
 	/* remove all unused elements */
 	rpi_remove_elements(&output->old_element_list, update);
 
-	/* schedule callback to rpi_output_update_complete() */
-	rpi_dispmanx_update_submit(update, output);
-
-	/* XXX: if there is anything to composite in GL,
-	 * framerate seems to suffer */
-	/* XXX: optimise the renderer for the case of nothing to render */
-	/* XXX: if nothing to render, remove the element...
-	 * but how, is destroying the EGLSurface a bad performance hit?
-	 */
+	rpi_renderer_set_update_handle(&output->base, update);
 	compositor->base.renderer->repaint_output(&output->base, damage);
 
 	pixman_region32_subtract(&primary_plane->damage,
 				 &primary_plane->damage, damage);
 
+	/* schedule callback to rpi_output_update_complete() */
+	rpi_dispmanx_update_submit(update, output);
+	DBG("frame update submitted\n");
+
 	/* Move the list of elements into the old_element_list. */
 	wl_list_insert_list(&output->old_element_list, &output->element_list);
 	wl_list_init(&output->element_list);
@@ -945,7 +942,9 @@ rpi_output_repaint(struct weston_output *base, pixman_region32_t *damage)
 static void
 rpi_output_update_complete(struct rpi_output *output, uint64_t time)
 {
+	DBG("frame update complete(%" PRIu64 ")\n", time);
 	rpi_output_destroy_old_elements(output);
+	rpi_renderer_finish_frame(&output->base);
 	weston_output_finish_frame(&output->base, time);
 }
 
@@ -958,15 +957,12 @@ rpi_output_destroy(struct weston_output *base)
 
 	DBG("%s\n", __func__);
 
-	rpi_flippipe_release(&output->flippipe);
-
 	update = vc_dispmanx_update_start(0);
 	rpi_remove_elements(&output->element_list, update);
 	rpi_remove_elements(&output->old_element_list, update);
-	vc_dispmanx_element_remove(update, output->egl_element);
 	vc_dispmanx_update_submit_sync(update);
 
-	gl_renderer_output_destroy(base);
+	rpi_renderer_output_destroy(base);
 
 	wl_list_for_each_safe(element, tmp, &output->element_list, link)
 		rpi_element_destroy(element);
@@ -974,6 +970,15 @@ rpi_output_destroy(struct weston_output *base)
 	wl_list_for_each_safe(element, tmp, &output->old_element_list, link)
 		rpi_element_destroy(element);
 
+	/* rpi_renderer_output_destroy() will schedule a removal of
+	 * all Dispmanx Elements, and wait for the update to complete.
+	 * Assuming updates are sequential, the wait should guarantee,
+	 * that any pending rpi_flippipe_update_complete() callbacks
+	 * have happened already. Therefore we can destroy the flippipe
+	 * now.
+	 */
+	rpi_flippipe_release(&output->flippipe);
+
 	wl_list_remove(&output->base.link);
 	weston_output_destroy(&output->base);
 
@@ -982,21 +987,45 @@ rpi_output_destroy(struct weston_output *base)
 	free(output);
 }
 
+static const char *transform_names[] = {
+	[WL_OUTPUT_TRANSFORM_NORMAL] = "normal",
+	[WL_OUTPUT_TRANSFORM_90] = "90",
+	[WL_OUTPUT_TRANSFORM_180] = "180",
+	[WL_OUTPUT_TRANSFORM_270] = "270",
+	[WL_OUTPUT_TRANSFORM_FLIPPED] = "flipped",
+	[WL_OUTPUT_TRANSFORM_FLIPPED_90] = "flipped-90",
+	[WL_OUTPUT_TRANSFORM_FLIPPED_180] = "flipped-180",
+	[WL_OUTPUT_TRANSFORM_FLIPPED_270] = "flipped-270",
+};
+
+static int
+str2transform(const char *name)
+{
+	unsigned i;
+
+	for (i = 0; i < ARRAY_LENGTH(transform_names); i++)
+		if (strcmp(name, transform_names[i]) == 0)
+			return i;
+
+	return -1;
+}
+
+static const char *
+transform2str(uint32_t output_transform)
+{
+	if (output_transform >= ARRAY_LENGTH(transform_names))
+		return "<illegal value>";
+
+	return transform_names[output_transform];
+}
+
 static int
-rpi_output_create(struct rpi_compositor *compositor)
+rpi_output_create(struct rpi_compositor *compositor, uint32_t transform)
 {
 	struct rpi_output *output;
 	DISPMANX_MODEINFO_T modeinfo;
-	DISPMANX_UPDATE_HANDLE_T update;
-	VC_RECT_T dst_rect;
-	VC_RECT_T src_rect;
 	int ret;
 	float mm_width, mm_height;
-	VC_DISPMANX_ALPHA_T alphasetup = {
-		DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS,
-		255, /* opacity 0-255 */
-		0 /* mask resource handle */
-	};
 
 	output = calloc(1, sizeof *output);
 	if (!output)
@@ -1024,32 +1053,10 @@ rpi_output_create(struct rpi_compositor *compositor)
 		goto out_dmx_close;
 	}
 
-	vc_dispmanx_rect_set(&dst_rect, 0, 0, modeinfo.width, modeinfo.height);
-	vc_dispmanx_rect_set(&src_rect, 0, 0,
-			     modeinfo.width << 16, modeinfo.height << 16);
-
-	update = vc_dispmanx_update_start(0);
-	output->egl_element = vc_dispmanx_element_add(update,
-						      output->display,
-						      0 /* layer */,
-						      &dst_rect,
-						      0 /* src resource */,
-						      &src_rect,
-						      DISPMANX_PROTECTION_NONE,
-						      &alphasetup,
-						      NULL /* clamp */,
-						      DISPMANX_NO_ROTATE);
-	vc_dispmanx_update_submit_sync(update);
-
-	output->egl_window.element = output->egl_element;
-	output->egl_window.width = modeinfo.width;
-	output->egl_window.height = modeinfo.height;
-
 	output->base.start_repaint_loop = rpi_output_start_repaint_loop;
 	output->base.repaint = rpi_output_repaint;
 	output->base.destroy = rpi_output_destroy;
-	if (compositor->max_planes > 0)
-		output->base.assign_planes = rpi_output_assign_planes;
+	output->base.assign_planes = NULL;
 	output->base.set_backlight = NULL;
 	output->base.set_dpms = NULL;
 	output->base.switch_mode = NULL;
@@ -1080,36 +1087,27 @@ rpi_output_create(struct rpi_compositor *compositor)
 
 	weston_output_init(&output->base, &compositor->base,
 			   0, 0, round(mm_width), round(mm_height),
-			   WL_OUTPUT_TRANSFORM_NORMAL);
+			   transform);
 
-	if (gl_renderer_output_create(&output->base,
-			(EGLNativeWindowType)&output->egl_window) < 0)
+	if (rpi_renderer_output_create(&output->base, output->display) < 0)
 		goto out_output;
 
-	if (!eglSurfaceAttrib(gl_renderer_display(&compositor->base),
-			      gl_renderer_output_surface(&output->base),
-			      EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED)) {
-		weston_log("Failed to set swap behaviour to preserved.\n");
-		gl_renderer_print_egl_error_state();
-		goto out_gl;
-	}
-
 	wl_list_insert(compositor->base.output_list.prev, &output->base.link);
 
 	weston_log("Raspberry Pi HDMI output %dx%d px\n",
 		   output->mode.width, output->mode.height);
 	weston_log_continue(STAMP_SPACE "guessing %d Hz and 96 dpi\n",
 			    output->mode.refresh / 1000);
+	weston_log_continue(STAMP_SPACE "orientation: %s\n",
+			    transform2str(output->base.transform));
+
+	if (!strncmp(transform2str(output->base.transform), "flipped", 7))
+		weston_log("warning: flipped output transforms may not work\n");
 
 	return 0;
 
-out_gl:
-	gl_renderer_output_destroy(&output->base);
 out_output:
 	weston_output_destroy(&output->base);
-	update = vc_dispmanx_update_start(0);
-	vc_dispmanx_element_remove(update, output->egl_element);
-	vc_dispmanx_update_submit_sync(update);
 
 out_dmx_close:
 	vc_dispmanx_display_close(output->display);
@@ -1436,7 +1434,8 @@ switch_vt_binding(struct weston_seat *seat, uint32_t time, uint32_t key, void *d
 struct rpi_parameters {
 	int tty;
 	int max_planes;
-	int single_buffer;
+	struct rpi_renderer_parameters renderer;
+	uint32_t output_transform;
 };
 
 static struct weston_compositor *
@@ -1446,16 +1445,6 @@ rpi_compositor_create(struct wl_display *display, int *argc, char *argv[],
 	struct rpi_compositor *compositor;
 	const char *seat = default_seat;
 	uint32_t key;
-	static const EGLint config_attrs[] = {
-		EGL_SURFACE_TYPE, EGL_WINDOW_BIT |
-				  EGL_SWAP_BEHAVIOR_PRESERVED_BIT,
-		EGL_RED_SIZE, 1,
-		EGL_GREEN_SIZE, 1,
-		EGL_BLUE_SIZE, 1,
-		EGL_ALPHA_SIZE, 0,
-		EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
-		EGL_NONE
-	};
 
 	weston_log("initializing Raspberry Pi backend\n");
 
@@ -1485,7 +1474,7 @@ rpi_compositor_create(struct wl_display *display, int *argc, char *argv[],
 	compositor->base.focus = 1;
 	compositor->prev_state = WESTON_COMPOSITOR_ACTIVE;
 	compositor->max_planes = int_max(param->max_planes, 0);
-	compositor->single_buffer = param->single_buffer;
+	compositor->single_buffer = param->renderer.single_buffer;
 
 	weston_log("Maximum number of additional Dispmanx planes: %d\n",
 		   compositor->max_planes);
@@ -1506,18 +1495,17 @@ rpi_compositor_create(struct wl_display *display, int *argc, char *argv[],
 	 */
 	bcm_host_init();
 
-	if (gl_renderer_create(&compositor->base, EGL_DEFAULT_DISPLAY,
-		config_attrs, NULL) < 0)
+	if (rpi_renderer_create(&compositor->base, &param->renderer) < 0)
 		goto out_tty;
 
-	if (rpi_output_create(compositor) < 0)
-		goto out_gl;
+	if (rpi_output_create(compositor, param->output_transform) < 0)
+		goto out_renderer;
 
 	evdev_input_create(&compositor->base, compositor->udev, seat);
 
 	return &compositor->base;
 
-out_gl:
+out_renderer:
 	compositor->base.renderer->destroy(&compositor->base);
 
 out_tty:
@@ -1556,20 +1544,31 @@ WL_EXPORT struct weston_compositor *
 backend_init(struct wl_display *display, int *argc, char *argv[],
 	     int config_fd)
 {
+	const char *transform = "normal";
+	int ret;
+
 	struct rpi_parameters param = {
 		.tty = 0, /* default to current tty */
 		.max_planes = DEFAULT_MAX_PLANES,
-		.single_buffer = 0,
+		.renderer.single_buffer = 0,
+		.output_transform = WL_OUTPUT_TRANSFORM_NORMAL,
 	};
 
 	const struct weston_option rpi_options[] = {
 		{ WESTON_OPTION_INTEGER, "tty", 0, &param.tty },
 		{ WESTON_OPTION_INTEGER, "max-planes", 0, &param.max_planes },
 		{ WESTON_OPTION_BOOLEAN, "single-buffer", 0,
-		  &param.single_buffer },
+		  &param.renderer.single_buffer },
+		{ WESTON_OPTION_STRING, "transform", 0, &transform },
 	};
 
 	parse_options(rpi_options, ARRAY_LENGTH(rpi_options), argc, argv);
 
+	ret = str2transform(transform);
+	if (ret < 0)
+		weston_log("invalid transform \"%s\"\n", transform);
+	else
+		param.output_transform = ret;
+
 	return rpi_compositor_create(display, argc, argv, config_fd, &param);
 }
diff --git a/src/compositor.c b/src/compositor.c
index 33010dd..65da583 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -3107,6 +3107,16 @@ usage(int error_code)
 		"  --height=HEIGHT\tHeight of Wayland surface\n"
 		"  --display=DISPLAY\tWayland display to connect to\n\n");
 
+#if defined(BUILD_RPI_COMPOSITOR) && defined(HAVE_BCM_HOST)
+	fprintf(stderr,
+		"Options for rpi-backend.so:\n\n"
+		"  --tty=TTY\t\tThe tty to use\n"
+		"  --single-buffer\tUse single-buffered Dispmanx elements.\n"
+		"  --transform=TR\tThe output transformation, TR is one of:\n"
+		"\tnormal 90 180 270 flipped flipped-90 flipped-180 flipped-270\n"
+		"\n");
+#endif
+
 	exit(error_code);
 }
 
-- 
1.8.1.5



More information about the wayland-devel mailing list