HYL_OK3568_LINUX/yocto/meta-rockchip/recipes-graphics/wayland/weston_10.0.2/0028-backend-drm-Add-dummy-output-when-no-screens-connect.patch
2025-05-10 21:49:39 +08:00

378 lines
11 KiB
Diff

From 54619af12a927bbef47382587f977e8ca6062625 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/79] 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 4cb29dd..a8b8f35 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