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

Derek Foreman derekf at osg.samsung.com
Mon Feb 5 16:13:40 UTC 2018


On 2018-02-05 05:23 AM, Pekka Paalanen wrote:
> On Fri, 2 Feb 2018 15:00:09 -0600
> Derek Foreman <derekf at osg.samsung.com> wrote:
> 
>> On 2017-12-14 05:40 AM, Pekka Paalanen wrote:
>>> From: Pekka Paalanen <pekka.paalanen at collabora.co.uk>
>>>
>>> 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 <pekka.paalanen at collabora.co.uk>
>>> ---
>>>    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 are as they were,
> but a migrated frontend will call weston_output_destroy().
> 
> In the migrated backend case, weston_outputs are created and destroyed
> by the frontend's command.
> 
> If we have a migrated frontend and a legacy backend, we just pretend
> the frontend is in charge of the weston_output lifetime.
> 
> It is enough to check only the first head for the legacy backend case,
> because in that case there cannot be more heads attached.
> weston_output_attach_head() ensures that.
> 
>> I think the code all looks sound and the API looks reasonable to me, but
>> I have to concede that I don't know the output handling path enough to
>> understand weston_compositor_reflow_output's setting up of the
>> allocator_output.
> 
> Why do you mention weston_compositor_reflow_outputs()?

Wow, for really embarrassing reasons actually.

> allocator_output is a note in weston_head to say we have a legacy
> backend that created a weston_output automatically. So when a migrated
> frontend goes to weston_compositor_create_output_with_head() to create
> a new weston_output, we can return the (pending) weston_output that
> already exists.

That made sense to me...

>> Acked-by: Derek Foreman <derekf at osg.samsung.com>

After re-reading the patch a couple of times I think I can upgrade this to
Reviewed-by: Derek Foreman <derekf at osg.samsung.com>

Thanks,
Derek
> 
> Thanks,
> pq
> 
>>> +	if (head->allocator_output) {
>>> +		/* The old design: backend is responsible for destroying the
>>> +		 * output, so just undo create_output_with_head()
>>> +		 */
>>> +		weston_head_detach(head);
>>> +		return;
>>> +	}
>>> +
>>> +	output->destroy(output);
>>> +}
>>> +
>>>    /** When you need a head...
>>>     *
>>>     * This function is a hack, used until all code has been converted to become
>>> diff --git a/libweston/compositor.h b/libweston/compositor.h
>>> index f7b7050c..f9d034c3 100644
>>> --- a/libweston/compositor.h
>>> +++ b/libweston/compositor.h
>>> @@ -172,6 +172,8 @@ struct weston_head {
>>>    
>>>    	char *name;			/**< head name, e.g. connector name */
>>>    	bool connected;			/**< is physically connected */
>>> +
>>> +	struct weston_output *allocator_output;	/**< XXX: to be removed */
>>>    };



More information about the wayland-devel mailing list