[PATCH v3] present: restore screen pixmap when aborting a flip

Frank Binns frank.binns at imgtec.com
Tue Jun 10 05:43:31 PDT 2014


If a 2D application is started on top of a fullscreen 3D application, which
is flipping, then we need to stop flipping and restore the root window, and
possibly the flip window, to using the screen pixmap. Normally this would
be done as part of an unflip. However, in the case that there is a pending
flip there is no mechanism to abort so the unflip is deferred until the
pending flip completes. This provides a window of opportunity for the 2D
application to draw to the wrong pixmap.

Restore the screen pixmap at the point a pending flip is marked as aborted,
thus avoiding this issue.

Reviewed-by: Keith Packard <keithp at keithp.com>
Signed-off-by: Frank Binns <frank.binns at imgtec.com>
---
This was part of the "present: various fixes" series (see
http://lists.x.org/archives/xorg-devel/2014-May/042601.html) but I've
broken it out into an individual patch as this one was reviewed but
the others weren't.

v3: remove uncessary NULL check of screen->root.

v2: always restore the screen pixmap at the point a pending flip is
    marked as aborted.

 present/present.c | 24 +++++++++++++++++++++---
 1 file changed, 21 insertions(+), 3 deletions(-)

diff --git a/present/present.c b/present/present.c
index 1bf3a58..c5951d4 100644
--- a/present/present.c
+++ b/present/present.c
@@ -383,6 +383,24 @@ present_set_tree_pixmap(WindowPtr window, PixmapPtr pixmap)
 }
 
 static void
+present_set_abort_flip(ScreenPtr screen)
+{
+    present_screen_priv_ptr screen_priv = present_screen_priv(screen);
+
+    /* Switch back to using the screen pixmap now to avoid
+     * 2D applications drawing to the wrong pixmap.
+     */
+
+    if (screen_priv->flip_window)
+        present_set_tree_pixmap(screen_priv->flip_window,
+                                  (*screen->GetScreenPixmap)(screen));
+
+    present_set_tree_pixmap(screen->root, (*screen->GetScreenPixmap)(screen));
+
+    screen_priv->flip_pending->abort_flip = TRUE;
+}
+
+static void
 present_unflip(ScreenPtr screen)
 {
     present_screen_priv_ptr screen_priv = present_screen_priv(screen);
@@ -511,7 +529,7 @@ present_check_flip_window (WindowPtr window)
         if (flip_pending->window == window) {
             if (!present_check_flip(flip_pending->crtc, window, flip_pending->pixmap,
                                     flip_pending->sync_flip, NULL, 0, 0))
-                flip_pending->abort_flip = TRUE;
+                present_set_abort_flip(screen);
         }
     } else {
         /*
@@ -633,7 +651,7 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
             /* Check pending flip
              */
             if (window == screen_priv->flip_pending->window)
-                screen_priv->flip_pending->abort_flip = TRUE;
+                present_set_abort_flip(screen);
         } else if (!screen_priv->unflip_event_id) {
 
             /* Check current flip
@@ -915,7 +933,7 @@ present_flip_destroy(ScreenPtr screen)
 
     /* Do the actual cleanup once the flip has been performed by the hardware */
     if (screen_priv->flip_pending)
-        screen_priv->flip_pending->abort_flip = TRUE;
+        present_set_abort_flip(screen);
 }
 
 void
-- 
1.8.5.4.gfdaaaa2



More information about the xorg-devel mailing list