compositor-drm: move mode list to set_mode()
authorPekka Paalanen <pekka.paalanen@collabora.co.uk>
Mon, 11 Sep 2017 12:01:12 +0000 (15:01 +0300)
committerPekka Paalanen <pekka.paalanen@collabora.co.uk>
Wed, 18 Apr 2018 08:53:54 +0000 (11:53 +0300)
Move the initialization of the drm_output mode list to
drm_output_set_mode() time.

Once we stop creating the drm_head with the drm_output, there will not
be a head to get the mode list from at drm_output creation time.

Furthermore, once DRM-backend starts supporting more than one head per
output, the combined mode list to be exposed to clients (and the
compositor?) must be constructed with all heads attached.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
Reviewed-by: Daniel Stone <daniels@collabora.com>
Acked-by: Derek Foreman <derekf@osg.samsung.com>
libweston/compositor-drm.c

index f54257c..df31f87 100644 (file)
@@ -4439,6 +4439,43 @@ parse_gbm_format(const char *s, uint32_t default_value, uint32_t *gbm_format)
        return ret;
 }
 
+/** Rewrite the output's mode list
+ *
+ * @param output The output.
+ * @return 0 on success, -1 on failure.
+ *
+ * Destroy all existing modes in the list, and reconstruct a new list from
+ * scratch, based on the currently attached heads.
+ *
+ * On failure the output's mode list may contain some modes.
+ */
+static int
+drm_output_update_modelist_from_heads(struct drm_output *output)
+{
+       struct drm_backend *backend = to_drm_backend(output->base.compositor);
+       struct weston_head *head_base;
+       struct drm_head *head;
+       struct drm_mode *mode;
+       int i;
+
+       assert(!output->base.enabled);
+
+       drm_mode_list_destroy(backend, &output->base.mode_list);
+
+       /* XXX: needs a strategy for combining mode lists from multiple heads */
+       head_base = weston_output_get_first_head(&output->base);
+       assert(head_base);
+       head = to_drm_head(head_base);
+
+       for (i = 0; i < head->connector->count_modes; i++) {
+               mode = drm_output_add_mode(output, &head->connector->modes[i]);
+               if (!mode)
+                       return -1;
+       }
+
+       return 0;
+}
+
 /**
  * Choose suitable mode for an output
  *
@@ -4563,6 +4600,9 @@ drm_output_set_mode(struct weston_output *base,
 
        struct drm_mode *current;
 
+       if (drm_output_update_modelist_from_heads(output) < 0)
+               return -1;
+
        current = drm_output_choose_initial_mode(b, output, mode, modeline,
                                                 &head->inherited_mode);
        if (!current)
@@ -5140,8 +5180,6 @@ create_output_for_connector(struct drm_backend *b,
 {
        struct drm_output *output;
        struct drm_head *head;
-       struct drm_mode *drm_mode;
-       int i;
 
        output = zalloc(sizeof *output);
        if (output == NULL)
@@ -5165,14 +5203,6 @@ create_output_for_connector(struct drm_backend *b,
 
        output->state_cur = drm_output_state_alloc(output, NULL);
 
-       for (i = 0; i < head->connector->count_modes; i++) {
-               drm_mode = drm_output_add_mode(output, &head->connector->modes[i]);
-               if (!drm_mode) {
-                       weston_log("failed to add mode\n");
-                       goto err_output;
-               }
-       }
-
        weston_compositor_add_pending_output(&output->base, b->compositor);
 
        /* drm_head_create() made its own connector */
@@ -5180,10 +5210,6 @@ create_output_for_connector(struct drm_backend *b,
 
        return 0;
 
-err_output:
-       drm_head_destroy(head);
-       drm_output_destroy(&output->base);
-
 err_init:
        drmModeFreeConnector(connector);
        return -1;