<div dir="ltr"><div>Another note: With this patch, I had an issue that, when it woke my monitor up after a lock, it was entirely black + cursor.  VT switching didn't help.  I killed gnome shell and, when I came back things were mostly OK except it was tearing like crazy.  Not sure if it's related, but I haven't seen it without the patch.<br></div>--Jason<br></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Dec 12, 2014 at 10:21 AM, Jason Ekstrand <span dir="ltr"><<a href="mailto:jason@jlekstrand.net" target="_blank">jason@jlekstrand.net</a>></span> wrote:<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote"><div><div class="h5">On Thu, Dec 11, 2014 at 3:16 PM, Kenneth Graunke <span dir="ltr"><<a href="mailto:kenneth@whitecape.org" target="_blank">kenneth@whitecape.org</a>></span> wrote:<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">modesetting hooked up vblank support for DRI2, but was missing support<br>
for vblanks in Present.<br>
<br>
This is mostly copy and pasted from Keith's code in the intel driver.<br>
<br>
Signed-off-by: Kenneth Graunke <<a href="mailto:kenneth@whitecape.org" target="_blank">kenneth@whitecape.org</a>><br>
---<br>
 hw/xfree86/drivers/modesetting/Makefile.am |   1 +<br>
 hw/xfree86/drivers/modesetting/driver.c    |   5 +<br>
 hw/xfree86/drivers/modesetting/driver.h    |   6 +<br>
 hw/xfree86/drivers/modesetting/present.c   | 237 +++++++++++++++++++++++++++++<br>
 hw/xfree86/drivers/modesetting/vblank.c    |  18 +++<br>
 5 files changed, 267 insertions(+)<br>
 create mode 100644 hw/xfree86/drivers/modesetting/present.c<br>
<br>
diff --git a/hw/xfree86/drivers/modesetting/Makefile.am b/hw/xfree86/drivers/modesetting/Makefile.am<br>
index 921ca00..82c4f2f 100644<br>
--- a/hw/xfree86/drivers/modesetting/Makefile.am<br>
+++ b/hw/xfree86/drivers/modesetting/Makefile.am<br>
@@ -50,6 +50,7 @@ modesetting_drv_la_SOURCES = \<br>
         drmmode_display.h \<br>
         dumb_bo.c \<br>
         dumb_bo.h \<br>
+        present.c \<br>
         vblank.c \<br>
         $(NULL)<br>
<br>
diff --git a/hw/xfree86/drivers/modesetting/driver.c b/hw/xfree86/drivers/modesetting/driver.c<br>
index 476c814..5dda96b 100644<br>
--- a/hw/xfree86/drivers/modesetting/driver.c<br>
+++ b/hw/xfree86/drivers/modesetting/driver.c<br>
@@ -1113,6 +1113,11 @@ ScreenInit(ScreenPtr pScreen, int argc, char **argv)<br>
             xf86DrvMsg(pScrn->scrnIndex, X_ERROR,<br>
                        "Failed to initialize the DRI2 extension.\n");<br>
         }<br>
+<br>
+        if (!ms_present_screen_init(pScreen)) {<br>
+            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,<br>
+                       "Failed to initialize the Present extension.\n");<br>
+        }<br>
     }<br>
 #endif<br>
<br>
diff --git a/hw/xfree86/drivers/modesetting/driver.h b/hw/xfree86/drivers/modesetting/driver.h<br>
index 4267fa1..3decc3e 100644<br>
--- a/hw/xfree86/drivers/modesetting/driver.h<br>
+++ b/hw/xfree86/drivers/modesetting/driver.h<br>
@@ -114,6 +114,10 @@ uint32_t ms_drm_queue_alloc(xf86CrtcPtr crtc,<br>
                             ms_drm_handler_proc handler,<br>
                             ms_drm_abort_proc abort);<br>
<br>
+void ms_drm_abort(ScrnInfoPtr scrn,<br>
+                  Bool (*match)(void *data, void *match_data),<br>
+                  void *match_data);<br>
+<br>
 xf86CrtcPtr ms_dri2_crtc_covering_drawable(DrawablePtr pDraw);<br>
 xf86CrtcPtr ms_covering_crtc(ScrnInfoPtr scrn, BoxPtr box,<br>
                              xf86CrtcPtr desired, BoxPtr crtc_box_ret);<br>
@@ -129,3 +133,5 @@ void ms_dri2_close_screen(ScreenPtr screen);<br>
<br>
 Bool ms_vblank_screen_init(ScreenPtr screen);<br>
 void ms_vblank_close_screen(ScreenPtr screen);<br>
+<br>
+Bool ms_present_screen_init(ScreenPtr screen);<br>
diff --git a/hw/xfree86/drivers/modesetting/present.c b/hw/xfree86/drivers/modesetting/present.c<br>
new file mode 100644<br>
index 0000000..92de421<br>
--- /dev/null<br>
+++ b/hw/xfree86/drivers/modesetting/present.c<br>
@@ -0,0 +1,237 @@<br>
+/*<br>
+ * Copyright © 2014 Intel Corporation<br>
+ *<br>
+ * Permission to use, copy, modify, distribute, and sell this software and its<br>
+ * documentation for any purpose is hereby granted without fee, provided that<br>
+ * the above copyright notice appear in all copies and that both that copyright<br>
+ * notice and this permission notice appear in supporting documentation, and<br>
+ * that the name of the copyright holders not be used in advertising or<br>
+ * publicity pertaining to distribution of the software without specific,<br>
+ * written prior permission.  The copyright holders make no representations<br>
+ * about the suitability of this software for any purpose.  It is provided "as<br>
+ * is" without express or implied warranty.<br>
+ *<br>
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,<br>
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO<br>
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR<br>
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,<br>
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER<br>
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE<br>
+ * OF THIS SOFTWARE.<br>
+ */<br>
+<br>
+#ifdef HAVE_DIX_CONFIG_H<br>
+#include "dix-config.h"<br>
+#endif<br>
+<br>
+#include <assert.h><br>
+#include <errno.h><br>
+#include <fcntl.h><br>
+#include <poll.h><br>
+#include <unistd.h><br>
+#include <stdio.h><br>
+#include <stdint.h><br>
+#include <string.h><br>
+#include <sys/ioctl.h><br>
+#include <sys/time.h><br>
+#include <sys/types.h><br>
+#include <time.h><br>
+<br>
+#include <xf86.h><br>
+#include <xf86Crtc.h><br>
+#include <xf86drm.h><br>
+#include <xf86str.h><br>
+#include <present.h><br>
+<br>
+#include "driver.h"<br></blockquote><div><br></div></div></div><div>You need to include galmor.h here.  It won't build for me without it.<span class="HOEnZb"><font color="#888888"><br></font></span></div><span class="HOEnZb"><font color="#888888"><div>--Jason<br></div></font></span><div><div class="h5"><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+<br>
+#if 0<br>
+#define DebugPresent(x) ErrorF x<br>
+#else<br>
+#define DebugPresent(x)<br>
+#endif<br>
+<br>
+struct ms_present_vblank_event {<br>
+    uint64_t        event_id;<br>
+};<br>
+<br>
+static RRCrtcPtr<br>
+ms_present_get_crtc(WindowPtr window)<br>
+{<br>
+    ScreenPtr screen = window->drawable.pScreen;<br>
+    ScrnInfoPtr pScrn = xf86ScreenToScrn(screen);<br>
+    BoxRec box, crtcbox;<br>
+    xf86CrtcPtr crtc;<br>
+    RRCrtcPtr randr_crtc = NULL;<br>
+<br>
+    box.x1 = window->drawable.x;<br>
+    box.y1 = window->drawable.y;<br>
+    box.x2 = box.x1 + window->drawable.width;<br>
+    box.y2 = box.y1 + window->drawable.height;<br>
+<br>
+    crtc = ms_covering_crtc(pScrn, &box, NULL, &crtcbox);<br>
+<br>
+    /* Make sure the CRTC is valid and this is the real front buffer */<br>
+    if (crtc != NULL && !crtc->rotatedData)<br>
+        randr_crtc = crtc->randr_crtc;<br>
+<br>
+    return randr_crtc;<br>
+}<br>
+<br>
+static int<br>
+ms_present_get_ust_msc(RRCrtcPtr crtc, CARD64 *ust, CARD64 *msc)<br>
+{<br>
+    xf86CrtcPtr xf86_crtc = crtc->devPrivate;<br>
+<br>
+    return ms_get_crtc_ust_msc(xf86_crtc, ust, msc);<br>
+}<br>
+<br>
+/*<br>
+ * Flush the DRM event queue when full; makes space for new events.<br>
+ */<br>
+static Bool<br>
+ms_flush_drm_events(ScreenPtr screen)<br>
+{<br>
+    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);<br>
+    modesettingPtr ms = modesettingPTR(scrn);<br>
+<br>
+    struct pollfd p = { .fd = ms->fd, .events = POLLIN };<br>
+    int r;<br>
+<br>
+    do {<br>
+            r = poll(&p, 1, 0);<br>
+    } while (r == -1 && (errno == EINTR || errno == EAGAIN));<br>
+<br>
+    if (r <= 0)<br>
+        return 0;<br>
+<br>
+    return drmHandleEvent(ms->fd, &ms->event_context);<br>
+}<br>
+<br>
+/*<br>
+ * Called when the queued vblank event has occurred<br>
+ */<br>
+static void<br>
+ms_present_vblank_handler(uint64_t msc, uint64_t usec, void *data)<br>
+{<br>
+    struct ms_present_vblank_event *event = data;<br>
+<br>
+    present_event_notify(event->event_id, usec, msc);<br>
+    free(event);<br>
+}<br>
+<br>
+/*<br>
+ * Called when the queued vblank is aborted<br>
+ */<br>
+static void<br>
+ms_present_vblank_abort(void *data)<br>
+{<br>
+    struct ms_present_vblank_event *event = data;<br>
+<br>
+    free(event);<br>
+}<br>
+<br>
+/*<br>
+ * Queue an event to report back to the Present extension when the specified<br>
+ * MSC has past<br>
+ */<br>
+static int<br>
+ms_present_queue_vblank(RRCrtcPtr crtc,<br>
+                        uint64_t event_id,<br>
+                        uint64_t msc)<br>
+{<br>
+    xf86CrtcPtr xf86_crtc = crtc->devPrivate;<br>
+    ScreenPtr screen = crtc->pScreen;<br>
+    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);<br>
+    modesettingPtr ms = modesettingPTR(scrn);<br>
+    drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;<br>
+    struct ms_present_vblank_event *event;<br>
+    drmVBlank vbl;<br>
+    int ret;<br>
+    uint32_t seq;<br>
+<br>
+    event = calloc(sizeof(struct ms_present_vblank_event), 1);<br>
+    if (!event)<br>
+        return BadAlloc;<br>
+    event->event_id = event_id;<br>
+    seq = ms_drm_queue_alloc(xf86_crtc, event,<br>
+                             ms_present_vblank_handler,<br>
+                             ms_present_vblank_abort);<br>
+    if (!seq) {<br>
+        free(event);<br>
+        return BadAlloc;<br>
+    }<br>
+<br>
+    vbl.request.type =<br>
+        DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT | drmmode_crtc->vblank_pipe;<br>
+    vbl.request.sequence = msc;<br>
+    vbl.request.signal = seq;<br>
+    for (;;) {<br>
+        ret = drmWaitVBlank(ms->fd, &vbl);<br>
+        if (!ret)<br>
+            break;<br>
+        if (errno != EBUSY || !ms_flush_drm_events(screen))<br>
+            return BadAlloc;<br>
+    }<br>
+    DebugPresent(("\t\tiq %lld seq %u msc %llu (hw msc %u)\n",<br>
+                 (long long) event_id, seq, (long long) msc,<br>
+                 vbl.request.sequence));<br>
+    return Success;<br>
+}<br>
+<br>
+static Bool<br>
+ms_present_event_match(void *data, void *match_data)<br>
+{<br>
+    struct ms_present_vblank_event *event = data;<br>
+    uint64_t *match = match_data;<br>
+<br>
+    return *match == event->event_id;<br>
+}<br>
+<br>
+/*<br>
+ * Remove a pending vblank event from the DRM queue so that it is not reported<br>
+ * to the extension<br>
+ */<br>
+static void<br>
+ms_present_abort_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)<br>
+{<br>
+    ScreenPtr screen = crtc->pScreen;<br>
+    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);<br>
+<br>
+    ms_drm_abort(scrn, ms_present_event_match, &event_id);<br>
+}<br>
+<br>
+/*<br>
+ * Flush our batch buffer when requested by the Present extension.<br>
+ */<br>
+static void<br>
+ms_present_flush(WindowPtr window)<br>
+{<br>
+    ScreenPtr screen = window->drawable.pScreen;<br>
+    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);<br>
+    modesettingPtr ms = modesettingPTR(scrn);<br>
+<br>
+    if (ms->drmmode.glamor)<br>
+        glamor_block_handler(screen);<br>
+}<br>
+<br>
+static present_screen_info_rec ms_present_screen_info = {<br>
+    .version = PRESENT_SCREEN_INFO_VERSION,<br>
+<br>
+    .get_crtc = ms_present_get_crtc,<br>
+    .get_ust_msc = ms_present_get_ust_msc,<br>
+    .queue_vblank = ms_present_queue_vblank,<br>
+    .abort_vblank = ms_present_abort_vblank,<br>
+    .flush = ms_present_flush,<br>
+<br>
+    .capabilities = PresentCapabilityNone,<br>
+    .check_flip = 0,<br>
+    .flip = 0,<br>
+    .unflip = 0,<br>
+};<br>
+<br>
+Bool<br>
+ms_present_screen_init(ScreenPtr screen)<br>
+{<br>
+    return present_screen_init(screen, &ms_present_screen_info);<br>
+}<br>
diff --git a/hw/xfree86/drivers/modesetting/vblank.c b/hw/xfree86/drivers/modesetting/vblank.c<br>
index 5031ef8..c123205 100644<br>
--- a/hw/xfree86/drivers/modesetting/vblank.c<br>
+++ b/hw/xfree86/drivers/modesetting/vblank.c<br>
@@ -323,6 +323,24 @@ ms_drm_abort_scrn(ScrnInfoPtr scrn)<br>
 }<br>
<br>
 /*<br>
+ * Externally usable abort function that uses a callback to match a single<br>
+ * queued entry to abort<br>
+ */<br>
+void<br>
+ms_drm_abort(ScrnInfoPtr scrn, Bool (*match)(void *data, void *match_data),<br>
+             void *match_data)<br>
+{<br>
+    struct ms_drm_queue *q;<br>
+<br>
+    xorg_list_for_each_entry(q, &ms_drm_queue, list) {<br>
+        if (match(q->data, match_data)) {<br>
+            ms_drm_abort_one(q);<br>
+            break;<br>
+        }<br>
+    }<br>
+}<br>
+<br>
+/*<br>
  * General DRM kernel handler. Looks for the matching sequence number in the<br>
  * drm event queue and calls the handler for it.<br>
  */<br>
<span><font color="#888888">--<br>
2.1.3<br>
<br>
_______________________________________________<br>
<a href="mailto:xorg-devel@lists.x.org" target="_blank">xorg-devel@lists.x.org</a>: X.Org development<br>
Archives: <a href="http://lists.x.org/archives/xorg-devel" target="_blank">http://lists.x.org/archives/xorg-devel</a><br>
Info: <a href="http://lists.x.org/mailman/listinfo/xorg-devel" target="_blank">http://lists.x.org/mailman/listinfo/xorg-devel</a></font></span></blockquote></div></div></div></div></div>
</blockquote></div></div>