diff options
author | Daniel Stone <daniels@collabora.com> | 2016-11-02 11:12:43 +0000 |
---|---|---|
committer | Daniel Stone <daniels@collabora.com> | 2017-02-07 19:16:31 +0000 |
commit | 99f860c2d7b78e50bdb8bf1194307fef3f79d894 (patch) | |
tree | 91caea7bc993648a2f05efc5a517d4ad24daaab3 | |
parent | fef7cb2e20daae342afbb4aa2ab71fc7a38c375d (diff) |
compositor-drm: Introduce fb_last member
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 <daniels@collabora.com>
Differential Revision: https://phabricator.freedesktop.org/D1411
-rw-r--r-- | libweston/compositor-drm.c | 42 |
1 files changed, 30 insertions, 12 deletions
diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index 3cbb1513..825e0afe 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -189,7 +189,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]; @@ -210,7 +210,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; } @@ -934,9 +945,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; @@ -964,9 +975,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; @@ -1496,10 +1506,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); @@ -2718,6 +2734,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; @@ -2749,8 +2766,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); } |