mirror of
https://gitlab.freedesktop.org/wayland/weston
synced 2024-07-21 02:25:36 +00:00
backend-drm: schedule connector disable for detached head
Currently, if a head is detached, the entire state of the device is invalidated to make sure that the connector is disabled on the next atomic commit. Side effect of the invalid state is that all planes are disabled on the next commit. This includes planes that are used with a different head that is not part of the next atomic commit. Disabling the planes of unrelated outputs causes a blanking of these outputs until output is repainted and the plane is reenabled. Store the detached heads in a list on the output and disable the connectors for all heads in this list in the next atomic commit. Signed-off-by: Michael Tretter <m.tretter@pengutronix.de>
This commit is contained in:
parent
78818c6d24
commit
bcacd9ec5a
|
@ -623,6 +623,9 @@ struct drm_head {
|
||||||
drmModeModeInfo inherited_mode; /**< Original mode on the connector */
|
drmModeModeInfo inherited_mode; /**< Original mode on the connector */
|
||||||
uint32_t inherited_max_bpc; /**< Original max_bpc on the connector */
|
uint32_t inherited_max_bpc; /**< Original max_bpc on the connector */
|
||||||
uint32_t inherited_crtc_id; /**< Original CRTC assignment */
|
uint32_t inherited_crtc_id; /**< Original CRTC assignment */
|
||||||
|
|
||||||
|
/* drm_output::disable_head */
|
||||||
|
struct wl_list disable_head_link;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct drm_crtc {
|
struct drm_crtc {
|
||||||
|
@ -646,6 +649,9 @@ struct drm_output {
|
||||||
struct drm_device *device;
|
struct drm_device *device;
|
||||||
struct drm_crtc *crtc;
|
struct drm_crtc *crtc;
|
||||||
|
|
||||||
|
/* drm_head::disable_head_link */
|
||||||
|
struct wl_list disable_head;
|
||||||
|
|
||||||
bool page_flip_pending;
|
bool page_flip_pending;
|
||||||
bool atomic_complete_pending;
|
bool atomic_complete_pending;
|
||||||
bool destroy_pending;
|
bool destroy_pending;
|
||||||
|
|
|
@ -1527,10 +1527,14 @@ drm_output_attach_head(struct weston_output *output_base,
|
||||||
struct drm_output *output = to_drm_output(output_base);
|
struct drm_output *output = to_drm_output(output_base);
|
||||||
struct drm_backend *b = output->backend;
|
struct drm_backend *b = output->backend;
|
||||||
struct drm_device *device = b->drm;
|
struct drm_device *device = b->drm;
|
||||||
|
struct drm_head *head = to_drm_head(head_base);
|
||||||
|
|
||||||
if (wl_list_length(&output_base->head_list) >= MAX_CLONED_CONNECTORS)
|
if (wl_list_length(&output_base->head_list) >= MAX_CLONED_CONNECTORS)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
wl_list_remove(&head->disable_head_link);
|
||||||
|
wl_list_init(&head->disable_head_link);
|
||||||
|
|
||||||
if (!output_base->enabled)
|
if (!output_base->enabled)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -1555,18 +1559,13 @@ drm_output_detach_head(struct weston_output *output_base,
|
||||||
struct weston_head *head_base)
|
struct weston_head *head_base)
|
||||||
{
|
{
|
||||||
struct drm_output *output = to_drm_output(output_base);
|
struct drm_output *output = to_drm_output(output_base);
|
||||||
struct drm_backend *b = output->backend;
|
struct drm_head *head = to_drm_head(head_base);
|
||||||
struct drm_device *device = b->drm;
|
|
||||||
|
|
||||||
if (!output_base->enabled)
|
if (!output_base->enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Need to go through modeset to drop connectors that should no longer
|
/* Drop connectors that should no longer be driven on next repaint. */
|
||||||
* be driven. */
|
wl_list_insert(&output->disable_head, &head->disable_head_link);
|
||||||
/* XXX: Ideally we'd do this per-output, not globally. */
|
|
||||||
device->state_invalid = true;
|
|
||||||
|
|
||||||
weston_output_schedule_repaint(output_base);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -2497,6 +2496,8 @@ drm_head_create(struct drm_device *device, drmModeConnector *conn,
|
||||||
|
|
||||||
head->base.backend = &backend->base;
|
head->base.backend = &backend->base;
|
||||||
|
|
||||||
|
wl_list_init(&head->disable_head_link);
|
||||||
|
|
||||||
ret = drm_head_update_info(head, conn);
|
ret = drm_head_update_info(head, conn);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto err_update;
|
goto err_update;
|
||||||
|
@ -2594,6 +2595,8 @@ drm_output_create(struct weston_backend *backend, const char *name)
|
||||||
output->device = device;
|
output->device = device;
|
||||||
output->crtc = NULL;
|
output->crtc = NULL;
|
||||||
|
|
||||||
|
wl_list_init(&output->disable_head);
|
||||||
|
|
||||||
output->max_bpc = 16;
|
output->max_bpc = 16;
|
||||||
#ifdef BUILD_DRM_GBM
|
#ifdef BUILD_DRM_GBM
|
||||||
output->gbm_bo_flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING;
|
output->gbm_bo_flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING;
|
||||||
|
|
|
@ -1163,6 +1163,7 @@ drm_output_apply_state_atomic(struct drm_output_state *state,
|
||||||
struct drm_plane_state *plane_state;
|
struct drm_plane_state *plane_state;
|
||||||
struct drm_mode *current_mode = to_drm_mode(output->base.current_mode);
|
struct drm_mode *current_mode = to_drm_mode(output->base.current_mode);
|
||||||
struct drm_head *head;
|
struct drm_head *head;
|
||||||
|
struct drm_head *tmp;
|
||||||
struct drm_writeback_state *wb_state = output->wb_state;
|
struct drm_writeback_state *wb_state = output->wb_state;
|
||||||
enum writeback_screenshot_state wb_screenshot_state =
|
enum writeback_screenshot_state wb_screenshot_state =
|
||||||
drm_output_get_writeback_state(output);
|
drm_output_get_writeback_state(output);
|
||||||
|
@ -1235,6 +1236,14 @@ drm_output_apply_state_atomic(struct drm_output_state *state,
|
||||||
wl_list_for_each(head, &output->base.head_list, base.output_link)
|
wl_list_for_each(head, &output->base.head_list, base.output_link)
|
||||||
ret |= connector_add_prop(req, &head->connector,
|
ret |= connector_add_prop(req, &head->connector,
|
||||||
WDRM_CONNECTOR_CRTC_ID, 0);
|
WDRM_CONNECTOR_CRTC_ID, 0);
|
||||||
|
|
||||||
|
wl_list_for_each_safe(head, tmp, &output->disable_head,
|
||||||
|
disable_head_link) {
|
||||||
|
ret |= connector_add_prop(req, &head->connector,
|
||||||
|
WDRM_CONNECTOR_CRTC_ID, 0);
|
||||||
|
wl_list_remove(&head->disable_head_link);
|
||||||
|
wl_list_init(&head->disable_head_link);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wl_list_for_each(head, &output->base.head_list, base.output_link) {
|
wl_list_for_each(head, &output->base.head_list, base.output_link) {
|
||||||
|
|
Loading…
Reference in a new issue