[PATCH 2/9] find primary output during drm_compositor_create in clone mode
Xiong Zhang
xiong.y.zhang at intel.com
Tue Sep 17 20:50:57 PDT 2013
the output with most width will be selected as primary output.
primary output occupy the first position in weston_compositor->output_list
if clone_output's height is larger than primary_output's height
clone_output's mode should be changed, otherwise the setting mode
for clone_output will fail. choose a nearest mode below primary_output's
mode.
Signed-off-by: Xiong Zhang <xiong.y.zhang at intel.com>
---
src/compositor-drm.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 97 insertions(+), 3 deletions(-)
diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index 1e2f3ab..8d16d29 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -1051,6 +1051,97 @@ drm_assign_planes(struct weston_output *output)
pixman_region32_fini(&overlap);
}
+/* the output with maximum width is the primary output */
+static struct drm_output *
+choose_output(struct drm_output *primary,
+ struct drm_output *clone)
+{
+ if (clone->base.current->width > primary->base.current->width)
+ primary = clone;
+
+ return primary;
+}
+
+/*if clone_output's height > primary_output's height */
+/*clone_output's mode shoulde be changed, or else set mode for clone_output */
+/*will fail. Choose a nearest mode below primary_output's current_mode */
+static void
+adjust_clone_output_mode(struct drm_output *clone_output)
+{
+ struct drm_mode *mode, *choose_mode;
+ uint32_t multiple_delta, choose_delta;
+ struct weston_mode *current_mode;
+
+ choose_mode = NULL;
+ choose_delta = 0xffffffff;
+ current_mode = clone_output->base.compositor->primary_output->current;
+
+ wl_list_for_each(mode, &clone_output->base.mode_list, base.link) {
+ if (mode->mode_info.hdisplay <= current_mode->width &&
+ mode->mode_info.vdisplay <= current_mode->height) {
+ if (mode->mode_info.hdisplay == current_mode->width) {
+ choose_mode = mode;
+ break;
+ } else if (mode->mode_info.vdisplay == current_mode->height) {
+ choose_mode = mode;
+ break;
+ } else {
+ multiple_delta = (current_mode->width - mode->mode_info.hdisplay) *
+ (current_mode->height - mode->mode_info.vdisplay);
+ if (multiple_delta < choose_delta) {
+ choose_delta = multiple_delta;
+ choose_mode = mode;
+ }
+ }
+ }
+ }
+ if (!choose_mode) {
+ weston_log("clone mode fail in chooseing mode for clone output\n");
+ return;
+ }
+ clone_output->base.current->flags &= ~WL_OUTPUT_MODE_CURRENT;
+ clone_output->base.current = &choose_mode->base;
+ clone_output->base.current->flags |= WL_OUTPUT_MODE_CURRENT;
+}
+
+static int
+clone_output_need_adjust_mode(struct drm_output *clone_output)
+{
+ struct drm_output *primary_output;
+
+ primary_output = (struct drm_output *)clone_output->base.compositor->primary_output;
+ if (clone_output->base.current->height > primary_output->base.current->height ||
+ clone_output->base.current->width > primary_output->base.current->width)
+ return 1;
+ else
+ return 0;
+}
+
+static void
+clone_mode_add_output(struct drm_output *output)
+{
+ struct drm_compositor *ec = (struct drm_compositor *)output->base.compositor;
+ struct drm_output *origin_output;
+
+ if (!ec->base.primary_output) {
+ ec->base.primary_output = &output->base;
+ return;
+ } else
+ origin_output = (struct drm_output *)ec->base.primary_output;
+
+ if (choose_output(origin_output, output) != origin_output) {
+ /* make sure primary output is the first in output_list when clone mode is enabled */
+ wl_list_remove(&output->base.link);
+ wl_list_insert(&ec->base.output_list, &output->base.link);
+ ec->base.primary_output = &output->base;
+ } else {
+ /* added output used as clone output, set it mode here */
+ if (clone_output_need_adjust_mode(output))
+ /*new added output need to adjust mode*/
+ adjust_clone_output_mode(output);
+ }
+}
+
static void
drm_output_fini_pixman(struct drm_output *output);
@@ -1939,6 +2030,8 @@ create_output_for_connector(struct drm_compositor *ec,
}
wl_list_insert(ec->base.output_list.prev, &output->base.link);
+ if (ec->base.multiscreen_mode == WESTON_MULTISCREEN_CLONE)
+ clone_mode_add_output(output);
find_and_parse_output_edid(ec, output, connector);
if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
@@ -2109,9 +2202,10 @@ create_outputs(struct drm_compositor *ec, uint32_t option_connector,
continue;
}
- x += container_of(ec->base.output_list.prev,
- struct weston_output,
- link)->width;
+ if (ec->base.multiscreen_mode == WESTON_MULTISCREEN_EXTEND)
+ x += container_of(ec->base.output_list.prev,
+ struct weston_output,
+ link)->width;
}
drmModeFreeConnector(connector);
--
1.8.3.2
More information about the wayland-devel
mailing list