summaryrefslogtreecommitdiff
path: root/xserver/present/present_wnmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'xserver/present/present_wnmd.c')
-rw-r--r--xserver/present/present_wnmd.c84
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"));