From 7347bc7a3b2ee0bf8226ba2f15ae4c6a02110bdd Mon Sep 17 00:00:00 2001
|
From: Jeffy Chen <jeffy.chen@rock-chips.com>
|
Date: Thu, 12 Nov 2020 16:59:50 +0800
|
Subject: [PATCH 28/74] backend-drm: Add dummy output when no screens connected
|
|
Some clients are not expecting no screens, add a dummy output for them.
|
|
Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
|
---
|
compositor/main.c | 3 +
|
desktop-shell/shell.c | 7 +-
|
libweston/backend-drm/drm-internal.h | 3 +
|
libweston/backend-drm/drm.c | 203 ++++++++++++++++++++++++++-
|
libweston/backend-drm/kms.c | 3 +
|
libweston/compositor.c | 3 +
|
6 files changed, 216 insertions(+), 6 deletions(-)
|
|
diff --git a/compositor/main.c b/compositor/main.c
|
index 128016b..3824404 100644
|
--- a/compositor/main.c
|
+++ b/compositor/main.c
|
@@ -2337,6 +2337,9 @@ drm_heads_changed(struct wl_listener *listener, void *arg)
|
* output.
|
*/
|
while ((head = weston_compositor_iterate_heads(compositor, head))) {
|
+ if (!strcasecmp(weston_head_get_name(head), "dummy"))
|
+ continue;
|
+
|
drm_head_update_output_section(head);
|
|
connected = weston_head_is_connected(head);
|
diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
|
index aedb1e9..c57e7ef 100644
|
--- a/desktop-shell/shell.c
|
+++ b/desktop-shell/shell.c
|
@@ -4820,10 +4820,6 @@ shell_reposition_view_on_output_change(struct weston_view *view)
|
shsurf = get_shell_surface(view->surface);
|
if (!shsurf)
|
return;
|
-
|
- shsurf->saved_position_valid = false;
|
- set_maximized(shsurf, false);
|
- set_fullscreen(shsurf, false, NULL);
|
}
|
|
void
|
@@ -4955,6 +4951,9 @@ handle_output_resized(struct wl_listener *listener, void *data)
|
struct weston_output *output = (struct weston_output *)data;
|
struct shell_output *sh_output = find_shell_output_from_weston_output(shell, output);
|
|
+ if (!sh_output)
|
+ return;
|
+
|
if (shell->lock_surface)
|
shell->lock_surface->committed(shell->lock_surface, 0, 0);
|
|
diff --git a/libweston/backend-drm/drm-internal.h b/libweston/backend-drm/drm-internal.h
|
index 9d24017..67e6dd2 100644
|
--- a/libweston/backend-drm/drm-internal.h
|
+++ b/libweston/backend-drm/drm-internal.h
|
@@ -354,6 +354,9 @@ struct drm_backend {
|
|
struct wl_event_source *config_timer;
|
struct stat config_stat;
|
+
|
+ struct weston_output *dummy_output;
|
+ struct drm_head *dummy_head;
|
};
|
|
struct drm_mode {
|
diff --git a/libweston/backend-drm/drm.c b/libweston/backend-drm/drm.c
|
index 53a3d49..e829d77 100644
|
--- a/libweston/backend-drm/drm.c
|
+++ b/libweston/backend-drm/drm.c
|
@@ -210,8 +210,14 @@ drm_backend_update_outputs(struct drm_backend *b)
|
{
|
struct weston_output *base, *primary;
|
|
- if (!b->primary_head)
|
+ if (!b->primary_head) {
|
+ if (!b->dummy_output->enabled)
|
+ weston_output_enable(b->dummy_output);
|
return;
|
+ } else {
|
+ if (b->dummy_output->enabled)
|
+ weston_output_disable(b->dummy_output);
|
+ }
|
|
primary = b->primary_head->base.output;
|
|
@@ -1245,7 +1251,7 @@ drm_output_find_special_plane(struct drm_backend *b, struct drm_output *output,
|
num_primary - 1 != output->crtc->pipe)
|
continue;
|
|
- if (plane->type != type)
|
+ if (!plane->plane_id || plane->type != type)
|
continue;
|
if (!drm_plane_is_available(plane, output))
|
continue;
|
@@ -2591,11 +2597,15 @@ drm_head_destroy(struct drm_head *head)
|
{
|
weston_head_release(&head->base);
|
|
+ if (!head->connector.connector_id)
|
+ goto out;
|
+
|
drm_connector_fini(&head->connector);
|
|
if (head->backlight)
|
backlight_destroy(head->backlight);
|
|
+out:
|
free(head);
|
}
|
|
@@ -2827,6 +2837,9 @@ drm_backend_update_connectors(struct drm_backend *b, struct udev_device *drm_dev
|
wl_list_for_each_safe(base, base_next,
|
&b->compositor->head_list, compositor_link) {
|
head = to_drm_head(base);
|
+ if (!head->connector.connector_id)
|
+ continue;
|
+
|
connector_id = head->connector.connector_id;
|
|
if (resources_has_connector(resources, connector_id))
|
@@ -2871,6 +2884,9 @@ drm_backend_update_connectors(struct drm_backend *b, struct udev_device *drm_dev
|
continue;
|
|
head = to_drm_head(base);
|
+ if (!head->connector.connector_id)
|
+ continue;
|
+
|
conn = head->connector.conn;
|
|
if (conn->connection != DRM_MODE_CONNECTED ||
|
@@ -2900,6 +2916,8 @@ drm_backend_update_connectors(struct drm_backend *b, struct udev_device *drm_dev
|
}
|
match_done:
|
|
+ weston_head_set_connection_status(&b->dummy_head->base,
|
+ !b->primary_head);
|
drm_backend_update_outputs(b);
|
|
weston_compositor_read_presentation_clock(b->compositor, &now);
|
@@ -3072,6 +3090,8 @@ drm_destroy(struct weston_compositor *ec)
|
struct drm_crtc *crtc, *crtc_tmp;
|
struct drm_writeback *writeback, *writeback_tmp;
|
|
+ weston_output_destroy(b->dummy_output);
|
+
|
udev_input_destroy(&b->input);
|
|
wl_event_source_remove(b->config_timer);
|
@@ -3776,6 +3796,180 @@ config_timer_handler(void *data)
|
return 0;
|
}
|
|
+static int
|
+drm_dummy_output_start_repaint_loop(struct weston_output *output_base)
|
+{
|
+ weston_output_finish_frame(output_base, NULL,
|
+ WP_PRESENTATION_FEEDBACK_INVALID);
|
+
|
+ return 0;
|
+}
|
+
|
+static int
|
+drm_dummy_output_repaint(struct weston_output *output_base,
|
+ pixman_region32_t *damage,
|
+ void *repaint_data)
|
+{
|
+ struct drm_backend *b = to_drm_backend(output_base->compositor);
|
+
|
+ wl_signal_emit(&output_base->frame_signal, damage);
|
+
|
+ if (b->use_pixman)
|
+ return -1;
|
+
|
+ /* Switch GL output context to avoid corruption */
|
+ output_base->compositor->renderer->repaint_output(output_base, damage);
|
+ return -1;
|
+}
|
+
|
+static int
|
+drm_dummy_output_enable(struct weston_output *output_base)
|
+{
|
+ struct drm_backend *b = to_drm_backend(output_base->compositor);
|
+ struct drm_output *output = to_drm_output(output_base);
|
+
|
+ if (b->use_pixman)
|
+ return 0;
|
+
|
+ return drm_output_init_egl(output, b);
|
+}
|
+
|
+static int
|
+drm_dummy_output_disable(struct weston_output *output_base)
|
+{
|
+ struct drm_backend *b = to_drm_backend(output_base->compositor);
|
+ struct drm_output *output = to_drm_output(output_base);
|
+
|
+ if (!b->use_pixman)
|
+ drm_output_fini_egl(output);
|
+
|
+ return 0;
|
+}
|
+
|
+static void
|
+drm_dummy_output_destroy(struct weston_output *output_base)
|
+{
|
+ struct drm_output *output = to_drm_output(output_base);
|
+ struct drm_plane *plane = output->scanout_plane;
|
+ struct weston_mode *mode, *next;
|
+
|
+ if (output->base.enabled)
|
+ drm_dummy_output_disable(&output->base);
|
+
|
+ wl_list_for_each_safe(mode, next, &output_base->mode_list, link) {
|
+ wl_list_remove(&mode->link);
|
+ free(mode);
|
+ }
|
+
|
+ drm_plane_state_free(plane->state_cur, true);
|
+ weston_plane_release(&plane->base);
|
+ wl_list_remove(&plane->link);
|
+ weston_drm_format_array_fini(&plane->formats);
|
+ free(plane);
|
+
|
+ weston_output_release(output_base);
|
+ free(output);
|
+}
|
+
|
+static struct weston_output *
|
+drm_dummy_output_create(struct drm_backend *b)
|
+{
|
+ struct drm_output *output;
|
+ struct drm_plane *plane;
|
+ struct weston_drm_format *fmt;
|
+
|
+ output = zalloc(sizeof *output);
|
+ if (!output)
|
+ return NULL;
|
+
|
+ weston_output_init(&output->base, b->compositor, "DUMMY");
|
+
|
+ output->base.enable = drm_dummy_output_enable;
|
+ output->base.destroy = drm_dummy_output_destroy;
|
+ output->base.disable = drm_dummy_output_disable;
|
+
|
+ output->base.start_repaint_loop = drm_dummy_output_start_repaint_loop;
|
+ output->base.repaint = drm_dummy_output_repaint;
|
+ output->base.set_dpms = NULL;
|
+ output->base.switch_mode = NULL;
|
+ output->base.gamma_size = 0;
|
+ output->base.set_gamma = NULL;
|
+ output->base.unavailable = true;
|
+
|
+ weston_compositor_add_pending_output(&output->base, b->compositor);
|
+
|
+#ifdef BUILD_DRM_GBM
|
+ output->gbm_bo_flags = GBM_BO_USE_LINEAR | GBM_BO_USE_RENDERING;
|
+ output->gbm_format = DRM_FORMAT_XRGB8888;
|
+#endif
|
+
|
+ plane = zalloc(sizeof(*plane));
|
+ if (!plane) {
|
+ weston_output_release(&output->base);
|
+ free(output);
|
+ return NULL;
|
+ }
|
+
|
+ plane->type = WDRM_PLANE_TYPE_PRIMARY;
|
+ plane->backend = b;
|
+ plane->state_cur = drm_plane_state_alloc(NULL, plane);
|
+ plane->state_cur->complete = true;
|
+
|
+ weston_drm_format_array_init(&plane->formats);
|
+ fmt = weston_drm_format_array_add_format(&plane->formats,
|
+ output->gbm_format);
|
+ weston_drm_format_add_modifier(fmt, DRM_FORMAT_MOD_LINEAR);
|
+
|
+ weston_plane_init(&plane->base, b->compositor, 0, 0);
|
+ wl_list_insert(&b->plane_list, &plane->link);
|
+
|
+ output->scanout_plane = plane;
|
+
|
+ return &output->base;
|
+}
|
+
|
+static int drm_backend_init_dummy(struct drm_backend *b)
|
+{
|
+ struct weston_mode *mode;
|
+
|
+ b->dummy_output = drm_dummy_output_create(b);
|
+ if (!b->dummy_output)
|
+ return -1;
|
+
|
+ mode = zalloc(sizeof *mode);
|
+ if (!mode)
|
+ goto err;
|
+
|
+ mode->flags = WL_OUTPUT_MODE_CURRENT;
|
+ mode->width = 1920;
|
+ mode->height = 1080;
|
+ mode->refresh = 60 * 1000LL;
|
+
|
+ wl_list_insert(b->dummy_output->mode_list.prev, &mode->link);
|
+
|
+ b->dummy_output->current_mode = mode;
|
+
|
+ weston_output_set_scale(b->dummy_output, 1);
|
+ weston_output_set_transform(b->dummy_output,
|
+ WL_OUTPUT_TRANSFORM_NORMAL);
|
+
|
+ b->dummy_head = zalloc(sizeof *b->dummy_head);
|
+ if (!b->dummy_head)
|
+ goto err;
|
+
|
+ weston_head_init(&b->dummy_head->base, "DUMMY");
|
+ weston_head_set_monitor_strings(&b->dummy_head->base,
|
+ "DUMMY", "DUMMY", "DUMMY");
|
+ weston_compositor_add_head(b->compositor, &b->dummy_head->base);
|
+ weston_output_attach_head(b->dummy_output, &b->dummy_head->base);
|
+
|
+ return 0;
|
+err:
|
+ drm_dummy_output_destroy(b->dummy_output);
|
+ b->dummy_output = NULL;
|
+ return -1;
|
+}
|
+
|
enum drm_head_mode {
|
DRM_HEAD_MODE_DEFAULT,
|
DRM_HEAD_MODE_PRIMARY,
|
@@ -4007,6 +4201,11 @@ drm_backend_create(struct weston_compositor *compositor,
|
goto err_sprite;
|
}
|
|
+ if (drm_backend_init_dummy(b) < 0) {
|
+ weston_log("Failed to init dummy output\n");
|
+ goto err_udev_input;
|
+ }
|
+
|
wl_list_init(&b->writeback_connector_list);
|
if (drm_backend_update_connectors(b, drm_device) < 0) {
|
weston_log("Failed to create heads for %s\n", b->drm.filename);
|
diff --git a/libweston/backend-drm/kms.c b/libweston/backend-drm/kms.c
|
index 4b5ba42..a3c55bd 100644
|
--- a/libweston/backend-drm/kms.c
|
+++ b/libweston/backend-drm/kms.c
|
@@ -1170,6 +1170,9 @@ drm_pending_state_apply_atomic(struct drm_pending_state *pending_state,
|
continue;
|
|
head = to_drm_head(head_base);
|
+ if (head == b->dummy_head)
|
+ continue;
|
+
|
connector_id = head->connector.connector_id;
|
|
drm_debug(b, "\t\t[atomic] disabling inactive head %s\n",
|
diff --git a/libweston/compositor.c b/libweston/compositor.c
|
index 121871c..67766df 100644
|
--- a/libweston/compositor.c
|
+++ b/libweston/compositor.c
|
@@ -6436,6 +6436,9 @@ weston_output_set_color_transforms(struct weston_output *output)
|
struct weston_color_transform *sRGB_to_blend = NULL;
|
bool ok;
|
|
+ if (!cm)
|
+ return false;
|
+
|
ok = cm->get_output_color_transform(cm, output, &blend_to_output);
|
ok = ok && cm->get_sRGB_to_output_color_transform(cm, output,
|
&sRGB_to_output);
|
--
|
2.20.1
|