xserver: Branch 'master' - 5 commits

Keith Packard keithp at kemper.freedesktop.org
Thu Dec 25 13:39:32 PST 2014


 hw/xfree86/drivers/modesetting/Makefile.am       |    1 
 hw/xfree86/drivers/modesetting/dri2.c            |    2 
 hw/xfree86/drivers/modesetting/driver.c          |   10 -
 hw/xfree86/drivers/modesetting/driver.h          |   14 +
 hw/xfree86/drivers/modesetting/drmmode_display.c |   25 --
 hw/xfree86/drivers/modesetting/drmmode_display.h |    1 
 hw/xfree86/drivers/modesetting/present.c         |  226 +++++++++++++++++++++++
 hw/xfree86/drivers/modesetting/vblank.c          |   28 ++
 present/present.c                                |   15 -
 9 files changed, 286 insertions(+), 36 deletions(-)

New commits:
commit 09230a2d435aa7f893ad5022220e3eb39ffb6db5
Author: Kenneth Graunke <kenneth at whitecape.org>
Date:   Thu Dec 11 13:37:14 2014 -0800

    modesetting: Add vblank synchronization support when using Present.
    
    modesetting hooked up vblank support for DRI2, but was missing support
    for vblanks in Present.
    
    This is mostly copy and pasted from Keith's code in the intel driver.
    
    v2: Use ms_crtc_msc_to_kernel_msc in ms_present_queue_vblank to hook
        up the vblank_offset workaround for bogus MSC values (which the
        DRI2 code already did).
    
        Also simplify the ms_present_get_crtc function.  vblank.c already
        implements the functionality; we just need to convert types.
    
    v3: Fix ms_flush_drm_events return code.  I'd copied code where 0 meant
        success into a function that returned a boolean, so the return code
        was always backwards.
    
        Also add DebugPresent calls in ms_present_vblank_{handler,abort}.
    
    Signed-off-by: Kenneth Graunke <kenneth at whitecape.org>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Tested-by: Jason Ekstrand <jason.ekstrand at intel.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/xfree86/drivers/modesetting/Makefile.am b/hw/xfree86/drivers/modesetting/Makefile.am
index 921ca00..82c4f2f 100644
--- a/hw/xfree86/drivers/modesetting/Makefile.am
+++ b/hw/xfree86/drivers/modesetting/Makefile.am
@@ -50,6 +50,7 @@ modesetting_drv_la_SOURCES = \
 	 drmmode_display.h \
 	 dumb_bo.c \
 	 dumb_bo.h \
+	 present.c \
 	 vblank.c \
 	 $(NULL)
 
diff --git a/hw/xfree86/drivers/modesetting/driver.c b/hw/xfree86/drivers/modesetting/driver.c
index 26054f2..1ebf807 100644
--- a/hw/xfree86/drivers/modesetting/driver.c
+++ b/hw/xfree86/drivers/modesetting/driver.c
@@ -1128,6 +1128,11 @@ ScreenInit(ScreenPtr pScreen, int argc, char **argv)
             xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
                        "Failed to initialize the DRI2 extension.\n");
         }
+
+        if (!ms_present_screen_init(pScreen)) {
+            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+                       "Failed to initialize the Present extension.\n");
+        }
     }
 #endif
 
diff --git a/hw/xfree86/drivers/modesetting/driver.h b/hw/xfree86/drivers/modesetting/driver.h
index 4267fa1..3decc3e 100644
--- a/hw/xfree86/drivers/modesetting/driver.h
+++ b/hw/xfree86/drivers/modesetting/driver.h
@@ -114,6 +114,10 @@ uint32_t ms_drm_queue_alloc(xf86CrtcPtr crtc,
                             ms_drm_handler_proc handler,
                             ms_drm_abort_proc abort);
 
+void ms_drm_abort(ScrnInfoPtr scrn,
+                  Bool (*match)(void *data, void *match_data),
+                  void *match_data);
+
 xf86CrtcPtr ms_dri2_crtc_covering_drawable(DrawablePtr pDraw);
 xf86CrtcPtr ms_covering_crtc(ScrnInfoPtr scrn, BoxPtr box,
                              xf86CrtcPtr desired, BoxPtr crtc_box_ret);
@@ -129,3 +133,5 @@ void ms_dri2_close_screen(ScreenPtr screen);
 
 Bool ms_vblank_screen_init(ScreenPtr screen);
 void ms_vblank_close_screen(ScreenPtr screen);
+
+Bool ms_present_screen_init(ScreenPtr screen);
diff --git a/hw/xfree86/drivers/modesetting/present.c b/hw/xfree86/drivers/modesetting/present.c
new file mode 100644
index 0000000..63d7b76
--- /dev/null
+++ b/hw/xfree86/drivers/modesetting/present.c
@@ -0,0 +1,226 @@
+/*
+ * Copyright © 2014 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include "dix-config.h"
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <time.h>
+
+#include <xf86.h>
+#include <xf86Crtc.h>
+#include <xf86drm.h>
+#include <xf86str.h>
+#include <present.h>
+
+#include "driver.h"
+
+#if 0
+#define DebugPresent(x) ErrorF x
+#else
+#define DebugPresent(x)
+#endif
+
+struct ms_present_vblank_event {
+    uint64_t        event_id;
+};
+
+static RRCrtcPtr
+ms_present_get_crtc(WindowPtr window)
+{
+    xf86CrtcPtr xf86_crtc = ms_dri2_crtc_covering_drawable(&window->drawable);
+    return xf86_crtc ? xf86_crtc->randr_crtc : NULL;
+}
+
+static int
+ms_present_get_ust_msc(RRCrtcPtr crtc, CARD64 *ust, CARD64 *msc)
+{
+    xf86CrtcPtr xf86_crtc = crtc->devPrivate;
+
+    return ms_get_crtc_ust_msc(xf86_crtc, ust, msc);
+}
+
+/*
+ * Flush the DRM event queue when full; makes space for new events.
+ */
+static Bool
+ms_flush_drm_events(ScreenPtr screen)
+{
+    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+    modesettingPtr ms = modesettingPTR(scrn);
+
+    struct pollfd p = { .fd = ms->fd, .events = POLLIN };
+    int r;
+
+    do {
+            r = poll(&p, 1, 0);
+    } while (r == -1 && (errno == EINTR || errno == EAGAIN));
+
+    if (r <= 0)
+        return TRUE;
+
+    return drmHandleEvent(ms->fd, &ms->event_context) >= 0;
+}
+
+/*
+ * Called when the queued vblank event has occurred
+ */
+static void
+ms_present_vblank_handler(uint64_t msc, uint64_t usec, void *data)
+{
+    struct ms_present_vblank_event *event = data;
+
+    DebugPresent(("\t\tmh %lld msc %llu\n",
+                 (long long) event->event_id, (long long) msc));
+
+    present_event_notify(event->event_id, usec, msc);
+    free(event);
+}
+
+/*
+ * Called when the queued vblank is aborted
+ */
+static void
+ms_present_vblank_abort(void *data)
+{
+    struct ms_present_vblank_event *event = data;
+
+    DebugPresent(("\t\tma %lld\n", (long long) event->event_id));
+
+    free(event);
+}
+
+/*
+ * Queue an event to report back to the Present extension when the specified
+ * MSC has past
+ */
+static int
+ms_present_queue_vblank(RRCrtcPtr crtc,
+                        uint64_t event_id,
+                        uint64_t msc)
+{
+    xf86CrtcPtr xf86_crtc = crtc->devPrivate;
+    ScreenPtr screen = crtc->pScreen;
+    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+    modesettingPtr ms = modesettingPTR(scrn);
+    drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
+    struct ms_present_vblank_event *event;
+    drmVBlank vbl;
+    int ret;
+    uint32_t seq;
+
+    event = calloc(sizeof(struct ms_present_vblank_event), 1);
+    if (!event)
+        return BadAlloc;
+    event->event_id = event_id;
+    seq = ms_drm_queue_alloc(xf86_crtc, event,
+                             ms_present_vblank_handler,
+                             ms_present_vblank_abort);
+    if (!seq) {
+        free(event);
+        return BadAlloc;
+    }
+
+    vbl.request.type =
+        DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT | drmmode_crtc->vblank_pipe;
+    vbl.request.sequence = ms_crtc_msc_to_kernel_msc(xf86_crtc, msc);
+    vbl.request.signal = seq;
+    for (;;) {
+        ret = drmWaitVBlank(ms->fd, &vbl);
+        if (!ret)
+            break;
+        if (errno != EBUSY || !ms_flush_drm_events(screen))
+            return BadAlloc;
+    }
+    DebugPresent(("\t\tmq %lld seq %u msc %llu (hw msc %u)\n",
+                 (long long) event_id, seq, (long long) msc,
+                 vbl.request.sequence));
+    return Success;
+}
+
+static Bool
+ms_present_event_match(void *data, void *match_data)
+{
+    struct ms_present_vblank_event *event = data;
+    uint64_t *match = match_data;
+
+    return *match == event->event_id;
+}
+
+/*
+ * Remove a pending vblank event from the DRM queue so that it is not reported
+ * to the extension
+ */
+static void
+ms_present_abort_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
+{
+    ScreenPtr screen = crtc->pScreen;
+    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+
+    ms_drm_abort(scrn, ms_present_event_match, &event_id);
+}
+
+/*
+ * Flush our batch buffer when requested by the Present extension.
+ */
+static void
+ms_present_flush(WindowPtr window)
+{
+    ScreenPtr screen = window->drawable.pScreen;
+    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+    modesettingPtr ms = modesettingPTR(scrn);
+
+    if (ms->drmmode.glamor)
+        glamor_block_handler(screen);
+}
+
+static present_screen_info_rec ms_present_screen_info = {
+    .version = PRESENT_SCREEN_INFO_VERSION,
+
+    .get_crtc = ms_present_get_crtc,
+    .get_ust_msc = ms_present_get_ust_msc,
+    .queue_vblank = ms_present_queue_vblank,
+    .abort_vblank = ms_present_abort_vblank,
+    .flush = ms_present_flush,
+
+    .capabilities = PresentCapabilityNone,
+    .check_flip = 0,
+    .flip = 0,
+    .unflip = 0,
+};
+
+Bool
+ms_present_screen_init(ScreenPtr screen)
+{
+    return present_screen_init(screen, &ms_present_screen_info);
+}
diff --git a/hw/xfree86/drivers/modesetting/vblank.c b/hw/xfree86/drivers/modesetting/vblank.c
index ee5e371..711f6ed 100644
--- a/hw/xfree86/drivers/modesetting/vblank.c
+++ b/hw/xfree86/drivers/modesetting/vblank.c
@@ -331,6 +331,24 @@ ms_drm_abort_scrn(ScrnInfoPtr scrn)
 }
 
 /*
+ * Externally usable abort function that uses a callback to match a single
+ * queued entry to abort
+ */
+void
+ms_drm_abort(ScrnInfoPtr scrn, Bool (*match)(void *data, void *match_data),
+             void *match_data)
+{
+    struct ms_drm_queue *q;
+
+    xorg_list_for_each_entry(q, &ms_drm_queue, list) {
+        if (match(q->data, match_data)) {
+            ms_drm_abort_one(q);
+            break;
+        }
+    }
+}
+
+/*
  * General DRM kernel handler. Looks for the matching sequence number in the
  * drm event queue and calls the handler for it.
  */
commit 3b5be33fc55b3090d996014fa56603edb9c1d411
Author: Kenneth Graunke <kenneth at whitecape.org>
Date:   Thu Dec 11 13:48:04 2014 -0800

    modesetting: Include glamor.h from driver.h.
    
    We basically want it throughout the driver.
    
    Signed-off-by: Kenneth Graunke <kenneth at whitecape.org>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Tested-by: Jason Ekstrand <jason.ekstrand at intel.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/xfree86/drivers/modesetting/dri2.c b/hw/xfree86/drivers/modesetting/dri2.c
index 6c88060..63cb065 100644
--- a/hw/xfree86/drivers/modesetting/dri2.c
+++ b/hw/xfree86/drivers/modesetting/dri2.c
@@ -43,8 +43,6 @@
 #include "dri2.h"
 
 #ifdef GLAMOR
-#define GLAMOR_FOR_XORG 1
-#include "glamor.h"
 
 enum ms_dri2_frame_event_type {
     MS_DRI2_QUEUE_SWAP,
diff --git a/hw/xfree86/drivers/modesetting/driver.c b/hw/xfree86/drivers/modesetting/driver.c
index be025bd..26054f2 100644
--- a/hw/xfree86/drivers/modesetting/driver.c
+++ b/hw/xfree86/drivers/modesetting/driver.c
@@ -61,11 +61,6 @@
 
 #include "driver.h"
 
-#ifdef GLAMOR
-#define GLAMOR_FOR_XORG 1
-#include "glamor.h"
-#endif
-
 static void AdjustFrame(ScrnInfoPtr pScrn, int x, int y);
 static Bool CloseScreen(ScreenPtr pScreen);
 static Bool EnterVT(ScrnInfoPtr pScrn);
diff --git a/hw/xfree86/drivers/modesetting/driver.h b/hw/xfree86/drivers/modesetting/driver.h
index bbf1ae0..4267fa1 100644
--- a/hw/xfree86/drivers/modesetting/driver.h
+++ b/hw/xfree86/drivers/modesetting/driver.h
@@ -33,6 +33,14 @@
 #include <xf86Crtc.h>
 #include <damage.h>
 
+#ifdef GLAMOR
+#define GLAMOR_FOR_XORG 1
+#include "glamor.h"
+#ifdef GLAMOR_HAS_GBM
+#include <gbm.h>
+#endif
+#endif
+
 #include "drmmode_display.h"
 #define DRV_ERROR(msg)	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, msg);
 
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c
index fd5cf2b..824500b 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.c
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.c
@@ -50,14 +50,6 @@
 
 #include "driver.h"
 
-#ifdef GLAMOR
-#define GLAMOR_FOR_XORG 1
-#include "glamor.h"
-#ifdef GLAMOR_HAS_GBM
-#include <gbm.h>
-#endif
-#endif
-
 static int
 drmmode_bo_destroy(drmmode_ptr drmmode, drmmode_bo *bo)
 {
commit 7d1fc04d27857c999bd732d54a0b36f5079449b8
Author: Kenneth Graunke <kenneth at whitecape.org>
Date:   Thu Dec 18 17:58:18 2014 -0800

    modesetting: Check DPMS mode in ms_covering_crtc().
    
    crtc->enabled is insufficient; we should also make sure DPMS is on.
    
    Signed-off-by: Kenneth Graunke <kenneth at whitecape.org>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Tested-by: Jason Ekstrand <jason.ekstrand at intel.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/xfree86/drivers/modesetting/vblank.c b/hw/xfree86/drivers/modesetting/vblank.c
index 5031ef8..ee5e371 100644
--- a/hw/xfree86/drivers/modesetting/vblank.c
+++ b/hw/xfree86/drivers/modesetting/vblank.c
@@ -88,6 +88,14 @@ static int ms_box_area(BoxPtr box)
     return (int)(box->x2 - box->x1) * (int)(box->y2 - box->y1);
 }
 
+static Bool
+ms_crtc_on(xf86CrtcPtr crtc)
+{
+    drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
+    return crtc->enabled && drmmode_crtc->dpms_mode == DPMSModeOn;
+}
+
 /*
  * Return the crtc covering 'box'. If two crtcs cover a portion of
  * 'box', then prefer 'desired'. If 'desired' is NULL, then prefer the crtc
@@ -114,7 +122,7 @@ ms_covering_crtc(ScrnInfoPtr scrn,
         crtc = xf86_config->crtc[c];
 
         /* If the CRTC is off, treat it as not covering */
-        if (!crtc->enabled)
+        if (!ms_crtc_on(crtc))
             continue;
 
         ms_crtc_box(crtc, &crtc_box);
commit 8affaade2c127ea08989c86e7d71cc9da3db1824
Author: Kenneth Graunke <kenneth at whitecape.org>
Date:   Thu Dec 18 17:55:29 2014 -0800

    modesetting: Track the CRTC's DPMS mode.
    
    We don't want to try to vblank synchronize to monitors which are off.
    
    In order to handle that properly, we need to know the CRTC's DPMS mode.
    
    Signed-off-by: Kenneth Graunke <kenneth at whitecape.org>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Tested-by: Jason Ekstrand <jason.ekstrand at intel.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c
index 8d9bf8b..fd5cf2b 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.c
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.c
@@ -193,18 +193,8 @@ drmmode_ConvertToKMode(ScrnInfoPtr scrn,
 static void
 drmmode_crtc_dpms(xf86CrtcPtr crtc, int mode)
 {
-#if 0
-    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
-
-//      drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
-//      drmmode_ptr drmmode = drmmode_crtc->drmmode;
-
-    /* bonghits in the randr 1.2 - uses dpms to disable crtc - bad buzz */
-    if (mode == DPMSModeOff) {
-//              drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
-//                             0, 0, 0, NULL, 0, NULL);
-    }
-#endif
+    drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+    drmmode_crtc->dpms_mode = mode;
 }
 
 #if 0
@@ -347,6 +337,9 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
 
         if (crtc->scrn->pScreen)
             xf86CrtcSetScreenSubpixelOrder(crtc->scrn->pScreen);
+
+        crtc->funcs->dpms(crtc, DPMSModeOn);
+
         /* go through all the outputs and force DPMS them back on? */
         for (i = 0; i < xf86_config->num_output; i++) {
             xf86OutputPtr output = xf86_config->output[i];
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.h b/hw/xfree86/drivers/modesetting/drmmode_display.h
index 0983cf1..66d0ca2 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.h
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.h
@@ -86,6 +86,7 @@ typedef struct {
     drmmode_ptr drmmode;
     drmModeCrtcPtr mode_crtc;
     uint32_t vblank_pipe;
+    int dpms_mode;
     struct dumb_bo *cursor_bo;
     Bool cursor_up;
     unsigned rotate_fb_id;
commit b51f804b1ca826699296aff9de27d19257d78dae
Author: Kenneth Graunke <kenneth at whitecape.org>
Date:   Thu Dec 18 17:22:00 2014 -0800

    present: If present_queue_vblank() fails, do present_execute().
    
    Previously, if present_queue_vblank() failed, we simply dropped the
    present request on the floor, and returned an error.  This was rather
    mean to clients - after presenting, they wait for a PresentComplete
    event to come back.  But since the present never happens, they end up
    waiting forever, and lock up in poll().
    
    This patch falls back to present_execute if present_queue_vblank fails.
    We still print a debugging message to warn when queueing fails, which
    allows us to continue debugging problems, but makes Present robust
    enough to not lock up people's compositing manager when vblank bugs
    happen.
    
    v2: Don't do present_queue_vblank() /and/ present_execute() (a bug that
        snuck in during last minute tidying).
    
    Signed-off-by: Kenneth Graunke <kenneth at whitecape.org>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Tested-by: Jason Ekstrand <jason.ekstrand at intel.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/present/present.c b/present/present.c
index e27fe30..2a705a9 100644
--- a/present/present.c
+++ b/present/present.c
@@ -871,19 +871,18 @@ present_pixmap(WindowPtr window,
     vblank->queued = TRUE;
     if ((pixmap && target_msc >= crtc_msc) || (!pixmap && target_msc > crtc_msc)) {
         ret = present_queue_vblank(screen, target_crtc, vblank->event_id, target_msc);
-        if (ret != Success) {
-            xorg_list_del(&vblank->event_queue);
-            vblank->queued = FALSE;
-            goto failure;
-        }
-    } else
-        present_execute(vblank, ust, crtc_msc);
+        if (ret == Success)
+            return Success;
+
+        DebugPresent(("present_queue_vblank failed\n"));
+    }
+
+    present_execute(vblank, ust, crtc_msc);
 
     return Success;
 
 no_mem:
     ret = BadAlloc;
-failure:
     vblank->notifies = NULL;
     present_vblank_destroy(vblank);
     return ret;


More information about the xorg-commit mailing list