Clean up some ambiguity around current/next: current could previously
have referred to a buffer which was being displayed, or the last buffer
being displayed whilst we waited for a configuration we'd requested to
take effect.

Introduce a new variable, fb_last, which exclusively holds the latter
case, thus leaving us with three unambiguous members: fb_pending is used
as a scratch space for a buffer we're about to post, fb_current holds
the buffer we last requested to display (whether active yet or not), and
fb_last is again scratch space for a buffer which is no longer being
displayed after a previous configuration reqeust.

Signed-off-by: Daniel Stone <dani...@collabora.com>

Differential Revision: https://phabricator.freedesktop.org/D1411
---
 libweston/compositor-drm.c | 42 ++++++++++++++++++++++++++++++------------
 1 file changed, 30 insertions(+), 12 deletions(-)

diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c
index ee66dbe..5d27801 100644
--- a/libweston/compositor-drm.c
+++ b/libweston/compositor-drm.c
@@ -186,7 +186,7 @@ struct drm_output {
        int current_cursor;
 
        struct weston_plane fb_plane;
-       struct drm_fb *fb_current, *fb_pending;
+       struct drm_fb *fb_current, *fb_pending, *fb_last;
        struct backlight *backlight;
 
        struct drm_fb *dumb[2];
@@ -207,7 +207,7 @@ struct drm_sprite {
 
        struct weston_plane plane;
 
-       struct drm_fb *fb_current, *fb_pending;
+       struct drm_fb *fb_current, *fb_pending, *fb_last;
        struct drm_output *output;
        struct drm_backend *backend;
 
@@ -741,6 +741,8 @@ drm_output_repaint(struct weston_output *output_base,
        if (output->disable_pending || output->destroy_pending)
                return -1;
 
+       assert(!output->fb_last);
+
        drm_output_render(output, damage);
        if (!output->fb_pending)
                return -1;
@@ -766,6 +768,10 @@ drm_output_repaint(struct weston_output *output_base,
                goto err_pageflip;
        }
 
+       output->fb_last = output->fb_current;
+       output->fb_current = output->fb_pending;
+       output->fb_pending = NULL;
+
        output->page_flip_pending = 1;
 
        drm_output_set_cursor(output);
@@ -780,6 +786,8 @@ drm_output_repaint(struct weston_output *output_base,
                        .request.sequence = 1,
                };
 
+               /* XXX: Set output much earlier, so we don't attempt to place
+                *      planes on entirely the wrong output. */
                if ((!s->fb_current && !s->fb_pending) ||
                    !drm_sprite_crtc_supported(output, s))
                        continue;
@@ -811,6 +819,9 @@ drm_output_repaint(struct weston_output *output_base,
                }
 
                s->output = output;
+               s->fb_last = s->fb_current;
+               s->fb_current = s->fb_pending;
+               s->fb_pending = NULL;
                output->vblank_pending = 1;
        }
 
@@ -921,9 +932,9 @@ vblank_handler(int fd, unsigned int frame, unsigned int 
sec, unsigned int usec,
        drm_output_update_msc(output, frame);
        output->vblank_pending = 0;
 
-       drm_fb_unref(s->fb_current);
-       s->fb_current = s->fb_pending;
-       s->fb_pending = NULL;
+       assert(s->fb_last || s->fb_current);
+       drm_fb_unref(s->fb_last);
+       s->fb_last = NULL;
 
        if (!output->page_flip_pending) {
                ts.tv_sec = sec;
@@ -951,9 +962,8 @@ page_flip_handler(int fd, unsigned int frame,
         * we just want to page flip to the current buffer to get an accurate
         * timestamp */
        if (output->page_flip_pending) {
-               drm_fb_unref(output->fb_current);
-               output->fb_current = output->fb_pending;
-               output->fb_pending = NULL;
+               drm_fb_unref(output->fb_last);
+               output->fb_last = NULL;
        }
 
        output->page_flip_pending = 0;
@@ -1473,10 +1483,16 @@ drm_output_switch_mode(struct weston_output 
*output_base, struct weston_mode *mo
        output->base.current_mode->flags =
                WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
 
-       /* reset rendering stuff. */
+       /* XXX: This drops our current buffer too early, before we've started
+        *      displaying it. Ideally this should be much more atomic and
+        *      integrated with a full repaint cycle, rather than doing a
+        *      sledgehammer modeswitch first, and only later showing new
+        *      content.
+        */
        drm_fb_unref(output->fb_current);
-       drm_fb_unref(output->fb_pending);
-       output->fb_current = output->fb_pending = NULL;
+       assert(!output->fb_last);
+       assert(!output->fb_pending);
+       output->fb_last = output->fb_current = NULL;
 
        if (b->use_pixman) {
                drm_output_fini_pixman(output);
@@ -2692,6 +2708,7 @@ create_sprites(struct drm_backend *b)
 
                sprite->possible_crtcs = plane->possible_crtcs;
                sprite->plane_id = plane->plane_id;
+               sprite->fb_last = NULL;
                sprite->fb_current = NULL;
                sprite->fb_pending = NULL;
                sprite->backend = b;
@@ -2723,8 +2740,9 @@ destroy_sprites(struct drm_backend *backend)
                                sprite->plane_id,
                                output->crtc_id, 0, 0,
                                0, 0, 0, 0, 0, 0, 0, 0);
+               drm_fb_unref(sprite->fb_last);
                drm_fb_unref(sprite->fb_current);
-               drm_fb_unref(sprite->fb_pending);
+               assert(!sprite->fb_pending);
                weston_plane_release(&sprite->plane);
                free(sprite);
        }
-- 
2.9.3

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

Reply via email to