mirror of
https://gitlab.freedesktop.org/wayland/weston.git
synced 2026-05-06 14:58:06 +02:00
compositor-wayland: migrate to head-based output API
Follow the standard pattern used in the headless and x11 backend migration, but also cater for the two other backend modes: --sprawl or fullscreen-shell, and --fullscreen. Stops relying on the implicit weston_output::head. Unlike other backends, this uses the attach_head hook to do the required head setup that is not possible to do without an output, but must be done before weston_output_enable(). This also requires the detach_head hook for the one case where the user attaches a --fullscreen head and then detaches it without enabling the output. It is a little awkward to fully initialize heads as late as attach, but aside from the --sprawl/fullscreen-shell case, there is not really a way to know the head properties without creating the parent wl_surface and configuring it. Heads/outputs created for parent outputs now have distinct names instead of all being called "wlparent". Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk> Reviewed-by: Ian Ray <ian.ray@ge.com> Acked-by: Derek Foreman <derekf@osg.samsung.com>
This commit is contained in:
parent
39069fa27c
commit
c80e954123
1 changed files with 184 additions and 67 deletions
|
|
@ -137,7 +137,7 @@ struct wayland_output {
|
|||
|
||||
struct wayland_parent_output {
|
||||
struct wayland_backend *backend; /**< convenience */
|
||||
struct wayland_output *output;
|
||||
struct wayland_head *head;
|
||||
struct wl_list link;
|
||||
|
||||
struct wl_output *global;
|
||||
|
|
@ -161,6 +161,11 @@ struct wayland_parent_output {
|
|||
struct weston_mode *current_mode;
|
||||
};
|
||||
|
||||
struct wayland_head {
|
||||
struct weston_head base;
|
||||
struct wayland_parent_output *parent_output;
|
||||
};
|
||||
|
||||
struct wayland_shm_buffer {
|
||||
struct wayland_output *output;
|
||||
struct wl_list link;
|
||||
|
|
@ -210,6 +215,12 @@ struct wayland_input {
|
|||
|
||||
struct gl_renderer_interface *gl_renderer;
|
||||
|
||||
static inline struct wayland_head *
|
||||
to_wayland_head(struct weston_head *base)
|
||||
{
|
||||
return container_of(base, struct wayland_head, base);
|
||||
}
|
||||
|
||||
static inline struct wayland_output *
|
||||
to_wayland_output(struct weston_output *base)
|
||||
{
|
||||
|
|
@ -1275,9 +1286,59 @@ err_output:
|
|||
return -1;
|
||||
}
|
||||
|
||||
static struct wayland_output *
|
||||
wayland_output_create_common(struct weston_compositor *compositor,
|
||||
const char *name)
|
||||
static int
|
||||
wayland_output_setup_for_parent_output(struct wayland_output *output,
|
||||
struct wayland_parent_output *poutput);
|
||||
|
||||
static int
|
||||
wayland_output_setup_fullscreen(struct wayland_output *output,
|
||||
struct wayland_head *head);
|
||||
|
||||
static int
|
||||
wayland_output_attach_head(struct weston_output *output_base,
|
||||
struct weston_head *head_base)
|
||||
{
|
||||
struct wayland_backend *b = to_wayland_backend(output_base->compositor);
|
||||
struct wayland_output *output = to_wayland_output(output_base);
|
||||
struct wayland_head *head = to_wayland_head(head_base);
|
||||
|
||||
if (!wl_list_empty(&output->base.head_list))
|
||||
return -1;
|
||||
|
||||
if (head->parent_output) {
|
||||
if (wayland_output_setup_for_parent_output(output,
|
||||
head->parent_output) < 0)
|
||||
return -1;
|
||||
} else if (b->fullscreen) {
|
||||
if (wayland_output_setup_fullscreen(output, head) < 0)
|
||||
return -1;
|
||||
} else {
|
||||
/* A floating window, nothing to do. */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
wayland_output_detach_head(struct weston_output *output_base,
|
||||
struct weston_head *head)
|
||||
{
|
||||
struct wayland_output *output = to_wayland_output(output_base);
|
||||
|
||||
/* Rely on the disable hook if the output was enabled. We do not
|
||||
* support cloned heads, so detaching is guaranteed to disable the
|
||||
* output.
|
||||
*/
|
||||
if (output->base.enabled)
|
||||
return;
|
||||
|
||||
/* undo setup fullscreen */
|
||||
if (output->parent.surface)
|
||||
wayland_backend_destroy_output_surface(output);
|
||||
}
|
||||
|
||||
static struct weston_output *
|
||||
wayland_output_create(struct weston_compositor *compositor, const char *name)
|
||||
{
|
||||
struct wayland_output *output;
|
||||
char *title;
|
||||
|
|
@ -1302,29 +1363,87 @@ wayland_output_create_common(struct weston_compositor *compositor,
|
|||
output->base.destroy = wayland_output_destroy;
|
||||
output->base.disable = wayland_output_disable;
|
||||
output->base.enable = wayland_output_enable;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
static int
|
||||
wayland_output_create(struct weston_compositor *compositor, const char *name)
|
||||
{
|
||||
struct wayland_output *output;
|
||||
|
||||
output = wayland_output_create_common(compositor, name);
|
||||
if (!output)
|
||||
return -1;
|
||||
output->base.attach_head = wayland_output_attach_head;
|
||||
output->base.detach_head = wayland_output_detach_head;
|
||||
|
||||
weston_compositor_add_pending_output(&output->base, compositor);
|
||||
|
||||
return &output->base;
|
||||
}
|
||||
|
||||
static struct wayland_head *
|
||||
wayland_head_create(struct weston_compositor *compositor, const char *name)
|
||||
{
|
||||
struct wayland_head *head;
|
||||
|
||||
assert(name);
|
||||
|
||||
head = zalloc(sizeof *head);
|
||||
if (!head)
|
||||
return NULL;
|
||||
|
||||
weston_head_init(&head->base, name);
|
||||
weston_head_set_connection_status(&head->base, true);
|
||||
weston_compositor_add_head(compositor, &head->base);
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
static int
|
||||
wayland_head_create_windowed(struct weston_compositor *compositor,
|
||||
const char *name)
|
||||
{
|
||||
if (!wayland_head_create(compositor, name))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
wayland_head_create_for_parent_output(struct weston_compositor *compositor,
|
||||
struct wayland_parent_output *poutput)
|
||||
{
|
||||
struct wayland_head *head;
|
||||
char name[100];
|
||||
int ret;
|
||||
|
||||
ret = snprintf(name, sizeof(name), "wlparent-%d", poutput->id);
|
||||
if (ret < 1 || (unsigned)ret >= sizeof(name))
|
||||
return -1;
|
||||
|
||||
head = wayland_head_create(compositor, name);
|
||||
if (!head)
|
||||
return -1;
|
||||
|
||||
assert(!poutput->head);
|
||||
head->parent_output = poutput;
|
||||
poutput->head = head;
|
||||
|
||||
weston_head_set_monitor_strings(&head->base,
|
||||
poutput->physical.make,
|
||||
poutput->physical.model, NULL);
|
||||
weston_head_set_physical_size(&head->base,
|
||||
poutput->physical.width,
|
||||
poutput->physical.height);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
wayland_head_destroy(struct wayland_head *head)
|
||||
{
|
||||
if (head->parent_output)
|
||||
head->parent_output->head = NULL;
|
||||
|
||||
weston_head_release(&head->base);
|
||||
free(head);
|
||||
}
|
||||
|
||||
static int
|
||||
wayland_output_set_size(struct weston_output *base, int width, int height)
|
||||
{
|
||||
struct wayland_output *output = to_wayland_output(base);
|
||||
struct weston_head *head = &output->base.head;
|
||||
struct weston_head *head;
|
||||
int output_width, output_height;
|
||||
|
||||
/* We can only be called once. */
|
||||
|
|
@ -1345,6 +1464,13 @@ wayland_output_set_size(struct weston_output *base, int width, int height)
|
|||
return -1;
|
||||
}
|
||||
|
||||
wl_list_for_each(head, &output->base.head_list, output_link) {
|
||||
weston_head_set_monitor_strings(head, "wayland", "none", NULL);
|
||||
|
||||
/* XXX: Calculate proper size. */
|
||||
weston_head_set_physical_size(head, width, height);
|
||||
}
|
||||
|
||||
output_width = width * output->base.scale;
|
||||
output_height = height * output->base.scale;
|
||||
|
||||
|
|
@ -1358,25 +1484,15 @@ wayland_output_set_size(struct weston_output *base, int width, int height)
|
|||
|
||||
output->base.current_mode = &output->mode;
|
||||
|
||||
weston_head_set_monitor_strings(head, "wayland", "none", NULL);
|
||||
|
||||
/* XXX: Calculate proper size. */
|
||||
weston_head_set_physical_size(head, width, height);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
wayland_output_create_for_parent_output(struct wayland_backend *b,
|
||||
struct wayland_parent_output *poutput)
|
||||
wayland_output_setup_for_parent_output(struct wayland_output *output,
|
||||
struct wayland_parent_output *poutput)
|
||||
{
|
||||
struct wayland_output *output;
|
||||
struct weston_mode *mode;
|
||||
|
||||
output = wayland_output_create_common(b->compositor, "wlparent");
|
||||
if (!output)
|
||||
return -1;
|
||||
|
||||
if (poutput->current_mode) {
|
||||
mode = poutput->current_mode;
|
||||
} else if (poutput->preferred_mode) {
|
||||
|
|
@ -1386,7 +1502,7 @@ wayland_output_create_for_parent_output(struct wayland_backend *b,
|
|||
struct weston_mode, link);
|
||||
} else {
|
||||
weston_log("No valid modes found. Skipping output.\n");
|
||||
goto out;
|
||||
return -1;
|
||||
}
|
||||
|
||||
output->base.scale = 1;
|
||||
|
|
@ -1394,13 +1510,6 @@ wayland_output_create_for_parent_output(struct wayland_backend *b,
|
|||
|
||||
output->parent.output = poutput->global;
|
||||
|
||||
weston_head_set_monitor_strings(&output->base.head,
|
||||
poutput->physical.make,
|
||||
poutput->physical.model, NULL);
|
||||
weston_head_set_physical_size(&output->base.head,
|
||||
poutput->physical.width,
|
||||
poutput->physical.height);
|
||||
|
||||
wl_list_insert_list(&output->base.mode_list, &poutput->mode_list);
|
||||
wl_list_init(&poutput->mode_list);
|
||||
|
||||
|
|
@ -1410,33 +1519,21 @@ wayland_output_create_for_parent_output(struct wayland_backend *b,
|
|||
|
||||
/* output->mode is unused in this path. */
|
||||
|
||||
weston_compositor_add_pending_output(&output->base, b->compositor);
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
weston_output_release(&output->base);
|
||||
free(output->title);
|
||||
free(output);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
wayland_output_create_fullscreen(struct wayland_backend *b)
|
||||
wayland_output_setup_fullscreen(struct wayland_output *output,
|
||||
struct wayland_head *head)
|
||||
{
|
||||
struct wayland_output *output;
|
||||
struct wayland_backend *b = to_wayland_backend(output->base.compositor);
|
||||
int width = 0, height = 0;
|
||||
|
||||
output = wayland_output_create_common(b->compositor, "wayland-fullscreen");
|
||||
if (!output)
|
||||
return -1;
|
||||
|
||||
output->base.scale = 1;
|
||||
output->base.transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
|
||||
if (wayland_backend_create_output_surface(output) < 0)
|
||||
goto err_surface;
|
||||
return -1;
|
||||
|
||||
/* What should size be set if conditional is false? */
|
||||
if (b->parent.xdg_shell || b->parent.shell) {
|
||||
|
|
@ -1456,16 +1553,15 @@ wayland_output_create_fullscreen(struct wayland_backend *b)
|
|||
if (wayland_output_set_size(&output->base, width, height) < 0)
|
||||
goto err_set_size;
|
||||
|
||||
weston_compositor_add_pending_output(&output->base, b->compositor);
|
||||
/* The head is not attached yet, so set_size did not set these. */
|
||||
weston_head_set_monitor_strings(&head->base, "wayland", "none", NULL);
|
||||
/* XXX: Calculate proper size. */
|
||||
weston_head_set_physical_size(&head->base, width, height);
|
||||
|
||||
return 0;
|
||||
|
||||
err_set_size:
|
||||
wayland_backend_destroy_output_surface(output);
|
||||
err_surface:
|
||||
weston_output_release(&output->base);
|
||||
free(output->title);
|
||||
free(output);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -2286,16 +2382,32 @@ find_mode(struct wl_list *list, int32_t width, int32_t height, uint32_t refresh)
|
|||
return mode;
|
||||
}
|
||||
|
||||
static struct weston_output *
|
||||
wayland_parent_output_get_enabled_output(struct wayland_parent_output *poutput)
|
||||
{
|
||||
struct wayland_head *head = poutput->head;
|
||||
|
||||
if (!head)
|
||||
return NULL;
|
||||
|
||||
if (!weston_head_is_enabled(&head->base))
|
||||
return NULL;
|
||||
|
||||
return weston_head_get_output(&head->base);
|
||||
}
|
||||
|
||||
static void
|
||||
wayland_parent_output_mode(void *data, struct wl_output *wl_output_proxy,
|
||||
uint32_t flags, int32_t width, int32_t height,
|
||||
int32_t refresh)
|
||||
{
|
||||
struct wayland_parent_output *output = data;
|
||||
struct weston_output *enabled_output;
|
||||
struct weston_mode *mode;
|
||||
|
||||
if (output->output) {
|
||||
mode = find_mode(&output->output->base.mode_list,
|
||||
enabled_output = wayland_parent_output_get_enabled_output(output);
|
||||
if (enabled_output) {
|
||||
mode = find_mode(&enabled_output->mode_list,
|
||||
width, height, refresh);
|
||||
if (!mode)
|
||||
return;
|
||||
|
|
@ -2329,7 +2441,7 @@ output_sync_callback(void *data, struct wl_callback *callback, uint32_t unused)
|
|||
|
||||
assert(output->backend->sprawl_across_outputs);
|
||||
|
||||
wayland_output_create_for_parent_output(output->backend, output);
|
||||
wayland_head_create_for_parent_output(output->backend->compositor, output);
|
||||
}
|
||||
|
||||
static const struct wl_callback_listener output_sync_listener = {
|
||||
|
|
@ -2377,8 +2489,8 @@ wayland_parent_output_destroy(struct wayland_parent_output *output)
|
|||
if (output->sync_cb)
|
||||
wl_callback_destroy(output->sync_cb);
|
||||
|
||||
if (output->output)
|
||||
wayland_output_destroy(&output->output->base);
|
||||
if (output->head)
|
||||
wayland_head_destroy(output->head);
|
||||
|
||||
wl_output_destroy(output->global);
|
||||
free(output->physical.make);
|
||||
|
|
@ -2483,11 +2595,15 @@ static void
|
|||
wayland_destroy(struct weston_compositor *ec)
|
||||
{
|
||||
struct wayland_backend *b = to_wayland_backend(ec);
|
||||
struct weston_head *base, *next;
|
||||
|
||||
wl_event_source_remove(b->parent.wl_source);
|
||||
|
||||
weston_compositor_shutdown(ec);
|
||||
|
||||
wl_list_for_each_safe(base, next, &ec->head_list, compositor_link)
|
||||
wayland_head_destroy(to_wayland_head(base));
|
||||
|
||||
if (b->parent.shm)
|
||||
wl_shm_destroy(b->parent.shm);
|
||||
|
||||
|
|
@ -2642,6 +2758,7 @@ wayland_backend_create(struct weston_compositor *compositor,
|
|||
}
|
||||
|
||||
b->base.destroy = wayland_destroy;
|
||||
b->base.create_output = wayland_output_create;
|
||||
|
||||
loop = wl_display_get_event_loop(compositor->wl_display);
|
||||
|
||||
|
|
@ -2686,7 +2803,7 @@ wayland_backend_destroy(struct wayland_backend *b)
|
|||
|
||||
static const struct weston_windowed_output_api windowed_api = {
|
||||
wayland_output_set_size,
|
||||
wayland_output_create,
|
||||
wayland_head_create_windowed,
|
||||
};
|
||||
|
||||
static void
|
||||
|
|
@ -2723,14 +2840,14 @@ weston_backend_init(struct weston_compositor *compositor,
|
|||
wl_display_roundtrip(b->parent.wl_display);
|
||||
|
||||
wl_list_for_each(poutput, &b->parent.output_list, link)
|
||||
wayland_output_create_for_parent_output(b, poutput);
|
||||
wayland_head_create_for_parent_output(compositor, poutput);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (new_config.fullscreen) {
|
||||
if (wayland_output_create_fullscreen(b) < 0) {
|
||||
weston_log("Unable to create a fullscreen output.\n");
|
||||
if (!wayland_head_create(compositor, "wayland-fullscreen")) {
|
||||
weston_log("Unable to create a fullscreen head.\n");
|
||||
goto err_outputs;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue