diff options
Diffstat (limited to 'xserver/present/present_wnmd.c')
-rw-r--r-- | xserver/present/present_wnmd.c | 84 |
1 files changed, 51 insertions, 33 deletions
diff --git a/xserver/present/present_wnmd.c b/xserver/present/present_wnmd.c index 82bae4022..a2e00cebb 100644 --- a/xserver/present/present_wnmd.c +++ b/xserver/present/present_wnmd.c @@ -42,6 +42,17 @@ static void present_wnmd_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc); +static int +present_wnmd_queue_vblank(ScreenPtr screen, + WindowPtr window, + RRCrtcPtr crtc, + uint64_t event_id, + uint64_t msc) +{ + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + return (*screen_priv->wnmd_info->queue_vblank) (window, crtc, event_id, msc); +} + static void present_wnmd_create_event_id(present_window_priv_ptr window_priv, present_vblank_ptr vblank) { @@ -111,7 +122,8 @@ present_wnmd_free_idle_vblanks(WindowPtr window) present_vblank_ptr vblank, tmp; xorg_list_for_each_entry_safe(vblank, tmp, &window_priv->idle_queue, event_queue) { - present_wnmd_free_idle_vblank(vblank); + if (vblank->flip) + present_wnmd_free_idle_vblank(vblank); } if (window_priv->flip_active) { @@ -168,8 +180,8 @@ present_wnmd_flip_notify(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_ WindowPtr window = vblank->window; present_window_priv_ptr window_priv = present_window_priv(window); - DebugPresent(("\tn %" PRIu64 " %p %" PRIu64 ": %08" PRIx32 " -> %08" PRIx32 "\n", - vblank->event_id, vblank, vblank->target_msc, + DebugPresent(("\tn %" PRIu64 " %p %" PRIu64 " %" PRIu64 ": %08" PRIx32 " -> %08" PRIx32 "\n", + vblank->event_id, vblank, vblank->exec_msc, vblank->target_msc, vblank->pixmap ? vblank->pixmap->drawable.id : 0, vblank->window ? vblank->window->drawable.id : 0)); @@ -234,7 +246,12 @@ present_wnmd_event_notify(WindowPtr window, uint64_t event_id, uint64_t ust, uin xorg_list_for_each_entry(vblank, &window_priv->idle_queue, event_queue) { if (vblank->event_id == event_id) { - present_wnmd_free_idle_vblank(vblank); + if (vblank->flip) + present_wnmd_free_idle_vblank(vblank); + else + /* Copies which were executed but need their completion event sent */ + present_execute_post(vblank, ust, msc); + return; } } @@ -270,15 +287,13 @@ present_wnmd_check_flip(RRCrtcPtr crtc, if (!screen_priv->wnmd_info->flip) return FALSE; - /* Can't flip redirected child windows */ - if (screen->GetWindowPixmap(window) != screen->GetWindowPixmap(toplvl_window)) - return FALSE; - /* Source pixmap must align with window exactly */ if (x_off || y_off) return FALSE; - // TODO: Check for valid region? + /* Valid area must contain window (for simplicity for now just never flip when one is set). */ + if (valid) + return FALSE; /* Flip pixmap must have same dimensions as window */ if (window->drawable.width != pixmap->drawable.width || @@ -289,6 +304,10 @@ present_wnmd_check_flip(RRCrtcPtr crtc, if ( !RegionEqual(&window->winSize, &toplvl_window->winSize) ) return FALSE; + /* Can't flip if window clipped by children */ + if (!RegionEqual(&window->clipList, &window->winSize)) + return FALSE; + /* Ask the driver for permission */ if (screen_priv->wnmd_info->check_flip2) { if (!(*screen_priv->wnmd_info->check_flip2) (crtc, window, pixmap, sync_flip, reason)) { @@ -325,11 +344,11 @@ present_wnmd_check_flip_window (WindowPtr window) if (flip_pending) { if (!present_wnmd_check_flip(flip_pending->crtc, flip_pending->window, flip_pending->pixmap, - flip_pending->sync_flip, NULL, 0, 0, NULL)) + flip_pending->sync_flip, flip_pending->valid, 0, 0, NULL)) present_wnmd_set_abort_flip(window); } else if (flip_active) { if (!present_wnmd_check_flip(flip_active->crtc, flip_active->window, flip_active->pixmap, - flip_active->sync_flip, NULL, 0, 0, NULL)) + flip_active->sync_flip, flip_active->valid, 0, 0, NULL)) present_wnmd_flips_stop(window); } @@ -337,11 +356,9 @@ present_wnmd_check_flip_window (WindowPtr window) xorg_list_for_each_entry(vblank, &window_priv->vblank, window_list) { if (vblank->queued && vblank->flip && !present_wnmd_check_flip(vblank->crtc, window, vblank->pixmap, - vblank->sync_flip, NULL, 0, 0, &reason)) { + vblank->sync_flip, vblank->valid, 0, 0, &reason)) { vblank->flip = FALSE; vblank->reason = reason; - if (vblank->sync_flip) - vblank->requeue = TRUE; } } } @@ -441,6 +458,7 @@ present_wnmd_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) vblank->queued = FALSE; if (vblank->pixmap && vblank->window) { + ScreenPtr screen = window->drawable.pScreen; if (vblank->flip) { RegionPtr damage; @@ -455,10 +473,13 @@ present_wnmd_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) /* Set update region as damaged */ if (vblank->update) { - damage = vblank->update; + damage = RegionDuplicate(vblank->update); + /* Translate update region to screen space */ + assert(vblank->x_off == 0 && vblank->y_off == 0); + RegionTranslate(damage, window->drawable.x, window->drawable.y); RegionIntersect(damage, damage, &window->clipList); } else - damage = &window->clipList; + damage = RegionDuplicate(&window->clipList); /* Try to flip - the vblank is now pending */ @@ -466,7 +487,6 @@ present_wnmd_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) // ask the driver if (present_wnmd_flip(vblank->window, vblank->crtc, vblank->event_id, vblank->target_msc, vblank->pixmap, vblank->sync_flip, damage)) { - ScreenPtr screen = window->drawable.pScreen; WindowPtr toplvl_window = present_wnmd_toplvl_pixmap_window(vblank->window); PixmapPtr old_pixmap = screen->GetWindowPixmap(window); @@ -481,6 +501,7 @@ present_wnmd_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) /* Report damage */ DamageDamageRegion(&vblank->window->drawable, damage); + RegionDestroy(damage); return; } @@ -496,9 +517,12 @@ present_wnmd_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) present_wnmd_cancel_flip(window); present_execute_copy(vblank, crtc_msc); + assert(!vblank->queued); - if (vblank->queued) { - xorg_list_add(&vblank->event_queue, &window_priv->exec_queue); + if (present_wnmd_queue_vblank(screen, window, vblank->crtc, + vblank->event_id, crtc_msc + 1) + == Success) { + xorg_list_add(&vblank->event_queue, &window_priv->idle_queue); xorg_list_append(&vblank->window_list, &window_priv->vblank); return; @@ -508,17 +532,6 @@ present_wnmd_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) present_execute_post(vblank, ust, crtc_msc); } -static int -present_wnmd_queue_vblank(ScreenPtr screen, - WindowPtr window, - RRCrtcPtr crtc, - uint64_t event_id, - uint64_t msc) -{ - present_screen_priv_ptr screen_priv = present_screen_priv(screen); - return (*screen_priv->wnmd_info->queue_vblank) (window, crtc, event_id, msc); -} - static uint64_t present_wnmd_window_to_crtc_msc(WindowPtr window, RRCrtcPtr crtc, uint64_t window_msc, uint64_t new_msc) { @@ -624,15 +637,20 @@ present_wnmd_pixmap(WindowPtr window, &screen_priv->wnmd_info->capabilities, notifies, num_notifies, - &target_msc, + target_msc, crtc_msc); if (!vblank) return BadAlloc; + /* WNMD presentations always complete (at least) one frame after they + * are executed + */ + vblank->exec_msc = vblank->target_msc - 1; + xorg_list_append(&vblank->event_queue, &window_priv->exec_queue); vblank->queued = TRUE; - if (crtc_msc < target_msc) { - if (present_wnmd_queue_vblank(screen, window, target_crtc, vblank->event_id, target_msc) == Success) { + if (crtc_msc < vblank->exec_msc) { + if (present_wnmd_queue_vblank(screen, window, target_crtc, vblank->event_id, vblank->exec_msc) == Success) { return Success; } DebugPresent(("present_queue_vblank failed\n")); |