[Intel-gfx] [PATCH] present: Avoid dereferencing vblank past a successful call to present_flip()

Chris Wilson chris at chris-wilson.co.uk
Sat May 31 09:33:07 CEST 2014


The driver may complete the flip instantaneously resulting in an immediate
call to present_flip_notify(). This has the side-effect of destroying
the vblank. We could add a reference count to the vblank structure to
defer the destruction, or make the assume that further accesses are
invalid and cache all the values we need in local variables before the
call.

Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
 present/present.c | 29 ++++++++++++++---------------
 1 file changed, 14 insertions(+), 15 deletions(-)

diff --git a/present/present.c b/present/present.c
index 73d5f69..75e9e00 100644
--- a/present/present.c
+++ b/present/present.c
@@ -522,6 +522,7 @@ present_wait_fence_triggered(void *param)
 static void
 present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
 {
+    PixmapPtr                   pixmap = vblank->pixmap;
     WindowPtr                   window = vblank->window;
     ScreenPtr                   screen = window->drawable.pScreen;
     present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
@@ -537,11 +538,11 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
     xorg_list_del(&vblank->event_queue);
     vblank->queued = FALSE;
 
-    if (vblank->pixmap && vblank->window) {
-
+    if (pixmap) {
         if (vblank->flip && screen_priv->flip_pending == NULL && !screen_priv->unflip_event_id) {
+            RegionPtr damage = vblank->update;
 
-            DebugPresent(("\tf %p %8lld: %08lx -> %08lx\n", vblank, crtc_msc, vblank->pixmap->drawable.id, vblank->window->drawable.id));
+            DebugPresent(("\tf %p %8lld: %08lx -> %08lx\n", vblank, crtc_msc, pixmap->drawable.id, window->drawable.id));
             /* Prepare to flip by placing it in the flip queue and
              * and sticking it into the flip_pending field
              */
@@ -550,8 +551,7 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
             xorg_list_add(&vblank->event_queue, &present_flip_queue);
             /* Try to flip
              */
-            if (present_flip(vblank->crtc, vblank->event_id, vblank->target_msc, vblank->pixmap, vblank->sync_flip)) {
-                RegionPtr damage;
+            if (present_flip(vblank->crtc, vblank->event_id, vblank->target_msc, pixmap, vblank->sync_flip)) {
 
                 /* Fix window pixmaps:
                  *  1) Restore previous flip window pixmap
@@ -560,18 +560,17 @@ 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);
+                present_set_tree_pixmap(window, pixmap);
+                present_set_tree_pixmap(screen->root, pixmap);
 
                 /* Report update region as damaged
                  */
-                if (vblank->update) {
-                    damage = vblank->update;
+                if (damage)
                     RegionIntersect(damage, damage, &window->clipList);
-                } else
+                else
                     damage = &window->clipList;
 
-                DamageDamageRegion(&vblank->window->drawable, damage);
+                DamageDamageRegion(&window->drawable, damage);
                 return;
             }
 
@@ -581,7 +580,7 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
             screen_priv->flip_pending = NULL;
             vblank->flip = FALSE;
         }
-        DebugPresent(("\tc %p %8lld: %08lx -> %08lx\n", vblank, crtc_msc, vblank->pixmap->drawable.id, vblank->window->drawable.id));
+        DebugPresent(("\tc %p %8lld: %08lx -> %08lx\n", vblank, crtc_msc, pixmap->drawable.id, window->drawable.id));
         if (screen_priv->flip_pending) {
 
             /* Check pending flip
@@ -595,7 +594,7 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
             if (window == screen_priv->flip_window)
                 present_unflip(screen);
         }
-        present_copy_region(&window->drawable, vblank->pixmap, vblank->update, vblank->x_off, vblank->y_off);
+        present_copy_region(&window->drawable, pixmap, vblank->update, vblank->x_off, vblank->y_off);
 
         /* present_copy_region sticks the region into a scratch GC,
          * which is then freed, freeing the region
@@ -603,13 +602,13 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
         vblank->update = NULL;
         present_flush(window);
 
-        present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence);
+        present_pixmap_idle(pixmap, window, vblank->serial, vblank->idle_fence);
     }
 
     /* Compute correct CompleteMode
      */
     if (vblank->kind == PresentCompleteKindPixmap) {
-        if (vblank->pixmap && vblank->window)
+        if (pixmap)
             mode = PresentCompleteModeCopy;
         else
             mode = PresentCompleteModeSkip;
-- 
2.0.0.rc4




More information about the Intel-gfx mailing list