If multiple drawables are doing page flipping, the global drmmode
structure can't be used to keep per swap information. For example
flip_count can increase prematurely due to another swap request,
and then the previous swap request never gets completed, leading to a
stuck client. Move the relevant pieces of data to a strucuture that
gets allocated once per swap request and shared by all involved CRTCs.

Signed-off-by: Ville Syrjala <[email protected]>
---
 src/drmmode_display.c |   45 ++++++++++++++++++++++++++-------------------
 src/drmmode_display.h |   10 +++++++---
 2 files changed, 33 insertions(+), 22 deletions(-)

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 7873d57..7dd5d86 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -1331,31 +1331,34 @@ drmmode_flip_handler(int fd, unsigned int frame, 
unsigned int tv_sec,
                     unsigned int tv_usec, void *event_data)
 {
        drmmode_flipevtcarrier_ptr flipcarrier = event_data;
-       drmmode_ptr drmmode = flipcarrier->drmmode;
+       drmmode_flipdata_ptr flipdata = flipcarrier->flipdata;
+       drmmode_ptr drmmode = flipdata->drmmode;
 
        /* Is this the event whose info shall be delivered to higher level? */
        if (flipcarrier->dispatch_me) {
                /* Yes: Cache msc, ust for later delivery. */
-               drmmode->fe_frame = frame;
-               drmmode->fe_tv_sec = tv_sec;
-               drmmode->fe_tv_usec = tv_usec;
+               flipdata->fe_frame = frame;
+               flipdata->fe_tv_sec = tv_sec;
+               flipdata->fe_tv_usec = tv_usec;
        }
        free(flipcarrier);
 
        /* Last crtc completed flip? */
-       drmmode->flip_count--;
-       if (drmmode->flip_count > 0)
+       flipdata->flip_count--;
+       if (flipdata->flip_count > 0)
                return;
 
        /* Release framebuffer */
-       drmModeRmFB(drmmode->fd, drmmode->old_fb_id);
+       drmModeRmFB(drmmode->fd, flipdata->old_fb_id);
 
-       if (drmmode->event_data == NULL)
+       if (flipdata->event_data == NULL)
                return;
 
        /* Deliver cached msc, ust from reference crtc to flip event handler */
-       radeon_dri2_flip_event_handler(drmmode->fe_frame, drmmode->fe_tv_sec,
-                                      drmmode->fe_tv_usec, 
drmmode->event_data);
+       radeon_dri2_flip_event_handler(flipdata->fe_frame, flipdata->fe_tv_sec,
+                                      flipdata->fe_tv_usec, 
flipdata->event_data);
+
+       free(flipdata);
 }
 
 
@@ -1399,12 +1402,10 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr 
drmmode, int cpp)
 
        xf86InitialConfiguration(pScrn, TRUE);
 
-       drmmode->flip_count = 0;
        drmmode->event_context.version = DRM_EVENT_CONTEXT_VERSION;
        drmmode->event_context.vblank_handler = drmmode_vblank_handler;
        drmmode->event_context.page_flip_handler = drmmode_flip_handler;
        if (!pRADEONEnt->fd_wakeup_registered && 
info->dri->pKernelDRMVersion->version_minor >= 4) {
-               drmmode->flip_count = 0;
                AddGeneralSocket(drmmode->fd);
                RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
                                drm_wakeup_handler, drmmode);
@@ -1654,6 +1655,7 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct 
radeon_bo *new_front, void *dat
        int i, old_fb_id;
        uint32_t tiling_flags = 0;
        int height;
+       drmmode_flipdata_ptr flipdata;
        drmmode_flipevtcarrier_ptr flipcarrier;
 
        if (info->allowColorTiling) {
@@ -1676,6 +1678,12 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct 
radeon_bo *new_front, void *dat
                         new_front->handle, &drmmode->fb_id))
                goto error_out;
 
+        flipdata = calloc(1, sizeof(drmmode_flipdata_rec));
+        if (!flipdata) {
+             xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+                        "flip queue: data alloc failed.\n");
+             goto error_undo;
+        }
        /*
         * Queue flips on all enabled CRTCs
         * Note that if/when we get per-CRTC buffers, we'll have to update this.
@@ -1685,16 +1693,15 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct 
radeon_bo *new_front, void *dat
         * Also, flips queued on disabled or incorrectly configured displays
         * may never complete; this is a configuration error.
         */
-       drmmode->fe_frame = 0;
-       drmmode->fe_tv_sec = 0;
-       drmmode->fe_tv_usec = 0;
+
+        flipdata->event_data = data;
+        flipdata->drmmode = drmmode;
 
        for (i = 0; i < config->num_crtc; i++) {
                if (!config->crtc[i]->enabled)
                        continue;
 
-               drmmode->event_data = data;
-               drmmode->flip_count++;
+               flipdata->flip_count++;
                drmmode_crtc = config->crtc[i]->driver_private;
 
                flipcarrier = calloc(1, sizeof(drmmode_flipevtcarrier_rec));
@@ -1708,7 +1715,7 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct 
radeon_bo *new_front, void *dat
                 * completion event. All other crtc's events will be discarded.
                 */
                flipcarrier->dispatch_me = (drmmode_crtc->hw_id == 
ref_crtc_hw_id);
-               flipcarrier->drmmode = drmmode;
+               flipcarrier->flipdata = flipdata;
 
                if (drmModePageFlip(drmmode->fd, 
drmmode_crtc->mode_crtc->crtc_id,
                                    drmmode->fb_id, DRM_MODE_PAGE_FLIP_EVENT, 
flipcarrier)) {
@@ -1719,7 +1726,7 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct 
radeon_bo *new_front, void *dat
                }
        }
 
-       drmmode->old_fb_id = old_fb_id;
+       flipdata->old_fb_id = old_fb_id;
        return TRUE;
 
 error_undo:
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index 548907b..eb271f5 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -39,7 +39,6 @@
 typedef struct {
   int fd;
   unsigned fb_id;
-  unsigned old_fb_id;
   drmModeResPtr mode_res;
   drmModeFBPtr mode_fb;
   int cpp;
@@ -50,15 +49,20 @@ typedef struct {
   InputHandlerProc uevent_handler;
 #endif
   drmEventContext event_context;
+} drmmode_rec, *drmmode_ptr;
+
+typedef struct {
+  drmmode_ptr drmmode;
+  unsigned old_fb_id;
   int flip_count;
   void *event_data;
   unsigned int fe_frame;
   unsigned int fe_tv_sec;
   unsigned int fe_tv_usec;
-} drmmode_rec, *drmmode_ptr;
+} drmmode_flipdata_rec, *drmmode_flipdata_ptr;
 
 typedef struct {
-  drmmode_ptr drmmode;
+  drmmode_flipdata_ptr flipdata;
   Bool dispatch_me;
 } drmmode_flipevtcarrier_rec, *drmmode_flipevtcarrier_ptr;
 
-- 
1.7.3.4

_______________________________________________
[email protected]: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: http://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to