compositor-fbdev: make re-enable less drastic
authorPekka Paalanen <pekka.paalanen@collabora.co.uk>
Wed, 13 Sep 2017 13:19:02 +0000 (16:19 +0300)
committerPekka Paalanen <pekka.paalanen@collabora.co.uk>
Tue, 17 Apr 2018 12:19:57 +0000 (15:19 +0300)
Destroying the whole output in reenable would cause list walk
corruption: the loop over output_list in session_notify() is not using
wl_list_for_each_safe so output removal would break it.

Creating a new output is also problematic as it needs the compositor to
configure it, but that probably saved us from another list walk failure:
adding the new output to be list while walking the list, possibly
causing it to be destroyed and re-created ad infinitum.

Instead of a complete destroy/create cycle, just do our internal
disable/enable cycle. That will re-open the fbdev, re-read the
parameters, re-create hw_surface, and reinitialize the renderer output.

A problem with this is if fbdev_set_screen_info() fails. We do read the
new parameters, but we don't communicate them to libweston core or old
clients.

However, it is hard to care: to trigger this path, one needs to
VT-switch to another fbdev app which changes the fbdev parameters. That
is quite difficult as VT-switching has been broken for a good while for
fbdev-backend, at least with logind. Also fbdev_set_screen_info() would
have to fail before one should be able to tell something is wrong.

The real reason behind this patch, though, is the migration to the
head-based output API. Destroying and re-creating an output really does
not fit that design. Destroying and re-creating a head would be better,
but again not testable in the current state.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
Reviewed-by: Ian Ray <ian.ray@ge.com>
Acked-by: Daniel Stone <daniels@collabora.com>
Acked-by: Derek Foreman <derekf@osg.samsung.com>
libweston/compositor-fbdev.c

index 7db95d2..af33862 100644 (file)
@@ -594,15 +594,15 @@ fbdev_output_reenable(struct fbdev_backend *backend,
        struct fbdev_output *output = to_fbdev_output(base);
        struct fbdev_screeninfo new_screen_info;
        int fb_fd;
-       char *device;
 
        weston_log("Re-enabling fbdev output.\n");
+       assert(output->base.enabled);
 
        /* Create the frame buffer. */
        fb_fd = fbdev_frame_buffer_open(output->device, &new_screen_info);
        if (fb_fd < 0) {
                weston_log("Creating frame buffer failed.\n");
-               goto err;
+               return -1;
        }
 
        /* Check whether the frame buffer details have changed since we were
@@ -616,27 +616,20 @@ fbdev_output_reenable(struct fbdev_backend *backend,
 
                close(fb_fd);
 
-               /* Remove and re-add the output so that resources depending on
+               /* Disable and enable the output so that resources depending on
                 * the frame buffer X/Y resolution (such as the shadow buffer)
                 * are re-initialised. */
-               device = strdup(output->device);
-               fbdev_output_destroy(&output->base);
-               fbdev_output_create(backend, device);
-               free(device);
-
-               return 0;
+               fbdev_output_disable(&output->base);
+               return fbdev_output_enable(&output->base);
        }
 
        /* Map the device if it has the same details as before. */
        if (fbdev_frame_buffer_map(output, fb_fd) < 0) {
                weston_log("Mapping frame buffer failed.\n");
-               goto err;
+               return -1;
        }
 
        return 0;
-
-err:
-       return -1;
 }
 
 static void