402 lines
11 KiB
Diff
402 lines
11 KiB
Diff
From bed745ad33c089e72475db462714079630903730 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 31/95] 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 | 6 +
|
|
libweston/backend-drm/drm.c | 210 ++++++++++++++++++++++++++-
|
|
libweston/backend-drm/kms.c | 2 +-
|
|
libweston/compositor.c | 3 +
|
|
6 files changed, 224 insertions(+), 7 deletions(-)
|
|
|
|
diff --git a/compositor/main.c b/compositor/main.c
|
|
index 987c8f9..f151a77 100644
|
|
--- a/compositor/main.c
|
|
+++ b/compositor/main.c
|
|
@@ -2595,6 +2595,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 463c64e..e48db31 100644
|
|
--- a/desktop-shell/shell.c
|
|
+++ b/desktop-shell/shell.c
|
|
@@ -4317,10 +4317,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
|
|
@@ -4447,6 +4443,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 532593e..e175f16 100644
|
|
--- a/libweston/backend-drm/drm-internal.h
|
|
+++ b/libweston/backend-drm/drm-internal.h
|
|
@@ -370,6 +370,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 {
|
|
@@ -667,6 +670,8 @@ void
|
|
drm_output_destroy(struct weston_output *output_base);
|
|
void
|
|
drm_virtual_output_destroy(struct weston_output *output_base);
|
|
+void
|
|
+drm_dummy_output_destroy(struct weston_output *output_base);
|
|
|
|
static inline struct drm_output *
|
|
to_drm_output(struct weston_output *base)
|
|
@@ -675,6 +680,7 @@ to_drm_output(struct weston_output *base)
|
|
#ifdef BUILD_DRM_VIRTUAL
|
|
base->destroy != drm_virtual_output_destroy &&
|
|
#endif
|
|
+ base->destroy != drm_dummy_output_destroy &&
|
|
base->destroy != drm_output_destroy)
|
|
return NULL;
|
|
return container_of(base, struct drm_output, base);
|
|
diff --git a/libweston/backend-drm/drm.c b/libweston/backend-drm/drm.c
|
|
index 2dc38b5..9d4354d 100644
|
|
--- a/libweston/backend-drm/drm.c
|
|
+++ b/libweston/backend-drm/drm.c
|
|
@@ -213,8 +213,14 @@ drm_backend_update_outputs(struct drm_backend *b)
|
|
{
|
|
struct weston_output *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;
|
|
|
|
@@ -1275,6 +1281,10 @@ drm_output_find_special_plane(struct drm_device *device,
|
|
struct weston_output *base;
|
|
bool found_elsewhere = false;
|
|
|
|
+ /* Ignore non-real planes */
|
|
+ if (!plane->plane_id)
|
|
+ continue;
|
|
+
|
|
if (plane->type != type)
|
|
continue;
|
|
if (!drm_plane_is_available(plane, output))
|
|
@@ -2710,11 +2720,15 @@ drm_head_destroy(struct weston_head *base)
|
|
|
|
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);
|
|
}
|
|
|
|
@@ -2951,8 +2965,9 @@ drm_backend_update_connectors(struct drm_device *device,
|
|
wl_list_for_each_safe(base, base_next,
|
|
&b->compositor->head_list, compositor_link) {
|
|
head = to_drm_head(base);
|
|
- if (!head)
|
|
+ if (!head || !head->connector.connector_id)
|
|
continue;
|
|
+
|
|
connector_id = head->connector.connector_id;
|
|
|
|
if (head->connector.device != device)
|
|
@@ -3000,6 +3015,9 @@ drm_backend_update_connectors(struct drm_device *device,
|
|
continue;
|
|
|
|
head = to_drm_head(base);
|
|
+ if (!head || !head->connector.connector_id)
|
|
+ continue;
|
|
+
|
|
conn = head->connector.conn;
|
|
|
|
if (conn->connection != DRM_MODE_CONNECTED ||
|
|
@@ -3029,6 +3047,8 @@ drm_backend_update_connectors(struct drm_device *device,
|
|
}
|
|
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);
|
|
@@ -3204,6 +3224,11 @@ drm_destroy(struct weston_compositor *ec)
|
|
struct drm_crtc *crtc, *crtc_tmp;
|
|
struct drm_writeback *writeback, *writeback_tmp;
|
|
|
|
+ weston_output_destroy(b->dummy_output);
|
|
+
|
|
+ if (b->dummy_head)
|
|
+ drm_head_destroy(&b->dummy_head->base);
|
|
+
|
|
udev_input_destroy(&b->input);
|
|
|
|
wl_event_source_remove(b->config_timer);
|
|
@@ -3906,6 +3931,182 @@ 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)
|
|
+{
|
|
+ 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;
|
|
+}
|
|
+
|
|
+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_device *device)
|
|
+{
|
|
+ struct drm_backend *b = device->backend;
|
|
+ struct drm_output *output;
|
|
+ struct drm_plane *plane;
|
|
+ struct weston_drm_format *fmt;
|
|
+
|
|
+ output = zalloc(sizeof *output);
|
|
+ if (!output)
|
|
+ return NULL;
|
|
+
|
|
+ output->device = device;
|
|
+ output->crtc = NULL;
|
|
+
|
|
+#ifdef BUILD_DRM_GBM
|
|
+ output->gbm_bo_flags = GBM_BO_USE_LINEAR | GBM_BO_USE_RENDERING;
|
|
+ output->gbm_format = DRM_FORMAT_XRGB8888;
|
|
+#endif
|
|
+
|
|
+ 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.unavailable = true;
|
|
+
|
|
+ weston_compositor_add_pending_output(&output->base, b->compositor);
|
|
+
|
|
+ plane = zalloc(sizeof(*plane));
|
|
+ if (!plane) {
|
|
+ weston_output_release(&output->base);
|
|
+ free(output);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ plane->type = WDRM_PLANE_TYPE_PRIMARY;
|
|
+ plane->device = device;
|
|
+ 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(&device->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->drm);
|
|
+ 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");
|
|
+
|
|
+ b->dummy_head->base.backend_id = drm_head_destroy;
|
|
+
|
|
+ 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,
|
|
@@ -4143,6 +4344,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->drm->writeback_connector_list);
|
|
if (drm_backend_update_connectors(b->drm, drm_device) < 0) {
|
|
weston_log("Failed to create heads for %s\n", b->drm->drm.filename);
|
|
diff --git a/libweston/backend-drm/kms.c b/libweston/backend-drm/kms.c
|
|
index 0008e83..fb43c43 100644
|
|
--- a/libweston/backend-drm/kms.c
|
|
+++ b/libweston/backend-drm/kms.c
|
|
@@ -1196,7 +1196,7 @@ drm_pending_state_apply_atomic(struct drm_pending_state *pending_state,
|
|
&b->compositor->head_list, compositor_link) {
|
|
struct drm_property_info *info;
|
|
head = to_drm_head(head_base);
|
|
- if (!head)
|
|
+ if (!head || head == b->dummy_head)
|
|
continue;
|
|
|
|
if (weston_head_is_enabled(head_base))
|
|
diff --git a/libweston/compositor.c b/libweston/compositor.c
|
|
index 74b21ac..1f48796 100644
|
|
--- a/libweston/compositor.c
|
|
+++ b/libweston/compositor.c
|
|
@@ -6932,6 +6932,9 @@ weston_output_set_color_outcome(struct weston_output *output)
|
|
struct weston_color_manager *cm = output->compositor->color_manager;
|
|
struct weston_output_color_outcome *colorout;
|
|
|
|
+ if (!cm)
|
|
+ return false;
|
|
+
|
|
colorout = cm->create_output_color_outcome(cm, output);
|
|
if (!colorout) {
|
|
weston_log("Creating color transformation for output \"%s\" failed.\n",
|
|
--
|
|
2.20.1
|
|
|