xf86-video-intel: Branch 'dri2-swapbuffers' - src/drmmode_display.c src/i830_dri.c src/i830.h

Jesse Barnes jbarnes at kemper.freedesktop.org
Fri Oct 2 16:54:24 PDT 2009


 src/drmmode_display.c |    5 -
 src/i830.h            |    2 
 src/i830_dri.c        |  232 +++++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 230 insertions(+), 9 deletions(-)

New commits:
commit d329cfd0e54952240e1d20b5b9643eaf331f61e5
Author: Jesse Barnes <jbarnes at virtuousgeek.org>
Date:   Sat Oct 3 01:57:19 2009 -0700

    DRI2: add OML and SGI_video_sync support
    
    Add hooks to support OML functionality and older SGI_video_sync
    functionality.  Requires a server with support for the new hooks.

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index e982a70..f52a59a 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -1098,10 +1098,9 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
 }
 
 Bool
-drmmode_do_pageflip(DrawablePtr pDraw, dri_bo *new_front, dri_bo *old_front,
+drmmode_do_pageflip(ScreenPtr pScreen, dri_bo *new_front, dri_bo *old_front,
 		    void *data)
 {
-    ScreenPtr pScreen = pDraw->pScreen;
     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
     xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
@@ -1180,8 +1179,6 @@ drmmode_page_flip_handler(int fd,
 	return;
 
     drmModeRmFB(drmmode->fd, drmmode->old_fb_id);
-
-    DRI2SwapComplete(drmmode->swap_data);
 }
 
 static void
diff --git a/src/i830.h b/src/i830.h
index 16e3c55..e164a0c 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -695,7 +695,7 @@ void I830DRI2CloseScreen(ScreenPtr pScreen);
 extern Bool drmmode_pre_init(ScrnInfoPtr pScrn, int fd, int cpp);
 extern int drmmode_get_pipe_from_crtc_id(drm_intel_bufmgr *bufmgr, xf86CrtcPtr crtc);
 extern int drmmode_output_dpms_status(xf86OutputPtr output);
-extern Bool drmmode_do_pageflip(DrawablePtr pDraw, dri_bo *new_front,
+extern Bool drmmode_do_pageflip(ScreenPtr pScreen, dri_bo *new_front,
 				dri_bo *old_front, void *data);
 
 extern Bool i830_crtc_on(xf86CrtcPtr crtc);
diff --git a/src/i830_dri.c b/src/i830_dri.c
index b34b9b7..b4b6be6 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -273,6 +273,29 @@ I830DRI2DestroyBuffer(DrawablePtr pDraw, DRI2Buffer2Ptr buffer)
 
 #endif
 
+static int
+I830DRI2DrawablePipe(DrawablePtr pDraw)
+{
+    ScreenPtr pScreen = pDraw->pScreen;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    BoxRec box, crtcbox;
+    xf86CrtcPtr crtc;
+    int pipe = -1;
+
+    box.x1 = pDraw->x;
+    box.y1 = pDraw->y;
+    box.x2 = box.x1 + pDraw->width;
+    box.y2 = box.y1 + pDraw->height;
+
+    crtc = i830_covering_crtc(pScrn, &box, NULL, &crtcbox);
+
+    /* Make sure the CRTC is valid and this is the real front buffer */
+    if (crtc != NULL && !crtc->rotatedData)
+	pipe = i830_crtc_to_pipe(crtc);
+
+    return pipe;
+}
+
 static void
 I830DRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion,
 		   DRI2BufferPtr pDstBuffer, DRI2BufferPtr pSrcBuffer)
@@ -359,6 +382,86 @@ I830DRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion,
 #if DRI2INFOREC_VERSION >= 4
 
 /*
+ * Request a DRM event when the requested conditions will be satisfied.
+ * Event will be handled by the server and wake up any clients waiting
+ * on the specified frame count.
+ */
+static int
+I830DRI2SetupSwap(DrawablePtr pDraw, CARD64 target_msc, CARD64 divisor,
+		  CARD64 remainder, void *data, CARD64 *event_frame)
+{
+    ScreenPtr pScreen = pDraw->pScreen;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+    drmVBlank vbl;
+    int ret, pipe = I830DRI2DrawablePipe(pDraw);
+
+    /* Get current count */
+    vbl.request.type = DRM_VBLANK_RELATIVE;
+    if (pipe > 0)
+	vbl.request.type |= DRM_VBLANK_SECONDARY;
+    vbl.request.sequence = 0;
+    ret = drmWaitVBlank(pI830->drmSubFD, &vbl);
+    if (ret) {
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		   "get vblank counter failed: %s\n", strerror(errno));
+	return FALSE;
+    }
+
+    /*
+     * If divisor is zero, we just need to make sure target_msc passes
+     * before waking up the client.
+     */
+    if (divisor == 0) {
+	vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
+	if (pipe > 0)
+	    vbl.request.type |= DRM_VBLANK_SECONDARY;
+	vbl.request.sequence = target_msc;
+	vbl.request.signal = (unsigned long)data;
+	ret = drmWaitVBlank(pI830->drmSubFD, &vbl);
+	if (ret) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		       "get vblank counter failed: %s\n", strerror(errno));
+	    return FALSE;
+	}
+	return TRUE;
+    }
+
+    /*
+     * If we get here, target_msc has already passed or we don't have one,
+     * so we queue an event that will satisfy the divisor/remainder equation.
+     */
+    if ((vbl.reply.sequence % divisor) == remainder)
+	return FALSE;
+
+    vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
+    if (pipe > 0)
+	vbl.request.type |= DRM_VBLANK_SECONDARY;
+
+    /*
+     * If we have no remainder, and the test above failed, it means we've
+     * passed the last point where seq % divisor == remainder, so we need
+     * to wait for the next time that will happen.
+     */
+    if (!remainder)
+	vbl.request.sequence += divisor;
+
+    vbl.request.sequence = vbl.reply.sequence - (vbl.reply.sequence % divisor) +
+	remainder;
+    vbl.request.signal = (unsigned long)data;
+    ret = drmWaitVBlank(pI830->drmSubFD, &vbl);
+    if (ret) {
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		   "get vblank counter failed: %s\n", strerror(errno));
+	return FALSE;
+    }
+
+    *event_frame = vbl.reply.sequence;
+
+    return TRUE;
+}
+
+/*
  * DRI2SwapBuffers should try to do a buffer swap if possible, however:
  *   - if we're swapping buffers smaller than the screen, we have to blit
  *   - if the back buffer doesn't match the screen depth, we have to blit
@@ -366,10 +469,9 @@ I830DRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion,
  *     and back buffers
  */
 static Bool
-I830DRI2SwapBuffers(DrawablePtr pDraw,
+I830DRI2SwapBuffers(ScreenPtr pScreen,
 		    DRI2BufferPtr front, DRI2BufferPtr back, void *data)
 {
-    ScreenPtr pScreen = pDraw->pScreen;
     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
     I830DRI2BufferPrivatePtr front_priv, back_priv;
@@ -399,9 +501,125 @@ I830DRI2SwapBuffers(DrawablePtr pDraw,
 	FatalError("swapbuffers with bad front\n");
 
     /* Page flip the full screen buffer */
-    return drmmode_do_pageflip(pDraw, i830_get_pixmap_bo(front_priv->pPixmap),
+    return drmmode_do_pageflip(pScreen, i830_get_pixmap_bo(front_priv->pPixmap),
 			       i830_get_pixmap_bo(back_priv->pPixmap), data);
 }
+
+/*
+ * Get current frame count and frame count timestamp, based on drawable's
+ * crtc.
+ */
+static int
+I830DRI2GetMSC(DrawablePtr pDraw, CARD64 *ust, CARD64 *msc)
+{
+    ScreenPtr pScreen = pDraw->pScreen;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+    drmVBlank vbl;
+    int ret, pipe = I830DRI2DrawablePipe(pDraw);
+
+    /* FIXME: we shouldn't be called if the window isn't mapped or is
+       redirected */
+    if (pipe < 0) {
+	*ust = 0;
+	*msc = 0;
+	return TRUE;
+    }
+
+    vbl.request.type = DRM_VBLANK_RELATIVE;
+    if (pipe > 0)
+	vbl.request.type |= DRM_VBLANK_SECONDARY;
+    vbl.request.sequence = 0;
+
+    ret = drmWaitVBlank(pI830->drmSubFD, &vbl);
+    if (ret) {
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		   "get vblank counter failed: %s\n", strerror(errno));
+	return FALSE;
+    }
+
+    *ust = ((CARD64)vbl.reply.tval_sec * 1000000) + vbl.reply.tval_usec;
+    *msc = vbl.reply.sequence;
+
+    return TRUE;
+}
+
+/*
+ * Request a DRM event when the requested conditions will be satisfied.
+ * Event will be handled by the server and wake up any clients waiting
+ * on the specified frame count.
+ */
+static int
+I830DRI2SetupWaitMSC(DrawablePtr pDraw, CARD64 target_msc, CARD64 divisor,
+		     CARD64 remainder, void *data, CARD64 *event_frame)
+{
+    ScreenPtr pScreen = pDraw->pScreen;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+    drmVBlank vbl;
+    int ret, pipe = I830DRI2DrawablePipe(pDraw);
+
+    /* Get current count */
+    vbl.request.type = DRM_VBLANK_RELATIVE;
+    if (pipe > 0)
+	vbl.request.type |= DRM_VBLANK_SECONDARY;
+    vbl.request.sequence = 0;
+    ret = drmWaitVBlank(pI830->drmSubFD, &vbl);
+    if (ret) {
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		   "get vblank counter failed: %s\n", strerror(errno));
+	return FALSE;
+    }
+
+    /*
+     * If divisor is zero, we just need to make sure target_msc passes
+     * before waking up the client.
+     */
+    if (divisor == 0) {
+	vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
+	if (pipe > 0)
+	    vbl.request.type |= DRM_VBLANK_SECONDARY;
+	vbl.request.sequence = target_msc;
+	vbl.request.signal = (unsigned long)data;
+	ret = drmWaitVBlank(pI830->drmSubFD, &vbl);
+	if (ret) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		       "get vblank counter failed: %s\n", strerror(errno));
+	    return FALSE;
+	}
+	return TRUE;
+    }
+
+    /*
+     * If we get here, target_msc has already passed or we don't have one,
+     * so we queue an event that will satisfy the divisor/remainder equation.
+     */
+    vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
+    if (pipe > 0)
+	vbl.request.type |= DRM_VBLANK_SECONDARY;
+
+    /*
+     * If we have no remainder and the condition isn't satisified, it means
+     * we've passed the last point where seq % divisor == remainder, so we need
+     * to wait for the next time that will happen.
+     */
+    if (((vbl.reply.sequence % divisor) != remainder) && !remainder)
+	vbl.request.sequence += divisor;
+
+    vbl.request.sequence = vbl.reply.sequence - (vbl.reply.sequence % divisor) +
+	remainder;
+    vbl.request.signal = (unsigned long)data;
+    ret = drmWaitVBlank(pI830->drmSubFD, &vbl);
+    if (ret) {
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		   "get vblank counter failed: %s\n", strerror(errno));
+	return FALSE;
+    }
+
+    *event_frame = vbl.reply.sequence;
+
+    return TRUE;
+}
 #endif
 
 Bool I830DRI2ScreenInit(ScreenPtr pScreen)
@@ -474,10 +692,16 @@ Bool I830DRI2ScreenInit(ScreenPtr pScreen)
 #endif
 
 #if DRI2INFOREC_VERSION >= 4
+    info.version = 4;
+    info.SetupSwap = I830DRI2SetupSwap;
     if (pI830->use_swap_buffers) {
-	info.version = 4;
 	info.SwapBuffers = I830DRI2SwapBuffers;
+    } else {
+	info.SwapBuffers = NULL;
     }
+
+    info.GetMSC = I830DRI2GetMSC;
+    info.SetupWaitMSC = I830DRI2SetupWaitMSC;
 #endif
 
     info.CopyRegion = I830DRI2CopyRegion;


More information about the xorg-commit mailing list