diff options
Diffstat (limited to 'present/present.c')
-rw-r--r-- | present/present.c | 79 |
1 files changed, 63 insertions, 16 deletions
diff --git a/present/present.c b/present/present.c index beb01dcbd..8cf3b6f77 100644 --- a/present/present.c +++ b/present/present.c @@ -374,12 +374,17 @@ present_set_tree_pixmap_visit(WindowPtr window, void *data) } static void -present_set_tree_pixmap(WindowPtr window, PixmapPtr pixmap) +present_set_tree_pixmap(WindowPtr window, + PixmapPtr expected, + PixmapPtr pixmap) { struct pixmap_visit visit; ScreenPtr screen = window->drawable.pScreen; visit.old = (*screen->GetWindowPixmap)(window); + if (expected && visit.old != expected) + return; + visit.new = pixmap; if (visit.old == visit.new) return; @@ -390,6 +395,7 @@ static void present_set_abort_flip(ScreenPtr screen) { present_screen_priv_ptr screen_priv = present_screen_priv(screen); + PixmapPtr pixmap = (*screen->GetScreenPixmap)(screen); /* Switch back to using the screen pixmap now to avoid * 2D applications drawing to the wrong pixmap. @@ -397,10 +403,11 @@ present_set_abort_flip(ScreenPtr screen) if (screen_priv->flip_window) present_set_tree_pixmap(screen_priv->flip_window, - (*screen->GetScreenPixmap)(screen)); + screen_priv->flip_pixmap, + pixmap); if (screen->root) - present_set_tree_pixmap(screen->root, (*screen->GetScreenPixmap)(screen)); + present_set_tree_pixmap(screen->root, NULL, pixmap); screen_priv->flip_pending->abort_flip = TRUE; } @@ -414,10 +421,12 @@ present_unflip(ScreenPtr screen) assert (!screen_priv->unflip_event_id); assert (!screen_priv->flip_pending); - if (screen_priv->flip_window) - present_set_tree_pixmap(screen_priv->flip_window, pixmap); + if (screen_priv->flip_pixmap && screen_priv->flip_window) + present_set_tree_pixmap(screen_priv->flip_window, + screen_priv->flip_pixmap, + pixmap); - present_set_tree_pixmap(screen->root, pixmap); + present_set_tree_pixmap(screen->root, NULL, pixmap); /* Update the screen pixmap with the current flip pixmap contents */ @@ -453,6 +462,7 @@ present_flip_notify(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) screen_priv->flip_window = vblank->window; screen_priv->flip_serial = vblank->serial; screen_priv->flip_pixmap = vblank->pixmap; + screen_priv->flip_sync = vblank->sync_flip; screen_priv->flip_idle_fence = vblank->idle_fence; vblank->pixmap = NULL; @@ -541,15 +551,20 @@ present_check_flip_window (WindowPtr window) * Check current flip */ if (window == screen_priv->flip_window) { - if (!present_check_flip(screen_priv->flip_crtc, window, screen_priv->flip_pixmap, FALSE, NULL, 0, 0)) + if (!present_check_flip(screen_priv->flip_crtc, window, screen_priv->flip_pixmap, screen_priv->flip_sync, NULL, 0, 0)) present_unflip(screen); } } /* Now check any queued vblanks */ xorg_list_for_each_entry(vblank, &window_priv->vblank, window_list) { - if (vblank->queued && vblank->flip && !present_check_flip(vblank->crtc, window, vblank->pixmap, FALSE, NULL, 0, 0)) + if (vblank->queued && vblank->flip && !present_check_flip(vblank->crtc, window, vblank->pixmap, vblank->sync_flip, NULL, 0, 0)) { vblank->flip = FALSE; + if (vblank->sync_flip) { + vblank->requeue = TRUE; + vblank->target_msc++; + } + } } } @@ -583,6 +598,15 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) present_screen_priv_ptr screen_priv = present_screen_priv(screen); uint8_t mode; + if (vblank->requeue) { + vblank->requeue = FALSE; + if (Success == present_queue_vblank(screen, + vblank->crtc, + vblank->event_id, + vblank->target_msc)) + return; + } + if (vblank->wait_fence) { if (!present_fence_check_triggered(vblank->wait_fence)) { present_fence_set_callback(vblank->wait_fence, present_wait_fence_triggered, vblank); @@ -629,9 +653,10 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) */ if (screen_priv->flip_window && screen_priv->flip_window != window) present_set_tree_pixmap(screen_priv->flip_window, - (*screen->GetScreenPixmap)(screen)); - present_set_tree_pixmap(vblank->window, vblank->pixmap); - present_set_tree_pixmap(screen->root, vblank->pixmap); + screen_priv->flip_pixmap, + (*screen->GetScreenPixmap)(screen)); + present_set_tree_pixmap(vblank->window, NULL, vblank->pixmap); + present_set_tree_pixmap(screen->root, NULL, vblank->pixmap); /* Report update region as damaged */ @@ -692,6 +717,28 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) present_vblank_destroy(vblank); } +/* + * Returns: + * TRUE if the first MSC value is after the second one + * FALSE if the first MSC value is equal to or before the second one + */ +static Bool +msc_is_after(uint64_t test, uint64_t reference) +{ + return (int64_t)(test - reference) > 0; +} + +/* + * Returns: + * TRUE if the first MSC value is equal to or after the second one + * FALSE if the first MSC value is before the second one + */ +static Bool +msc_is_equal_or_after(uint64_t test, uint64_t reference) +{ + return (int64_t)(test - reference) >= 0; +} + int present_pixmap(WindowPtr window, PixmapPtr pixmap, @@ -746,14 +793,14 @@ present_pixmap(WindowPtr window, /* Adjust target_msc to match modulus */ - if (crtc_msc >= target_msc) { + if (msc_is_equal_or_after(crtc_msc, target_msc)) { if (divisor != 0) { target_msc = crtc_msc - (crtc_msc % divisor) + remainder; if (options & PresentOptionAsync) { - if (target_msc < crtc_msc) + if (msc_is_after(crtc_msc, target_msc)) target_msc += divisor; } else { - if (target_msc <= crtc_msc) + if (msc_is_equal_or_after(crtc_msc, target_msc)) target_msc += divisor; } } else { @@ -839,7 +886,7 @@ present_pixmap(WindowPtr window, if (pixmap != NULL && !(options & PresentOptionCopy) && screen_priv->info) { - if (target_msc > crtc_msc && + if (msc_is_after(target_msc, crtc_msc) && present_check_flip (target_crtc, window, pixmap, TRUE, valid, x_off, y_off)) { vblank->flip = TRUE; @@ -872,7 +919,7 @@ present_pixmap(WindowPtr window, xorg_list_add(&vblank->event_queue, &present_exec_queue); vblank->queued = TRUE; - if (target_msc > crtc_msc) { + if (msc_is_after(target_msc, crtc_msc)) { ret = present_queue_vblank(screen, target_crtc, vblank->event_id, target_msc); if (ret == Success) return Success; |