[Xquartz-changes] xserver: Branch 'master' - 5 commits

Jeremy Huddleston jeremyhu at freedesktop.org
Wed Jan 13 11:21:30 PST 2010


 configure.ac                     |    4 
 glx/extension_string.c           |    1 
 glx/extension_string.h           |    1 
 glx/glxcmds.c                    |    2 
 glx/glxcontext.h                 |    4 
 glx/glxdrawable.h                |    2 
 glx/glxdri.c                     |    2 
 glx/glxdri2.c                    |  102 ++++++++-
 glx/glxdriswrast.c               |    2 
 glx/glxext.c                     |    5 
 glx/glxscreens.c                 |    1 
 glx/glxserver.h                  |   20 -
 glx/swap_interval.c              |    7 
 hw/xfree86/dri2/dri2.c           |  403 ++++++++++++++++++++++++++++++++++++++-
 hw/xfree86/dri2/dri2.h           |  129 ++++++++++++
 hw/xfree86/dri2/dri2ext.c        |  217 +++++++++++++++++++++
 hw/xquartz/bundle/Info.plist.cpp |    4 
 hw/xquartz/quartzKeyboard.c      |    4 
 include/protocol-versions.h      |    2 
 19 files changed, 869 insertions(+), 43 deletions(-)

New commits:
commit 6bde306f7f6b9bbabeaa8bb910ea549be906cd8b
Author: Jeremy Huddleston <jeremyhu at freedesktop.org>
Date:   Wed Jan 13 11:20:29 2010 -0800

    XQuartz: Update copyright in bundle for 2010
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at freedesktop.org>

diff --git a/hw/xquartz/bundle/Info.plist.cpp b/hw/xquartz/bundle/Info.plist.cpp
index 87214f4..e89d985 100644
--- a/hw/xquartz/bundle/Info.plist.cpp
+++ b/hw/xquartz/bundle/Info.plist.cpp
@@ -35,9 +35,9 @@
                 <string>http://xquartz.macosforge.org/downloads/sparkle/release.xml</string>
 #endif
 	<key>NSHumanReadableCopyright</key>
-		<string>© 2003-2009 Apple Inc.
+		<string>© 2003-2010 Apple Inc.
 © 2003 XFree86 Project, Inc.
-© 2003-2009 X.org Foundation, Inc.
+© 2003-2010 X.org Foundation, Inc.
 </string>
 	<key>NSMainNibFile</key>
 		<string>main</string>
commit 6008cc116493cb2825ad0bda0b407b7aefabb3f4
Author: Jeremy Huddleston <jeremyhu at freedesktop.org>
Date:   Mon Jan 11 18:02:55 2010 -0800

    XQuartz: Setup the modifier map in the quartz thread
    
    This avoids possible doing it twice which could result in incorrect
    keycodes for alt due to our loss of information about its side.
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at freedesktop.org>

diff --git a/hw/xquartz/quartzKeyboard.c b/hw/xquartz/quartzKeyboard.c
index 62b2ebb..96b5fa5 100644
--- a/hw/xquartz/quartzKeyboard.c
+++ b/hw/xquartz/quartzKeyboard.c
@@ -260,6 +260,7 @@ static void DarwinBuildModifierMaps(darwinKeyboardInfo *info) {
                 break;
 
             case XK_Mode_switch:
+                ErrorF("DarwinBuildModifierMaps: XK_Mode_switch encountered, unable to determine side.\n");
                 info->modifierKeycodes[NX_MODIFIERKEY_ALTERNATE][0] = i;
 #ifdef NX_MODIFIERKEY_RALTERNATE
                 info->modifierKeycodes[NX_MODIFIERKEY_RALTERNATE][0] = i;
@@ -388,7 +389,6 @@ void DarwinKeyboardReloadHandler(void) {
     
     pthread_mutex_lock(&keyInfo_mutex); {
         /* Initialize our keySyms */
-        DarwinBuildModifierMaps(&keyInfo);
         keySyms.map = keyInfo.keyMap;
         keySyms.mapWidth   = GLYPHS_PER_KEY;
         keySyms.minKeyCode = MIN_KEYCODE;
@@ -808,5 +808,7 @@ Bool QuartzReadSystemKeymap(darwinKeyboardInfo *info) {
         }
     }
 
+    DarwinBuildModifierMaps(info);
+
     return TRUE;
 }
commit 44f9c3d16c9c9b3362306a9ba26ee52e7baafeca
Merge: 032f978... 84956ca...
Author: Keith Packard <keithp at keithp.com>
Date:   Wed Jan 13 10:19:21 2010 -0800

    Merge remote branch 'jbarnes/master'

commit 84956ca43b087600d9db297cffd62e960c516d9e
Author: Jesse Barnes <jbarnes at virtuousgeek.org>
Date:   Mon Jan 11 14:56:24 2010 -0500

    GLX/DRI2: add INTEL_swap_event support
    
    This allows clients to easily check for swap completion status in their
    main loop.
    
    Reviewed-by: Kristian Høgsberg <krh at bitplanet.net>
    Reviewed-by: Adam Jackson <ajax at nwnk.net>
    Signed-off-by: Jesse Barnes <jbarnes at virtuousgeek.org>

diff --git a/configure.ac b/configure.ac
index 1b20fc6..029c9b4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -755,7 +755,7 @@ XINERAMAPROTO="xineramaproto"
 BIGFONTPROTO="xf86bigfontproto >= 1.2.0"
 XCALIBRATEPROTO="xcalibrateproto"
 DGAPROTO="xf86dgaproto >= 2.0.99.1"
-GLPROTO="glproto >= 1.4.9"
+GLPROTO="glproto >= 1.4.10"
 DMXPROTO="dmxproto >= 2.2.99.1"
 VIDMODEPROTO="xf86vidmodeproto >= 2.2.99.1"
 WINDOWSWMPROTO="windowswmproto"
diff --git a/glx/extension_string.c b/glx/extension_string.c
index 9d110cf..7721cb0 100644
--- a/glx/extension_string.c
+++ b/glx/extension_string.c
@@ -82,6 +82,7 @@ static const struct extension_info known_glx_extensions[] = {
    { GLX(SGIX_fbconfig),               VER(1,3), Y, },
    { GLX(SGIX_pbuffer),                VER(1,3), Y, },
    { GLX(SGIX_visual_select_group),    VER(0,0), Y, },
+   { GLX(INTEL_swap_event),            VER(1,4), N, },
    { NULL }
 };
 
diff --git a/glx/extension_string.h b/glx/extension_string.h
index 98e91bc..912534a 100644
--- a/glx/extension_string.h
+++ b/glx/extension_string.h
@@ -50,6 +50,7 @@ enum {
    SGIX_fbconfig_bit,
    SGIX_pbuffer_bit,
    SGIX_visual_select_group_bit,
+   INTEL_swap_event_bit,
    __NUM_GLX_EXTS,
 };
 
diff --git a/glx/glxdri2.c b/glx/glxdri2.c
index 58e4684..69fd39b 100644
--- a/glx/glxdri2.c
+++ b/glx/glxdri2.c
@@ -167,6 +167,43 @@ __glXDRIdrawableWaitGL(__GLXdrawable *drawable)
 		   DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
 }
 
+static void
+__glXdriSwapEvent(ClientPtr client, void *data, int type, CARD64 ust,
+		  CARD64 msc, CARD64 sbc)
+{
+    __GLXdrawable *drawable = data;
+    xGLXBufferSwapComplete wire;
+
+    if (!drawable->eventMask & GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK)
+	return;
+
+    wire.type = __glXEventBase + GLX_BufferSwapComplete;
+    switch (type) {
+    case DRI2_EXCHANGE_COMPLETE:
+	wire.event_type = GLX_EXCHANGE_COMPLETE_INTEL;
+	break;
+    case DRI2_BLIT_COMPLETE:
+	wire.event_type = GLX_BLIT_COMPLETE_INTEL;
+	break;
+    case DRI2_FLIP_COMPLETE:
+	wire.event_type = GLX_FLIP_COMPLETE_INTEL;
+	break;
+    default:
+	/* unknown swap completion type */
+	break;
+    }
+    wire.sequenceNumber = client->sequence;
+    wire.drawable = drawable->drawId;
+    wire.ust_hi = ust >> 32;
+    wire.ust_lo = ust & 0xffffffff;
+    wire.msc_hi = msc >> 32;
+    wire.msc_lo = msc & 0xffffffff;
+    wire.sbc_hi = sbc >> 32;
+    wire.sbc_lo = sbc & 0xffffffff;
+
+    WriteEventsToClient(client, 1, (xEvent *) &wire);
+}
+
 /*
  * Copy or flip back to front, honoring the swap interval if possible.
  *
@@ -184,7 +221,7 @@ __glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable *drawable)
 	(*screen->flush->flushInvalidate)(priv->driDrawable);
 
     if (DRI2SwapBuffers(client, drawable->pDraw, 0, 0, 0, &unused,
-			NULL, drawable->pDraw) != Success)
+			__glXdriSwapEvent, drawable->pDraw) != Success)
 	return FALSE;
 
     return TRUE;
@@ -581,6 +618,10 @@ initializeExtensions(__GLXDRIscreen *screen)
 			 "GLX_MESA_copy_sub_buffer");
     LogMessage(X_INFO, "AIGLX: enabled GLX_MESA_copy_sub_buffer\n");
 
+    /* FIXME: only if DDX supports it */
+    __glXEnableExtension(screen->glx_enable_bits, "GLX_INTEL_swap_event");
+    LogMessage(X_INFO, "AIGLX: enabled GLX_INTEL_swap_event\n");
+
     for (i = 0; extensions[i]; i++) {
 #ifdef __DRI_READ_DRAWABLE
 	if (strcmp(extensions[i]->name, __DRI_READ_DRAWABLE) == 0) {
diff --git a/glx/glxext.c b/glx/glxext.c
index 913c624..59bcfbe 100644
--- a/glx/glxext.c
+++ b/glx/glxext.c
@@ -267,6 +267,7 @@ GLboolean __glXErrorOccured(void)
 }
 
 static int __glXErrorBase;
+int __glXEventBase;
 
 int __glXError(int error)
 {
@@ -403,6 +404,7 @@ void GlxExtensionInit(void)
     }
 
     __glXErrorBase = extEntry->errorBase;
+    __glXEventBase = extEntry->eventBase;
 }
 
 /************************************************************************/
diff --git a/glx/glxscreens.c b/glx/glxscreens.c
index 674e2c6..58d8ee0 100644
--- a/glx/glxscreens.c
+++ b/glx/glxscreens.c
@@ -181,6 +181,7 @@ static char GLXServerExtensions[] =
 			"GLX_SGIX_fbconfig "
 			"GLX_SGIX_pbuffer "
 			"GLX_MESA_copy_sub_buffer "
+                        "GLX_INTEL_swap_event"
 			;
 
 /*
diff --git a/glx/glxserver.h b/glx/glxserver.h
index 10c4889..1daf977 100644
--- a/glx/glxserver.h
+++ b/glx/glxserver.h
@@ -249,4 +249,6 @@ extern int __glXImageSize(GLenum format, GLenum type,
 extern unsigned glxMajorVersion;
 extern unsigned glxMinorVersion;
 
+extern int __glXEventBase;
+
 #endif /* !__GLX_server_h__ */
diff --git a/hw/xfree86/dri2/dri2.h b/hw/xfree86/dri2/dri2.h
index be14b9d..dd59297 100644
--- a/hw/xfree86/dri2/dri2.h
+++ b/hw/xfree86/dri2/dri2.h
@@ -169,6 +169,8 @@ typedef struct {
     DRI2ScheduleWaitMSCProcPtr	ScheduleWaitMSC;
 }  DRI2InfoRec, *DRI2InfoPtr;
 
+extern _X_EXPORT int DRI2EventBase;
+
 extern _X_EXPORT Bool DRI2ScreenInit(ScreenPtr	pScreen,
 		    DRI2InfoPtr info);
 
diff --git a/hw/xfree86/dri2/dri2ext.c b/hw/xfree86/dri2/dri2ext.c
index fb8f908..3e6b03e 100644
--- a/hw/xfree86/dri2/dri2ext.c
+++ b/hw/xfree86/dri2/dri2ext.c
@@ -348,6 +348,25 @@ vals_to_card64(CARD32 lo, CARD32 hi)
     return (CARD64)hi << 32 | lo;
 }
 
+static void
+DRI2SwapEvent(ClientPtr client, void *data, int type, CARD64 ust, CARD64 msc,
+	      CARD64 sbc)
+{
+    xDRI2BufferSwapComplete event;
+
+    event.type = DRI2EventBase + DRI2_BufferSwapComplete;
+    event.sequenceNumber = client->sequence;
+    event.event_type = type;
+    event.ust_hi = (CARD64)ust >> 32;
+    event.ust_lo = ust & 0xffffffff;
+    event.msc_hi = (CARD64)msc >> 32;
+    event.msc_lo = msc & 0xffffffff;
+    event.sbc_hi = (CARD64)sbc >> 32;
+    event.sbc_lo = sbc & 0xffffffff;
+
+    WriteEventsToClient(client, 1, (xEvent *)&event);
+}
+
 static int
 ProcDRI2SwapBuffers(ClientPtr client)
 {
@@ -368,7 +387,7 @@ ProcDRI2SwapBuffers(ClientPtr client)
     remainder = vals_to_card64(stuff->remainder_lo, stuff->remainder_hi);
 
     status = DRI2SwapBuffers(client, pDrawable, target_msc, divisor, remainder,
-			     &swap_target, NULL, pDrawable);
+			     &swap_target, DRI2SwapEvent, pDrawable);
     if (status != Success)
 	return BadDrawable;
 
@@ -608,6 +627,8 @@ static int DRI2DrawableGone(pointer p, XID id)
     return Success;
 }
 
+int DRI2EventBase;
+
 static void
 DRI2ExtensionInit(void)
 {
@@ -624,6 +645,7 @@ DRI2ExtensionInit(void)
 				 NULL,
 				 StandardMinorOpcode);
 
+    DRI2EventBase = dri2Extension->eventBase;
 }
 
 extern Bool noDRI2Extension;
commit 04a54f69a8085ab3fe11a8713bd8b6b16ed1db27
Author: Jesse Barnes <jbarnes at virtuousgeek.org>
Date:   Thu Jul 16 09:01:17 2009 -0400

    DRI2: add support for new DRI2 protocol requests
    
    Support the new DRI2 2.2 protocol requests: DRI2SwapBuffers, DRI2GetMSC,
    DRI2WaitMSC, DRI2WaitSBC and DRI2SwapInterval.
    
    These requests allow the server to support the SGI_video_sync,
    SGI_swap_interval, and OML_sync_control GLX extensions if DDX support is
    present.  The new DDX APIs are documented in dri2.h.
    
    Reviewed-by: Kristian Høgsberg <krh at bitplanet.net>
    Reviewed-by: Adam Jackson <ajax at nwnk.net>
    Signed-off-by: Jesse Barnes <jbarnes at virtuousgeek.org>

diff --git a/configure.ac b/configure.ac
index 7e2c6a5..1b20fc6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -750,7 +750,7 @@ RECORDPROTO="recordproto >= 1.13.99.1"
 SCRNSAVERPROTO="scrnsaverproto >= 1.1"
 RESOURCEPROTO="resourceproto"
 DRIPROTO="xf86driproto >= 2.1.0"
-DRI2PROTO="dri2proto >= 2.1"
+DRI2PROTO="dri2proto >= 2.2"
 XINERAMAPROTO="xineramaproto"
 BIGFONTPROTO="xf86bigfontproto >= 1.2.0"
 XCALIBRATEPROTO="xcalibrateproto"
diff --git a/glx/glxcmds.c b/glx/glxcmds.c
index eedab65..77afbf4 100644
--- a/glx/glxcmds.c
+++ b/glx/glxcmds.c
@@ -1481,7 +1481,7 @@ int __glXDisp_SwapBuffers(__GLXclientState *cl, GLbyte *pc)
 	return error;
 
     if (pGlxDraw->type == DRAWABLE_WINDOW &&
-	(*pGlxDraw->swapBuffers)(pGlxDraw) == GL_FALSE)
+	(*pGlxDraw->swapBuffers)(cl->client, pGlxDraw) == GL_FALSE)
 	return __glXError(GLXBadDrawable);
 
     return Success;
diff --git a/glx/glxcontext.h b/glx/glxcontext.h
index 70a1411..79bc083 100644
--- a/glx/glxcontext.h
+++ b/glx/glxcontext.h
@@ -55,6 +55,10 @@ struct __GLXcontext {
 				     unsigned long mask);
     int            (*forceCurrent)  (__GLXcontext *context);
 
+    Bool           (*wait)          (__GLXcontext *context,
+				     __GLXclientState *cl,
+				     int *error);
+
     __GLXtextureFromPixmap *textureFromPixmap;
 
     /*
diff --git a/glx/glxdrawable.h b/glx/glxdrawable.h
index 3f165ed..2a365c5 100644
--- a/glx/glxdrawable.h
+++ b/glx/glxdrawable.h
@@ -45,7 +45,7 @@ enum {
 
 struct __GLXdrawable {
     void (*destroy)(__GLXdrawable *private);
-    GLboolean (*swapBuffers)(__GLXdrawable *);
+    GLboolean (*swapBuffers)(ClientPtr client, __GLXdrawable *);
     void      (*copySubBuffer)(__GLXdrawable *drawable,
 			       int x, int y, int w, int h);
     void      (*waitX)(__GLXdrawable *);
diff --git a/glx/glxdri.c b/glx/glxdri.c
index 6122653..21e44d1 100644
--- a/glx/glxdri.c
+++ b/glx/glxdri.c
@@ -245,7 +245,7 @@ __glXDRIdrawableDestroy(__GLXdrawable *drawable)
 }
 
 static GLboolean
-__glXDRIdrawableSwapBuffers(__GLXdrawable *basePrivate)
+__glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable *basePrivate)
 {
     __GLXDRIdrawable *private = (__GLXDRIdrawable *) basePrivate;
     __GLXDRIscreen *screen =
diff --git a/glx/glxdri2.c b/glx/glxdri2.c
index ed7dc80..58e4684 100644
--- a/glx/glxdri2.c
+++ b/glx/glxdri2.c
@@ -70,6 +70,7 @@ struct __GLXDRIscreen {
 
     const __DRIcoreExtension *core;
     const __DRIdri2Extension *dri2;
+    const __DRI2flushExtension *flush;
     const __DRIcopySubBufferExtension *copySubBuffer;
     const __DRIswapControlExtension *swapControl;
     const __DRItexBufferExtension *texBuffer;
@@ -132,17 +133,6 @@ __glXDRIdrawableCopySubBuffer(__GLXdrawable *drawable,
 		   DRI2BufferFrontLeft, DRI2BufferBackLeft);
 }
 
-static GLboolean
-__glXDRIdrawableSwapBuffers(__GLXdrawable *drawable)
-{
-    __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
-
-    __glXDRIdrawableCopySubBuffer(drawable, 0, 0,
-				  private->width, private->height);
-
-    return TRUE;
-}
-
 static void
 __glXDRIdrawableWaitX(__GLXdrawable *drawable)
 {
@@ -177,9 +167,37 @@ __glXDRIdrawableWaitGL(__GLXdrawable *drawable)
 		   DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
 }
 
+/*
+ * Copy or flip back to front, honoring the swap interval if possible.
+ *
+ * If the kernel supports it, we request an event for the frame when the
+ * swap should happen, then perform the copy when we receive it.
+ */
+static GLboolean
+__glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable *drawable)
+{
+    __GLXDRIdrawable *priv = (__GLXDRIdrawable *) drawable;
+    __GLXDRIscreen *screen = priv->screen;
+    CARD64 unused;
+
+    if (screen->flush)
+	(*screen->flush->flushInvalidate)(priv->driDrawable);
+
+    if (DRI2SwapBuffers(client, drawable->pDraw, 0, 0, 0, &unused,
+			NULL, drawable->pDraw) != Success)
+	return FALSE;
+
+    return TRUE;
+}
+
 static int
 __glXDRIdrawableSwapInterval(__GLXdrawable *drawable, int interval)
 {
+    if (interval <= 0) /* || interval > BIGNUM? */
+	return GLX_BAD_VALUE;
+
+    DRI2SwapInterval(drawable->pDraw, interval);
+
     return 0;
 }
 
@@ -241,6 +259,18 @@ __glXDRIcontextForceCurrent(__GLXcontext *baseContext)
 					read->driDrawable);
 }
 
+static Bool
+__glXDRIcontextWait(__GLXcontext *baseContext,
+		    __GLXclientState *cl, int *error)
+{
+    if (DRI2WaitSwap(cl->client, baseContext->drawPriv->pDraw)) {
+	*error = cl->client->noClientException;
+	return TRUE;
+    }
+
+    return FALSE;
+}
+
 #ifdef __DRI_TEX_BUFFER
 
 static int
@@ -346,6 +376,7 @@ __glXDRIscreenCreateContext(__GLXscreen *baseScreen,
     context->base.copy              = __glXDRIcontextCopy;
     context->base.forceCurrent      = __glXDRIcontextForceCurrent;
     context->base.textureFromPixmap = &__glXDRItextureFromPixmap;
+    context->base.wait              = __glXDRIcontextWait;
 
     context->driContext =
 	(*screen->dri2->createNewContext)(screen->driScreen,
@@ -581,6 +612,14 @@ initializeExtensions(__GLXDRIscreen *screen)
 	    LogMessage(X_INFO, "AIGLX: GLX_EXT_texture_from_pixmap backed by buffer objects\n");
 	}
 #endif
+
+#ifdef __DRI2_FLUSH
+	if (strcmp(extensions[i]->name, __DRI2_FLUSH) == 0 &&
+	    extensions[i]->version >= __DRI2_FLUSH_VERSION) {
+		screen->flush = (__DRI2flushExtension *) extensions[i];
+	}
+#endif
+
 	/* Ignore unknown extensions */
     }
 }
diff --git a/glx/glxdriswrast.c b/glx/glxdriswrast.c
index 20f9f90..c647d83 100644
--- a/glx/glxdriswrast.c
+++ b/glx/glxdriswrast.c
@@ -108,7 +108,7 @@ __glXDRIdrawableDestroy(__GLXdrawable *drawable)
 }
 
 static GLboolean
-__glXDRIdrawableSwapBuffers(__GLXdrawable *drawable)
+__glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable *drawable)
 {
     __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
     const __DRIcoreExtension *core = private->screen->core;
diff --git a/glx/glxext.c b/glx/glxext.c
index 751ea72..913c624 100644
--- a/glx/glxext.c
+++ b/glx/glxext.c
@@ -446,6 +446,9 @@ __GLXcontext *__glXForceCurrent(__GLXclientState *cl, GLXContextTag tag,
     	}
     }
     
+    if (cx->wait && (*cx->wait)(cx, cl, error))
+	return NULL;
+
     if (cx == __glXLastContext) {
 	/* No need to re-bind */
 	return cx;
diff --git a/glx/glxserver.h b/glx/glxserver.h
index 80f1b28..10c4889 100644
--- a/glx/glxserver.h
+++ b/glx/glxserver.h
@@ -56,7 +56,14 @@
 #include <GL/gl.h>
 #include <GL/glxproto.h>
 
-/* For glxscreens.h */
+/*
+** GLX resources.
+*/
+typedef XID GLXContextID;
+typedef XID GLXPixmap;
+typedef XID GLXDrawable;
+
+typedef struct __GLXclientStateRec __GLXclientState;
 typedef struct __GLXdrawable __GLXdrawable;
 typedef struct __GLXcontext __GLXcontext;
 
@@ -71,15 +78,6 @@ typedef struct __GLXcontext __GLXcontext;
 #define False 0
 #endif
 
-/*
-** GLX resources.
-*/
-typedef XID GLXContextID;
-typedef XID GLXPixmap;
-typedef XID GLXDrawable;
-
-typedef struct __GLXclientStateRec __GLXclientState;
-
 extern __GLXscreen *glxGetScreen(ScreenPtr pScreen);
 extern __GLXclientState *glxGetClient(ClientPtr pClient);
 
diff --git a/glx/swap_interval.c b/glx/swap_interval.c
index 3a52420..0bae324 100644
--- a/glx/swap_interval.c
+++ b/glx/swap_interval.c
@@ -53,8 +53,6 @@ int DoSwapInterval(__GLXclientState *cl, GLbyte *pc, int do_swap)
 
     cx = __glXLookupContextByTag(cl, tag);
 
-    LogMessage(X_ERROR, "%s: cx = %p, GLX screen = %p\n", __func__,
-	       cx, (cx == NULL) ? NULL : cx->pGlxScreen);
     if ((cx == NULL) || (cx->pGlxScreen == NULL)) {
 	client->errorValue = tag;
 	return __glXError(GLXBadContext);
@@ -68,7 +66,7 @@ int DoSwapInterval(__GLXclientState *cl, GLbyte *pc, int do_swap)
 
     if (cx->drawPriv == NULL) {
 	client->errorValue = tag;
-	return __glXError(GLXBadDrawable);
+	return BadValue;
     }
     
     pc += __GLX_VENDPRIV_HDR_SIZE;
@@ -76,6 +74,9 @@ int DoSwapInterval(__GLXclientState *cl, GLbyte *pc, int do_swap)
       ? bswap_32(*(int *)(pc + 0))
       :          *(int *)(pc + 0);
 
+    if (interval <= 0)
+	return BadValue;
+
     (void) (*cx->pGlxScreen->swapInterval)(cx->drawPriv, interval);
     return Success;
 }
diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
index d15ced1..3db826e 100644
--- a/hw/xfree86/dri2/dri2.c
+++ b/hw/xfree86/dri2/dri2.c
@@ -34,10 +34,12 @@
 #include <xorg-config.h>
 #endif
 
+#include <errno.h>
 #include <xf86drm.h>
 #include "xf86Module.h"
 #include "scrnintstr.h"
 #include "windowstr.h"
+#include "dixstruct.h"
 #include "dri2.h"
 #include "xf86VGAarbiter.h"
 
@@ -56,9 +58,17 @@ typedef struct _DRI2Drawable {
     int			 height;
     DRI2BufferPtr	*buffers;
     int			 bufferCount;
-    unsigned int	 pendingSequence;
+    unsigned int	 swapsPending;
+    ClientPtr		 blockedClient;
+    int			 swap_interval;
+    CARD64		 swap_count;
+    CARD64		 target_sbc; /* -1 means no SBC wait outstanding */
+    CARD64		 last_swap_target; /* most recently queued swap target */
+    int			 swap_limit; /* for N-buffering */
 } DRI2DrawableRec, *DRI2DrawablePtr;
 
+typedef struct _DRI2Screen *DRI2ScreenPtr;
+
 typedef struct _DRI2Screen {
     const char			*driverName;
     const char			*deviceName;
@@ -68,9 +78,12 @@ typedef struct _DRI2Screen {
     DRI2CreateBufferProcPtr	 CreateBuffer;
     DRI2DestroyBufferProcPtr	 DestroyBuffer;
     DRI2CopyRegionProcPtr	 CopyRegion;
+    DRI2ScheduleSwapProcPtr	 ScheduleSwap;
+    DRI2GetMSCProcPtr		 GetMSC;
+    DRI2ScheduleWaitMSCProcPtr	 ScheduleWaitMSC;
 
     HandleExposuresProcPtr       HandleExposures;
-} DRI2ScreenRec, *DRI2ScreenPtr;
+} DRI2ScreenRec;
 
 static DRI2ScreenPtr
 DRI2GetScreen(ScreenPtr pScreen)
@@ -84,6 +97,9 @@ DRI2GetDrawable(DrawablePtr pDraw)
     WindowPtr		  pWin;
     PixmapPtr		  pPixmap;
 
+    if (!pDraw)
+	return NULL;
+
     if (pDraw->type == DRAWABLE_WINDOW)
     {
 	pWin = (WindowPtr) pDraw;
@@ -119,6 +135,13 @@ DRI2CreateDrawable(DrawablePtr pDraw)
     pPriv->height = pDraw->height;
     pPriv->buffers = NULL;
     pPriv->bufferCount = 0;
+    pPriv->swapsPending = 0;
+    pPriv->blockedClient = NULL;
+    pPriv->swap_count = 0;
+    pPriv->target_sbc = -1;
+    pPriv->swap_interval = 1;
+    pPriv->last_swap_target = -1;
+    pPriv->swap_limit = 1; /* default to double buffering */
 
     if (pDraw->type == DRAWABLE_WINDOW)
     {
@@ -308,6 +331,50 @@ DRI2GetBuffersWithFormat(DrawablePtr pDraw, int *width, int *height,
 			  out_count, TRUE);
 }
 
+/*
+ * In the direct rendered case, we throttle the clients that have more
+ * than their share of outstanding swaps (and thus busy buffers) when a
+ * new GetBuffers request is received.  In the AIGLX case, we allow the
+ * client to get the new buffers, but throttle when the next GLX request
+ * comes in (see __glXDRIcontextWait()).
+ */
+Bool
+DRI2ThrottleClient(ClientPtr client, DrawablePtr pDraw)
+{
+    DRI2DrawablePtr pPriv;
+
+    pPriv = DRI2GetDrawable(pDraw);
+    if (pPriv == NULL)
+	return FALSE;
+
+    /* Throttle to swap limit */
+    if ((pPriv->swapsPending >= pPriv->swap_limit) &&
+	!pPriv->blockedClient) {
+	ResetCurrentRequest(client);
+	client->sequence--;
+	IgnoreClient(client);
+	pPriv->blockedClient = client;
+	return TRUE;
+    }
+
+    return FALSE;
+}
+
+void
+DRI2BlockClient(ClientPtr client, DrawablePtr pDraw)
+{
+    DRI2DrawablePtr pPriv;
+
+    pPriv = DRI2GetDrawable(pDraw);
+    if (pPriv == NULL)
+	return;
+
+    if (pPriv->blockedClient == NULL) {
+	IgnoreClient(client);
+	pPriv->blockedClient = client;
+    }
+}
+
 int
 DRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion,
 	       unsigned int dest, unsigned int src)
@@ -338,6 +405,324 @@ DRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion,
     return Success;
 }
 
+/* Can this drawable be page flipped? */
+Bool
+DRI2CanFlip(DrawablePtr pDraw)
+{
+    ScreenPtr pScreen = pDraw->pScreen;
+    WindowPtr pWin, pRoot;
+    PixmapPtr pWinPixmap, pRootPixmap;
+
+    if (pDraw->type == DRAWABLE_PIXMAP)
+	return TRUE;
+
+    pRoot = WindowTable[pScreen->myNum];
+    pRootPixmap = pScreen->GetWindowPixmap(pRoot);
+
+    pWin = (WindowPtr) pDraw;
+    pWinPixmap = pScreen->GetWindowPixmap(pWin);
+    if (pRootPixmap != pWinPixmap)
+	return FALSE;
+    if (!REGION_EQUAL(pScreen, &pWin->clipList, &pRoot->winSize))
+	return FALSE;
+
+    return TRUE;
+}
+
+/* Can we do a pixmap exchange instead of a blit? */
+Bool
+DRI2CanExchange(DrawablePtr pDraw)
+{
+    return FALSE;
+}
+
+void
+DRI2WaitMSCComplete(ClientPtr client, DrawablePtr pDraw, int frame,
+		    unsigned int tv_sec, unsigned int tv_usec)
+{
+    DRI2DrawablePtr pPriv;
+
+    pPriv = DRI2GetDrawable(pDraw);
+    if (pPriv == NULL)
+	return;
+
+    ProcDRI2WaitMSCReply(client, ((CARD64)tv_sec * 1000000) + tv_usec,
+			 frame, pPriv->swap_count);
+
+    if (pPriv->blockedClient)
+	AttendClient(pPriv->blockedClient);
+
+    pPriv->blockedClient = NULL;
+}
+
+static void
+DRI2WakeClient(ClientPtr client, DrawablePtr pDraw, int frame,
+	       unsigned int tv_sec, unsigned int tv_usec)
+{
+    ScreenPtr	    pScreen = pDraw->pScreen;
+    DRI2DrawablePtr pPriv;
+
+    pPriv = DRI2GetDrawable(pDraw);
+    if (pPriv == NULL) {
+        xf86DrvMsg(pScreen->myNum, X_ERROR,
+		   "[DRI2] %s: bad drawable\n", __func__);
+	return;
+    }
+
+    /*
+     * Swap completed.  Either wake up an SBC waiter or a client that was
+     * blocked due to GLX activity during a swap.
+     */
+    if (pPriv->target_sbc != -1 &&
+	pPriv->target_sbc >= pPriv->swap_count) {
+	ProcDRI2WaitMSCReply(client, ((CARD64)tv_sec * 1000000) + tv_usec,
+			     frame, pPriv->swap_count);
+	pPriv->target_sbc = -1;
+
+	AttendClient(pPriv->blockedClient);
+	pPriv->blockedClient = NULL;
+    } else if (pPriv->target_sbc == -1) {
+	if (pPriv->blockedClient)
+	    AttendClient(pPriv->blockedClient);
+	pPriv->blockedClient = NULL;
+    }
+}
+
+void
+DRI2SwapComplete(ClientPtr client, DrawablePtr pDraw, int frame,
+		   unsigned int tv_sec, unsigned int tv_usec, int type,
+		   DRI2SwapEventPtr swap_complete, void *swap_data)
+{
+    ScreenPtr	    pScreen = pDraw->pScreen;
+    DRI2DrawablePtr pPriv;
+    CARD64          ust = 0;
+
+    pPriv = DRI2GetDrawable(pDraw);
+    if (pPriv == NULL) {
+        xf86DrvMsg(pScreen->myNum, X_ERROR,
+		   "[DRI2] %s: bad drawable\n", __func__);
+	return;
+    }
+
+    if (pPriv->refCount == 0) {
+        xf86DrvMsg(pScreen->myNum, X_ERROR,
+		   "[DRI2] %s: bad drawable refcount\n", __func__);
+	xfree(pPriv);
+	return;
+    }
+
+    ust = ((CARD64)tv_sec * 1000000) + tv_usec;
+    if (swap_complete)
+	swap_complete(client, swap_data, type, ust, frame, pPriv->swap_count);
+
+    pPriv->swapsPending--;
+    pPriv->swap_count++;
+
+    DRI2WakeClient(client, pDraw, frame, tv_sec, tv_usec);
+}
+
+Bool
+DRI2WaitSwap(ClientPtr client, DrawablePtr pDrawable)
+{
+    DRI2DrawablePtr pPriv = DRI2GetDrawable(pDrawable);
+
+    /* If we're currently waiting for a swap on this drawable, reset
+     * the request and suspend the client.  We only support one
+     * blocked client per drawable. */
+    if ((pPriv->swapsPending) &&
+	pPriv->blockedClient == NULL) {
+	ResetCurrentRequest(client);
+	client->sequence--;
+	DRI2BlockClient(client, pDrawable);
+	return TRUE;
+    }
+
+    return FALSE;
+}
+
+int
+DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
+		CARD64 divisor, CARD64 remainder, CARD64 *swap_target,
+		DRI2SwapEventPtr func, void *data)
+{
+    ScreenPtr       pScreen = pDraw->pScreen;
+    DRI2ScreenPtr   ds = DRI2GetScreen(pDraw->pScreen);
+    DRI2DrawablePtr pPriv;
+    DRI2BufferPtr   pDestBuffer = NULL, pSrcBuffer = NULL;
+    CARD64          ust;
+    int             ret, i;
+
+    pPriv = DRI2GetDrawable(pDraw);
+    if (pPriv == NULL) {
+        xf86DrvMsg(pScreen->myNum, X_ERROR,
+		   "[DRI2] %s: bad drawable\n", __func__);
+	return BadDrawable;
+    }
+
+    for (i = 0; i < pPriv->bufferCount; i++) {
+	if (pPriv->buffers[i]->attachment == DRI2BufferFrontLeft)
+	    pDestBuffer = (DRI2BufferPtr) pPriv->buffers[i];
+	if (pPriv->buffers[i]->attachment == DRI2BufferBackLeft)
+	    pSrcBuffer = (DRI2BufferPtr) pPriv->buffers[i];
+    }
+    if (pSrcBuffer == NULL || pDestBuffer == NULL) {
+        xf86DrvMsg(pScreen->myNum, X_ERROR,
+		   "[DRI2] %s: drawable has no back or front?\n", __func__);
+	return BadDrawable;
+    }
+
+    /* Old DDX, just blit */
+    if (!ds->ScheduleSwap) {
+	BoxRec box;
+	RegionRec region;
+
+	box.x1 = 0;
+	box.y1 = 0;
+	box.x2 = pDraw->width;
+	box.y2 = pDraw->height;
+	REGION_INIT(pScreen, &region, &box, 0);
+
+	pPriv->swapsPending++;
+
+	(*ds->CopyRegion)(pDraw, &region, pDestBuffer, pSrcBuffer);
+	DRI2SwapComplete(client, pDraw, target_msc, 0, 0, DRI2_BLIT_COMPLETE,
+			 func, data);
+	return Success;
+    }
+
+    /*
+     * In the simple glXSwapBuffers case, all params will be 0, and we just
+     * need to schedule a swap for the last swap target + the swap interval.
+     * If the last swap target hasn't been set yet, call into the driver
+     * to get the current count.
+     */
+    if (target_msc == 0 && divisor == 0 && remainder == 0 &&
+	pPriv->last_swap_target < 0) {
+	ret = (*ds->GetMSC)(pDraw, &ust, &target_msc);
+	if (!ret) {
+	    xf86DrvMsg(pScreen->myNum, X_ERROR,
+		       "[DRI2] %s: driver failed to return current MSC\n",
+		       __func__);
+	    return BadDrawable;
+	}
+    }
+
+    /* First swap needs to initialize last_swap_target */
+    if (pPriv->last_swap_target < 0)
+	pPriv->last_swap_target = target_msc;
+
+    /*
+     * Swap target for this swap is last swap target + swap interval since
+     * we have to account for the current swap count, interval, and the
+     * number of pending swaps.
+     */
+    *swap_target = pPriv->last_swap_target + pPriv->swap_interval;
+
+    ret = (*ds->ScheduleSwap)(client, pDraw, pDestBuffer, pSrcBuffer,
+			      swap_target, divisor, remainder, func, data);
+    if (!ret) {
+        xf86DrvMsg(pScreen->myNum, X_ERROR,
+		   "[DRI2] %s: driver failed to schedule swap\n", __func__);
+	return BadDrawable;
+    }
+
+    pPriv->swapsPending++;
+    pPriv->last_swap_target = *swap_target;
+
+    return Success;
+}
+
+void
+DRI2SwapInterval(DrawablePtr pDrawable, int interval)
+{
+    DRI2DrawablePtr pPriv = DRI2GetDrawable(pDrawable);
+
+    /* fixme: check against arbitrary max? */
+
+    pPriv->swap_interval = interval;
+}
+
+int
+DRI2GetMSC(DrawablePtr pDraw, CARD64 *ust, CARD64 *msc, CARD64 *sbc)
+{
+    ScreenPtr pScreen = pDraw->pScreen;
+    DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
+    DRI2DrawablePtr pPriv;
+    Bool ret;
+
+    pPriv = DRI2GetDrawable(pDraw);
+    if (pPriv == NULL) {
+        xf86DrvMsg(pScreen->myNum, X_ERROR,
+		   "[DRI2] %s: bad drawable\n", __func__);
+	return BadDrawable;
+    }
+
+    if (!ds->GetMSC) {
+	*ust = 0;
+	*msc = 0;
+	*sbc = pPriv->swap_count;
+	return Success;
+    }
+
+    /*
+     * Spec needs to be updated to include unmapped or redirected
+     * drawables
+     */
+
+    ret = (*ds->GetMSC)(pDraw, ust, msc);
+    if (!ret)
+	return BadDrawable;
+
+    *sbc = pPriv->swap_count;
+
+    return Success;
+}
+
+int
+DRI2WaitMSC(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
+	    CARD64 divisor, CARD64 remainder)
+{
+    DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
+    DRI2DrawablePtr pPriv;
+    Bool ret;
+
+    pPriv = DRI2GetDrawable(pDraw);
+    if (pPriv == NULL)
+	return BadDrawable;
+
+    /* Old DDX just completes immediately */
+    if (!ds->ScheduleWaitMSC) {
+	DRI2WaitMSCComplete(client, pDraw, target_msc, 0, 0);
+
+	return Success;
+    }
+
+    ret = (*ds->ScheduleWaitMSC)(client, pDraw, target_msc, divisor, remainder);
+    if (!ret)
+	return BadDrawable;
+
+    return Success;
+}
+
+int
+DRI2WaitSBC(ClientPtr client, DrawablePtr pDraw, CARD64 target_sbc,
+	    CARD64 *ust, CARD64 *msc, CARD64 *sbc)
+{
+    DRI2DrawablePtr pPriv;
+
+    pPriv = DRI2GetDrawable(pDraw);
+    if (pPriv == NULL)
+	return BadDrawable;
+
+    if (pPriv->swap_count >= target_sbc)
+	return Success;
+
+    pPriv->target_sbc = target_sbc;
+    DRI2BlockClient(client, pDraw);
+
+    return Success;
+}
+
 void
 DRI2DestroyDrawable(DrawablePtr pDraw)
 {
@@ -363,7 +748,11 @@ DRI2DestroyDrawable(DrawablePtr pDraw)
 	xfree(pPriv->buffers);
     }
 
-    xfree(pPriv);
+    /* If the window is destroyed while we have a swap pending, don't
+     * actually free the priv yet.  We'll need it in the DRI2SwapComplete()
+     * callback and we'll free it there once we're done. */
+    if (!pPriv->swapsPending)
+	xfree(pPriv);
 
     if (pDraw->type == DRAWABLE_WINDOW)
     {
@@ -421,7 +810,7 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
         return FALSE;
     }
 
-    ds = xalloc(sizeof *ds);
+    ds = xcalloc(1, sizeof *ds);
     if (!ds)
 	return FALSE;
 
@@ -433,6 +822,12 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
     ds->DestroyBuffer  = info->DestroyBuffer;
     ds->CopyRegion     = info->CopyRegion;
 
+    if (info->version >= 4) {
+	ds->ScheduleSwap = info->ScheduleSwap;
+	ds->ScheduleWaitMSC = info->ScheduleWaitMSC;
+	ds->GetMSC = info->GetMSC;
+    }
+
     dixSetPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey, ds);
 
     xf86DrvMsg(pScreen->myNum, X_INFO, "[DRI2] Setup complete\n");
diff --git a/hw/xfree86/dri2/dri2.h b/hw/xfree86/dri2/dri2.h
index 175471a..be14b9d 100644
--- a/hw/xfree86/dri2/dri2.h
+++ b/hw/xfree86/dri2/dri2.h
@@ -47,6 +47,9 @@ typedef struct {
 } DRI2BufferRec, *DRI2BufferPtr;
 
 typedef DRI2BufferRec DRI2Buffer2Rec, *DRI2Buffer2Ptr;
+typedef void (*DRI2SwapEventPtr)(ClientPtr client, void *data, int type,
+				 CARD64 ust, CARD64 msc, CARD64 sbc);
+
 
 typedef DRI2BufferPtr	(*DRI2CreateBuffersProcPtr)(DrawablePtr pDraw,
 						    unsigned int *attachments,
@@ -58,20 +61,98 @@ typedef void		(*DRI2CopyRegionProcPtr)(DrawablePtr pDraw,
 						 RegionPtr pRegion,
 						 DRI2BufferPtr pDestBuffer,
 						 DRI2BufferPtr pSrcBuffer);
-
 typedef void		(*DRI2WaitProcPtr)(WindowPtr pWin,
 					   unsigned int sequence);
-
+/**
+ * Schedule a buffer swap
+ *
+ * This callback is used to support glXSwapBuffers and the OML_sync_control
+ * extension (see it for a description of the params).
+ *
+ * Drivers should queue an event for the frame count that satisfies the
+ * parameters passed in.  If the event is in the future (i.e. the conditions
+ * aren't currently satisfied), the server may block the client at the next
+ * GLX request using DRI2WaitSwap. When the event arrives, drivers should call
+ * \c DRI2SwapComplete, which will handle waking the client and returning
+ * the appropriate data.
+ *
+ * The DDX is responsible for doing a flip, exchange, or blit of the swap
+ * when the corresponding event arrives.  The \c DRI2CanFlip and
+ * \c DRI2CanExchange functions can be used as helpers for this purpose.
+ *
+ * \param client client pointer (used for block/unblock)
+ * \param pDraw drawable whose count we want
+ * \param pDestBuffer current front buffer
+ * \param pSrcBuffer current back buffer
+ * \param target_msc frame count to wait for
+ * \param divisor divisor for condition equation
+ * \param remainder remainder for division equation
+ * \param func function to call when the swap completes
+ * \param data data for the callback \p func.
+ */
+typedef int		(*DRI2ScheduleSwapProcPtr)(ClientPtr client,
+						   DrawablePtr pDraw,
+						   DRI2BufferPtr pDestBuffer,
+						   DRI2BufferPtr pSrcBuffer,
+						   CARD64 *target_msc,
+						   CARD64 divisor,
+						   CARD64 remainder,
+						   DRI2SwapEventPtr func,
+						   void *data);
 typedef DRI2BufferPtr	(*DRI2CreateBufferProcPtr)(DrawablePtr pDraw,
 						   unsigned int attachment,
 						   unsigned int format);
 typedef void		(*DRI2DestroyBufferProcPtr)(DrawablePtr pDraw,
 						    DRI2BufferPtr buffer);
-
+/**
+ * Get current media stamp counter values
+ *
+ * This callback is used to support the SGI_video_sync and OML_sync_control
+ * extensions.
+ *
+ * Drivers should return the current frame counter and the timestamp from
+ * when the returned frame count was last incremented.
+ *
+ * The count should correspond to the screen where the drawable is currently
+ * visible.  If the drawable isn't visible (e.g. redirected), the server
+ * should return BadDrawable to the client, pending GLX spec updates to
+ * define this behavior.
+ *
+ * \param pDraw drawable whose count we want
+ * \param ust timestamp from when the count was last incremented.
+ * \param mst current frame count
+ */
+typedef int		(*DRI2GetMSCProcPtr)(DrawablePtr pDraw, CARD64 *ust,
+					     CARD64 *msc);
+/**
+ * Schedule a frame count related wait
+ *
+ * This callback is used to support the SGI_video_sync and OML_sync_control
+ * extensions.  See those specifications for details on how to handle
+ * the divisor and remainder parameters.
+ *
+ * Drivers should queue an event for the frame count that satisfies the
+ * parameters passed in.  If the event is in the future (i.e. the conditions
+ * aren't currently satisfied), the driver should block the client using
+ * \c DRI2BlockClient.  When the event arrives, drivers should call
+ * \c DRI2WaitMSCComplete, which will handle waking the client and returning
+ * the appropriate data.
+ *
+ * \param client client pointer (used for block/unblock)
+ * \param pDraw drawable whose count we want
+ * \param target_msc frame count to wait for
+ * \param divisor divisor for condition equation
+ * \param remainder remainder for division equation
+ */
+typedef int		(*DRI2ScheduleWaitMSCProcPtr)(ClientPtr client,
+						      DrawablePtr pDraw,
+						      CARD64 target_msc,
+						      CARD64 divisor,
+						      CARD64 remainder);
 /**
  * Version of the DRI2InfoRec structure defined in this header
  */
-#define DRI2INFOREC_VERSION 3
+#define DRI2INFOREC_VERSION 4
 
 typedef struct {
     unsigned int version;	/**< Version of this struct */
@@ -83,7 +164,9 @@ typedef struct {
     DRI2DestroyBufferProcPtr	DestroyBuffer;
     DRI2CopyRegionProcPtr	CopyRegion;
     DRI2WaitProcPtr		Wait;
-
+    DRI2ScheduleSwapProcPtr	ScheduleSwap;
+    DRI2GetMSCProcPtr		GetMSC;
+    DRI2ScheduleWaitMSCProcPtr	ScheduleWaitMSC;
 }  DRI2InfoRec, *DRI2InfoPtr;
 
 extern _X_EXPORT Bool DRI2ScreenInit(ScreenPtr	pScreen,
@@ -137,4 +220,38 @@ extern _X_EXPORT DRI2BufferPtr *DRI2GetBuffersWithFormat(DrawablePtr pDraw,
 	int *width, int *height, unsigned int *attachments, int count,
 	int *out_count);
 
+extern _X_EXPORT void DRI2SwapInterval(DrawablePtr pDrawable, int interval);
+extern _X_EXPORT int DRI2SwapBuffers(ClientPtr client, DrawablePtr pDrawable,
+				     CARD64 target_msc, CARD64 divisor,
+				     CARD64 remainder, CARD64 *swap_target,
+				     DRI2SwapEventPtr func, void *data);
+extern _X_EXPORT Bool DRI2WaitSwap(ClientPtr client, DrawablePtr pDrawable);
+
+extern _X_EXPORT int DRI2GetMSC(DrawablePtr pDrawable, CARD64 *ust,
+				CARD64 *msc, CARD64 *sbc);
+extern _X_EXPORT int DRI2WaitMSC(ClientPtr client, DrawablePtr pDrawable,
+				 CARD64 target_msc, CARD64 divisor,
+				 CARD64 remainder);
+extern _X_EXPORT int ProcDRI2WaitMSCReply(ClientPtr client, CARD64 ust,
+					  CARD64 msc, CARD64 sbc);
+extern _X_EXPORT int DRI2WaitSBC(ClientPtr client, DrawablePtr pDraw,
+				 CARD64 target_sbc, CARD64 *ust, CARD64 *msc,
+				 CARD64 *sbc);
+extern _X_EXPORT Bool DRI2ThrottleClient(ClientPtr client, DrawablePtr pDraw);
+
+extern _X_EXPORT Bool DRI2CanFlip(DrawablePtr pDraw);
+
+extern _X_EXPORT Bool DRI2CanExchange(DrawablePtr pDraw);
+
+extern _X_EXPORT void DRI2BlockClient(ClientPtr client, DrawablePtr pDraw);
+
+extern _X_EXPORT void DRI2SwapComplete(ClientPtr client, DrawablePtr pDraw,
+				       int frame, unsigned int tv_sec,
+				       unsigned int tv_usec, int type,
+				       DRI2SwapEventPtr swap_complete,
+				       void *swap_data);
+extern _X_EXPORT void DRI2WaitMSCComplete(ClientPtr client, DrawablePtr pDraw,
+					  int frame, unsigned int tv_sec,
+					  unsigned int tv_usec);
+
 #endif
diff --git a/hw/xfree86/dri2/dri2ext.c b/hw/xfree86/dri2/dri2ext.c
index 7d6064a..fb8f908 100644
--- a/hw/xfree86/dri2/dri2ext.c
+++ b/hw/xfree86/dri2/dri2ext.c
@@ -259,6 +259,9 @@ ProcDRI2GetBuffers(ClientPtr client)
 		       &pDrawable, &status))
 	return status;
 
+    if (DRI2ThrottleClient(client, pDrawable))
+	return client->noClientException;
+
     attachments = (unsigned int *) &stuff[1];
     buffers = DRI2GetBuffers(pDrawable, &width, &height,
 			     attachments, stuff->count, &count);
@@ -283,6 +286,9 @@ ProcDRI2GetBuffersWithFormat(ClientPtr client)
 		       &pDrawable, &status))
 	return status;
 
+    if (DRI2ThrottleClient(client, pDrawable))
+	return client->noClientException;
+
     attachments = (unsigned int *) &stuff[1];
     buffers = DRI2GetBuffersWithFormat(pDrawable, &width, &height,
 				       attachments, stuff->count, &count);
@@ -329,6 +335,185 @@ ProcDRI2CopyRegion(ClientPtr client)
     return client->noClientException;
 }
 
+static void
+load_swap_reply(xDRI2SwapBuffersReply *rep, CARD64 sbc)
+{
+    rep->swap_hi = sbc >> 32;
+    rep->swap_lo = sbc & 0xffffffff;
+}
+
+static CARD64
+vals_to_card64(CARD32 lo, CARD32 hi)
+{
+    return (CARD64)hi << 32 | lo;
+}
+
+static int
+ProcDRI2SwapBuffers(ClientPtr client)
+{
+    REQUEST(xDRI2SwapBuffersReq);
+    xDRI2SwapBuffersReply rep;
+    DrawablePtr pDrawable;
+    CARD64 target_msc, divisor, remainder, swap_target;
+    int status;
+
+    REQUEST_SIZE_MATCH(xDRI2SwapBuffersReq);
+
+    if (!validDrawable(client, stuff->drawable,
+		       DixReadAccess | DixWriteAccess, &pDrawable, &status))
+	return status;
+
+    target_msc = vals_to_card64(stuff->target_msc_lo, stuff->target_msc_hi);
+    divisor = vals_to_card64(stuff->divisor_lo, stuff->divisor_hi);
+    remainder = vals_to_card64(stuff->remainder_lo, stuff->remainder_hi);
+
+    status = DRI2SwapBuffers(client, pDrawable, target_msc, divisor, remainder,
+			     &swap_target, NULL, pDrawable);
+    if (status != Success)
+	return BadDrawable;
+
+    rep.type = X_Reply;
+    rep.length = 0;
+    rep.sequenceNumber = client->sequence;
+    load_swap_reply(&rep, swap_target);
+
+    WriteToClient(client, sizeof(xDRI2SwapBuffersReply), &rep);
+
+    return client->noClientException;
+}
+
+static void
+load_msc_reply(xDRI2MSCReply *rep, CARD64 ust, CARD64 msc, CARD64 sbc)
+{
+    rep->ust_hi = ust >> 32;
+    rep->ust_lo = ust & 0xffffffff;
+    rep->msc_hi = msc >> 32;
+    rep->msc_lo = msc & 0xffffffff;
+    rep->sbc_hi = sbc >> 32;
+    rep->sbc_lo = sbc & 0xffffffff;
+}
+
+static int
+ProcDRI2GetMSC(ClientPtr client)
+{
+    REQUEST(xDRI2GetMSCReq);
+    xDRI2MSCReply rep;
+    DrawablePtr pDrawable;
+    CARD64 ust, msc, sbc;
+    int status;
+
+    REQUEST_SIZE_MATCH(xDRI2GetMSCReq);
+
+    if (!validDrawable(client, stuff->drawable, DixReadAccess, &pDrawable,
+		       &status))
+	return status;
+
+    status = DRI2GetMSC(pDrawable, &ust, &msc, &sbc);
+    if (status != Success)
+	return status;
+
+    rep.type = X_Reply;
+    rep.length = 0;
+    rep.sequenceNumber = client->sequence;
+    load_msc_reply(&rep, ust, msc, sbc);
+
+    WriteToClient(client, sizeof(xDRI2MSCReply), &rep);
+
+    return client->noClientException;
+}
+
+static int
+ProcDRI2WaitMSC(ClientPtr client)
+{
+    REQUEST(xDRI2WaitMSCReq);
+    DrawablePtr pDrawable;
+    CARD64 target, divisor, remainder;
+    int status;
+
+    /* FIXME: in restart case, client may be gone at this point */
+
+    REQUEST_SIZE_MATCH(xDRI2WaitMSCReq);
+
+    if (!validDrawable(client, stuff->drawable, DixReadAccess, &pDrawable,
+		       &status))
+	return status;
+
+    target = vals_to_card64(stuff->target_msc_lo, stuff->target_msc_hi);
+    divisor = vals_to_card64(stuff->divisor_lo, stuff->divisor_hi);
+    remainder = vals_to_card64(stuff->remainder_lo, stuff->remainder_hi);
+
+    status = DRI2WaitMSC(client, pDrawable, target, divisor, remainder);
+    if (status != Success)
+	return status;
+
+    return client->noClientException;
+}
+
+int
+ProcDRI2WaitMSCReply(ClientPtr client, CARD64 ust, CARD64 msc, CARD64 sbc)
+{
+    xDRI2MSCReply rep;
+
+    rep.type = X_Reply;
+    rep.length = 0;
+    rep.sequenceNumber = client->sequence;
+    load_msc_reply(&rep, ust, msc, sbc);
+
+    WriteToClient(client, sizeof(xDRI2MSCReply), &rep);
+
+    return client->noClientException;
+}
+
+static int
+ProcDRI2SwapInterval(ClientPtr client)
+{
+    REQUEST(xDRI2SwapIntervalReq);
+    DrawablePtr pDrawable;
+    int status;
+
+    /* FIXME: in restart case, client may be gone at this point */
+
+    REQUEST_SIZE_MATCH(xDRI2SwapIntervalReq);
+
+    if (!validDrawable(client, stuff->drawable, DixReadAccess | DixWriteAccess,
+		       &pDrawable, &status))
+	return status;
+
+    DRI2SwapInterval(pDrawable, stuff->interval);
+
+    return client->noClientException;
+}
+
+static int
+ProcDRI2WaitSBC(ClientPtr client)
+{
+    REQUEST(xDRI2WaitSBCReq);
+    xDRI2MSCReply rep;
+    DrawablePtr pDrawable;
+    CARD64 target, ust, msc, sbc;
+    int status;
+
+    REQUEST_SIZE_MATCH(xDRI2WaitSBCReq);
+
+    if (!validDrawable(client, stuff->drawable, DixReadAccess, &pDrawable,
+		       &status))
+	return status;
+
+    target = vals_to_card64(stuff->target_sbc_lo, stuff->target_sbc_hi);
+    status = DRI2WaitSBC(client, pDrawable, target, &ust, &msc, &sbc);
+    if (status != Success)
+	return status;
+
+    rep.type = X_Reply;
+    rep.length = 0;
+    rep.sequenceNumber = client->sequence;
+    load_msc_reply(&rep, ust, msc, sbc);
+
+    WriteToClient(client, sizeof(xDRI2MSCReply), &rep);
+
+    return client->noClientException;
+}
+
 static int
 ProcDRI2Dispatch (ClientPtr client)
 {
@@ -357,6 +542,16 @@ ProcDRI2Dispatch (ClientPtr client)
 	return ProcDRI2CopyRegion(client);
     case X_DRI2GetBuffersWithFormat:
 	return ProcDRI2GetBuffersWithFormat(client);
+    case X_DRI2SwapBuffers:
+	return ProcDRI2SwapBuffers(client);
+    case X_DRI2GetMSC:
+	return ProcDRI2GetMSC(client);
+    case X_DRI2WaitMSC:
+	return ProcDRI2WaitMSC(client);
+    case X_DRI2WaitSBC:
+	return ProcDRI2WaitSBC(client);
+    case X_DRI2SwapInterval:
+	return ProcDRI2SwapInterval(client);
     default:
 	return BadRequest;
     }
diff --git a/include/protocol-versions.h b/include/protocol-versions.h
index d688c66..c74b7fa 100644
--- a/include/protocol-versions.h
+++ b/include/protocol-versions.h
@@ -53,7 +53,7 @@
 
 /* DRI2 */
 #define SERVER_DRI2_MAJOR_VERSION		1
-#define SERVER_DRI2_MINOR_VERSION		1
+#define SERVER_DRI2_MINOR_VERSION		2
 
 /* Generic event extension */
 #define SERVER_GE_MAJOR_VERSION                 1


More information about the Xquartz-changes mailing list