[PATCH weston 7/7] compositor-drm: Add support for using the pixman renderer

Ander Conselvan de Oliveira ander.conselvan.de.oliveira at intel.com
Tue Jan 22 08:07:15 PST 2013


If --use-pixman is passed as command line option to weston, the drm
backend will use the pixman renderer instead of the gl one.
---
 src/compositor-drm.c |  209 ++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 187 insertions(+), 22 deletions(-)

diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index 7c11af1..0bc2990 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -42,6 +42,7 @@
 
 #include "compositor.h"
 #include "gl-renderer.h"
+#include "pixman-renderer.h"
 #include "evdev.h"
 #include "launcher-util.h"
 
@@ -104,6 +105,8 @@ struct drm_compositor {
 
 	int cursors_are_broken;
 
+	int use_pixman;
+
 	uint32_t prev_state;
 };
 
@@ -145,6 +148,11 @@ struct drm_output {
 	int current_cursor;
 	struct drm_fb *current, *next;
 	struct backlight *backlight;
+
+	struct drm_fb *dumb[2];
+	pixman_image_t *image[2];
+	int current_image;
+	pixman_region32_t previous_damage;
 };
 
 /*
@@ -376,7 +384,8 @@ drm_output_release_fb(struct drm_output *output, struct drm_fb *fb)
 	if (!fb)
 		return;
 
-	if (fb->map) {
+	if (fb->map &&
+            (fb != output->dumb[0] && fb != output->dumb[1])) {
 		drm_fb_destroy_dumb(fb);
 	} else if (fb->bo) {
 		if (fb->is_client_buffer)
@@ -432,7 +441,7 @@ drm_output_prepare_scanout_surface(struct weston_output *_output,
 
 	if (es->geometry.x != output->base.x ||
 	    es->geometry.y != output->base.y ||
-	    buffer == NULL ||
+	    buffer == NULL || c->gbm == NULL ||
 	    buffer->width != output->base.current->width ||
 	    buffer->height != output->base.current->height ||
 	    output->base.transform != es->buffer_transform ||
@@ -464,7 +473,7 @@ drm_output_prepare_scanout_surface(struct weston_output *_output,
 }
 
 static void
-drm_output_render(struct drm_output *output, pixman_region32_t *damage)
+drm_output_render_gl(struct drm_output *output, pixman_region32_t *damage)
 {
 	struct drm_compositor *c =
 		(struct drm_compositor *) output->base.compositor;
@@ -472,9 +481,6 @@ drm_output_render(struct drm_output *output, pixman_region32_t *damage)
 
 	c->base.renderer->repaint_output(&output->base, damage);
 
-	pixman_region32_subtract(&c->base.primary_plane.damage,
-				 &c->base.primary_plane.damage, damage);
-
 	bo = gbm_surface_lock_front_buffer(output->surface);
 	if (!bo) {
 		weston_log("failed to lock front buffer: %m\n");
@@ -490,6 +496,47 @@ drm_output_render(struct drm_output *output, pixman_region32_t *damage)
 }
 
 static void
+drm_output_render_pixman(struct drm_output *output, pixman_region32_t *damage)
+{
+	struct weston_compositor *ec = output->base.compositor;
+	pixman_region32_t total_damage, previous_damage;
+
+	pixman_region32_init(&total_damage);
+	pixman_region32_init(&previous_damage);
+
+	pixman_region32_copy(&previous_damage, damage);
+
+	pixman_region32_union(&total_damage, damage, &output->previous_damage);
+	pixman_region32_copy(&output->previous_damage, &previous_damage);
+
+	output->current_image ^= 1;
+
+	output->next = output->dumb[output->current_image];
+	pixman_renderer_output_set_buffer(&output->base,
+					  output->image[output->current_image]);
+
+	ec->renderer->repaint_output(&output->base, &total_damage);
+
+	pixman_region32_fini(&total_damage);
+	pixman_region32_fini(&previous_damage);
+}
+
+static void
+drm_output_render(struct drm_output *output, pixman_region32_t *damage)
+{
+	struct drm_compositor *c =
+		(struct drm_compositor *) output->base.compositor;
+
+	if (c->use_pixman)
+		drm_output_render_pixman(output, damage);
+	else
+		drm_output_render_gl(output, damage);
+
+	pixman_region32_subtract(&c->base.primary_plane.damage,
+				 &c->base.primary_plane.damage, damage);
+}
+
+static void
 drm_output_repaint(struct weston_output *output_base,
 		   pixman_region32_t *damage)
 {
@@ -688,6 +735,9 @@ drm_output_prepare_overlay_surface(struct weston_output *output_base,
 	uint32_t format;
 	wl_fixed_t sx1, sy1, sx2, sy2;
 
+	if (c->gbm == NULL)
+		return NULL;
+
 	if (es->buffer_transform != output_base->transform)
 		return NULL;
 
@@ -814,6 +864,8 @@ drm_output_prepare_cursor_surface(struct weston_output *output_base,
 		(struct drm_compositor *) output_base->compositor;
 	struct drm_output *output = (struct drm_output *) output_base;
 
+	if (c->gbm == NULL)
+		return NULL;
 	if (output->base.transform != WL_OUTPUT_TRANSFORM_NORMAL)
 		return NULL;
 	if (output->cursor_surface)
@@ -964,6 +1016,9 @@ drm_assign_planes(struct weston_output *output)
 }
 
 static void
+drm_output_fini_pixman(struct drm_output *output);
+
+static void
 drm_output_destroy(struct weston_output *output_base)
 {
 	struct drm_output *output = (struct drm_output *) output_base;
@@ -986,9 +1041,12 @@ drm_output_destroy(struct weston_output *output_base)
 	c->crtc_allocator &= ~(1 << output->crtc_id);
 	c->connector_allocator &= ~(1 << output->connector_id);
 
-	gl_renderer_output_destroy(output_base);
-
-	gbm_surface_destroy(output->surface);
+	if (c->use_pixman) {
+		drm_output_fini_pixman(output);
+	} else {
+		gl_renderer_output_destroy(output_base);
+		gbm_surface_destroy(output->surface);
+	}
 
 	weston_plane_release(&output->fb_plane);
 	weston_plane_release(&output->cursor_plane);
@@ -1027,6 +1085,8 @@ choose_mode (struct drm_output *output, struct weston_mode *target_mode)
 
 static int
 drm_output_init_egl(struct drm_output *output, struct drm_compositor *ec);
+static int
+drm_output_init_pixman(struct drm_output *output);
 
 static int
 drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mode)
@@ -1068,12 +1128,22 @@ drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mo
 	drm_output_release_fb(output, output->next);
 	output->current = output->next = NULL;
 
-	gl_renderer_output_destroy(&output->base);
-	gbm_surface_destroy(output->surface);
+	if (ec->use_pixman) {
+		drm_output_fini_pixman(output);
+		if (drm_output_init_pixman(output) < 0) {
+			weston_log("failed to init output pixman state with "
+				   "new mode\n");
+			return -1;
+		}
+	} else {
+		gl_renderer_output_destroy(&output->base);
+		gbm_surface_destroy(output->surface);
 
-	if (drm_output_init_egl(output, ec) < 0) {
-		weston_log("failed to init output egl state with new mode");
-		return -1;
+		if (drm_output_init_egl(output, ec) < 0) {
+			weston_log("failed to init output egl state with "
+				   "new mode");
+			return -1;
+		}
 	}
 
 	return 0;
@@ -1151,6 +1221,26 @@ init_egl(struct drm_compositor *ec)
 	return 0;
 }
 
+static int
+init_pixman(struct drm_compositor *ec)
+{
+	struct drm_output *output;
+
+	if (pixman_renderer_init(&ec->base) < 0)
+		return -1;
+
+	wl_list_for_each(output, &ec->base.output_list, base.link) {
+		if (drm_output_init_pixman(output) < 0) {
+			weston_log("Failed to init pixman state for output %s\n",
+				   output->name);
+			weston_output_destroy(&output->base);
+			wl_list_remove(&output->base.link);
+		}
+	}
+
+	return 0;
+}
+
 static struct drm_mode *
 drm_output_add_mode(struct drm_output *output, drmModeModeInfo *info)
 {
@@ -1376,6 +1466,68 @@ drm_output_init_egl(struct drm_output *output, struct drm_compositor *ec)
 }
 
 static int
+drm_output_init_pixman(struct drm_output *output)
+{
+	struct drm_compositor *c = (struct drm_compositor *)
+		output->base.compositor;
+	int w = output->base.current->width;
+	int h = output->base.current->height;
+	unsigned int i;
+
+	/* FIXME error checking */
+
+	for (i = 0; i < ARRAY_LENGTH(output->dumb); i++) {
+		output->dumb[i] = drm_fb_create_dumb(c, w, h);
+		if (!output->dumb[i])
+			goto err;
+
+		output->image[i] =
+			pixman_image_create_bits(PIXMAN_x8r8g8b8, w, h,
+						 output->dumb[i]->map,
+						 output->dumb[i]->stride);
+		if (!output->image[i])
+			goto err;
+	}
+
+	if (pixman_renderer_output_create(&output->base) < 0)
+		goto err;
+
+	pixman_region32_init_rect(&output->previous_damage,
+				  output->base.x, output->base.y, w, h);
+
+	return 0;
+
+err:
+	for (i = 0; i < ARRAY_LENGTH(output->dumb); i++) {
+		if (output->dumb[i])
+			drm_fb_destroy_dumb(output->dumb[i]);
+		if (output->image[i])
+			pixman_image_unref(output->image[i]);
+
+		output->dumb[i] = NULL;
+		output->image[i] = NULL;
+	}
+
+	return -1;
+}
+
+static void
+drm_output_fini_pixman(struct drm_output *output)
+{
+	unsigned int i;
+
+	pixman_renderer_output_destroy(&output->base);
+	pixman_region32_fini(&output->previous_damage);
+
+	for (i = 0; i < ARRAY_LENGTH(output->dumb); i++) {
+		drm_fb_destroy_dumb(output->dumb[i]);
+		pixman_image_unref(output->image[i]);
+		output->dumb[i] = NULL;
+		output->image[i] = NULL;
+	}
+}
+
+static int
 create_output_for_connector(struct drm_compositor *ec,
 			    drmModeRes *resources,
 			    drmModeConnector *connector,
@@ -2099,7 +2251,10 @@ drm_destroy(struct weston_compositor *ec)
 	ec->renderer->destroy(ec);
 
 	destroy_sprites(d);
-	gbm_device_destroy(d->gbm);
+
+	if (d->gbm)
+		gbm_device_destroy(d->gbm);
+
 	if (weston_launcher_drm_set_master(&d->base, d->drm.fd, 0) < 0)
 		weston_log("failed to drop master: %m\n");
 	tty_destroy(d->tty);
@@ -2279,7 +2434,7 @@ planes_binding(struct wl_seat *seat, uint32_t time, uint32_t key, void *data)
 
 static struct weston_compositor *
 drm_compositor_create(struct wl_display *display,
-		      int connector, const char *seat, int tty,
+		      int connector, const char *seat, int tty, int pixman,
 		      int argc, char *argv[], const char *config_file)
 {
 	struct drm_compositor *ec;
@@ -2300,6 +2455,8 @@ drm_compositor_create(struct wl_display *display,
 	 * functionality for now. */
 	ec->sprites_are_broken = 1;
 
+	ec->use_pixman = pixman;
+
 	if (weston_compositor_init(&ec->base, display, argc, argv,
 				   config_file) < 0) {
 		weston_log("weston_compositor_init failed\n");
@@ -2351,9 +2508,16 @@ drm_compositor_create(struct wl_display *display,
 		goto err_sprite;
 	}
 
-	if (init_egl(ec) < 0) {
-		weston_log("failed to initialize egl\n");
-		goto err_udev_dev;
+	if (ec->use_pixman) {
+		if (init_pixman(ec) < 0) {
+			weston_log("failed to initialize pixman renderer\n");
+			goto err_udev_dev;
+		}
+	} else {
+		if (init_egl(ec) < 0) {
+			weston_log("failed to initialize egl\n");
+			goto err_udev_dev;
+		}
 	}
 
 	path = NULL;
@@ -2565,7 +2729,7 @@ WL_EXPORT struct weston_compositor *
 backend_init(struct wl_display *display, int argc, char *argv[],
 	     const char *config_file)
 {
-	int connector = 0, tty = 0;
+	int connector = 0, tty = 0, use_pixman = 0;
 	const char *seat = default_seat;
 
 	const struct weston_option drm_options[] = {
@@ -2573,6 +2737,7 @@ backend_init(struct wl_display *display, int argc, char *argv[],
 		{ WESTON_OPTION_STRING, "seat", 0, &seat },
 		{ WESTON_OPTION_INTEGER, "tty", 0, &tty },
 		{ WESTON_OPTION_BOOLEAN, "current-mode", 0, &option_current_mode },
+		{ WESTON_OPTION_BOOLEAN, "use-pixman", 0, &use_pixman },
 	};
 
 	parse_options(drm_options, ARRAY_LENGTH(drm_options), argc, argv);
@@ -2593,6 +2758,6 @@ backend_init(struct wl_display *display, int argc, char *argv[],
 	parse_config_file(config_file, config_section,
 				ARRAY_LENGTH(config_section), NULL);
 
-	return drm_compositor_create(display, connector, seat, tty, argc, argv,
-				     config_file);
+	return drm_compositor_create(display, connector, seat, tty, use_pixman,
+				     argc, argv, config_file);
 }
-- 
1.7.10.4



More information about the wayland-devel mailing list