Re: [PATCH weston v5 14/36] libweston: new head-based output management API

2018-02-05 Thread Derek Foreman

On 2018-02-05 05:23 AM, Pekka Paalanen wrote:

On Fri, 2 Feb 2018 15:00:09 -0600
Derek Foreman  wrote:


On 2017-12-14 05:40 AM, Pekka Paalanen wrote:

From: Pekka Paalanen 

Introduce the API for users (compositors) to create an output from a
head, attach and detach heads, and destroy outputs created this way.
This also adds the backend-facing API to libweston.

In the new API design, a backend creates heads, and the compositor
chooses one or more heads (clone mode) to be driven by an output.
In the future backends will be converted to not create outputs directly
but only in the new create_output hook.

The user subscribes to a heads_changed hook and arranges heads into
outputs from there.

Adding the API this way will allow frontends (main.c) and backends to be
converted one by one. This adds compatiblity paths in
weston_compositor_create_output_with_head() and weston_output_destroy()
so that frontends can be converted first to call these, and then
backends can be converted one by one to the new design. Afterwards, the
compatibility paths will be removed along with weston_output::head.

Currently heads can be added to a disabled output only. This is less
than ideal for clone mode hotplug and should be improved on later.

v4: Remove the wl_output global on head detach if output is enabled.

Signed-off-by: Pekka Paalanen 
---
   libweston/compositor.c | 187 
++---
   libweston/compositor.h |  78 +
   2 files changed, 256 insertions(+), 9 deletions(-)

diff --git a/libweston/compositor.c b/libweston/compositor.c



@@ -4583,7 +4629,7 @@ weston_compositor_iterate_heads(struct weston_compositor 
*compositor,
*
* \memberof weston_output
*/
-static int
+WL_EXPORT int
   weston_output_attach_head(struct weston_output *output,
  struct weston_head *head)
   {
@@ -4593,9 +4639,13 @@ weston_output_attach_head(struct weston_output *output,
if (!wl_list_empty(&head->output_link))
return -1;
   
-	/* XXX: no support for multi-head yet */

-   if (!wl_list_empty(&output->head_list))
+   if (output->attach_head) {
+   if (output->attach_head(output, head) < 0)
+   return -1;
+   } else if (!wl_list_empty(&output->head_list)) {
+   /* No support for clones in the legacy path. */
return -1;
+   }
   
   	head->output = output;

wl_list_insert(output->head_list.prev, &head->output_link);



+/** Create an output for an unused head
+ *
+ * \param compositor The compositor.
+ * \param head The head to attach to the output.
+ * \return A new \c weston_output, or NULL on failure.
+ *
+ * This creates a new weston_output that starts with the given head attached.
+ * The output inherits the name of the head. The head must not be already
+ * attached to another output.
+ *
+ * An output must be configured before it can be enabled.
+ *
+ * \memberof weston_compositor
+ */
+WL_EXPORT struct weston_output *
+weston_compositor_create_output_with_head(struct weston_compositor *compositor,
+ struct weston_head *head)
+{
+   struct weston_output *output;
+
+   if (head->allocator_output) {
+   /* XXX: compatibility path to be removed after all converted */
+   output = head->allocator_output;
+   } else {
+   assert(compositor->backend->create_output);
+   output = compositor->backend->create_output(compositor,
+   head->name);
+   }
+
+   if (!output)
+   return NULL;
+
+   if (weston_output_attach_head(output, head) < 0) {
+   if (!head->allocator_output)
+   output->destroy(output);
+
+   return NULL;
+   }
+
+   return output;
+}
+
+/** Destroy an output
+ *
+ * \param output The output to destroy.
+ *
+ * The heads attached to the given output are detached and become unused again.
+ *
+ * It is not necessary to explicitly destroy all outputs at compositor exit.
+ * weston_compositor_destroy() will automatically destroy any remaining
+ * outputs.
+ *
+ * \memberof weston_output
+ */
+WL_EXPORT void
+weston_output_destroy(struct weston_output *output)
+{
+   struct weston_head *head;
+
+   /* XXX: compatibility path to be removed after all converted */
+   head = weston_output_get_first_head(output);


This took me a couple of reads...  if I understand correctly, the full
list of outputs is going to be torn down in the backend
output->destroy()?  And we hit that path if we don't have the legacy
allocator_output.


Yes, the backend will call weston_output_release() which will detach
all attached heads.

In the legacy backend case, the backend is in charge of creating and
destroying weston_outputs, so we cannot let weston_output_destroy()
call output->destroy(). With legacy frontend things a

Re: [PATCH weston v5 14/36] libweston: new head-based output management API

2018-02-05 Thread Pekka Paalanen
On Fri, 2 Feb 2018 15:00:09 -0600
Derek Foreman  wrote:

> On 2017-12-14 05:40 AM, Pekka Paalanen wrote:
> > From: Pekka Paalanen 
> > 
> > Introduce the API for users (compositors) to create an output from a
> > head, attach and detach heads, and destroy outputs created this way.
> > This also adds the backend-facing API to libweston.
> > 
> > In the new API design, a backend creates heads, and the compositor
> > chooses one or more heads (clone mode) to be driven by an output.
> > In the future backends will be converted to not create outputs directly
> > but only in the new create_output hook.
> > 
> > The user subscribes to a heads_changed hook and arranges heads into
> > outputs from there.
> > 
> > Adding the API this way will allow frontends (main.c) and backends to be
> > converted one by one. This adds compatiblity paths in
> > weston_compositor_create_output_with_head() and weston_output_destroy()
> > so that frontends can be converted first to call these, and then
> > backends can be converted one by one to the new design. Afterwards, the
> > compatibility paths will be removed along with weston_output::head.
> > 
> > Currently heads can be added to a disabled output only. This is less
> > than ideal for clone mode hotplug and should be improved on later.
> > 
> > v4: Remove the wl_output global on head detach if output is enabled.
> > 
> > Signed-off-by: Pekka Paalanen 
> > ---
> >   libweston/compositor.c | 187 
> > ++---
> >   libweston/compositor.h |  78 +
> >   2 files changed, 256 insertions(+), 9 deletions(-)
> > 
> > diff --git a/libweston/compositor.c b/libweston/compositor.c

> > @@ -4583,7 +4629,7 @@ weston_compositor_iterate_heads(struct 
> > weston_compositor *compositor,
> >*
> >* \memberof weston_output
> >*/
> > -static int
> > +WL_EXPORT int
> >   weston_output_attach_head(struct weston_output *output,
> >   struct weston_head *head)
> >   {
> > @@ -4593,9 +4639,13 @@ weston_output_attach_head(struct weston_output 
> > *output,
> > if (!wl_list_empty(&head->output_link))
> > return -1;
> >   
> > -   /* XXX: no support for multi-head yet */
> > -   if (!wl_list_empty(&output->head_list))
> > +   if (output->attach_head) {
> > +   if (output->attach_head(output, head) < 0)
> > +   return -1;
> > +   } else if (!wl_list_empty(&output->head_list)) {
> > +   /* No support for clones in the legacy path. */
> > return -1;
> > +   }
> >   
> > head->output = output;
> > wl_list_insert(output->head_list.prev, &head->output_link);

> > +/** Create an output for an unused head
> > + *
> > + * \param compositor The compositor.
> > + * \param head The head to attach to the output.
> > + * \return A new \c weston_output, or NULL on failure.
> > + *
> > + * This creates a new weston_output that starts with the given head 
> > attached.
> > + * The output inherits the name of the head. The head must not be already
> > + * attached to another output.
> > + *
> > + * An output must be configured before it can be enabled.
> > + *
> > + * \memberof weston_compositor
> > + */
> > +WL_EXPORT struct weston_output *
> > +weston_compositor_create_output_with_head(struct weston_compositor 
> > *compositor,
> > + struct weston_head *head)
> > +{
> > +   struct weston_output *output;
> > +
> > +   if (head->allocator_output) {
> > +   /* XXX: compatibility path to be removed after all converted */
> > +   output = head->allocator_output;
> > +   } else {
> > +   assert(compositor->backend->create_output);
> > +   output = compositor->backend->create_output(compositor,
> > +   head->name);
> > +   }
> > +
> > +   if (!output)
> > +   return NULL;
> > +
> > +   if (weston_output_attach_head(output, head) < 0) {
> > +   if (!head->allocator_output)
> > +   output->destroy(output);
> > +
> > +   return NULL;
> > +   }
> > +
> > +   return output;
> > +}
> > +
> > +/** Destroy an output
> > + *
> > + * \param output The output to destroy.
> > + *
> > + * The heads attached to the given output are detached and become unused 
> > again.
> > + *
> > + * It is not necessary to explicitly destroy all outputs at compositor 
> > exit.
> > + * weston_compositor_destroy() will automatically destroy any remaining
> > + * outputs.
> > + *
> > + * \memberof weston_output
> > + */
> > +WL_EXPORT void
> > +weston_output_destroy(struct weston_output *output)
> > +{
> > +   struct weston_head *head;
> > +
> > +   /* XXX: compatibility path to be removed after all converted */
> > +   head = weston_output_get_first_head(output);  
> 
> This took me a couple of reads...  if I understand correctly, the full 
> list of outputs is going to be torn down in the backend 
> output->destroy()?  And we hit that path if

Re: [PATCH weston v5 14/36] libweston: new head-based output management API

2018-02-02 Thread Derek Foreman

On 2017-12-14 05:40 AM, Pekka Paalanen wrote:

From: Pekka Paalanen 

Introduce the API for users (compositors) to create an output from a
head, attach and detach heads, and destroy outputs created this way.
This also adds the backend-facing API to libweston.

In the new API design, a backend creates heads, and the compositor
chooses one or more heads (clone mode) to be driven by an output.
In the future backends will be converted to not create outputs directly
but only in the new create_output hook.

The user subscribes to a heads_changed hook and arranges heads into
outputs from there.

Adding the API this way will allow frontends (main.c) and backends to be
converted one by one. This adds compatiblity paths in
weston_compositor_create_output_with_head() and weston_output_destroy()
so that frontends can be converted first to call these, and then
backends can be converted one by one to the new design. Afterwards, the
compatibility paths will be removed along with weston_output::head.

Currently heads can be added to a disabled output only. This is less
than ideal for clone mode hotplug and should be improved on later.

v4: Remove the wl_output global on head detach if output is enabled.

Signed-off-by: Pekka Paalanen 
---
  libweston/compositor.c | 187 ++---
  libweston/compositor.h |  78 +
  2 files changed, 256 insertions(+), 9 deletions(-)

diff --git a/libweston/compositor.c b/libweston/compositor.c
index 1d436522..a43ee277 100644
--- a/libweston/compositor.c
+++ b/libweston/compositor.c
@@ -4424,7 +4424,7 @@ weston_head_from_resource(struct wl_resource *resource)
   * \memberof weston_head
   * \internal
   */
-static void
+WL_EXPORT void
  weston_head_init(struct weston_head *head, const char *name)
  {
/* Add some (in)sane defaults which can be used
@@ -4483,7 +4483,7 @@ weston_compositor_schedule_heads_changed(struct 
weston_compositor *compositor)
   * \memberof weston_compositor
   * \internal
   */
-static void
+WL_EXPORT void
  weston_compositor_add_head(struct weston_compositor *compositor,
   struct weston_head *head)
  {
@@ -4564,6 +4564,52 @@ weston_compositor_iterate_heads(struct weston_compositor 
*compositor,
return container_of(node, struct weston_head, compositor_link);
  }
  
+/** Iterate over attached heads

+ *
+ * \param output The output whose heads to iterate.
+ * \param item The iterator, or NULL for start.
+ * \return The next attached head in the list.
+ *
+ * Returns all heads currently attached to the output.
+ *
+ * You can iterate over all heads as follows:
+ * \code
+ * struct weston_head *head = NULL;
+ *
+ * while ((head = weston_output_iterate_heads(output, head))) {
+ * ...
+ * }
+ * \endcode
+ *
+ *  If you cause \c iter to be removed from the list, you cannot use it to
+ * continue iterating. Removing any other item is safe.
+ *
+ * \memberof weston_compositor
+ */
+WL_EXPORT struct weston_head *
+weston_output_iterate_heads(struct weston_output *output,
+   struct weston_head *iter)
+{
+   struct wl_list *list = &output->head_list;
+   struct wl_list *node;
+
+   assert(output);
+   assert(!iter || iter->output == output);
+
+   if (iter)
+   node = iter->output_link.next;
+   else
+   node = list->next;
+
+   assert(node);
+   assert(!iter || node != &iter->output_link);
+
+   if (node == list)
+   return NULL;
+
+   return container_of(node, struct weston_head, output_link);
+}
+
  /** Attach a head to an inactive output
   *
   * \param output The output to attach to.
@@ -4583,7 +4629,7 @@ weston_compositor_iterate_heads(struct weston_compositor 
*compositor,
   *
   * \memberof weston_output
   */
-static int
+WL_EXPORT int
  weston_output_attach_head(struct weston_output *output,
  struct weston_head *head)
  {
@@ -4593,9 +4639,13 @@ weston_output_attach_head(struct weston_output *output,
if (!wl_list_empty(&head->output_link))
return -1;
  
-	/* XXX: no support for multi-head yet */

-   if (!wl_list_empty(&output->head_list))
+   if (output->attach_head) {
+   if (output->attach_head(output, head) < 0)
+   return -1;
+   } else if (!wl_list_empty(&output->head_list)) {
+   /* No support for clones in the legacy path. */
return -1;
+   }
  
  	head->output = output;

wl_list_insert(output->head_list.prev, &head->output_link);
@@ -4609,14 +4659,33 @@ weston_output_attach_head(struct weston_output *output,
   *
   * It is safe to detach a non-attached head.
   *
+ * If the head is attached to an enabled output and the output will be left
+ * with no heads, the output will be disabled.
+ *
   * \memberof weston_head
+ * \sa weston_output_disable
   */
-static void
+WL_EXPORT void
  weston_head_detach(struct weston_head *head)