[PATCH 4/9] output gl repaint in clone mode

Xiong Zhang xiong.y.zhang at intel.com
Tue Sep 17 20:50:59 PDT 2013


Only repsone to primary output repaint request; Primary output and
clone output share the same frame buffer, once primary output do page
flip, clone output will do page flip also. When both primary output
and clone output finish the page flip, the fb obj can be released.

Signed-off-by: Xiong Zhang <xiong.y.zhang at intel.com>
---
 src/compositor-drm.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/compositor.c     |   9 +++++
 2 files changed, 110 insertions(+)

diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index 8d16d29..0b9ab45 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -103,6 +103,8 @@ struct drm_compositor {
 
 	clockid_t clock;
 	struct udev_input input;
+
+	uint32_t flip_counter;
 };
 
 struct drm_mode {
@@ -581,6 +583,12 @@ drm_output_repaint(struct weston_output *output_base,
 	struct drm_sprite *s;
 	struct drm_mode *mode;
 	int ret = 0;
+	struct drm_output *clone_output;
+
+	/*ignore clone output repaint request*/
+	if ((compositor->base.multiscreen_mode == WESTON_MULTISCREEN_CLONE) &&
+			output_base != compositor->base.primary_output)
+		return;
 
 	if (!output->next)
 		drm_output_render(output, damage);
@@ -598,6 +606,22 @@ drm_output_repaint(struct weston_output *output_base,
 			return;
 		}
 		output_base->set_dpms(output_base, WESTON_DPMS_ON);
+		if (compositor->base.multiscreen_mode == WESTON_MULTISCREEN_CLONE) {
+			wl_list_for_each(clone_output, &compositor->base.output_list, base.link) {
+				if (&clone_output->base != output_base) {
+					mode = container_of(clone_output->base.current, struct drm_mode, base);
+					ret = drmModeSetCrtc(compositor->drm.fd, clone_output->crtc_id,
+										output->next->fb_id, 0, 0,
+										&clone_output->connector_id, 1,
+										&mode->mode_info);
+					if (ret) {
+						weston_log("set mode failed: %m\n");
+						return;
+					}
+					clone_output->base.set_dpms(&clone_output->base, WESTON_DPMS_ON);
+				}
+			}
+		}
 	}
 
 	if (drmModePageFlip(compositor->drm.fd, output->crtc_id,
@@ -608,6 +632,21 @@ drm_output_repaint(struct weston_output *output_base,
 	}
 
 	output->page_flip_pending = 1;
+	compositor->flip_counter++;
+
+	if (compositor->base.multiscreen_mode == WESTON_MULTISCREEN_CLONE) {
+		wl_list_for_each(clone_output, &compositor->base.output_list, base.link) {
+			if (&clone_output->base != output_base) {
+				if (drmModePageFlip(compositor->drm.fd, clone_output->crtc_id,
+								output->next->fb_id,
+								DRM_MODE_PAGE_FLIP_EVENT, clone_output) < 0) {
+					weston_log("queueing pageflip failed: %m\n");
+					return;
+				}
+				compositor->flip_counter++;
+			}
+		}
+	}
 
 	drm_output_set_cursor(output);
 
@@ -666,9 +705,19 @@ drm_output_start_repaint_loop(struct weston_output *output_base)
 	struct drm_compositor *compositor = (struct drm_compositor *)
 		output_base->compositor;
 	uint32_t fb_id;
+	struct drm_output *clone_output;
 
 	struct timespec ts;
 
+	/* ignore clone output repaint request */
+	/* clear clone_output->repaint_scheduled, so when clone_output became primary */
+	/* output, it can repaint */
+	if ((compositor->base.multiscreen_mode == WESTON_MULTISCREEN_CLONE) &&
+			output_base != compositor->base.primary_output) {
+		output_base->repaint_scheduled = 0;
+		return;
+	}
+
 	if (!output->current) {
 		/* We can't page flip if there's no mode set */
 		uint32_t msec;
@@ -686,6 +735,21 @@ drm_output_start_repaint_loop(struct weston_output *output_base)
 		weston_log("queueing pageflip failed: %m\n");
 		return;
 	}
+	compositor->flip_counter++;
+
+	/*clone output repiant*/
+	if (compositor->base.multiscreen_mode == WESTON_MULTISCREEN_CLONE) {
+		wl_list_for_each(clone_output, &compositor->base.output_list, base.link) {
+			if (compositor->base.primary_output != &clone_output->base) {
+				if (drmModePageFlip(compositor->drm.fd, clone_output->crtc_id, fb_id,
+						DRM_MODE_PAGE_FLIP_EVENT, clone_output) < 0) {
+					weston_log("queueing pageflip failed: %m\n");
+					return;
+				}
+				compositor->flip_counter++;
+			}
+		}
+	}
 }
 
 static void
@@ -714,6 +778,15 @@ page_flip_handler(int fd, unsigned int frame,
 {
 	struct drm_output *output = (struct drm_output *) data;
 	uint32_t msecs;
+	struct drm_compositor *c = (struct drm_compositor *)output->base.compositor;
+
+	if ((--c->flip_counter != 0) &&
+		(c->base.multiscreen_mode == WESTON_MULTISCREEN_CLONE))
+		return;
+
+	if ((c->base.multiscreen_mode == WESTON_MULTISCREEN_CLONE) &&
+		(&output->base != c->base.primary_output))
+		output = (struct drm_output *)c->base.primary_output;
 
 	/* We don't set page_flip_pending on start_repaint_loop, in that case
 	 * we just want to page flip to the current buffer to get an accurate
@@ -947,10 +1020,17 @@ drm_output_set_cursor(struct drm_output *output)
 	uint32_t buf[64 * 64];
 	unsigned char *s;
 	int i, x, y;
+	struct drm_output *clone_output;
 
 	output->cursor_surface = NULL;
 	if (es == NULL) {
 		drmModeSetCursor(c->drm.fd, output->crtc_id, 0, 0, 0);
+		if (c->base.multiscreen_mode == WESTON_MULTISCREEN_CLONE) {
+			wl_list_for_each(clone_output, &c->base.output_list, base.link) {
+				if (&clone_output->base != c->base.primary_output)
+					drmModeSetCursor(c->drm.fd, clone_output->crtc_id, 0, 0, 0);
+			}
+		}
 		return;
 	}
 
@@ -976,6 +1056,16 @@ drm_output_set_cursor(struct drm_output *output)
 			weston_log("failed to set cursor: %m\n");
 			c->cursors_are_broken = 1;
 		}
+		if (c->base.multiscreen_mode == WESTON_MULTISCREEN_CLONE) {
+			wl_list_for_each(clone_output, &c->base.output_list, base.link) {
+				if ((&clone_output->base != c->base.primary_output) &&
+					(drmModeSetCursor(c->drm.fd,
+									  clone_output->crtc_id, handle, 64, 64) < 0)) {
+					weston_log("failed to set cursor:%m\n");
+					c->cursors_are_broken = 1;
+				}
+			}
+		}
 	}
 
 	x = (es->geometry.x - output->base.x) * output->base.scale;
@@ -989,6 +1079,17 @@ drm_output_set_cursor(struct drm_output *output)
 		output->cursor_plane.x = x;
 		output->cursor_plane.y = y;
 	}
+	if (c->base.multiscreen_mode == WESTON_MULTISCREEN_CLONE) {
+		wl_list_for_each(clone_output, &c->base.output_list, base.link) {
+			if ((&clone_output->base != c->base.primary_output) &&
+				drmModeMoveCursor(c->drm.fd, clone_output->crtc_id, x, y) < 0) {
+				weston_log("failed to move cursor: %m\n");
+				c->cursors_are_broken = 1;
+			}
+			clone_output->cursor_plane.x = x;
+			clone_output->cursor_plane.y = y;
+		}
+	}
 }
 
 static void
diff --git a/src/compositor.c b/src/compositor.c
index f9e9ba1..5d927fd 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -564,6 +564,9 @@ weston_surface_assign_output(struct weston_surface *es)
 			new_output = output;
 			max = area;
 		}
+		/*surface can only be assigned to primary output in clone mode */
+		if (ec->multiscreen_mode == WESTON_MULTISCREEN_CLONE)
+			break;
 	}
 	pixman_region32_fini(&region);
 
@@ -1294,6 +1297,12 @@ weston_output_repaint(struct weston_output *output, uint32_t msecs)
 	struct wl_list frame_callback_list;
 	pixman_region32_t output_damage;
 
+	/* ignore clone output repaint request */
+	if ((ec->multiscreen_mode == WESTON_MULTISCREEN_CLONE) &&
+		(output != ec->primary_output)) {
+		return;
+	}
+
 	/* Rebuild the surface list and update surface transforms up front. */
 	weston_compositor_build_surface_list(ec);
 
-- 
1.8.3.2



More information about the wayland-devel mailing list