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 5909239..0d3ca35 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -190,7 +190,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]; @@ -211,7 +211,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; @@ -755,6 +755,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; @@ -780,6 +782,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); @@ -794,6 +800,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; @@ -825,6 +833,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; } @@ -935,9 +946,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; @@ -965,9 +976,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; @@ -1486,10 +1496,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); @@ -2705,6 +2721,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; @@ -2736,8 +2753,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