<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">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>You need to include galmor.h here. It won't build for me without it.<br></div><div>--Jason<br></div><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>