If we have an unused CRTC or connector, explicitly disable it during the
end of the repaint cycle, or when we get VT-switched back in.

This commit moves state_invalid from an output property to a backend
property, as the unused CRTCs or connectors are likely not tracked by
drm_outputs. This matches the mechanics of later commits, where we move
to a global repaint-flush hook, applying the state for all outputs in
one go.

The output state_invalid flag originally provoked full changes on output
creation (via setting the flag at output enable time) and session enter.

For the new-output case, we will not have any FB in output->state_cur,
so we still take the same path in repaint as if state_invalid were set.
At session enter, we preserve the existing behaviour: as
start_repaint_loop will fail when state_invalid is set, all outputs will
be scheduled for repaint together, and state_invalid will not be cleared
until after all outputs have been repainted, inside repaint_flush.

Signed-off-by: Daniel Stone <dani...@collabora.com>
---
 libweston/compositor-drm.c | 34 +++++++++++++++++++++-------------
 1 file changed, 21 insertions(+), 13 deletions(-)

diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c
index f2d99b97f..22bf75aec 100644
--- a/libweston/compositor-drm.c
+++ b/libweston/compositor-drm.c
@@ -188,6 +188,8 @@ struct drm_backend {
 
        void *repaint_data;
 
+       bool state_invalid;
+
        /* Connector and CRTC IDs not used by any enabled output. */
        struct wl_array unused_connectors;
        struct wl_array unused_crtcs;
@@ -351,8 +353,6 @@ struct drm_output {
        enum dpms_enum dpms;
        struct backlight *backlight;
 
-       bool state_invalid;
-
        int vblank_pending;
        int page_flip_pending;
        int destroy_pending;
@@ -1751,7 +1751,7 @@ drm_output_repaint(struct weston_output *output_base,
        assert(scanout_state->dest_h == scanout_state->src_h >> 16);
 
        mode = to_drm_mode(output->base.current_mode);
-       if (output->state_invalid || !scanout_plane->state_cur->fb ||
+       if (backend->state_invalid || !scanout_plane->state_cur->fb ||
            scanout_plane->state_cur->fb->stride != scanout_state->fb->stride) {
                ret = drmModeSetCrtc(backend->drm.fd, output->crtc_id,
                                     scanout_state->fb->fb_id,
@@ -1763,8 +1763,6 @@ drm_output_repaint(struct weston_output *output_base,
                        goto err;
                }
                output_base->set_dpms(output_base, WESTON_DPMS_ON);
-
-               output->state_invalid = false;
        }
 
        if (drmModePageFlip(backend->drm.fd, output->crtc_id,
@@ -1872,7 +1870,7 @@ drm_output_start_repaint_loop(struct weston_output 
*output_base)
        /* Need to smash all state in from scratch; current timings might not
         * be what we want, page flip might not work, etc.
         */
-       if (output->state_invalid)
+       if (backend->state_invalid)
                goto finish_frame;
 
        assert(scanout_plane->state_cur->output == output);
@@ -2036,12 +2034,26 @@ drm_repaint_flush(struct weston_compositor *compositor, 
void *repaint_data)
        struct drm_backend *b = to_drm_backend(compositor);
        struct drm_pending_state *pending_state = repaint_data;
        struct drm_output_state *output_state, *tmp;
+       uint32_t *unused;
+
+       if (b->state_invalid) {
+               /* If we need to reset all our state (e.g. because we've
+                * just started, or just been VT-switched in), explicitly
+                * disable all the CRTCs we aren't using. This also disables
+                * all connectors on these CRTCs, so we don't need to do that
+                * separately with the pre-atomic API. */
+               wl_array_for_each(unused, &b->unused_crtcs)
+                       drmModeSetCrtc(b->drm.fd, *unused, 0, 0, 0, NULL, 0,
+                                      NULL);
+       }
 
        wl_list_for_each_safe(output_state, tmp, &pending_state->output_list,
                              link) {
                drm_output_assign_state(output_state, DRM_STATE_APPLY_ASYNC);
        }
 
+       b->state_invalid = false;
+
        drm_pending_state_free(pending_state);
        b->repaint_data = NULL;
 }
@@ -2662,7 +2674,7 @@ drm_output_switch_mode(struct weston_output *output_base, 
struct weston_mode *mo
         *      sledgehammer modeswitch first, and only later showing new
         *      content.
         */
-       output->state_invalid = true;
+       b->state_invalid = true;
 
        if (b->use_pixman) {
                drm_output_fini_pixman(output);
@@ -4003,8 +4015,6 @@ drm_output_enable(struct weston_output *base)
                                    output->connector->count_modes == 0 ?
                                    ", built-in" : "");
 
-       output->state_invalid = true;
-
        return 0;
 
 err:
@@ -4523,10 +4533,7 @@ session_notify(struct wl_listener *listener, void *data)
                weston_log("activating session\n");
                weston_compositor_wake(compositor);
                weston_compositor_damage_all(compositor);
-
-               wl_list_for_each(output, &compositor->output_list, base.link)
-                       output->state_invalid = true;
-
+               b->state_invalid = true;
                udev_input_enable(&b->input);
        } else {
                weston_log("deactivating session\n");
@@ -4938,6 +4945,7 @@ drm_backend_create(struct weston_compositor *compositor,
        if (b == NULL)
                return NULL;
 
+       b->state_invalid = true;
        b->drm.fd = -1;
        wl_array_init(&b->unused_crtcs);
        wl_array_init(&b->unused_connectors);
-- 
2.14.3

_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to