xserver: Branch 'master' - 11 commits

Jeremy Huddleston Sequoia jeremyhu at apple.com
Sat Nov 2 18:09:00 CET 2013


Why does this now require mesa 9.2.0?  >= 9.0 doesn't build on OS X, and I haven't had time to address the issue in mesa.  I'm wondering if I can just revert this and keep the old requirement for now since this change seems to be related just to dri3 (which doesn't affect XQuartz anyways).

-LIBGL="gl >= 7.1.0"
+LIBGL="gl >= 9.2.0"

commit ccc8bb1153ec669f7540a174a81a8ec0e0d6dd67
Author: Daniel Czarnowski <daniel.czarnowski at intel.com>
Date:   Wed Oct 23 12:53:59 2013 +0200

    glx: Handle float config types in glxConvertConfigs
    
    Replaces old use of floatMode attribute with new, extended range of
    values in __DRI_ATTRIB_RENDER_TYPE. Also adds new conditions, where the
    float modes support requires it. Enables support for not only float
    configs, but packed float configs as well.
    
    v2 (idr): Whitespace and formatting fixes.  Refactor render type
    vs. pbuffer checking to a separate function that includes a quote from
    the spec.  Re-write commit message.  Fix compiler warnings:
    
    glxdricommon.c: In function 'glxConvertConfigs':
    glxdricommon.c:212:35: warning: pointer targets in passing argument 3 of 'core->getConfigAttrib' differ in signedness [-Wpointer-sign]
    glxdricommon.c:212:35: note: expected 'unsigned int *' but argument is of type 'int *'
    glxdricommon.c:230:35: warning: pointer targets in passing argument 3 of 'core->getConfigAttrib' differ in signedness [-Wpointer-sign]
    glxdricommon.c:230:35: note: expected 'unsigned int *' but argument is of type 'int *'
    
    Signed-off-by: Daniel Czarnowski <daniel.czarnowski at intel.com>
    Signed-off-by: Ian Romanick <ian.d.romanick at intel.com>
    Reviewed-by: Ian Romanick <ian.d.romanick at intel.com>


On Oct 31, 2013, at 17:09, Keith Packard <keithp at kemper.freedesktop.org> wrote:

> Makefile.am               |   10 
> Xext/shm.c                |  168 +++++++++
> Xext/shmint.h             |   10 
> Xext/sync.c               |   32 +
> Xext/syncsrv.h            |   13 
> Xext/xvdisp.c             |   13 
> configure.ac              |   46 ++
> dix/region.c              |   15 
> dri3/Makefile.am          |   13 
> dri3/dri3.c               |   87 +++++
> dri3/dri3.h               |   59 +++
> dri3/dri3_event.c         |  163 +++++++++
> dri3/dri3_priv.h          |   80 ++++
> dri3/dri3_request.c       |  394 +++++++++++++++++++++++
> dri3/dri3_screen.c        |   80 ++++
> dri3/dri3int.h            |   26 +
> hw/dmx/dmxextension.c     |    3 
> hw/dmx/dmxinit.c          |    2 
> hw/xfree86/Makefile.am    |    4 
> hw/xfree86/sdksyms.sh     |    1 
> include/dix-config.h.in   |    6 
> include/dixstruct.h       |    8 
> include/extinit.h         |   10 
> include/misc.h            |   29 +
> include/os.h              |    5 
> include/regionstr.h       |    2 
> include/xorg-server.h.in  |    6 
> mi/miinitext.c            |    4 
> miext/sync/Makefile.am    |    3 
> miext/sync/misync.c       |   31 -
> miext/sync/misync.h       |   21 +
> miext/sync/misyncshm.c    |  176 ++++++++++
> miext/sync/misyncshm.h    |   28 +
> miext/sync/misyncstr.h    |   15 
> os/connection.c           |    2 
> os/io.c                   |   29 +
> os/utils.c                |   27 +
> os/xstrans.c              |    2 
> present/Makefile.am       |   17 +
> present/present.c         |  775 ++++++++++++++++++++++++++++++++++++++++++++++
> present/present.h         |  118 +++++++
> present/present_event.c   |  239 ++++++++++++++
> present/present_fake.c    |  140 ++++++++
> present/present_fence.c   |  112 ++++++
> present/present_notify.c  |  114 ++++++
> present/present_priv.h    |  288 +++++++++++++++++
> present/present_request.c |  330 +++++++++++++++++++
> present/present_screen.c  |  231 +++++++++++++
> present/presentext.h      |   29 +
> test/Makefile.am          |   11 
> 50 files changed, 3968 insertions(+), 59 deletions(-)
> 
> New commits:
> commit e4636072949a76477fe7c9d54662a0b3536b1372
> Merge: 17ed7ac 5c5c1b7
> Author: Keith Packard <keithp at keithp.com>
> Date:   Thu Oct 31 17:05:48 2013 -0700
> 
>    Merge remote-tracking branch 'keithp/dri3'
> 
> commit 5c5c1b77982a9af7279a90bc3c2be48adaa9c778
> Author: Keith Packard <keithp at keithp.com>
> Date:   Thu Jul 11 16:11:57 2013 -0700
> 
>    present: Add Present extension
> 
>    Provides both a software implementation using timers and driver hooks
>    to base everything on vblank intervals.
> 
>    Signed-off-by: Keith Packard <keithp at keithp.com>
>    Reviewed-by: Adam Jackson <ajax at redhat.com>
> 
> diff --git a/Makefile.am b/Makefile.am
> index 7a8fc5b..28266c5 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -21,6 +21,10 @@ if DRI3
> DRI3_DIR=dri3
> endif
> 
> +if PRESENT
> +PRESENT_DIR=present
> +endif
> +
> SUBDIRS = \
> 	doc \
> 	man \
> @@ -42,6 +46,7 @@ SUBDIRS = \
> 	damageext \
> 	$(COMPOSITE_DIR) \
> 	$(GLX_DIR) \
> +	$(PRESENT_DIR) \
> 	$(DRI3_DIR) \
> 	exa \
> 	config \
> diff --git a/configure.ac b/configure.ac
> index 546790d..7432912 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -614,6 +614,7 @@ AC_ARG_ENABLE(glx,            AS_HELP_STRING([--disable-glx], [Build GLX extensi
> AC_ARG_ENABLE(dri,            AS_HELP_STRING([--enable-dri], [Build DRI extension (default: auto)]), [DRI=$enableval])
> AC_ARG_ENABLE(dri2,           AS_HELP_STRING([--enable-dri2], [Build DRI2 extension (default: auto)]), [DRI2=$enableval], [DRI2=auto])
> AC_ARG_ENABLE(dri3,           AS_HELP_STRING([--enable-dri3], [Build DRI3 extension (default: auto)]), [DRI3=$enableval], [DRI3=auto])
> +AC_ARG_ENABLE(present,	      AS_HELP_STRING([--disable-present], [Build Present extension (default: enabled)]), [PRESENT=$enableval], [PRESENT=yes])
> AC_ARG_ENABLE(xinerama,	      AS_HELP_STRING([--disable-xinerama], [Build Xinerama extension (default: enabled)]), [XINERAMA=$enableval], [XINERAMA=yes])
> AC_ARG_ENABLE(xf86vidmode,    AS_HELP_STRING([--disable-xf86vidmode], [Build XF86VidMode extension (default: auto)]), [XF86VIDMODE=$enableval], [XF86VIDMODE=auto])
> AC_ARG_ENABLE(xace,           AS_HELP_STRING([--disable-xace], [Build X-ACE extension (default: enabled)]), [XACE=$enableval], [XACE=yes])
> @@ -807,6 +808,7 @@ DAMAGEPROTO="damageproto >= 1.1"
> XCMISCPROTO="xcmiscproto >= 1.2.0"
> BIGREQSPROTO="bigreqsproto >= 1.1.0"
> XTRANS="xtrans >= 1.2.2"
> +PRESENTPROTO="presentproto >= 1.0"
> 
> dnl List of libraries that require a specific version
> LIBAPPLEWM="applewm >= 1.4"
> @@ -1160,6 +1162,14 @@ if test "x$DRI2" = xyes; then
> fi
> AM_CONDITIONAL(DRI2_AIGLX, test "x$DRI2_AIGLX" = xyes)
> 
> +AM_CONDITIONAL(PRESENT, [test "x$PRESENT" = xyes])
> +if test "x$PRESENT" = xyes; then
> +	AC_DEFINE(PRESENT, 1, [Support Present extension])
> +	REQUIRED_MODULES="$REQUIRED_MODULES $PRESENTPROTO"
> +	SDK_REQUIRED_MODULES="$SDK_REQUIRED_MODULES $PRESENTPROTO"
> +	PRESENT_INC='-I$(top_srcdir)/present'
> +	PRESENT_LIB='$(top_builddir)/present/libpresent.la'
> +fi
> 
> AM_CONDITIONAL(XINERAMA, [test "x$XINERAMA" = xyes])
> if test "x$XINERAMA" = xyes; then
> @@ -1584,7 +1594,7 @@ AC_EGREP_CPP([I_AM_SVR4],[
> AC_DEFINE([SVR4],1,[Define to 1 on systems derived from System V Release 4])
> AC_MSG_RESULT([yes])], AC_MSG_RESULT([no]))
> 
> -XSERVER_CFLAGS="$XSERVER_CFLAGS $CORE_INCS $XEXT_INC $COMPOSITE_INC $DAMAGE_INC $FIXES_INC $XI_INC $MI_INC $MIEXT_SYNC_INC $MIEXT_SHADOW_INC $MIEXT_LAYER_INC $MIEXT_DAMAGE_INC $RENDER_INC $RANDR_INC $FB_INC $DBE_INC"
> +XSERVER_CFLAGS="$XSERVER_CFLAGS $CORE_INCS $XEXT_INC $COMPOSITE_INC $DAMAGE_INC $FIXES_INC $XI_INC $MI_INC $MIEXT_SYNC_INC $MIEXT_SHADOW_INC $MIEXT_LAYER_INC $MIEXT_DAMAGE_INC $RENDER_INC $RANDR_INC $FB_INC $DBE_INC $PRESENT_INC"
> 
> dnl ---------------------------------------------------------------------------
> dnl DDX section.
> @@ -1597,7 +1607,7 @@ AC_MSG_RESULT([$XVFB])
> AM_CONDITIONAL(XVFB, [test "x$XVFB" = xyes])
> 
> if test "x$XVFB" = xyes; then
> -	XVFB_LIBS="$FB_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB"
> +	XVFB_LIBS="$FB_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB"
> 	XVFB_SYS_LIBS="$XVFBMODULES_LIBS $GLX_SYS_LIBS"
> 	AC_SUBST([XVFB_LIBS])
> 	AC_SUBST([XVFB_SYS_LIBS])
> @@ -1618,7 +1628,7 @@ if test "x$XNEST" = xyes; then
> 	if test "x$have_xnest" = xno; then
> 		AC_MSG_ERROR([Xnest build explicitly requested, but required modules not found.])
> 	fi
> -	XNEST_LIBS="$FB_LIB $FIXES_LIB $MI_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB  $DRI3_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB $DIX_LIB $OS_LIB"
> +	XNEST_LIBS="$FB_LIB $FIXES_LIB $MI_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB  $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB $DIX_LIB $OS_LIB"
> 	XNEST_SYS_LIBS="$XNESTMODULES_LIBS $GLX_SYS_LIBS"
> 	AC_SUBST([XNEST_LIBS])
> 	AC_SUBST([XNEST_SYS_LIBS])
> @@ -1643,7 +1653,7 @@ if test "x$XORG" = xyes; then
> 	XORG_OSINCS='-I$(top_srcdir)/hw/xfree86/os-support -I$(top_srcdir)/hw/xfree86/os-support/bus -I$(top_srcdir)/os'
> 	XORG_INCS="$XORG_DDXINCS $XORG_OSINCS"
> 	XORG_CFLAGS="$XORGSERVER_CFLAGS -DHAVE_XORG_CONFIG_H"
> -	XORG_LIBS="$COMPOSITE_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $XI_LIB $XKB_LIB"
> +	XORG_LIBS="$COMPOSITE_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $XI_LIB $XKB_LIB"
> 
> 	dnl ==================================================================
> 	dnl symbol visibility
> @@ -2056,7 +2066,7 @@ if test "x$DMX" = xyes; then
> 	fi
> 	DMX_INCLUDES="$XEXT_INC $RENDER_INC $RECORD_INC"
> 	XDMX_CFLAGS="$DMXMODULES_CFLAGS"
> -	XDMX_LIBS="$FB_LIB $MI_LIB $XEXT_LIB $RENDER_LIB $RECORD_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB  $DRI3_LIB $MIEXT_SYNC_LIB $MIEXT_SHADOW_LIB $MIEXT_DAMAGE_LIB $COMPOSITE_LIB $DAMAGE_LIB $MAIN_LIB $DIX_LIB $CONFIG_LIB $OS_LIB $FIXES_LIB"
> +	XDMX_LIBS="$FB_LIB $MI_LIB $XEXT_LIB $RENDER_LIB $RECORD_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB  $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_SHADOW_LIB $MIEXT_DAMAGE_LIB $COMPOSITE_LIB $DAMAGE_LIB $MAIN_LIB $DIX_LIB $CONFIG_LIB $OS_LIB $FIXES_LIB"
> 	XDMX_SYS_LIBS="$DMXMODULES_LIBS"
> 	AC_SUBST([XDMX_CFLAGS])
> 	AC_SUBST([XDMX_LIBS])
> @@ -2165,7 +2175,7 @@ if test "$KDRIVE" = yes; then
> 
>     KDRIVE_CFLAGS="$XSERVER_CFLAGS -DHAVE_KDRIVE_CONFIG_H $TSLIB_CFLAGS"
> 
> -    KDRIVE_PURE_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $OS_LIB"
> +    KDRIVE_PURE_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $OS_LIB"
>     KDRIVE_LIB='$(top_builddir)/hw/kdrive/src/libkdrive.la'
>     case $host_os in
> 	*linux*)
> @@ -2288,6 +2298,7 @@ Xi/Makefile
> xfixes/Makefile
> exa/Makefile
> dri3/Makefile
> +present/Makefile
> hw/Makefile
> hw/xfree86/Makefile
> hw/xfree86/common/Makefile
> diff --git a/hw/dmx/dmxextension.c b/hw/dmx/dmxextension.c
> index d7296ae..c6c6a8e 100644
> --- a/hw/dmx/dmxextension.c
> +++ b/hw/dmx/dmxextension.c
> @@ -68,6 +68,9 @@
>  * _any_ header files. */
> extern FontPtr defaultFont;
> 
> +/* Hack to get Present to build (present requires RandR) */
> +RESTYPE RRCrtcType;
> +
> /** This routine provides information to the DMX protocol extension
>  * about a particular screen. */
> Bool
> diff --git a/include/dix-config.h.in b/include/dix-config.h.in
> index d96da6a..397ee96 100644
> --- a/include/dix-config.h.in
> +++ b/include/dix-config.h.in
> @@ -255,6 +255,9 @@
> /* Internal define for Xinerama */
> #undef PANORAMIX
> 
> +/* Support Present extension */
> +#undef PRESENT
> +
> /* Overall prefix */
> #undef PROJECTROOT
> 
> diff --git a/include/extinit.h b/include/extinit.h
> index bdb149c..fa5f293 100644
> --- a/include/extinit.h
> +++ b/include/extinit.h
> @@ -181,4 +181,9 @@ extern void XvMCExtensionInit(void);
> extern void dri3_extension_init(void);
> #endif
> 
> +#if defined(PRESENT)
> +#include <X11/extensions/presentproto.h>
> +#include "presentext.h"
> +#endif
> +
> #endif
> diff --git a/include/xorg-server.h.in b/include/xorg-server.h.in
> index 5b3b664..1281b3e 100644
> --- a/include/xorg-server.h.in
> +++ b/include/xorg-server.h.in
> @@ -70,6 +70,9 @@
> /* Internal define for Xinerama */
> #undef PANORAMIX
> 
> +/* Support Present extension */
> +#undef PRESENT
> +
> /* Support RANDR extension */
> #undef RANDR
> 
> diff --git a/mi/miinitext.c b/mi/miinitext.c
> index e49948b..6366182 100644
> --- a/mi/miinitext.c
> +++ b/mi/miinitext.c
> @@ -287,7 +287,10 @@ static ExtensionModule staticExtensions[] = {
> #ifdef DPMSExtension
>     {DPMSExtensionInit, DPMSExtensionName, &noDPMSExtension},
> #endif
> +    {present_extension_init, PRESENT_NAME, NULL},
> +#ifdef DRI3
>     {dri3_extension_init, DRI3_NAME, NULL},
> +#endif
> #ifdef RES
>     {ResExtensionInit, XRES_NAME, &noResExtension},
> #endif
> diff --git a/present/Makefile.am b/present/Makefile.am
> new file mode 100644
> index 0000000..7fea669
> --- /dev/null
> +++ b/present/Makefile.am
> @@ -0,0 +1,17 @@
> +noinst_LTLIBRARIES = libpresent.la
> +AM_CFLAGS = \
> +	-DHAVE_XORG_CONFIG_H \
> +	@DIX_CFLAGS@ @XORG_CFLAGS@
> +
> +libpresent_la_SOURCES = \
> +	present.h \
> +	present.c \
> +	present_event.c \
> +	present_fake.c \
> +	present_fence.c \
> +	present_notify.c \
> +	present_priv.h \
> +	present_request.c \
> +	present_screen.c
> +
> +sdk_HEADERS = present.h presentext.h
> diff --git a/present/present.c b/present/present.c
> new file mode 100644
> index 0000000..4c97ce4
> --- /dev/null
> +++ b/present/present.c
> @@ -0,0 +1,775 @@
> +/*
> + * Copyright © 2013 Keith Packard
> + *
> + * 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_XORG_CONFIG_H
> +#include <xorg-config.h>
> +#endif
> +
> +#include "present_priv.h"
> +#include <gcstruct.h>
> +#include <misync.h>
> +#include <misyncstr.h>
> +#ifdef MONOTONIC_CLOCK
> +#include <time.h>
> +#endif
> +
> +static uint64_t         present_event_id;
> +static struct xorg_list present_exec_queue;
> +static struct xorg_list present_flip_queue;
> +
> +#if 0
> +#define DebugPresent(x) ErrorF x
> +#else
> +#define DebugPresent(x)
> +#endif
> +
> +/*
> + * Copies the update region from a pixmap to the target drawable
> + */
> +static void
> +present_copy_region(DrawablePtr drawable,
> +                    PixmapPtr pixmap,
> +                    RegionPtr update,
> +                    int16_t x_off,
> +                    int16_t y_off)
> +{
> +    ScreenPtr   screen = drawable->pScreen;
> +    GCPtr       gc;
> +
> +    gc = GetScratchGC(drawable->depth, screen);
> +    if (update) {
> +        ChangeGCVal     changes[2];
> +
> +        changes[0].val = x_off;
> +        changes[1].val = y_off;
> +        ChangeGC(serverClient, gc,
> +                 GCClipXOrigin|GCClipYOrigin,
> +                 changes);
> +        (*gc->funcs->ChangeClip)(gc, CT_REGION, update, 0);
> +    }
> +    ValidateGC(drawable, gc);
> +    (*gc->ops->CopyArea)(&pixmap->drawable,
> +                         drawable,
> +                         gc,
> +                         0, 0,
> +                         pixmap->drawable.width, pixmap->drawable.height,
> +                         x_off, y_off);
> +    if (update)
> +        (*gc->funcs->ChangeClip)(gc, CT_NONE, NULL, 0);
> +    FreeScratchGC(gc);
> +}
> +
> +static Bool
> +present_check_flip(RRCrtcPtr    crtc,
> +                   WindowPtr    window,
> +                   PixmapPtr    pixmap,
> +                   Bool         sync_flip,
> +                   RegionPtr    valid,
> +                   int16_t      x_off,
> +                   int16_t      y_off)
> +{
> +    ScreenPtr                   screen = window->drawable.pScreen;
> +    WindowPtr                   root = screen->root;
> +    present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
> +
> +    if (!screen_priv)
> +        return FALSE;
> +
> +    if (!screen_priv->info)
> +        return FALSE;
> +
> +    if (!crtc)
> +        return FALSE;
> +
> +    /* Check to see if the driver supports flips at all */
> +    if (!screen_priv->info->flip)
> +        return FALSE;
> +
> +    /* Can't pend a flip while unflipping */
> +    if (screen_priv->unflip_event_id) {
> +        return FALSE;
> +    }
> +
> +    /* Can't have two pending flips at the same time */
> +    if (screen_priv->flip_pending) {
> +        return FALSE;
> +    }
> +
> +    /* Make sure the window hasn't been redirected with Composite */
> +    if (screen->GetWindowPixmap(window) != screen->GetScreenPixmap(screen))
> +        return FALSE;
> +
> +    /* Check for full-screen window */
> +    if (!RegionEqual(&window->clipList, &root->winSize)) {
> +        return FALSE;
> +    }
> +
> +    /* Source pixmap must align with window exactly */
> +    if (x_off || y_off) {
> +        return FALSE;
> +    }
> +
> +    /* Make sure the area marked as valid fills the screen */
> +    if (valid && !RegionEqual(valid, &root->winSize)) {
> +        return FALSE;
> +    }
> +
> +    /* Does the window match the pixmap exactly? */
> +    if (window->drawable.x != 0 || window->drawable.y != 0 ||
> +#ifdef COMPOSITE
> +        window->drawable.x != pixmap->screen_x || window->drawable.y != pixmap->screen_y ||
> +#endif
> +        window->drawable.width != pixmap->drawable.width ||
> +        window->drawable.height != pixmap->drawable.height) {
> +        return FALSE;
> +    }
> +
> +    /* Ask the driver for permission */
> +    if (screen_priv->info->check_flip) {
> +        if (!(*screen_priv->info->check_flip) (crtc, window, pixmap, sync_flip)) {
> +            return FALSE;
> +        }
> +    }
> +
> +    return TRUE;
> +}
> +
> +static Bool
> +present_flip(RRCrtcPtr crtc,
> +             uint64_t event_id,
> +             uint64_t target_msc,
> +             PixmapPtr pixmap,
> +             Bool sync_flip)
> +{
> +    ScreenPtr                   screen = crtc->pScreen;
> +    present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
> +
> +    return (*screen_priv->info->flip) (crtc, event_id, target_msc, pixmap, sync_flip);
> +}
> +
> +static void
> +present_vblank_notify(present_vblank_ptr vblank, CARD8 kind, CARD8 mode, uint64_t ust, uint64_t crtc_msc)
> +{
> +    int         n;
> +
> +    present_send_complete_notify(vblank->window, kind, mode, vblank->serial, ust, crtc_msc - vblank->msc_offset);
> +    for (n = 0; n < vblank->num_notifies; n++) {
> +        WindowPtr   window = vblank->notifies[n].window;
> +        CARD32      serial = vblank->notifies[n].serial;
> +
> +        if (window)
> +            present_send_complete_notify(window, kind, mode, serial, ust, crtc_msc - vblank->msc_offset);
> +    }
> +}
> +
> +static void
> +present_pixmap_idle(PixmapPtr pixmap, WindowPtr window, CARD32 serial, struct present_fence *present_fence)
> +{
> +    present_fence_set_triggered(present_fence);
> +    present_send_idle_notify(window, serial, pixmap, present_fence);
> +}
> +
> +RRCrtcPtr
> +present_get_crtc(WindowPtr window)
> +{
> +    ScreenPtr                   screen = window->drawable.pScreen;
> +    present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
> +
> +    if (!screen_priv)
> +        return NULL;
> +
> +    if (!screen_priv->info)
> +        return NULL;
> +
> +    return (*screen_priv->info->get_crtc)(window);
> +}
> +
> +uint32_t
> +present_query_capabilities(RRCrtcPtr crtc)
> +{
> +    present_screen_priv_ptr     screen_priv;
> +
> +    if (!crtc)
> +        return 0;
> +
> +    screen_priv = present_screen_priv(crtc->pScreen);
> +
> +    if (!screen_priv)
> +        return 0;
> +
> +    if (!screen_priv->info)
> +        return 0;
> +
> +    return screen_priv->info->capabilities;
> +}
> +
> +static int
> +present_get_ust_msc(WindowPtr window, RRCrtcPtr crtc, uint64_t *ust, uint64_t *msc)
> +{
> +    ScreenPtr                   screen = window->drawable.pScreen;
> +    present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
> +
> +    if (crtc == NULL)
> +        return present_fake_get_ust_msc(screen, ust, msc);
> +    else
> +        return (*screen_priv->info->get_ust_msc)(crtc, ust, msc);
> +}
> +
> +static void
> +present_flush(WindowPtr window)
> +{
> +    ScreenPtr                   screen = window->drawable.pScreen;
> +    present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
> +
> +    if (!screen_priv)
> +        return;
> +
> +    if (!screen_priv->info)
> +        return;
> +
> +    (*screen_priv->info->flush) (window);
> +}
> +
> +static int
> +present_queue_vblank(ScreenPtr screen,
> +                     RRCrtcPtr crtc,
> +                     uint64_t event_id,
> +                     uint64_t msc)
> +{
> +    Bool                        ret;
> +
> +    if (crtc == NULL)
> +        ret = present_fake_queue_vblank(screen, event_id, msc);
> +    else
> +    {
> +        present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
> +        ret = (*screen_priv->info->queue_vblank) (crtc, event_id, msc);
> +    }
> +    return ret;
> +}
> +
> +static uint64_t
> +present_window_to_crtc_msc(WindowPtr window, RRCrtcPtr crtc, uint64_t window_msc, uint64_t new_msc)
> +{
> +    present_window_priv_ptr     window_priv = present_get_window_priv(window, TRUE);
> +
> +    if (crtc != window_priv->crtc) {
> +        uint64_t        old_ust, old_msc;
> +
> +        /* The old CRTC may have been turned off, in which case
> +         * we'll just use whatever previous MSC we'd seen from this CRTC
> +         */
> +
> +        if (present_get_ust_msc(window, window_priv->crtc, &old_ust, &old_msc) != Success)
> +            old_msc = window_priv->msc;
> +
> +        window_priv->msc_offset += new_msc - old_msc;
> +        window_priv->crtc = crtc;
> +    }
> +
> +    return window_msc + window_priv->msc_offset;
> +}
> +
> +static void
> +present_flip_idle(ScreenPtr screen)
> +{
> +    present_screen_priv_ptr screen_priv = present_screen_priv(screen);
> +
> +    if (screen_priv->flip_pixmap) {
> +        present_pixmap_idle(screen_priv->flip_pixmap, screen_priv->flip_window,
> +                            screen_priv->flip_serial, screen_priv->flip_idle_fence);
> +        present_fence_destroy(screen_priv->flip_idle_fence);
> +        dixDestroyPixmap(screen_priv->flip_pixmap, screen_priv->flip_pixmap->drawable.id);
> +        screen_priv->flip_crtc = NULL;
> +        screen_priv->flip_window = NULL;
> +        screen_priv->flip_serial = 0;
> +        screen_priv->flip_pixmap = NULL;
> +        screen_priv->flip_idle_fence = NULL;
> +    }
> +}
> +
> +static void
> +present_unflip(ScreenPtr screen)
> +{
> +    present_screen_priv_ptr screen_priv = present_screen_priv(screen);
> +
> +    assert (!screen_priv->unflip_event_id);
> +    assert (!screen_priv->flip_pending);
> +
> +    /* Update the screen pixmap with the current flip pixmap contents
> +     */
> +    if (screen_priv->flip_pixmap) {
> +        present_copy_region(&screen->GetScreenPixmap(screen)->drawable,
> +                            screen_priv->flip_pixmap,
> +                            NULL, 0, 0);
> +    }
> +    screen_priv->unflip_event_id = ++present_event_id;
> +    DebugPresent(("u %lld\n", screen_priv->unflip_event_id));
> +    (*screen_priv->info->unflip) (screen, screen_priv->unflip_event_id);
> +}
> +
> +static void
> +present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc);
> +
> +static void
> +present_flip_notify(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
> +{
> +    WindowPtr                   window = vblank->window;
> +    ScreenPtr                   screen = window->drawable.pScreen;
> +    present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
> +
> +    DebugPresent(("\tn %p %8lld: %08lx -> %08lx\n", vblank, vblank->target_msc,
> +           vblank->pixmap ? vblank->pixmap->drawable.id : 0,
> +                  vblank->window->drawable.id));
> +
> +    assert (vblank == screen_priv->flip_pending);
> +
> +    present_flip_idle(screen);
> +
> +    /* Transfer reference for pixmap and fence from vblank to screen_priv */
> +    screen_priv->flip_crtc = vblank->crtc;
> +    screen_priv->flip_window = vblank->window;
> +    screen_priv->flip_serial = vblank->serial;
> +    screen_priv->flip_pixmap = vblank->pixmap;
> +    screen_priv->flip_idle_fence = vblank->idle_fence;
> +
> +    vblank->pixmap = NULL;
> +    vblank->idle_fence = NULL;
> +
> +    screen_priv->flip_pending = NULL;
> +
> +    if (vblank->abort_flip)
> +        present_unflip(screen);
> +
> +    if (!vblank->window_destroyed)
> +        present_vblank_notify(vblank, PresentCompleteKindPixmap, PresentCompleteModeFlip, ust, crtc_msc);
> +    present_vblank_destroy(vblank);
> +}
> +
> +void
> +present_event_notify(uint64_t event_id, uint64_t ust, uint64_t msc)
> +{
> +    present_vblank_ptr  vblank, tmp;
> +    int                 s;
> +
> +    xorg_list_for_each_entry_safe(vblank, tmp, &present_exec_queue, event_queue) {
> +        if (vblank->event_id == event_id) {
> +            xorg_list_del(&vblank->event_queue);
> +            present_execute(vblank, ust, msc);
> +            return;
> +        }
> +    }
> +    xorg_list_for_each_entry_safe(vblank, tmp, &present_flip_queue, event_queue) {
> +        if (vblank->event_id == event_id) {
> +            xorg_list_del(&vblank->event_queue);
> +            present_flip_notify(vblank, ust, msc);
> +            return;
> +        }
> +    }
> +
> +    for (s = 0; s < screenInfo.numScreens; s++) {
> +        ScreenPtr               screen = screenInfo.screens[s];
> +        present_screen_priv_ptr screen_priv = present_screen_priv(screen);
> +
> +        if (event_id == screen_priv->unflip_event_id) {
> +            DebugPresent(("\tun %lld\n", event_id));
> +            screen_priv->unflip_event_id = 0;
> +            present_flip_idle(screen);
> +        }
> +    }
> +}
> +
> +/*
> + * 'window' is being reconfigured. Check to see if it is involved
> + * in flipping and clean up as necessary
> + */
> +void
> +present_check_flip_window (WindowPtr window)
> +{
> +    ScreenPtr                   screen = window->drawable.pScreen;
> +    present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
> +    present_window_priv_ptr     window_priv = present_window_priv(window);
> +    present_vblank_ptr          flip_pending = screen_priv->flip_pending;
> +    present_vblank_ptr          vblank;
> +
> +    /* If this window hasn't ever been used with Present, it can't be
> +     * flipping
> +     */
> +    if (!window_priv)
> +        return;
> +
> +    if (screen_priv->unflip_event_id)
> +        return;
> +
> +    if (flip_pending) {
> +        /*
> +         * Check pending flip
> +         */
> +        if (flip_pending->window == window) {
> +            if (!present_check_flip(flip_pending->crtc, window, flip_pending->pixmap,
> +                                    flip_pending->sync_flip, NULL, 0, 0))
> +                flip_pending->abort_flip = TRUE;
> +        }
> +    } else {
> +        /*
> +         * Check current flip
> +         */
> +        if (window == screen_priv->flip_window) {
> +            if (!present_check_flip(screen_priv->flip_crtc, window, screen_priv->flip_pixmap, FALSE, NULL, 0, 0))
> +                present_unflip(screen);
> +        }
> +    }
> +
> +    /* Now check any queued vblanks */
> +    xorg_list_for_each_entry(vblank, &window_priv->vblank, window_list) {
> +        if (vblank->flip && !present_check_flip(vblank->crtc, window, vblank->pixmap, FALSE, NULL, 0, 0))
> +            vblank->flip = FALSE;
> +    }
> +}
> +
> +/*
> + * Once the required MSC has been reached, execute the pending request.
> + *
> + * For requests to actually present something, either blt contents to
> + * the screen or queue a frame buffer swap.
> + *
> + * For requests to just get the current MSC/UST combo, skip that part and
> + * go straight to event delivery
> + */
> +
> +static void
> +present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
> +{
> +    WindowPtr                   window = vblank->window;
> +    present_screen_priv_ptr     screen_priv = present_screen_priv(window->drawable.pScreen);
> +
> +    if (vblank->wait_fence) {
> +        /* XXX check fence, queue if not ready */
> +    }
> +
> +    xorg_list_del(&vblank->event_queue);
> +    if (vblank->pixmap) {
> +
> +        if (vblank->flip && screen_priv->flip_pending == NULL && !screen_priv->unflip_event_id) {
> +
> +            DebugPresent(("\tf %p %8lld: %08lx -> %08lx\n", vblank, crtc_msc, vblank->pixmap->drawable.id, vblank->window->drawable.id));
> +            /* Prepare to flip by removing from the window/screen lists
> +             * and sticking it into the flip_pending field
> +             */
> +            screen_priv->flip_pending = vblank;
> +            xorg_list_del(&vblank->window_list);
> +
> +            xorg_list_add(&vblank->event_queue, &present_flip_queue);
> +            /* Try to flip
> +             */
> +            if (present_flip(vblank->crtc, vblank->event_id, vblank->target_msc, vblank->pixmap, vblank->sync_flip))
> +                return;
> +
> +            xorg_list_del(&vblank->event_queue);
> +            /* Oops, flip failed. Clear the flip_pending field
> +              */
> +            screen_priv->flip_pending = NULL;
> +            vblank->flip = FALSE;
> +        }
> +        DebugPresent(("\tc %p %8lld: %08lx -> %08lx\n", vblank, crtc_msc, vblank->pixmap->drawable.id, vblank->window->drawable.id));
> +        if (screen_priv->flip_pending) {
> +
> +            /* Check pending flip
> +             */
> +            if (window == screen_priv->flip_pending->window)
> +                screen_priv->flip_pending->abort_flip = TRUE;
> +        } else if (!screen_priv->unflip_event_id) {
> +
> +            /* Check current flip
> +             */
> +            if (window == screen_priv->flip_window)
> +                present_unflip(window->drawable.pScreen);
> +        }
> +        present_copy_region(&window->drawable, vblank->pixmap, vblank->update, vblank->x_off, vblank->y_off);
> +
> +        /* present_copy_region sticks the region into a scratch GC,
> +         * which is then freed, freeing the region
> +         */
> +        vblank->update = NULL;
> +        present_flush(window);
> +
> +        present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence);
> +    }
> +    present_vblank_notify(vblank, vblank->kind, PresentCompleteModeCopy, ust, crtc_msc);
> +    present_vblank_destroy(vblank);
> +}
> +
> +int
> +present_pixmap(WindowPtr window,
> +               PixmapPtr pixmap,
> +               CARD32 serial,
> +               RegionPtr valid,
> +               RegionPtr update,
> +               int16_t x_off,
> +               int16_t y_off,
> +               RRCrtcPtr target_crtc,
> +               SyncFence *wait_fence,
> +               SyncFence *idle_fence,
> +               uint32_t options,
> +               uint64_t window_msc,
> +               uint64_t divisor,
> +               uint64_t remainder,
> +               present_notify_ptr notifies,
> +               int num_notifies)
> +{
> +    uint64_t                    ust;
> +    uint64_t                    target_msc;
> +    uint64_t                    crtc_msc;
> +    int                         ret;
> +    present_vblank_ptr          vblank;
> +    ScreenPtr                   screen = window->drawable.pScreen;
> +    present_window_priv_ptr     window_priv = present_get_window_priv(window, TRUE);
> +    present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
> +
> +    if (!window_priv)
> +        return BadAlloc;
> +
> +    if (!target_crtc) {
> +        /* Update the CRTC if we have a pixmap or we don't have a CRTC
> +         */
> +        if (!pixmap)
> +            target_crtc = window_priv->crtc;
> +
> +        if (!target_crtc)
> +            target_crtc = present_get_crtc(window);
> +    }
> +
> +    present_get_ust_msc(window, target_crtc, &ust, &crtc_msc);
> +
> +    target_msc = present_window_to_crtc_msc(window, target_crtc, window_msc, crtc_msc);
> +
> +    /* Stash the current MSC away in case we need it later
> +     */
> +    window_priv->msc = crtc_msc;
> +
> +    /* Adjust target_msc to match modulus
> +     */
> +    if (crtc_msc >= target_msc) {
> +        if (divisor != 0) {
> +            target_msc = crtc_msc - (crtc_msc % divisor) + remainder;
> +            if (target_msc <= crtc_msc)
> +                target_msc += divisor;
> +        } else
> +            target_msc = crtc_msc;
> +    }
> +
> +    /*
> +     * Look for a matching presentation already on the list and
> +     * don't bother doing the previous one if this one will overwrite it
> +     * in the same frame
> +     */
> +
> +    if (!update) {
> +        xorg_list_for_each_entry(vblank, &window_priv->vblank, window_list) {
> +
> +            if (!vblank->pixmap)
> +                continue;
> +
> +            if (vblank->crtc != target_crtc || vblank->target_msc != target_msc)
> +                continue;
> +
> +            present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence);
> +            present_fence_destroy(vblank->idle_fence);
> +            dixDestroyPixmap(vblank->pixmap, vblank->pixmap->drawable.id);
> +
> +            vblank->pixmap = NULL;
> +            vblank->idle_fence = NULL;
> +        }
> +    }
> +
> +    vblank = calloc (1, sizeof (present_vblank_rec));
> +    if (!vblank)
> +        return BadAlloc;
> +
> +    xorg_list_append(&vblank->window_list, &window_priv->vblank);
> +    xorg_list_init(&vblank->event_queue);
> +
> +    vblank->screen = screen;
> +    vblank->window = window;
> +    vblank->pixmap = pixmap;
> +    vblank->event_id = ++present_event_id;
> +    if (pixmap) {
> +        vblank->kind = PresentCompleteKindPixmap;
> +        pixmap->refcnt++;
> +    } else
> +        vblank->kind = PresentCompleteKindNotifyMSC;
> +
> +    vblank->serial = serial;
> +
> +    if (valid) {
> +        vblank->valid = RegionDuplicate(valid);
> +        if (!vblank->valid)
> +            goto no_mem;
> +    }
> +    if (update) {
> +        vblank->update = RegionDuplicate(update);
> +        if (!vblank->update)
> +            goto no_mem;
> +    }
> +
> +    vblank->x_off = x_off;
> +    vblank->y_off = y_off;
> +    vblank->target_msc = target_msc;
> +    vblank->crtc = target_crtc;
> +    vblank->msc_offset = window_priv->msc_offset;
> +    vblank->notifies = notifies;
> +    vblank->num_notifies = num_notifies;
> +
> +    if (!screen_priv->info || !(screen_priv->info->capabilities & PresentCapabilityAsync))
> +        vblank->sync_flip = TRUE;
> +
> +    if (pixmap && present_check_flip (target_crtc, window, pixmap, vblank->sync_flip, valid, x_off, y_off)) {
> +        vblank->flip = TRUE;
> +        if (vblank->sync_flip)
> +            target_msc--;
> +    }
> +
> +    if (idle_fence) {
> +        vblank->idle_fence = present_fence_create(idle_fence);
> +        if (!vblank->idle_fence)
> +            goto no_mem;
> +    }
> +
> +    if (pixmap)
> +        DebugPresent(("q %p %8lld: %08lx -> %08lx (crtc %d)\n",
> +                      vblank, target_msc, vblank->pixmap->drawable.id, vblank->window->drawable.id, target_crtc ? 1 : 0));
> +
> +    xorg_list_add(&vblank->event_queue, &present_exec_queue);
> +    if (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);
> +            goto failure;
> +        }
> +    } else
> +        present_execute(vblank, ust, crtc_msc);
> +
> +    return Success;
> +
> +no_mem:
> +    ret = BadAlloc;
> +failure:
> +    vblank->notifies = NULL;
> +    present_vblank_destroy(vblank);
> +    return ret;
> +}
> +
> +void
> +present_abort_vblank(ScreenPtr screen, RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
> +{
> +    present_vblank_ptr  vblank, tmp;
> +
> +    if (crtc == NULL)
> +        present_fake_abort_vblank(screen, event_id, msc);
> +    else
> +    {
> +        present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
> +
> +        (*screen_priv->info->abort_vblank) (crtc, event_id, msc);
> +    }
> +
> +    xorg_list_for_each_entry_safe(vblank, tmp, &present_exec_queue, event_queue) {
> +        if (vblank->event_id == event_id) {
> +            xorg_list_del(&vblank->event_queue);
> +            return;
> +        }
> +    }
> +    xorg_list_for_each_entry_safe(vblank, tmp, &present_flip_queue, event_queue) {
> +        if (vblank->event_id == event_id) {
> +            xorg_list_del(&vblank->event_queue);
> +            return;
> +        }
> +    }
> +}
> +
> +int
> +present_notify_msc(WindowPtr window,
> +                   CARD32 serial,
> +                   uint64_t target_msc,
> +                   uint64_t divisor,
> +                   uint64_t remainder)
> +{
> +    return present_pixmap(window,
> +                          NULL,
> +                          serial,
> +                          NULL, NULL,
> +                          0, 0,
> +                          NULL,
> +                          NULL, NULL,
> +                          0,
> +                          target_msc, divisor, remainder, NULL, 0);
> +}
> +
> +void
> +present_flip_destroy(ScreenPtr screen)
> +{
> +    present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
> +
> +    /* XXX this needs to be synchronous for server reset */
> +
> +    /* Do the actual cleanup once the flip has been performed by the hardware */
> +    if (screen_priv->flip_pending)
> +        screen_priv->flip_pending->abort_flip = TRUE;
> +}
> +
> +void
> +present_vblank_destroy(present_vblank_ptr vblank)
> +{
> +    /* Remove vblank from window and screen lists */
> +    xorg_list_del(&vblank->window_list);
> +
> +    DebugPresent(("\td %p %8lld: %08lx -> %08lx\n", vblank, vblank->target_msc,
> +                  vblank->pixmap ? vblank->pixmap->drawable.id : 0,
> +                  vblank->window->drawable.id));
> +
> +    /* Drop pixmap reference */
> +    if (vblank->pixmap)
> +        dixDestroyPixmap(vblank->pixmap, vblank->pixmap->drawable.id);
> +
> +    /* Free regions */
> +    if (vblank->valid)
> +        RegionDestroy(vblank->valid);
> +    if (vblank->update)
> +        RegionDestroy(vblank->update);
> +
> +    if (vblank->idle_fence)
> +        present_fence_destroy(vblank->idle_fence);
> +
> +    if (vblank->notifies)
> +        present_destroy_notifies(vblank->notifies, vblank->num_notifies);
> +
> +    free(vblank);
> +}
> +
> +Bool
> +present_init(void)
> +{
> +    xorg_list_init(&present_exec_queue);
> +    xorg_list_init(&present_flip_queue);
> +    present_fake_queue_init();
> +    return TRUE;
> +}
> diff --git a/present/present.h b/present/present.h
> new file mode 100644
> index 0000000..6a451fb
> --- /dev/null
> +++ b/present/present.h
> @@ -0,0 +1,118 @@
> +/*
> + * Copyright © 2013 Keith Packard
> + *
> + * 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.
> + */
> +
> +#ifndef _PRESENT_H_
> +#define _PRESENT_H_
> +
> +#include <X11/extensions/presentproto.h>
> +#include "randrstr.h"
> +#include "presentext.h"
> +
> +typedef struct present_vblank present_vblank_rec, *present_vblank_ptr;
> +
> +/* Return the current CRTC for 'window'.
> + */
> +typedef RRCrtcPtr (*present_get_crtc_ptr) (WindowPtr window);
> +
> +/* Return the current ust/msc for 'crtc'
> + */
> +typedef int (*present_get_ust_msc_ptr) (RRCrtcPtr crtc, uint64_t *ust, uint64_t *msc);
> +
> +/* Queue callback on 'crtc' for time 'msc'. Call present_event_notify with 'event_id'
> + * at or after 'msc'. Return false if it didn't happen (which might occur if 'crtc'
> + * is not currently generating vblanks).
> + */
> +typedef Bool (*present_queue_vblank_ptr) (RRCrtcPtr crtc,
> +                                          uint64_t event_id,
> +                                          uint64_t msc);
> +
> +/* Abort pending vblank. The extension is no longer interested in
> + * 'event_id' which was to be notified at 'msc'. If possible, the
> + * driver is free to de-queue the notification.
> + */
> +typedef void (*present_abort_vblank_ptr) (RRCrtcPtr crtc, uint64_t event_id, uint64_t msc);
> +
> +/* Flush pending drawing on 'window' to the hardware.
> + */
> +typedef void (*present_flush_ptr) (WindowPtr window);
> +
> +/* Check if 'pixmap' is suitable for flipping to 'window'.
> + */
> +typedef Bool (*present_check_flip_ptr) (RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap, Bool sync_flip);
> +
> +/* Flip pixmap, return false if it didn't happen.
> + *
> + * 'crtc' is to be used for any necessary synchronization.
> + *
> + * 'sync_flip' requests that the flip be performed at the next
> + * vertical blank interval to avoid tearing artifacts. If false, the
> + * flip should be performed as soon as possible.
> + *
> + * present_event_notify should be called with 'event_id' when the flip
> + * occurs
> + */
> +typedef Bool (*present_flip_ptr) (RRCrtcPtr crtc,
> +                                  uint64_t event_id,
> +                                  uint64_t target_msc,
> +                                  PixmapPtr pixmap,
> +                                  Bool sync_flip);
> +
> +/* "unflip" back to the regular screen scanout buffer
> + *
> + * present_event_notify should be called with 'event_id' when the unflip occurs.
> + */
> +typedef void (*present_unflip_ptr) (ScreenPtr screen,
> +                                    uint64_t event_id);
> +
> +#define PRESENT_SCREEN_INFO_VERSION        0
> +
> +typedef struct present_screen_info {
> +    uint32_t                            version;
> +
> +    present_get_crtc_ptr                get_crtc;
> +    present_get_ust_msc_ptr             get_ust_msc;
> +    present_queue_vblank_ptr            queue_vblank;
> +    present_abort_vblank_ptr            abort_vblank;
> +    present_flush_ptr                   flush;
> +    uint32_t                            capabilities;
> +    present_check_flip_ptr              check_flip;
> +    present_flip_ptr                    flip;
> +    present_unflip_ptr                  unflip;
> +
> +} present_screen_info_rec, *present_screen_info_ptr;
> +
> +/*
> + * Called when 'event_id' occurs. 'ust' and 'msc' indicate when the
> + * event actually happened
> + */
> +extern _X_EXPORT void
> +present_event_notify(uint64_t event_id, uint64_t ust, uint64_t msc);
> +
> +/* 'crtc' has been turned off, so any pending events will never occur.
> + */
> +extern _X_EXPORT void
> +present_event_abandon(RRCrtcPtr crtc);
> +
> +extern _X_EXPORT Bool
> +present_screen_init(ScreenPtr screen, present_screen_info_ptr info);
> +
> +#endif /* _PRESENT_H_ */
> diff --git a/present/present_event.c b/present/present_event.c
> new file mode 100644
> index 0000000..a30bc82
> --- /dev/null
> +++ b/present/present_event.c
> @@ -0,0 +1,239 @@
> +/*
> + * Copyright © 2013 Keith Packard
> + *
> + * 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_XORG_CONFIG_H
> +#include <xorg-config.h>
> +#endif
> +
> +#include "present_priv.h"
> +
> +#include "present_priv.h"
> +
> +RESTYPE present_event_type;
> +
> +static int
> +present_free_event(pointer data, XID id)
> +{
> +    present_event_ptr present_event = (present_event_ptr) data;
> +    present_window_priv_ptr window_priv = present_window_priv(present_event->window);
> +    present_event_ptr *previous, current;
> +
> +    for (previous = &window_priv->events; (current = *previous); previous = &current->next) {
> +        if (current == present_event) {
> +            *previous = present_event->next;
> +            break;
> +        }
> +    }
> +    free((pointer) present_event);
> +    return 1;
> +
> +}
> +
> +void
> +present_free_events(WindowPtr window)
> +{
> +    present_window_priv_ptr window_priv = present_window_priv(window);
> +    present_event_ptr event;
> +
> +    if (!window_priv)
> +        return;
> +
> +    while ((event = window_priv->events))
> +        FreeResource(event->id, RT_NONE);
> +}
> +
> +static void
> +present_event_swap(xGenericEvent *from, xGenericEvent *to)
> +{
> +    *to = *from;
> +    swaps(&to->sequenceNumber);
> +    swapl(&to->length);
> +    swaps(&to->evtype);
> +    switch (from->evtype) {
> +    case PresentConfigureNotify: {
> +        xPresentConfigureNotify *c = (xPresentConfigureNotify *) to;
> +
> +        swapl(&c->eid);
> +        swapl(&c->window);
> +        swaps(&c->x);
> +        swaps(&c->y);
> +        swaps(&c->width);
> +        swaps(&c->height);
> +        swaps(&c->off_x);
> +        swaps(&c->off_y);
> +        swaps(&c->pixmap_width);
> +        swaps(&c->pixmap_height);
> +        swapl(&c->pixmap_flags);
> +        break;
> +    }
> +    case PresentCompleteNotify:
> +    {
> +        xPresentCompleteNotify *c = (xPresentCompleteNotify *) to;
> +        swapl(&c->eid);
> +        swapl(&c->window);
> +        swapl(&c->serial);
> +        swapll(&c->ust);
> +        swapll(&c->msc);
> +    }
> +    case PresentIdleNotify:
> +    {
> +        xPresentIdleNotify *c = (xPresentIdleNotify *) to;
> +        swapl(&c->eid);
> +        swapl(&c->window);
> +        swapl(&c->serial);
> +        swapl(&c->idle_fence);
> +    }
> +    }
> +}
> +
> +void
> +present_send_config_notify(WindowPtr window, int x, int y, int w, int h, int bw, WindowPtr sibling)
> +{
> +    present_window_priv_ptr window_priv = present_window_priv(window);
> +
> +    if (window_priv) {
> +        xPresentConfigureNotify cn = {
> +            .type = GenericEvent,
> +            .extension = present_request,
> +            .length = (sizeof(xPresentConfigureNotify) - 32) >> 2,
> +            .evtype = PresentConfigureNotify,
> +            .eid = 0,
> +            .window = window->drawable.id,
> +            .x = x,
> +            .y = y,
> +            .width = w,
> +            .height = h,
> +            .off_x = 0,
> +            .off_y = 0,
> +            .pixmap_width = w,
> +            .pixmap_height = h,
> +            .pixmap_flags = 0
> +        };
> +        present_event_ptr event;
> +
> +        for (event = window_priv->events; event; event = event->next) {
> +            if (event->mask & (1 << PresentConfigureNotify)) {
> +                cn.eid = event->id;
> +                WriteEventsToClient(event->client, 1, (xEvent *) &cn);
> +            }
> +        }
> +    }
> +}
> +
> +void
> +present_send_complete_notify(WindowPtr window, CARD8 kind, CARD8 mode, CARD32 serial, uint64_t ust, uint64_t msc)
> +{
> +    present_window_priv_ptr window_priv = present_window_priv(window);
> +
> +    if (window_priv) {
> +        xPresentCompleteNotify cn = {
> +            .type = GenericEvent,
> +            .extension = present_request,
> +            .length = (sizeof(xPresentCompleteNotify) - 32) >> 2,
> +            .evtype = PresentCompleteNotify,
> +            .kind = kind,
> +            .mode = mode,
> +            .eid = 0,
> +            .window = window->drawable.id,
> +            .serial = serial,
> +            .ust = ust,
> +            .msc = msc,
> +        };
> +        present_event_ptr event;
> +
> +        for (event = window_priv->events; event; event = event->next) {
> +            if (event->mask & PresentCompleteNotifyMask) {
> +                cn.eid = event->id;
> +                WriteEventsToClient(event->client, 1, (xEvent *) &cn);
> +            }
> +        }
> +    }
> +}
> +
> +void
> +present_send_idle_notify(WindowPtr window, CARD32 serial, PixmapPtr pixmap, struct present_fence *idle_fence)
> +{
> +    present_window_priv_ptr window_priv = present_window_priv(window);
> +
> +    if (window_priv) {
> +        xPresentIdleNotify in = {
> +            .type = GenericEvent,
> +            .extension = present_request,
> +            .length = (sizeof(xPresentIdleNotify) - 32) >> 2,
> +            .evtype = PresentIdleNotify,
> +            .eid = 0,
> +            .window = window->drawable.id,
> +            .serial = serial,
> +            .pixmap = pixmap->drawable.id,
> +            .idle_fence = present_fence_id(idle_fence)
> +        };
> +        present_event_ptr event;
> +
> +        for (event = window_priv->events; event; event = event->next) {
> +            if (event->mask & PresentIdleNotifyMask) {
> +                in.eid = event->id;
> +                WriteEventsToClient(event->client, 1, (xEvent *) &in);
> +            }
> +        }
> +    }
> +}
> +
> +int
> +present_select_input(ClientPtr client, XID eid, WindowPtr window, CARD32 mask)
> +{
> +    present_window_priv_ptr window_priv = present_get_window_priv(window, mask != 0);
> +    present_event_ptr event;
> +
> +    if (!window_priv) {
> +        if (mask)
> +            return BadAlloc;
> +        return Success;
> +    }
> +
> +    event = calloc (1, sizeof (present_event_rec));
> +    if (!event)
> +        return BadAlloc;
> +
> +    event->client = client;
> +    event->window = window;
> +    event->id = eid;
> +    event->mask = mask;
> +
> +    event->next = window_priv->events;
> +    window_priv->events = event;
> +
> +    if (!AddResource(event->id, present_event_type, (pointer) event))
> +        return BadAlloc;
> +
> +    return Success;
> +}
> +
> +Bool
> +present_event_init(void)
> +{
> +    present_event_type = CreateNewResourceType(present_free_event, "PresentEvent");
> +    if (!present_event_type)
> +        return FALSE;
> +
> +    GERegisterExtension(present_request, present_event_swap);
> +    return TRUE;
> +}
> diff --git a/present/present_fake.c b/present/present_fake.c
> new file mode 100644
> index 0000000..a677592
> --- /dev/null
> +++ b/present/present_fake.c
> @@ -0,0 +1,140 @@
> +/*
> + * Copyright © 2013 Keith Packard
> + *
> + * 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_XORG_CONFIG_H
> +#include <xorg-config.h>
> +#endif
> +
> +#include "present_priv.h"
> +#include "list.h"
> +
> +static struct xorg_list fake_vblank_queue;
> +
> +typedef struct present_fake_vblank {
> +    struct xorg_list            list;
> +    uint64_t                    event_id;
> +    OsTimerPtr                  timer;
> +    ScreenPtr                   screen;
> +} present_fake_vblank_rec, *present_fake_vblank_ptr;
> +
> +int
> +present_fake_get_ust_msc(ScreenPtr screen, uint64_t *ust, uint64_t *msc)
> +{
> +    present_screen_priv_ptr screen_priv = present_screen_priv(screen);
> +
> +    *ust = GetTimeInMicros();
> +    *msc = *ust / screen_priv->fake_interval;
> +    return Success;
> +}
> +
> +static void
> +present_fake_notify(ScreenPtr screen, uint64_t event_id)
> +{
> +    uint64_t                    ust, msc;
> +
> +    present_fake_get_ust_msc(screen, &ust, &msc);
> +    present_event_notify(event_id, ust, msc);
> +}
> +
> +static CARD32
> +present_fake_do_timer(OsTimerPtr timer,
> +                      CARD32 time,
> +                      pointer arg)
> +{
> +    present_fake_vblank_ptr     fake_vblank = arg;
> +
> +    present_fake_notify(fake_vblank->screen, fake_vblank->event_id);
> +    xorg_list_del(&fake_vblank->list);
> +    free(fake_vblank);
> +    return 0;
> +}
> +
> +void
> +present_fake_abort_vblank(ScreenPtr screen, uint64_t event_id, uint64_t msc)
> +{
> +    present_fake_vblank_ptr     fake_vblank, tmp;
> +
> +    xorg_list_for_each_entry_safe(fake_vblank, tmp, &fake_vblank_queue, list) {
> +        if (fake_vblank->event_id == event_id) {
> +            TimerCancel(fake_vblank->timer);
> +            xorg_list_del(&fake_vblank->list);
> +            free (fake_vblank);
> +            break;
> +        }
> +    }
> +}
> +
> +int
> +present_fake_queue_vblank(ScreenPtr     screen,
> +                          uint64_t      event_id,
> +                          uint64_t      msc)
> +{
> +    present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
> +    uint64_t                    ust = msc * screen_priv->fake_interval;
> +    uint64_t                    now = GetTimeInMicros();
> +    INT32                       delay = ((int64_t) (ust - now)) / 1000;
> +    present_fake_vblank_ptr     fake_vblank;
> +
> +    if (delay <= 0) {
> +        present_fake_notify(screen, event_id);
> +        return Success;
> +    }
> +
> +    fake_vblank = calloc (1, sizeof (present_fake_vblank_rec));
> +    if (!fake_vblank)
> +        return BadAlloc;
> +
> +    fake_vblank->screen = screen;
> +    fake_vblank->event_id = event_id;
> +    fake_vblank->timer = TimerSet(NULL, 0, delay, present_fake_do_timer, fake_vblank);
> +    if (!fake_vblank->timer) {
> +        free(fake_vblank);
> +        return BadAlloc;
> +    }
> +
> +    xorg_list_add(&fake_vblank->list, &fake_vblank_queue);
> +
> +    return Success;
> +}
> +
> +void
> +present_fake_screen_init(ScreenPtr screen)
> +{
> +    present_screen_priv_ptr screen_priv = present_screen_priv(screen);
> +
> +    /* For screens with hardware vblank support, the fake code
> +     * will be used for off-screen windows and while screens are blanked,
> +     * in which case we want a slow interval here
> +     *
> +     * Otherwise, pretend that the screen runs at 60Hz
> +     */
> +    if (screen_priv->info && screen_priv->info->get_crtc)
> +        screen_priv->fake_interval = 1000000;
> +    else
> +        screen_priv->fake_interval = 16667;
> +}
> +
> +void
> +present_fake_queue_init(void)
> +{
> +    xorg_list_init(&fake_vblank_queue);
> +}
> diff --git a/present/present_fence.c b/present/present_fence.c
> new file mode 100644
> index 0000000..db5efca
> --- /dev/null
> +++ b/present/present_fence.c
> @@ -0,0 +1,112 @@
> +/*
> + * Copyright © 2013 Keith Packard
> + *
> + * 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_XORG_CONFIG_H
> +#include <xorg-config.h>
> +#endif
> +
> +#include "present_priv.h"
> +#include <gcstruct.h>
> +#include <misync.h>
> +#include <misyncstr.h>
> +
> +/*
> + * Wraps SyncFence objects so we can add a SyncTrigger to find out
> + * when the SyncFence gets destroyed and clean up appropriately
> + */
> +
> +struct present_fence {
> +    SyncTrigger         trigger;
> +    SyncFence           *fence;
> +};
> +
> +/*
> + * SyncTrigger callbacks
> + */
> +static Bool
> +present_fence_sync_check_trigger(SyncTrigger *trigger, XSyncValue oldval)
> +{
> +    return FALSE;
> +}
> +
> +static void
> +present_fence_sync_trigger_fired(SyncTrigger *trigger)
> +{
> +}
> +
> +static void
> +present_fence_sync_counter_destroyed(SyncTrigger *trigger)
> +{
> +    struct present_fence        *present_fence = container_of(trigger, struct present_fence, trigger);
> +
> +    present_fence->fence = NULL;
> +}
> +
> +struct present_fence *
> +present_fence_create(SyncFence *fence)
> +{
> +    struct present_fence        *present_fence;
> +
> +    present_fence = calloc (1, sizeof (struct present_fence));
> +    if (!present_fence)
> +        return NULL;
> +
> +    present_fence->fence = fence;
> +    present_fence->trigger.pSync = (SyncObject *) fence;
> +    present_fence->trigger.CheckTrigger = present_fence_sync_check_trigger;
> +    present_fence->trigger.TriggerFired = present_fence_sync_trigger_fired;
> +    present_fence->trigger.CounterDestroyed = present_fence_sync_counter_destroyed;
> +
> +    if (SyncAddTriggerToSyncObject(&present_fence->trigger) != Success) {
> +        free (present_fence);
> +        return NULL;
> +    }
> +    return present_fence;
> +}
> +
> +void
> +present_fence_destroy(struct present_fence *present_fence)
> +{
> +    if (present_fence) {
> +        if (present_fence->fence)
> +            SyncDeleteTriggerFromSyncObject(&present_fence->trigger);
> +        free(present_fence);
> +    }
> +}
> +
> +void
> +present_fence_set_triggered(struct present_fence *present_fence)
> +{
> +    if (present_fence)
> +        if (present_fence->fence)
> +            (*present_fence->fence->funcs.SetTriggered) (present_fence->fence);
> +}
> +
> +XID
> +present_fence_id(struct present_fence *present_fence)
> +{
> +    if (!present_fence)
> +        return None;
> +    if (!present_fence->fence)
> +        return None;
> +    return present_fence->fence->sync.id;
> +}
> diff --git a/present/present_notify.c b/present/present_notify.c
> new file mode 100644
> index 0000000..e272e08
> --- /dev/null
> +++ b/present/present_notify.c
> @@ -0,0 +1,114 @@
> +/*
> + * Copyright © 2013 Keith Packard
> + *
> + * 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_XORG_CONFIG_H
> +#include <xorg-config.h>
> +#endif
> +
> +#include "present_priv.h"
> +
> +/*
> + * Mark all pending notifies for 'window' as invalid when
> + * the window is destroyed
> + */
> +
> +void
> +present_clear_window_notifies(WindowPtr window)
> +{
> +    present_notify_ptr          notify;
> +    present_window_priv_ptr     window_priv = present_window_priv(window);
> +
> +    if (!window_priv)
> +        return;
> +
> +    xorg_list_for_each_entry(notify, &window_priv->notifies, window_list) {
> +        notify->window = NULL;
> +    }
> +}
> +
> +/*
> + * 'notify' is being freed; remove it from the window's notify list
> + */
> +
> +void
> +present_free_window_notify(present_notify_ptr notify)
> +{
> +    xorg_list_del(&notify->window_list);
> +}
> +
> +/*
> + * 'notify' is new; add it to the specified window
> + */
> +
> +int
> +present_add_window_notify(present_notify_ptr notify)
> +{
> +    WindowPtr                   window = notify->window;
> +    present_window_priv_ptr     window_priv = present_get_window_priv(window, TRUE);
> +
> +    if (!window_priv)
> +        return BadAlloc;
> +
> +    xorg_list_add(&notify->window_list, &window_priv->notifies);
> +    return Success;
> +}
> +
> +int
> +present_create_notifies(ClientPtr client, int num_notifies, xPresentNotify *x_notifies, present_notify_ptr *p_notifies)
> +{
> +    present_notify_ptr  notifies;
> +    int                 i;
> +    int                 added = 0;
> +    int                 status;
> +
> +    notifies = calloc (num_notifies, sizeof (present_notify_rec));
> +    if (!notifies)
> +        return BadAlloc;
> +
> +    for (i = 0; i < num_notifies; i++) {
> +        status = dixLookupWindow(&notifies[i].window, x_notifies[i].window, client, DixGetAttrAccess);
> +        if (status != Success)
> +            goto bail;
> +
> +        notifies[i].serial = x_notifies[i].serial;
> +        status = present_add_window_notify(&notifies[i]);
> +        if (status != Success)
> +            goto bail;
> +
> +        added = i;
> +    }
> +    return Success;
> +
> +bail:
> +    present_destroy_notifies(notifies, added);
> +    return status;
> +}
> +
> +void
> +present_destroy_notifies(present_notify_ptr notifies, int num_notifies)
> +{
> +    int i;
> +    for (i = 0; i < num_notifies; i++)
> +        present_free_window_notify(&notifies[i]);
> +
> +    free(notifies);
> +}
> diff --git a/present/present_priv.h b/present/present_priv.h
> new file mode 100644
> index 0000000..a92b62a
> --- /dev/null
> +++ b/present/present_priv.h
> @@ -0,0 +1,288 @@
> +/*
> + * Copyright © 2013 Keith Packard
> + *
> + * 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.
> + */
> +
> +#ifndef _PRESENT_PRIV_H_
> +#define _PRESENT_PRIV_H_
> +
> +#include <X11/X.h>
> +#include "scrnintstr.h"
> +#include "misc.h"
> +#include "list.h"
> +#include "windowstr.h"
> +#include "dixstruct.h"
> +#include "present.h"
> +#include <syncsdk.h>
> +#include <syncsrv.h>
> +#include <xfixes.h>
> +#include <randrstr.h>
> +
> +extern int present_request;
> +
> +extern DevPrivateKeyRec present_screen_private_key;
> +
> +typedef struct present_fence *present_fence_ptr;
> +
> +typedef struct present_notify present_notify_rec, *present_notify_ptr;
> +
> +struct present_notify {
> +    struct xorg_list    window_list;
> +    WindowPtr           window;
> +    CARD32              serial;
> +};
> +
> +struct present_vblank {
> +    struct xorg_list    window_list;
> +    struct xorg_list    event_queue;
> +    ScreenPtr           screen;
> +    WindowPtr           window;
> +    PixmapPtr           pixmap;
> +    RegionPtr           valid;
> +    RegionPtr           update;
> +    RRCrtcPtr           crtc;
> +    uint32_t            serial;
> +    int16_t             x_off;
> +    int16_t             y_off;
> +    CARD16              kind;
> +    uint64_t            event_id;
> +    uint64_t            target_msc;
> +    uint64_t            msc_offset;
> +    present_fence_ptr   idle_fence;
> +    present_fence_ptr   wait_fence;
> +    present_notify_ptr  notifies;
> +    int                 num_notifies;
> +    Bool                flip;
> +    Bool                sync_flip;
> +    Bool                abort_flip;
> +
> +    Bool                window_destroyed;
> +};
> +
> +typedef struct present_screen_priv {
> +    CloseScreenProcPtr          CloseScreen;
> +    ConfigNotifyProcPtr         ConfigNotify;
> +    DestroyWindowProcPtr        DestroyWindow;
> +    ClipNotifyProcPtr           ClipNotify;
> +
> +    present_vblank_ptr          flip_pending;
> +    uint64_t                    unflip_event_id;
> +
> +    uint32_t                    fake_interval;
> +
> +    /* Currently active flipped pixmap and fence */
> +    RRCrtcPtr                   flip_crtc;
> +    WindowPtr                   flip_window;
> +    uint32_t                    flip_serial;
> +    PixmapPtr                   flip_pixmap;
> +    present_fence_ptr           flip_idle_fence;
> +
> +    present_screen_info_ptr     info;
> +} present_screen_priv_rec, *present_screen_priv_ptr;
> +
> +#define wrap(priv,real,mem,func) {\
> +    priv->mem = real->mem; \
> +    real->mem = func; \
> +}
> +
> +#define unwrap(priv,real,mem) {\
> +    real->mem = priv->mem; \
> +}
> +
> +static inline present_screen_priv_ptr
> +present_screen_priv(ScreenPtr screen)
> +{
> +    return (present_screen_priv_ptr)dixLookupPrivate(&(screen)->devPrivates, &present_screen_private_key);
> +}
> +
> +/*
> + * Each window has a list of clients and event masks
> + */
> +typedef struct present_event *present_event_ptr;
> +
> +typedef struct present_event {
> +    present_event_ptr next;
> +    ClientPtr client;
> +    WindowPtr window;
> +    XID id;
> +    int mask;
> +} present_event_rec;
> +
> +typedef struct present_window_priv {
> +    present_event_ptr      events;
> +    RRCrtcPtr              crtc;        /* Last reported CRTC from get_ust_msc */
> +    uint64_t               msc_offset;
> +    uint64_t               msc;         /* Last reported MSC from the current crtc */
> +    struct xorg_list       vblank;
> +    struct xorg_list       notifies;
> +} present_window_priv_rec, *present_window_priv_ptr;
> +
> +extern DevPrivateKeyRec present_window_private_key;
> +
> +static inline present_window_priv_ptr
> +present_window_priv(WindowPtr window)
> +{
> +    return (present_window_priv_ptr)dixGetPrivate(&(window)->devPrivates, &present_window_private_key);
> +}
> +
> +present_window_priv_ptr
> +present_get_window_priv(WindowPtr window, Bool create);
> +
> +extern RESTYPE present_event_type;
> +
> +/*
> + * present.c
> + */
> +int
> +present_pixmap(WindowPtr window,
> +               PixmapPtr pixmap,
> +               CARD32 serial,
> +               RegionPtr valid,
> +               RegionPtr update,
> +               int16_t x_off,
> +               int16_t y_off,
> +               RRCrtcPtr target_crtc,
> +               SyncFence *wait_fence,
> +               SyncFence *idle_fence,
> +               uint32_t options,
> +               uint64_t target_msc,
> +               uint64_t divisor,
> +               uint64_t remainder,
> +               present_notify_ptr notifies,
> +               int num_notifies);
> +
> +int
> +present_notify_msc(WindowPtr window,
> +                   CARD32 serial,
> +                   uint64_t target_msc,
> +                   uint64_t divisor,
> +                   uint64_t remainder);
> +
> +void
> +present_abort_vblank(ScreenPtr screen, RRCrtcPtr crtc, uint64_t event_id, uint64_t msc);
> +
> +void
> +present_vblank_destroy(present_vblank_ptr vblank);
> +
> +void
> +present_flip_destroy(ScreenPtr screen);
> +
> +void
> +present_check_flip_window(WindowPtr window);
> +
> +RRCrtcPtr
> +present_get_crtc(WindowPtr window);
> +
> +uint32_t
> +present_query_capabilities(RRCrtcPtr crtc);
> +
> +Bool
> +present_init(void);
> +
> +/*
> + * present_event.c
> + */
> +
> +void
> +present_free_events(WindowPtr window);
> +
> +void
> +present_send_config_notify(WindowPtr window, int x, int y, int w, int h, int bw, WindowPtr sibling);
> +
> +void
> +present_send_complete_notify(WindowPtr window, CARD8 kind, CARD8 mode, CARD32 serial, uint64_t ust, uint64_t msc);
> +
> +void
> +present_send_idle_notify(WindowPtr window, CARD32 serial, PixmapPtr pixmap, present_fence_ptr idle_fence);
> +
> +int
> +present_select_input(ClientPtr client,
> +                     CARD32 eid,
> +                     WindowPtr window,
> +                     CARD32 event_mask);
> +
> +Bool
> +present_event_init(void);
> +
> +/*
> + * present_fake.c
> + */
> +int
> +present_fake_get_ust_msc(ScreenPtr screen, uint64_t *ust, uint64_t *msc);
> +
> +int
> +present_fake_queue_vblank(ScreenPtr screen, uint64_t event_id, uint64_t msc);
> +
> +void
> +present_fake_abort_vblank(ScreenPtr screen, uint64_t event_id, uint64_t msc);
> +
> +void
> +present_fake_screen_init(ScreenPtr screen);
> +
> +void
> +present_fake_queue_init(void);
> +
> +/*
> + * present_fence.c
> + */
> +struct present_fence *
> +present_fence_create(SyncFence *sync_fence);
> +
> +void
> +present_fence_destroy(struct present_fence *present_fence);
> +
> +void
> +present_fence_set_triggered(struct present_fence *present_fence);
> +
> +XID
> +present_fence_id(struct present_fence *present_fence);
> +
> +/*
> + * present_notify.c
> + */
> +void
> +present_clear_window_notifies(WindowPtr window);
> +
> +void
> +present_free_window_notify(present_notify_ptr notify);
> +
> +int
> +present_add_window_notify(present_notify_ptr notify);
> +
> +int
> +present_create_notifies(ClientPtr client, int num_notifies, xPresentNotify *x_notifies, present_notify_ptr *p_notifies);
> +
> +void
> +present_destroy_notifies(present_notify_ptr notifies, int num_notifies);
> +
> +/*
> + * present_request.c
> + */
> +int
> +proc_present_dispatch(ClientPtr client);
> +
> +int
> +sproc_present_dispatch(ClientPtr client);
> +
> +/*
> + * present_screen.c
> + */
> +
> +#endif /*  _PRESENT_PRIV_H_ */
> diff --git a/present/present_request.c b/present/present_request.c
> new file mode 100644
> index 0000000..095fa2d
> --- /dev/null
> +++ b/present/present_request.c
> @@ -0,0 +1,330 @@
> +/*
> + * Copyright © 2013 Keith Packard
> + *
> + * 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_XORG_CONFIG_H
> +#include <xorg-config.h>
> +#endif
> +
> +#include "present_priv.h"
> +#include "randrstr.h"
> +
> +static int
> +proc_present_query_version(ClientPtr client)
> +{
> +    REQUEST(xPresentQueryVersionReq);
> +    xPresentQueryVersionReply rep = {
> +        .type = X_Reply,
> +        .sequenceNumber = client->sequence,
> +        .length = 0,
> +        .majorVersion = PRESENT_MAJOR,
> +        .minorVersion = PRESENT_MINOR
> +    };
> +
> +    REQUEST_SIZE_MATCH(xPresentQueryVersionReq);
> +    (void) stuff;
> +    if (client->swapped) {
> +        swaps(&rep.sequenceNumber);
> +        swapl(&rep.length);
> +        swapl(&rep.majorVersion);
> +        swapl(&rep.minorVersion);
> +    }
> +    WriteToClient(client, sizeof(rep), &rep);
> +    return Success;
> +}
> +
> +#define VERIFY_FENCE_OR_NONE(fence_ptr, fence_id, client, access) do {  \
> +        if ((fence_id) == None)                                         \
> +            (fence_ptr) = NULL;                                         \
> +        else {                                                          \
> +            int __rc__ = SyncVerifyFence(&fence_ptr, fence_id, client, access); \
> +            if (__rc__ != Success)                                      \
> +                return __rc__;                                          \
> +        }                                                               \
> +    } while (0)
> +
> +#define VERIFY_CRTC_OR_NONE(crtc_ptr, crtc_id, client, access) do {     \
> +        if ((crtc_id) == None)                                          \
> +            (crtc_ptr) = NULL;                                          \
> +        else {                                                          \
> +            VERIFY_RR_CRTC(crtc_id, crtc_ptr, access);                  \
> +        }                                                               \
> +    } while (0)
> +
> +static int
> +proc_present_pixmap(ClientPtr client)
> +{
> +    REQUEST(xPresentPixmapReq);
> +    WindowPtr           window;
> +    PixmapPtr           pixmap;
> +    RegionPtr           valid = NULL;
> +    RegionPtr           update = NULL;
> +    SyncFence           *wait_fence;
> +    SyncFence           *idle_fence;
> +    RRCrtcPtr           target_crtc;
> +    int                 ret;
> +    int                 nnotifies;
> +    present_notify_ptr  notifies = NULL;
> +
> +    REQUEST_AT_LEAST_SIZE(xPresentPixmapReq);
> +    ret = dixLookupWindow(&window, stuff->window, client, DixWriteAccess);
> +    if (ret != Success)
> +        return ret;
> +    ret = dixLookupResourceByType((pointer *) &pixmap, stuff->pixmap, RT_PIXMAP, client, DixReadAccess);
> +    if (ret != Success)
> +        return ret;
> +
> +    if (window->drawable.depth != pixmap->drawable.depth)
> +        return BadMatch;
> +
> +    VERIFY_REGION_OR_NONE(valid, stuff->valid, client, DixReadAccess);
> +    VERIFY_REGION_OR_NONE(update, stuff->update, client, DixReadAccess);
> +
> +    VERIFY_CRTC_OR_NONE(target_crtc, stuff->target_crtc, client, DixReadAccess);
> +
> +    VERIFY_FENCE_OR_NONE(wait_fence, stuff->wait_fence, client, DixReadAccess);
> +    VERIFY_FENCE_OR_NONE(idle_fence, stuff->idle_fence, client, DixWriteAccess);
> +
> +    if (stuff->options & ~(PresentAllOptions)) {
> +        client->errorValue = stuff->options;
> +        return BadValue;
> +    }
> +
> +    /*
> +     * Check to see if remainder is sane
> +     */
> +    if (stuff->divisor == 0) {
> +        if (stuff->remainder != 0) {
> +            client->errorValue = (CARD32) stuff->remainder;
> +            return BadValue;
> +        }
> +    } else {
> +        if (stuff->remainder >= stuff->divisor) {
> +            client->errorValue = (CARD32) stuff->remainder;
> +            return BadValue;
> +        }
> +    }
> +
> +    nnotifies = (client->req_len << 2) - sizeof (xPresentPixmapReq);
> +    if (nnotifies % sizeof (xPresentNotify))
> +        return BadLength;
> +
> +    nnotifies /= sizeof (xPresentNotify);
> +    if (nnotifies) {
> +        ret = present_create_notifies(client, nnotifies, (xPresentNotify *) (stuff + 1), &notifies);
> +        if (ret != Success)
> +            return ret;
> +    }
> +
> +    ret = present_pixmap(window, pixmap, stuff->serial, valid, update,
> +                         stuff->x_off, stuff->y_off, target_crtc,
> +                         wait_fence, idle_fence, stuff->options,
> +                         stuff->target_msc, stuff->divisor, stuff->remainder, notifies, nnotifies);
> +    if (ret != Success)
> +        present_destroy_notifies(notifies, nnotifies);
> +    return ret;
> +}
> +
> +static int
> +proc_present_notify_msc(ClientPtr client)
> +{
> +    REQUEST(xPresentNotifyMSCReq);
> +    WindowPtr   window;
> +    int         rc;
> +
> +    REQUEST_SIZE_MATCH(xPresentNotifyMSCReq);
> +    rc = dixLookupWindow(&window, stuff->window, client, DixReadAccess);
> +    if (rc != Success)
> +        return rc;
> +
> +    /*
> +     * Check to see if remainder is sane
> +     */
> +    if (stuff->divisor == 0) {
> +        if (stuff->remainder != 0) {
> +            client->errorValue = (CARD32) stuff->remainder;
> +            return BadValue;
> +        }
> +    } else {
> +        if (stuff->remainder >= stuff->divisor) {
> +            client->errorValue = (CARD32) stuff->remainder;
> +            return BadValue;
> +        }
> +    }
> +
> +    return present_notify_msc(window, stuff->serial,
> +                              stuff->target_msc, stuff->divisor, stuff->remainder);
> +}
> +
> +static int
> +proc_present_select_input (ClientPtr client)
> +{
> +    REQUEST(xPresentSelectInputReq);
> +    WindowPtr window;
> +    int rc;
> +
> +    REQUEST_SIZE_MATCH(xPresentSelectInputReq);
> +
> +    LEGAL_NEW_RESOURCE(stuff->eid, client);
> +
> +    rc = dixLookupWindow(&window, stuff->window, client, DixGetAttrAccess);
> +    if (rc != Success)
> +        return rc;
> +
> +    if (stuff->eventMask & ~PresentAllEvents) {
> +        client->errorValue = stuff->eventMask;
> +        return BadValue;
> +    }
> +    return present_select_input(client, stuff->eid, window, stuff->eventMask);
> +}
> +
> +static int
> +proc_present_query_capabilities (ClientPtr client)
> +{
> +    REQUEST(xPresentQueryCapabilitiesReq);
> +    xPresentQueryCapabilitiesReply rep = {
> +        .type = X_Reply,
> +        .sequenceNumber = client->sequence,
> +        .length = 0,
> +    };
> +    WindowPtr   window;
> +    RRCrtcPtr   crtc = NULL;
> +    int         r;
> +
> +    r = dixLookupWindow(&window, stuff->target, client, DixGetAttrAccess);
> +    switch (r) {
> +    case Success:
> +        crtc = present_get_crtc(window);
> +        break;
> +    case BadWindow:
> +        VERIFY_RR_CRTC(stuff->target, crtc, DixGetAttrAccess);
> +        break;
> +    default:
> +        return r;
> +    }
> +
> +    rep.capabilities = present_query_capabilities(crtc);
> +
> +    if (client->swapped) {
> +        swaps(&rep.sequenceNumber);
> +        swapl(&rep.length);
> +        swapl(&rep.capabilities);
> +    }
> +    WriteToClient(client, sizeof(rep), &rep);
> +    return Success;
> +}
> +
> +int (*proc_present_vector[PresentNumberRequests]) (ClientPtr) = {
> +    proc_present_query_version,            /* 0 */
> +    proc_present_pixmap,                   /* 1 */
> +    proc_present_notify_msc,               /* 2 */
> +    proc_present_select_input,             /* 3 */
> +    proc_present_query_capabilities,       /* 4 */
> +};
> +
> +int
> +proc_present_dispatch(ClientPtr client)
> +{
> +    REQUEST(xReq);
> +    if (stuff->data >= PresentNumberRequests || !proc_present_vector[stuff->data])
> +        return BadRequest;
> +    return (*proc_present_vector[stuff->data]) (client);
> +}
> +
> +static int
> +sproc_present_query_version(ClientPtr client)
> +{
> +    REQUEST(xPresentQueryVersionReq);
> +
> +    swaps(&stuff->length);
> +    swapl(&stuff->majorVersion);
> +    swapl(&stuff->minorVersion);
> +    return (*proc_present_vector[stuff->presentReqType]) (client);
> +}
> +
> +static int
> +sproc_present_pixmap(ClientPtr client)
> +{
> +    REQUEST(xPresentPixmapReq);
> +
> +    swaps(&stuff->length);
> +    swapl(&stuff->window);
> +    swapl(&stuff->pixmap);
> +    swapl(&stuff->valid);
> +    swapl(&stuff->update);
> +    swaps(&stuff->x_off);
> +    swaps(&stuff->y_off);
> +    swapll(&stuff->target_msc);
> +    swapll(&stuff->divisor);
> +    swapll(&stuff->remainder);
> +    swapl(&stuff->idle_fence);
> +    return (*proc_present_vector[stuff->presentReqType]) (client);
> +}
> +
> +static int
> +sproc_present_notify_msc(ClientPtr client)
> +{
> +    REQUEST(xPresentNotifyMSCReq);
> +
> +    swaps(&stuff->length);
> +    swapl(&stuff->window);
> +    swapll(&stuff->target_msc);
> +    swapll(&stuff->divisor);
> +    swapll(&stuff->remainder);
> +    return (*proc_present_vector[stuff->presentReqType]) (client);
> +}
> +
> +static int
> +sproc_present_select_input (ClientPtr client)
> +{
> +    REQUEST(xPresentSelectInputReq);
> +
> +    swaps(&stuff->length);
> +    swapl(&stuff->window);
> +    swapl(&stuff->eventMask);
> +    return (*proc_present_vector[stuff->presentReqType]) (client);
> +}
> +
> +static int
> +sproc_present_query_capabilities (ClientPtr client)
> +{
> +    REQUEST(xPresentQueryCapabilitiesReq);
> +    swaps(&stuff->length);
> +    swapl(&stuff->target);
> +    return (*proc_present_vector[stuff->presentReqType]) (client);
> +}
> +
> +int (*sproc_present_vector[PresentNumberRequests]) (ClientPtr) = {
> +    sproc_present_query_version,           /* 0 */
> +    sproc_present_pixmap,                  /* 1 */
> +    sproc_present_notify_msc,              /* 2 */
> +    sproc_present_select_input,            /* 3 */
> +    sproc_present_query_capabilities,      /* 4 */
> +};
> +
> +int
> +sproc_present_dispatch(ClientPtr client)
> +{
> +    REQUEST(xReq);
> +    if (stuff->data >= PresentNumberRequests || !sproc_present_vector[stuff->data])
> +        return BadRequest;
> +    return (*sproc_present_vector[stuff->data]) (client);
> +}
> diff --git a/present/present_screen.c b/present/present_screen.c
> new file mode 100644
> index 0000000..50b2b2d
> --- /dev/null
> +++ b/present/present_screen.c
> @@ -0,0 +1,231 @@
> +/*
> + * Copyright © 2013 Keith Packard
> + *
> + * 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_XORG_CONFIG_H
> +#include <xorg-config.h>
> +#endif
> +
> +#include "present_priv.h"
> +
> +int present_request;
> +DevPrivateKeyRec present_screen_private_key;
> +DevPrivateKeyRec present_window_private_key;
> +
> +/*
> + * Get a pointer to a present window private, creating if necessary
> + */
> +present_window_priv_ptr
> +present_get_window_priv(WindowPtr window, Bool create)
> +{
> +    present_window_priv_ptr window_priv = present_window_priv(window);
> +
> +    if (!create || window_priv != NULL)
> +        return window_priv;
> +    window_priv = calloc (1, sizeof (present_window_priv_rec));
> +    if (!window_priv)
> +        return NULL;
> +    xorg_list_init(&window_priv->vblank);
> +    xorg_list_init(&window_priv->notifies);
> +    dixSetPrivate(&window->devPrivates, &present_window_private_key, window_priv);
> +    return window_priv;
> +}
> +
> +/*
> + * Hook the close screen function to clean up our screen private
> + */
> +static Bool
> +present_close_screen(ScreenPtr screen)
> +{
> +    present_screen_priv_ptr screen_priv = present_screen_priv(screen);
> +
> +    present_flip_destroy(screen);
> +
> +    unwrap(screen_priv, screen, CloseScreen);
> +    (*screen->CloseScreen) (screen);
> +    free(screen_priv);
> +    return TRUE;
> +}
> +
> +/*
> + * Free any queued presentations for this window
> + */
> +static void
> +present_free_window_vblank(WindowPtr window)
> +{
> +    present_window_priv_ptr     window_priv = present_window_priv(window);
> +    present_vblank_ptr          vblank, tmp;
> +
> +    xorg_list_for_each_entry_safe(vblank, tmp, &window_priv->vblank, window_list) {
> +        present_abort_vblank(window->drawable.pScreen, vblank->crtc, vblank->event_id, vblank->target_msc);
> +        present_vblank_destroy(vblank);
> +    }
> +}
> +
> +/*
> + * Clean up any pending or current flips for this window
> + */
> +static void
> +present_clear_window_flip(WindowPtr window)
> +{
> +    ScreenPtr                   screen = window->drawable.pScreen;
> +    present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
> +    present_vblank_ptr          flip_pending = screen_priv->flip_pending;
> +
> +    if (flip_pending && flip_pending->window == window) {
> +        assert (flip_pending->abort_flip);
> +        flip_pending->window_destroyed = TRUE;
> +    }
> +    if (screen_priv->flip_window == window)
> +        screen_priv->flip_window = NULL;
> +}
> +
> +/*
> + * Hook the close window function to clean up our window private
> + */
> +static Bool
> +present_destroy_window(WindowPtr window)
> +{
> +    Bool ret;
> +    ScreenPtr screen = window->drawable.pScreen;
> +    present_screen_priv_ptr screen_priv = present_screen_priv(screen);
> +    present_window_priv_ptr window_priv = present_window_priv(window);
> +
> +    if (window_priv) {
> +        present_clear_window_notifies(window);
> +        present_free_events(window);
> +        present_free_window_vblank(window);
> +        present_clear_window_flip(window);
> +        free(window_priv);
> +    }
> +    unwrap(screen_priv, screen, DestroyWindow);
> +    if (screen->DestroyWindow)
> +        ret = screen->DestroyWindow (window);
> +    else
> +        ret = TRUE;
> +    wrap(screen_priv, screen, DestroyWindow, present_destroy_window);
> +    return ret;
> +}
> +
> +/*
> + * Hook the config notify screen function to deliver present config notify events
> + */
> +static int
> +present_config_notify(WindowPtr window,
> +                   int x, int y, int w, int h, int bw,
> +                   WindowPtr sibling)
> +{
> +    int ret;
> +    ScreenPtr screen = window->drawable.pScreen;
> +    present_screen_priv_ptr screen_priv = present_screen_priv(screen);
> +
> +    present_send_config_notify(window, x, y, w, h, bw, sibling);
> +
> +    unwrap(screen_priv, screen, ConfigNotify);
> +    if (screen->ConfigNotify)
> +        ret = screen->ConfigNotify (window, x, y, w, h, bw, sibling);
> +    else
> +        ret = 0;
> +    wrap(screen_priv, screen, ConfigNotify, present_config_notify);
> +    return ret;
> +}
> +
> +/*
> + * Hook the clip notify screen function to un-flip as necessary
> + */
> +
> +static void
> +present_clip_notify(WindowPtr window, int dx, int dy)
> +{
> +    ScreenPtr screen = window->drawable.pScreen;
> +    present_screen_priv_ptr screen_priv = present_screen_priv(screen);
> +
> +    present_check_flip_window(window);
> +    unwrap(screen_priv, screen, ClipNotify)
> +    if (screen->ClipNotify)
> +        screen->ClipNotify (window, dx, dy);
> +    wrap(screen_priv, screen, ClipNotify, present_clip_notify);
> +}
> +
> +/*
> + * Initialize a screen for use with present
> + */
> +int
> +present_screen_init(ScreenPtr screen, present_screen_info_ptr info)
> +{
> +    if (!dixRegisterPrivateKey(&present_screen_private_key, PRIVATE_SCREEN, 0))
> +        return FALSE;
> +
> +    if (!dixRegisterPrivateKey(&present_window_private_key, PRIVATE_WINDOW, 0))
> +        return FALSE;
> +
> +    if (!present_screen_priv(screen)) {
> +        present_screen_priv_ptr screen_priv = calloc(1, sizeof (present_screen_priv_rec));
> +        if (!screen_priv)
> +            return FALSE;
> +
> +        wrap(screen_priv, screen, CloseScreen, present_close_screen);
> +        wrap(screen_priv, screen, DestroyWindow, present_destroy_window);
> +        wrap(screen_priv, screen, ConfigNotify, present_config_notify);
> +        wrap(screen_priv, screen, ClipNotify, present_clip_notify);
> +
> +        screen_priv->info = info;
> +
> +        dixSetPrivate(&screen->devPrivates, &present_screen_private_key, screen_priv);
> +
> +        present_fake_screen_init(screen);
> +    }
> +
> +    return TRUE;
> +}
> +
> +/*
> + * Initialize the present extension
> + */
> +void
> +present_extension_init(void)
> +{
> +    ExtensionEntry *extension;
> +    int i;
> +
> +    extension = AddExtension(PRESENT_NAME, PresentNumberEvents, PresentNumberErrors,
> +                             proc_present_dispatch, sproc_present_dispatch,
> +                             NULL, StandardMinorOpcode);
> +    if (!extension)
> +        goto bail;
> +
> +    present_request = extension->base;
> +
> +    if (!present_init())
> +        goto bail;
> +
> +    if (!present_event_init())
> +        goto bail;
> +
> +    for (i = 0; i < screenInfo.numScreens; i++) {
> +        if (!present_screen_init(screenInfo.screens[i], NULL))
> +            goto bail;
> +    }
> +    return;
> +
> +bail:
> +    FatalError("Cannot initialize Present extension");
> +}
> diff --git a/present/presentext.h b/present/presentext.h
> new file mode 100644
> index 0000000..f177f55
> --- /dev/null
> +++ b/present/presentext.h
> @@ -0,0 +1,29 @@
> +/*
> + * Copyright © 2013 Keith Packard
> + *
> + * 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.
> + */
> +
> +#ifndef _PRESENTEXT_H_
> +#define _PRESENTEXT_H_
> +
> +extern _X_EXPORT void
> +present_extension_init(void);
> +
> +#endif /* _PRESENTEXT_H_ */
> commit 563138298868f62501875d3016f03469dcffaad0
> Author: Keith Packard <keithp at keithp.com>
> Date:   Tue Apr 9 19:59:39 2013 -0700
> 
>    dri3: Add DRI3 extension
> 
>    Adds DRM compatible fences using futexes.
>    Uses FD passing to get pixmaps from DRM applications.
> 
>    Signed-off-by: Keith Packard <keithp at keithp.com>
>    Reviewed-by: Adam Jackson <ajax at redhat.com>
> 
> diff --git a/Makefile.am b/Makefile.am
> index 7be4271..7a8fc5b 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -17,6 +17,10 @@ if RECORD
> RECORD_DIR=record
> endif
> 
> +if DRI3
> +DRI3_DIR=dri3
> +endif
> +
> SUBDIRS = \
> 	doc \
> 	man \
> @@ -38,6 +42,7 @@ SUBDIRS = \
> 	damageext \
> 	$(COMPOSITE_DIR) \
> 	$(GLX_DIR) \
> +	$(DRI3_DIR) \
> 	exa \
> 	config \
> 	hw \
> diff --git a/Xext/sync.c b/Xext/sync.c
> index b2ee92e..126ce43 100644
> --- a/Xext/sync.c
> +++ b/Xext/sync.c
> @@ -141,7 +141,7 @@ SyncCheckWarnIsCounter(const SyncObject * pSync, const char *warning)
>  *  interested in the counter.  The two functions below are used to
>  *  delete and add triggers on this list.
>  */
> -static void
> +void
> SyncDeleteTriggerFromSyncObject(SyncTrigger * pTrigger)
> {
>     SyncTriggerList *pCur;
> @@ -184,7 +184,7 @@ SyncDeleteTriggerFromSyncObject(SyncTrigger * pTrigger)
>     }
> }
> 
> -static int
> +int
> SyncAddTriggerToSyncObject(SyncTrigger * pTrigger)
> {
>     SyncTriggerList *pCur;
> @@ -916,6 +916,34 @@ SyncCreate(ClientPtr client, XID id, unsigned char type)
>     return pSync;
> }
> 
> +int
> +SyncCreateFenceFromFD(ClientPtr client, DrawablePtr pDraw, XID id, int fd, BOOL initially_triggered)
> +{
> +    SyncFence  *pFence;
> +    int         status;
> +
> +    pFence = (SyncFence *) SyncCreate(client, id, SYNC_FENCE);
> +    if (!pFence)
> +        return BadAlloc;
> +
> +    status = miSyncInitFenceFromFD(pDraw, pFence, fd, initially_triggered);
> +    if (status != Success) {
> +        miSyncDestroyFence(pFence);
> +        return status;
> +    }
> +
> +    if (!AddResource(id, RTFence, (pointer) pFence))
> +        return BadAlloc;
> +
> +    return Success;
> +}
> +
> +int
> +SyncFDFromFence(ClientPtr client, DrawablePtr pDraw, SyncFence *pFence)
> +{
> +    return miSyncFDFromFence(pDraw, pFence);
> +}
> +
> static SyncCounter *
> SyncCreateCounter(ClientPtr client, XSyncCounter id, CARD64 initialvalue)
> {
> diff --git a/Xext/syncsrv.h b/Xext/syncsrv.h
> index c68229f..45fca04 100644
> --- a/Xext/syncsrv.h
> +++ b/Xext/syncsrv.h
> @@ -136,4 +136,17 @@ extern void SyncDestroySystemCounter(pointer pCounter);
> 
> extern SyncCounter *SyncInitDeviceIdleTime(DeviceIntPtr dev);
> extern void SyncRemoveDeviceIdleTime(SyncCounter *counter);
> +
> +int
> +SyncCreateFenceFromFD(ClientPtr client, DrawablePtr pDraw, XID id, int fd, BOOL initially_triggered);
> +
> +int
> +SyncFDFromFence(ClientPtr client, DrawablePtr pDraw, SyncFence *fence);
> +
> +void
> +SyncDeleteTriggerFromSyncObject(SyncTrigger * pTrigger);
> +
> +int
> +SyncAddTriggerToSyncObject(SyncTrigger * pTrigger);
> +
> #endif                          /* _SYNCSRV_H_ */
> diff --git a/configure.ac b/configure.ac
> index d29f170..546790d 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -613,6 +613,7 @@ AC_ARG_ENABLE(xdm-auth-1,     AS_HELP_STRING([--disable-xdm-auth-1], [Build XDM-
> AC_ARG_ENABLE(glx,            AS_HELP_STRING([--disable-glx], [Build GLX extension (default: enabled)]), [GLX=$enableval], [GLX=yes])
> AC_ARG_ENABLE(dri,            AS_HELP_STRING([--enable-dri], [Build DRI extension (default: auto)]), [DRI=$enableval])
> AC_ARG_ENABLE(dri2,           AS_HELP_STRING([--enable-dri2], [Build DRI2 extension (default: auto)]), [DRI2=$enableval], [DRI2=auto])
> +AC_ARG_ENABLE(dri3,           AS_HELP_STRING([--enable-dri3], [Build DRI3 extension (default: auto)]), [DRI3=$enableval], [DRI3=auto])
> AC_ARG_ENABLE(xinerama,	      AS_HELP_STRING([--disable-xinerama], [Build Xinerama extension (default: enabled)]), [XINERAMA=$enableval], [XINERAMA=yes])
> AC_ARG_ENABLE(xf86vidmode,    AS_HELP_STRING([--disable-xf86vidmode], [Build XF86VidMode extension (default: auto)]), [XF86VIDMODE=$enableval], [XF86VIDMODE=auto])
> AC_ARG_ENABLE(xace,           AS_HELP_STRING([--disable-xace], [Build X-ACE extension (default: enabled)]), [XACE=$enableval], [XACE=yes])
> @@ -715,6 +716,7 @@ case $host_os in
> 		CONFIG_UDEV_KMS=no
> 		DGA=no
> 		DRI2=no
> +		DRI3=no
> 		INT10MODULE=no
> 		PCI=no
> 		VGAHW=no
> @@ -732,6 +734,7 @@ case $host_os in
> 		VBE=no
> 		DRM=no
> 		DRI2=no
> +		DRI3=no
> 
> 		if test x$XQUARTZ = xauto; then
> 			AC_CACHE_CHECK([whether to build Xquartz],xorg_cv_Carbon_framework,[
> @@ -781,6 +784,7 @@ SCRNSAVERPROTO="scrnsaverproto >= 1.1"
> RESOURCEPROTO="resourceproto >= 1.2.0"
> DRIPROTO="xf86driproto >= 2.1.0"
> DRI2PROTO="dri2proto >= 2.8"
> +DRI3PROTO="dri3proto >= 1.0"
> XINERAMAPROTO="xineramaproto"
> BIGFONTPROTO="xf86bigfontproto >= 1.2.0"
> DGAPROTO="xf86dgaproto >= 2.0.99.1"
> @@ -1113,7 +1117,22 @@ case "$DRI2,$HAVE_DRI2PROTO" in
> esac
> AM_CONDITIONAL(DRI2, test "x$DRI2" = xyes)
> 
> -if test "x$DRI" = xyes || test "x$DRI2" = xyes || test "x$CONFIG_UDEV_KMS" = xyes; then
> +PKG_CHECK_MODULES([DRI3PROTO], $DRI3PROTO,
> +                  [HAVE_DRI3PROTO=yes], [HAVE_DRI3PROTO=no])
> +case "$DRI3,$HAVE_DRI3PROTO" in
> +	yes,no)
> +		AC_MSG_ERROR([DRI3 requested, but dri3proto not found.])
> +		;;
> +	yes,yes | auto,yes)
> +		AC_DEFINE(DRI3, 1, [Build DRI3 extension])
> +		DRI3=yes
> +		DRI3_LIB='$(top_builddir)/dri3/libdri3.la'
> +		SDK_REQUIRED_MODULES="$SDK_REQUIRED_MODULES $DRI3PROTO"
> +		;;
> +esac
> +AM_CONDITIONAL(DRI3, test "x$DRI3" = xyes)
> +
> +if test "x$DRI" = xyes || test "x$DRI2" = xyes || test "x$DRI3" = xyes || test "x$CONFIG_UDEV_KMS" = xyes; then
> 	if test "x$DRM" = xyes; then
> 		AC_DEFINE(WITH_LIBDRM, 1, [Building with libdrm support])
> 		PKG_CHECK_MODULES([LIBDRM], $LIBDRM)
> @@ -1306,6 +1325,7 @@ if test "x$XDMAUTH" = xyes; then
> 		XDMCP_MODULES="xdmcp"
> 	fi
> fi
> +REQUIRED_LIBS="$REQUIRED_LIBS xshmfence"
> 
> AC_DEFINE_DIR(COMPILEDDEFAULTFONTPATH, FONTPATH, [Default font path])
> AC_DEFINE_DIR(SERVER_MISC_CONFIG_PATH, SERVERCONFIG, [Server miscellaneous config path])
> @@ -1577,7 +1597,7 @@ AC_MSG_RESULT([$XVFB])
> AM_CONDITIONAL(XVFB, [test "x$XVFB" = xyes])
> 
> if test "x$XVFB" = xyes; then
> -	XVFB_LIBS="$FB_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB"
> +	XVFB_LIBS="$FB_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB"
> 	XVFB_SYS_LIBS="$XVFBMODULES_LIBS $GLX_SYS_LIBS"
> 	AC_SUBST([XVFB_LIBS])
> 	AC_SUBST([XVFB_SYS_LIBS])
> @@ -1598,7 +1618,7 @@ if test "x$XNEST" = xyes; then
> 	if test "x$have_xnest" = xno; then
> 		AC_MSG_ERROR([Xnest build explicitly requested, but required modules not found.])
> 	fi
> -	XNEST_LIBS="$FB_LIB $FIXES_LIB $MI_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB $DIX_LIB $OS_LIB"
> +	XNEST_LIBS="$FB_LIB $FIXES_LIB $MI_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB  $DRI3_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB $DIX_LIB $OS_LIB"
> 	XNEST_SYS_LIBS="$XNESTMODULES_LIBS $GLX_SYS_LIBS"
> 	AC_SUBST([XNEST_LIBS])
> 	AC_SUBST([XNEST_SYS_LIBS])
> @@ -1623,7 +1643,7 @@ if test "x$XORG" = xyes; then
> 	XORG_OSINCS='-I$(top_srcdir)/hw/xfree86/os-support -I$(top_srcdir)/hw/xfree86/os-support/bus -I$(top_srcdir)/os'
> 	XORG_INCS="$XORG_DDXINCS $XORG_OSINCS"
> 	XORG_CFLAGS="$XORGSERVER_CFLAGS -DHAVE_XORG_CONFIG_H"
> -	XORG_LIBS="$COMPOSITE_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $XI_LIB $XKB_LIB"
> +	XORG_LIBS="$COMPOSITE_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $XI_LIB $XKB_LIB"
> 
> 	dnl ==================================================================
> 	dnl symbol visibility
> @@ -2036,7 +2056,7 @@ if test "x$DMX" = xyes; then
> 	fi
> 	DMX_INCLUDES="$XEXT_INC $RENDER_INC $RECORD_INC"
> 	XDMX_CFLAGS="$DMXMODULES_CFLAGS"
> -	XDMX_LIBS="$FB_LIB $MI_LIB $XEXT_LIB $RENDER_LIB $RECORD_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $MIEXT_SYNC_LIB $MIEXT_SHADOW_LIB $MIEXT_DAMAGE_LIB $COMPOSITE_LIB $DAMAGE_LIB $MAIN_LIB $DIX_LIB $CONFIG_LIB $OS_LIB $FIXES_LIB"
> +	XDMX_LIBS="$FB_LIB $MI_LIB $XEXT_LIB $RENDER_LIB $RECORD_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB  $DRI3_LIB $MIEXT_SYNC_LIB $MIEXT_SHADOW_LIB $MIEXT_DAMAGE_LIB $COMPOSITE_LIB $DAMAGE_LIB $MAIN_LIB $DIX_LIB $CONFIG_LIB $OS_LIB $FIXES_LIB"
> 	XDMX_SYS_LIBS="$DMXMODULES_LIBS"
> 	AC_SUBST([XDMX_CFLAGS])
> 	AC_SUBST([XDMX_LIBS])
> @@ -2145,7 +2165,7 @@ if test "$KDRIVE" = yes; then
> 
>     KDRIVE_CFLAGS="$XSERVER_CFLAGS -DHAVE_KDRIVE_CONFIG_H $TSLIB_CFLAGS"
> 
> -    KDRIVE_PURE_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $OS_LIB"
> +    KDRIVE_PURE_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $OS_LIB"
>     KDRIVE_LIB='$(top_builddir)/hw/kdrive/src/libkdrive.la'
>     case $host_os in
> 	*linux*)
> @@ -2267,6 +2287,7 @@ Xext/Makefile
> Xi/Makefile
> xfixes/Makefile
> exa/Makefile
> +dri3/Makefile
> hw/Makefile
> hw/xfree86/Makefile
> hw/xfree86/common/Makefile
> diff --git a/dri3/Makefile.am b/dri3/Makefile.am
> new file mode 100644
> index 0000000..e47a734
> --- /dev/null
> +++ b/dri3/Makefile.am
> @@ -0,0 +1,13 @@
> +noinst_LTLIBRARIES = libdri3.la
> +AM_CFLAGS = \
> +	-DHAVE_XORG_CONFIG_H \
> +	@DIX_CFLAGS@ @XORG_CFLAGS@
> +
> +libdri3_la_SOURCES = \
> +	dri3.h \
> +	dri3_priv.h \
> +	dri3.c \
> +	dri3_request.c \
> +	dri3_screen.c
> +
> +sdk_HEADERS = dri3.h
> diff --git a/dri3/dri3.c b/dri3/dri3.c
> new file mode 100644
> index 0000000..2bca7ae
> --- /dev/null
> +++ b/dri3/dri3.c
> @@ -0,0 +1,87 @@
> +/*
> + * Copyright © 2013 Keith Packard
> + *
> + * 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_XORG_CONFIG_H
> +#include <xorg-config.h>
> +#endif
> +
> +#include "dri3_priv.h"
> +
> +int dri3_request;
> +DevPrivateKeyRec dri3_screen_private_key;
> +DevPrivateKeyRec dri3_window_private_key;
> +
> +static Bool
> +dri3_close_screen(ScreenPtr screen)
> +{
> +    dri3_screen_priv_ptr screen_priv = dri3_screen_priv(screen);
> +
> +    unwrap(screen_priv, screen, CloseScreen);
> +
> +    free(screen_priv);
> +    return (*screen->CloseScreen) (screen);
> +}
> +
> +Bool
> +dri3_screen_init(ScreenPtr screen, dri3_screen_info_ptr info)
> +{
> +    if (!dixRegisterPrivateKey(&dri3_screen_private_key, PRIVATE_SCREEN, 0))
> +        return FALSE;
> +
> +    if (!dri3_screen_priv(screen)) {
> +        dri3_screen_priv_ptr screen_priv = calloc(1, sizeof (dri3_screen_priv_rec));
> +        if (!screen_priv)
> +            return FALSE;
> +
> +        wrap(screen_priv, screen, CloseScreen, dri3_close_screen);
> +
> +        screen_priv->info = info;
> +
> +        dixSetPrivate(&screen->devPrivates, &dri3_screen_private_key, screen_priv);
> +    }
> +
> +    return TRUE;
> +}
> +
> +void
> +dri3_extension_init(void)
> +{
> +    ExtensionEntry *extension;
> +    int i;
> +
> +    extension = AddExtension(DRI3_NAME, DRI3NumberEvents, DRI3NumberErrors,
> +                             proc_dri3_dispatch, sproc_dri3_dispatch,
> +                             NULL, StandardMinorOpcode);
> +    if (!extension)
> +        goto bail;
> +
> +    dri3_request = extension->base;
> +
> +    for (i = 0; i < screenInfo.numScreens; i++) {
> +        if (!dri3_screen_init(screenInfo.screens[i], NULL))
> +            goto bail;
> +    }
> +    return;
> +
> +bail:
> +    FatalError("Cannot initialize DRI3 extension");
> +}
> diff --git a/dri3/dri3.h b/dri3/dri3.h
> new file mode 100644
> index 0000000..7774c87
> --- /dev/null
> +++ b/dri3/dri3.h
> @@ -0,0 +1,59 @@
> +/*
> + * Copyright © 2013 Keith Packard
> + *
> + * 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.
> + */
> +
> +#ifndef _DRI3_H_
> +#define _DRI3_H_
> +
> +#include <X11/extensions/dri3proto.h>
> +#include <randrstr.h>
> +
> +#define DRI3_SCREEN_INFO_VERSION        0
> +
> +typedef int (*dri3_open_proc)(ScreenPtr screen,
> +                              RRProviderPtr provider,
> +                              int *fd);
> +
> +typedef PixmapPtr (*dri3_pixmap_from_fd_proc) (ScreenPtr screen,
> +                                               int fd,
> +                                               CARD16 width,
> +                                               CARD16 height,
> +                                               CARD16 stride,
> +                                               CARD8 depth,
> +                                               CARD8 bpp);
> +
> +typedef int (*dri3_fd_from_pixmap_proc) (ScreenPtr screen,
> +                                         PixmapPtr pixmap,
> +                                         CARD16 *stride,
> +                                         CARD32 *size);
> +
> +typedef struct dri3_screen_info {
> +    uint32_t                    version;
> +
> +    dri3_open_proc              open;
> +    dri3_pixmap_from_fd_proc    pixmap_from_fd;
> +    dri3_fd_from_pixmap_proc    fd_from_pixmap;
> +} dri3_screen_info_rec, *dri3_screen_info_ptr;
> +
> +extern _X_EXPORT Bool
> +dri3_screen_init(ScreenPtr screen, dri3_screen_info_ptr info);
> +
> +#endif /* _DRI3_H_ */
> diff --git a/dri3/dri3_event.c b/dri3/dri3_event.c
> new file mode 100644
> index 0000000..02f0f65
> --- /dev/null
> +++ b/dri3/dri3_event.c
> @@ -0,0 +1,163 @@
> +/*
> + * Copyright © 2013 Keith Packard
> + *
> + * 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_XORG_CONFIG_H
> +#include <xorg-config.h>
> +#endif
> +
> +#include "dri3_priv.h"
> +
> +RESTYPE dri3_event_type;
> +
> +static int
> +dri3_free_event(pointer data, XID id)
> +{
> +    dri3_event_ptr dri3_event = (dri3_event_ptr) data;
> +    dri3_window_priv_ptr window_priv = dri3_window_priv(dri3_event->window);
> +    dri3_event_ptr *previous, current;
> +
> +    for (previous = &window_priv->events; (current = *previous); previous = &current->next) {
> +        if (current == dri3_event) {
> +            *previous = dri3_event->next;
> +            break;
> +        }
> +    }
> +    free((pointer) dri3_event);
> +    return 1;
> +
> +}
> +
> +void
> +dri3_free_events(WindowPtr window)
> +{
> +    dri3_window_priv_ptr window_priv = dri3_window_priv(window);
> +    dri3_event_ptr event;
> +
> +    if (!window_priv)
> +        return;
> +
> +    while ((event = window_priv->events))
> +        FreeResource(event->id, RT_NONE);
> +}
> +
> +static void
> +dri3_event_swap(xGenericEvent *from, xGenericEvent *to)
> +{
> +    *to = *from;
> +    swaps(&to->sequenceNumber);
> +    swapl(&to->length);
> +    swaps(&to->evtype);
> +    switch (from->evtype) {
> +    case DRI3_ConfigureNotify: {
> +        xDRI3ConfigureNotify *c = (xDRI3ConfigureNotify *) to;
> +
> +        swapl(&c->eid);
> +        swapl(&c->window);
> +        swaps(&c->x);
> +        swaps(&c->y);
> +        swaps(&c->width);
> +        swaps(&c->height);
> +        swaps(&c->off_x);
> +        swaps(&c->off_y);
> +        swaps(&c->pixmap_width);
> +        swaps(&c->pixmap_height);
> +        swapl(&c->pixmap_flags);
> +        break;
> +    }
> +    }
> +}
> +
> +void
> +dri3_send_config_notify(WindowPtr window, int x, int y, int w, int h, int bw, WindowPtr sibling)
> +{
> +    dri3_window_priv_ptr window_priv = dri3_window_priv(window);
> +
> +    if (window_priv) {
> +        xDRI3ConfigureNotify cn = {
> +            .type = GenericEvent,
> +            .extension = dri3_request,
> +            .length = (sizeof(xDRI3ConfigureNotify) - 32) >> 2,
> +            .evtype = DRI3_ConfigureNotify,
> +            .eid = 0,
> +            .window = window->drawable.id,
> +            .x = x,
> +            .y = y,
> +            .width = w,
> +            .height = h,
> +            .off_x = 0,
> +            .off_y = 0,
> +            .pixmap_width = w,
> +            .pixmap_height = h,
> +            .pixmap_flags = 0
> +        };
> +        dri3_event_ptr event;
> +        dri3_screen_priv_ptr screen_priv = dri3_screen_priv(window->drawable.pScreen);
> +
> +        if (screen_priv->info && screen_priv->info->driver_config)
> +            screen_priv->info->driver_config(window, &cn);
> +
> +        for (event = window_priv->events; event; event = event->next) {
> +            if (event->mask & (1 << DRI3ConfigureNotify)) {
> +                cn.eid = event->id;
> +                WriteEventsToClient(event->client, 1, (xEvent *) &cn);
> +            }
> +        }
> +    }
> +}
> +
> +int
> +dri3_select_input(ClientPtr client, XID eid, WindowPtr window, CARD32 mask)
> +{
> +    dri3_window_priv_ptr window_priv = dri3_window_priv(window);
> +    dri3_event_ptr event;
> +
> +    if (!window_priv)
> +        return BadAlloc;
> +
> +    event = calloc (1, sizeof (dri3_event_rec));
> +    if (!event)
> +        return BadAlloc;
> +
> +    event->client = client;
> +    event->window = window;
> +    event->id = eid;
> +    event->mask = mask;
> +
> +    event->next = window_priv->events;
> +    window_priv->events = event;
> +
> +    if (!AddResource(event->id, dri3_event_type, (pointer) event))
> +        return BadAlloc;
> +
> +    return Success;
> +}
> +
> +Bool
> +dri3_event_init(void)
> +{
> +    dri3_event_type = CreateNewResourceType(dri3_free_event, "DRI3Event");
> +    if (!dri3_event_type)
> +        return FALSE;
> +
> +    GERegisterExtension(dri3_request, dri3_event_swap);
> +    return TRUE;
> +}
> diff --git a/dri3/dri3_priv.h b/dri3/dri3_priv.h
> new file mode 100644
> index 0000000..e2fed83
> --- /dev/null
> +++ b/dri3/dri3_priv.h
> @@ -0,0 +1,80 @@
> +/*
> + * Copyright © 2013 Keith Packard
> + *
> + * 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.
> + */
> +
> +#ifndef _DRI3PRIV_H_
> +#define _DRI3PRIV_H_
> +
> +#include <X11/X.h>
> +#include "scrnintstr.h"
> +#include "misc.h"
> +#include "list.h"
> +#include "windowstr.h"
> +#include "dixstruct.h"
> +#include <randrstr.h>
> +#include "dri3.h"
> +
> +extern int dri3_request;
> +
> +extern DevPrivateKeyRec dri3_screen_private_key;
> +
> +typedef struct dri3_screen_priv {
> +    CloseScreenProcPtr          CloseScreen;
> +    ConfigNotifyProcPtr         ConfigNotify;
> +    DestroyWindowProcPtr        DestroyWindow;
> +
> +    dri3_screen_info_ptr        info;
> +} dri3_screen_priv_rec, *dri3_screen_priv_ptr;
> +
> +#define wrap(priv,real,mem,func) {\
> +    priv->mem = real->mem; \
> +    real->mem = func; \
> +}
> +
> +#define unwrap(priv,real,mem) {\
> +    real->mem = priv->mem; \
> +}
> +
> +static inline dri3_screen_priv_ptr
> +dri3_screen_priv(ScreenPtr screen)
> +{
> +    return (dri3_screen_priv_ptr)dixLookupPrivate(&(screen)->devPrivates, &dri3_screen_private_key);
> +}
> +
> +int
> +proc_dri3_dispatch(ClientPtr client);
> +
> +int
> +sproc_dri3_dispatch(ClientPtr client);
> +
> +/* DDX interface */
> +
> +int
> +dri3_open(ClientPtr client, ScreenPtr screen, RRProviderPtr provider, int *fd);
> +
> +int
> +dri3_pixmap_from_fd(PixmapPtr *ppixmap, ScreenPtr screen, int fd,
> +                    CARD16 width, CARD16 height, CARD16 stride, CARD8 depth, CARD8 bpp);
> +
> +int
> +dri3_fd_from_pixmap(int *pfd, PixmapPtr pixmap, CARD16 *stride, CARD32 *size);
> +
> +#endif /* _DRI3PRIV_H_ */
> diff --git a/dri3/dri3_request.c b/dri3/dri3_request.c
> new file mode 100644
> index 0000000..3ebb9d5
> --- /dev/null
> +++ b/dri3/dri3_request.c
> @@ -0,0 +1,394 @@
> +/*
> + * Copyright © 2013 Keith Packard
> + *
> + * 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_XORG_CONFIG_H
> +#include <xorg-config.h>
> +#endif
> +
> +#include "dri3_priv.h"
> +#include <syncsrv.h>
> +#include <unistd.h>
> +#include <xace.h>
> +#include "../Xext/syncsdk.h"
> +
> +static int
> +proc_dri3_query_version(ClientPtr client)
> +{
> +    REQUEST(xDRI3QueryVersionReq);
> +    xDRI3QueryVersionReply rep = {
> +        .type = X_Reply,
> +        .sequenceNumber = client->sequence,
> +        .length = 0,
> +        .majorVersion = DRI3_MAJOR,
> +        .minorVersion = DRI3_MINOR
> +    };
> +
> +    REQUEST_SIZE_MATCH(xDRI3QueryVersionReq);
> +    (void) stuff;
> +    if (client->swapped) {
> +        swaps(&rep.sequenceNumber);
> +        swapl(&rep.length);
> +        swapl(&rep.majorVersion);
> +        swapl(&rep.minorVersion);
> +    }
> +    WriteToClient(client, sizeof(rep), &rep);
> +    return Success;
> +}
> +
> +static int
> +proc_dri3_open(ClientPtr client)
> +{
> +    REQUEST(xDRI3OpenReq);
> +    xDRI3OpenReply rep = {
> +        .type = X_Reply,
> +        .nfd = 1,
> +        .sequenceNumber = client->sequence,
> +        .length = 0,
> +    };
> +    RRProviderPtr provider;
> +    DrawablePtr drawable;
> +    ScreenPtr screen;
> +    int fd;
> +    int status;
> +
> +    REQUEST_SIZE_MATCH(xDRI3OpenReq);
> +
> +    status = dixLookupDrawable(&drawable, stuff->drawable, client, 0, DixReadAccess);
> +    if (status != Success)
> +        return status;
> +
> +    if (stuff->provider == None)
> +        provider = NULL;
> +    else if (!RRProviderType) {
> +        return BadMatch;
> +    } else {
> +        VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess);
> +        if (drawable->pScreen != provider->pScreen)
> +            return BadMatch;
> +    }
> +    screen = drawable->pScreen;
> +
> +    status = dri3_open(client, screen, provider, &fd);
> +    if (status != Success)
> +        return status;
> +
> +    if (client->swapped) {
> +        swaps(&rep.sequenceNumber);
> +        swapl(&rep.length);
> +    }
> +
> +    if (WriteFdToClient(client, fd, TRUE) < 0) {
> +        close(fd);
> +        return BadAlloc;
> +    }
> +
> +    WriteToClient(client, sizeof (rep), &rep);
> +
> +    return Success;
> +}
> +
> +static int
> +proc_dri3_pixmap_from_buffer(ClientPtr client)
> +{
> +    REQUEST(xDRI3PixmapFromBufferReq);
> +    int fd;
> +    DrawablePtr drawable;
> +    PixmapPtr pixmap;
> +    int rc;
> +
> +    SetReqFds(client, 1);
> +    REQUEST_SIZE_MATCH(xDRI3PixmapFromBufferReq);
> +    LEGAL_NEW_RESOURCE(stuff->pixmap, client);
> +    rc = dixLookupDrawable(&drawable, stuff->drawable, client, M_ANY, DixGetAttrAccess);
> +    if (rc != Success) {
> +        client->errorValue = stuff->drawable;
> +        return rc;
> +    }
> +
> +    if (!stuff->width || !stuff->height) {
> +        client->errorValue = 0;
> +        return BadValue;
> +    }
> +
> +    if (stuff->width > 32767 || stuff->height > 32767)
> +        return BadAlloc;
> +
> +    if (stuff->depth != 1) {
> +        DepthPtr depth = drawable->pScreen->allowedDepths;
> +        int i;
> +        for (i = 0; i < drawable->pScreen->numDepths; i++, depth++)
> +            if (depth->depth == stuff->depth)
> +                break;
> +        if (i == drawable->pScreen->numDepths) {
> +            client->errorValue = stuff->depth;
> +            return BadValue;
> +        }
> +    }
> +
> +    fd = ReadFdFromClient(client);
> +    if (fd < 0)
> +        return BadValue;
> +
> +    rc = dri3_pixmap_from_fd(&pixmap,
> +                             drawable->pScreen, fd,
> +                             stuff->width, stuff->height,
> +                             stuff->stride, stuff->depth,
> +                             stuff->bpp);
> +    close (fd);
> +    if (rc != Success)
> +        return rc;
> +
> +    pixmap->drawable.id = stuff->pixmap;
> +
> +    /* security creation/labeling check */
> +    rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pixmap, RT_PIXMAP,
> +                  pixmap, RT_NONE, NULL, DixCreateAccess);
> +
> +    if (rc != Success) {
> +        (*drawable->pScreen->DestroyPixmap) (pixmap);
> +        return rc;
> +    }
> +    if (AddResource(stuff->pixmap, RT_PIXMAP, (pointer) pixmap))
> +        return Success;
> +
> +    return Success;
> +}
> +
> +static int
> +proc_dri3_buffer_from_pixmap(ClientPtr client)
> +{
> +    REQUEST(xDRI3BufferFromPixmapReq);
> +    xDRI3BufferFromPixmapReply rep = {
> +        .type = X_Reply,
> +        .nfd = 1,
> +        .sequenceNumber = client->sequence,
> +        .length = 0,
> +    };
> +    int rc;
> +    int fd;
> +    PixmapPtr pixmap;
> +
> +    REQUEST_SIZE_MATCH(xDRI3BufferFromPixmapReq);
> +    rc = dixLookupResourceByType((pointer *) &pixmap, stuff->pixmap, RT_PIXMAP,
> +                                 client, DixWriteAccess);
> +    if (rc != Success) {
> +        client->errorValue = stuff->pixmap;
> +        return rc;
> +    }
> +
> +    rep.width = pixmap->drawable.width;
> +    rep.height = pixmap->drawable.height;
> +    rep.depth = pixmap->drawable.depth;
> +    rep.bpp = pixmap->drawable.bitsPerPixel;
> +
> +    rc = dri3_fd_from_pixmap(&fd, pixmap, &rep.stride, &rep.size);
> +    if (rc != Success)
> +        return rc;
> +
> +    if (client->swapped) {
> +        swaps(&rep.sequenceNumber);
> +        swapl(&rep.length);
> +        swapl(&rep.size);
> +        swaps(&rep.width);
> +        swaps(&rep.height);
> +        swaps(&rep.stride);
> +    }
> +    if (WriteFdToClient(client, fd, TRUE) < 0) {
> +        close(fd);
> +        return BadAlloc;
> +    }
> +
> +    WriteToClient(client, sizeof(rep), &rep);
> +
> +    return client->noClientException;
> +}
> +
> +static int
> +proc_dri3_fence_from_fd(ClientPtr client)
> +{
> +    REQUEST(xDRI3FenceFromFDReq);
> +    DrawablePtr drawable;
> +    int fd;
> +    int status;
> +
> +    SetReqFds(client, 1);
> +    REQUEST_SIZE_MATCH(xDRI3FenceFromFDReq);
> +    LEGAL_NEW_RESOURCE(stuff->fence, client);
> +
> +    status = dixLookupDrawable(&drawable, stuff->drawable, client, M_ANY, DixGetAttrAccess);
> +    if (status != Success)
> +        return status;
> +
> +    fd = ReadFdFromClient(client);
> +    if (fd < 0)
> +        return BadValue;
> +
> +    status = SyncCreateFenceFromFD(client, drawable, stuff->fence,
> +                                   fd, stuff->initially_triggered);
> +
> +    return status;
> +}
> +
> +static int
> +proc_dri3_fd_from_fence(ClientPtr client)
> +{
> +    REQUEST(xDRI3FDFromFenceReq);
> +    xDRI3FDFromFenceReply rep = {
> +        .type = X_Reply,
> +        .nfd = 1,
> +        .sequenceNumber = client->sequence,
> +        .length = 0,
> +    };
> +    DrawablePtr drawable;
> +    int fd;
> +    int status;
> +    SyncFence *fence;
> +
> +    REQUEST_SIZE_MATCH(xDRI3FDFromFenceReq);
> +
> +    status = dixLookupDrawable(&drawable, stuff->drawable, client, M_ANY, DixGetAttrAccess);
> +    if (status != Success)
> +        return status;
> +    status = SyncVerifyFence(&fence, stuff->fence, client, DixWriteAccess);
> +    if (status != Success)
> +        return status;
> +
> +    fd = SyncFDFromFence(client, drawable, fence);
> +    if (fd < 0)
> +        return BadMatch;
> +
> +    if (client->swapped) {
> +        swaps(&rep.sequenceNumber);
> +        swapl(&rep.length);
> +    }
> +    if (WriteFdToClient(client, fd, FALSE) < 0)
> +        return BadAlloc;
> +
> +    WriteToClient(client, sizeof(rep), &rep);
> +
> +    return client->noClientException;
> +}
> +
> +int (*proc_dri3_vector[DRI3NumberRequests]) (ClientPtr) = {
> +    proc_dri3_query_version,            /* 0 */
> +    proc_dri3_open,                     /* 1 */
> +    proc_dri3_pixmap_from_buffer,       /* 2 */
> +    proc_dri3_buffer_from_pixmap,       /* 3 */
> +    proc_dri3_fence_from_fd,            /* 4 */
> +    proc_dri3_fd_from_fence,            /* 5 */
> +};
> +
> +int
> +proc_dri3_dispatch(ClientPtr client)
> +{
> +    REQUEST(xReq);
> +    if (stuff->data >= DRI3NumberRequests || !proc_dri3_vector[stuff->data])
> +        return BadRequest;
> +    return (*proc_dri3_vector[stuff->data]) (client);
> +}
> +
> +static int
> +sproc_dri3_query_version(ClientPtr client)
> +{
> +    REQUEST(xDRI3QueryVersionReq);
> +
> +    swaps(&stuff->length);
> +    swapl(&stuff->majorVersion);
> +    swapl(&stuff->minorVersion);
> +    return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
> +}
> +
> +static int
> +sproc_dri3_open(ClientPtr client)
> +{
> +    REQUEST(xDRI3OpenReq);
> +
> +    swaps(&stuff->length);
> +    swapl(&stuff->drawable);
> +    swapl(&stuff->provider);
> +    return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
> +}
> +
> +static int
> +sproc_dri3_pixmap_from_buffer(ClientPtr client)
> +{
> +    REQUEST(xDRI3PixmapFromBufferReq);
> +
> +    swaps(&stuff->length);
> +    swapl(&stuff->pixmap);
> +    swapl(&stuff->drawable);
> +    swapl(&stuff->size);
> +    swaps(&stuff->width);
> +    swaps(&stuff->height);
> +    swaps(&stuff->stride);
> +    return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
> +}
> +
> +static int
> +sproc_dri3_buffer_from_pixmap(ClientPtr client)
> +{
> +    REQUEST(xDRI3BufferFromPixmapReq);
> +
> +    swaps(&stuff->length);
> +    swapl(&stuff->pixmap);
> +    return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
> +}
> +
> +static int
> +sproc_dri3_fence_from_fd(ClientPtr client)
> +{
> +    REQUEST(xDRI3FenceFromFDReq);
> +
> +    swaps(&stuff->length);
> +    swapl(&stuff->drawable);
> +    swapl(&stuff->fence);
> +    return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
> +}
> +
> +static int
> +sproc_dri3_fd_from_fence(ClientPtr client)
> +{
> +    REQUEST(xDRI3FDFromFenceReq);
> +
> +    swaps(&stuff->length);
> +    swapl(&stuff->drawable);
> +    swapl(&stuff->fence);
> +    return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
> +}
> +
> +int (*sproc_dri3_vector[DRI3NumberRequests]) (ClientPtr) = {
> +    sproc_dri3_query_version,           /* 0 */
> +    sproc_dri3_open,                    /* 1 */
> +    sproc_dri3_pixmap_from_buffer,      /* 2 */
> +    sproc_dri3_buffer_from_pixmap,      /* 3 */
> +    sproc_dri3_fence_from_fd,           /* 4 */
> +    sproc_dri3_fd_from_fence,           /* 5 */
> +};
> +
> +int
> +sproc_dri3_dispatch(ClientPtr client)
> +{
> +    REQUEST(xReq);
> +    if (stuff->data >= DRI3NumberRequests || !sproc_dri3_vector[stuff->data])
> +        return BadRequest;
> +    return (*sproc_dri3_vector[stuff->data]) (client);
> +}
> diff --git a/dri3/dri3_screen.c b/dri3/dri3_screen.c
> new file mode 100644
> index 0000000..cf2735b
> --- /dev/null
> +++ b/dri3/dri3_screen.c
> @@ -0,0 +1,80 @@
> +/*
> + * Copyright © 2013 Keith Packard
> + *
> + * 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_XORG_CONFIG_H
> +#include <xorg-config.h>
> +#endif
> +
> +#include "dri3_priv.h"
> +#include <syncsdk.h>
> +#include <misync.h>
> +#include <misyncshm.h>
> +#include <randrstr.h>
> +
> +int
> +dri3_open(ClientPtr client, ScreenPtr screen, RRProviderPtr provider, int *fd)
> +{
> +    dri3_screen_priv_ptr        ds = dri3_screen_priv(screen);
> +    dri3_screen_info_ptr        info = ds->info;
> +    int                         rc;
> +
> +    if (!info || !info->open)
> +        return BadMatch;
> +
> +    rc = (*info->open) (screen, provider, fd);
> +    if (rc != Success)
> +        return rc;
> +
> +    return Success;
> +}
> +
> +int
> +dri3_pixmap_from_fd(PixmapPtr *ppixmap, ScreenPtr screen, int fd,
> +                    CARD16 width, CARD16 height, CARD16 stride, CARD8 depth, CARD8 bpp)
> +{
> +    dri3_screen_priv_ptr        ds = dri3_screen_priv(screen);
> +    dri3_screen_info_ptr        info = ds->info;
> +    PixmapPtr                   pixmap;
> +
> +    pixmap = (*info->pixmap_from_fd) (screen, fd, width, height, stride, depth, bpp);
> +    if (!pixmap)
> +        return BadAlloc;
> +
> +    *ppixmap = pixmap;
> +    return Success;
> +}
> +
> +int
> +dri3_fd_from_pixmap(int *pfd, PixmapPtr pixmap, CARD16 *stride, CARD32 *size)
> +{
> +    ScreenPtr                   screen = pixmap->drawable.pScreen;
> +    dri3_screen_priv_ptr        ds = dri3_screen_priv(screen);
> +    dri3_screen_info_ptr        info = ds->info;
> +    int                         fd;
> +
> +    fd = (*info->fd_from_pixmap)(screen, pixmap, stride, size);
> +    if (fd < 0)
> +        return BadAlloc;
> +    *pfd = fd;
> +    return Success;
> +}
> +
> diff --git a/dri3/dri3int.h b/dri3/dri3int.h
> new file mode 100644
> index 0000000..7f53eba
> --- /dev/null
> +++ b/dri3/dri3int.h
> @@ -0,0 +1,26 @@
> +/*
> + * Copyright © 2011 Daniel Stone
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> + * DEALINGS IN THE SOFTWARE.
> + *
> + * Author: Daniel Stone <daniel at fooishbar.org>
> + */
> +
> +extern Bool DRI2ModuleSetup(void);
> diff --git a/hw/dmx/dmxinit.c b/hw/dmx/dmxinit.c
> index 65416ed..bd868a0 100644
> --- a/hw/dmx/dmxinit.c
> +++ b/hw/dmx/dmxinit.c
> @@ -109,6 +109,8 @@ Bool dmxGLXSyncSwap = FALSE;
> Bool dmxGLXFinishSwap = FALSE;
> #endif
> 
> +RESTYPE RRProviderType = 0;
> +
> Bool dmxIgnoreBadFontPaths = FALSE;
> 
> Bool dmxAddRemoveScreens = FALSE;
> diff --git a/hw/xfree86/Makefile.am b/hw/xfree86/Makefile.am
> index 59cfb5f..eea16a8 100644
> --- a/hw/xfree86/Makefile.am
> +++ b/hw/xfree86/Makefile.am
> @@ -41,7 +41,7 @@ nodist_Xorg_SOURCES = sdksyms.c
> AM_CFLAGS = $(DIX_CFLAGS) @XORG_CFLAGS@
> AM_CPPFLAGS = $(XORG_INCS) -I$(srcdir)/parser -I$(top_srcdir)/miext/cw \
> 	-I$(srcdir)/ddc -I$(srcdir)/i2c -I$(srcdir)/modes -I$(srcdir)/ramdac \
> -	-I$(srcdir)/dri -I$(srcdir)/dri2
> +	-I$(srcdir)/dri -I$(srcdir)/dri2 -I$(top_srcdir)/dri3
> 
> LOCAL_LIBS = \
>             $(MAIN_LIB) \
> @@ -59,6 +59,8 @@ LOCAL_LIBS = \
>             dixmods/libxorgxkb.la \
>             $(DRI_LIB) \
>             $(DRI2_LIB) \
> +	    $(top_builddir)/dri3/libdri3.la \
> +	    $(top_builddir)/miext/sync/libsync.la \
>             $(top_builddir)/mi/libmi.la \
>             $(top_builddir)/os/libos.la
> Xorg_LDADD = \
> diff --git a/hw/xfree86/sdksyms.sh b/hw/xfree86/sdksyms.sh
> index 48b48b5..7c9734c 100755
> --- a/hw/xfree86/sdksyms.sh
> +++ b/hw/xfree86/sdksyms.sh
> @@ -99,6 +99,7 @@ cat > sdksyms.c << EOF
> # include "dri2.h"
> #endif
> 
> +# include "dri3.h"
> 
> /* hw/xfree86/vgahw/Makefile.am -- module */
> /*
> diff --git a/include/dix-config.h.in b/include/dix-config.h.in
> index a643dfc..d96da6a 100644
> --- a/include/dix-config.h.in
> +++ b/include/dix-config.h.in
> @@ -39,6 +39,9 @@
> /* Build DPMS extension */
> #undef DPMSExtension
> 
> +/* Build DRI3 extension */
> +#undef DRI3
> +
> /* Build GLX extension */
> #undef GLXEXT
> 
> diff --git a/include/extinit.h b/include/extinit.h
> index 6d67bf2..bdb149c 100644
> --- a/include/extinit.h
> +++ b/include/extinit.h
> @@ -176,4 +176,9 @@ extern void XvExtensionInit(void);
> extern void XvMCExtensionInit(void);
> #endif
> 
> +#if defined(DRI3)
> +#include <X11/extensions/dri3proto.h>
> +extern void dri3_extension_init(void);
> +#endif
> +
> #endif
> diff --git a/include/xorg-server.h.in b/include/xorg-server.h.in
> index 81935be..5b3b664 100644
> --- a/include/xorg-server.h.in
> +++ b/include/xorg-server.h.in
> @@ -28,6 +28,9 @@
> /* Build DPMS extension */
> #undef DPMSExtension
> 
> +/* Build DRI3 extension */
> +#undef DRI3
> +
> /* Build GLX extension */
> #undef GLXEXT
> 
> diff --git a/mi/miinitext.c b/mi/miinitext.c
> index 145da38..e49948b 100644
> --- a/mi/miinitext.c
> +++ b/mi/miinitext.c
> @@ -287,6 +287,7 @@ static ExtensionModule staticExtensions[] = {
> #ifdef DPMSExtension
>     {DPMSExtensionInit, DPMSExtensionName, &noDPMSExtension},
> #endif
> +    {dri3_extension_init, DRI3_NAME, NULL},
> #ifdef RES
>     {ResExtensionInit, XRES_NAME, &noResExtension},
> #endif
> diff --git a/miext/sync/Makefile.am b/miext/sync/Makefile.am
> index 9aa1ba5..e25ceac 100644
> --- a/miext/sync/Makefile.am
> +++ b/miext/sync/Makefile.am
> @@ -5,10 +5,11 @@ AM_CFLAGS = $(DIX_CFLAGS)
> AM_CPPFLAGS = 
> 
> if XORG
> -sdk_HEADERS = misync.h misyncstr.h
> +sdk_HEADERS = misync.h misyncstr.h misyncshm.h
> endif
> 
> libsync_la_SOURCES =	\
> 	misync.c	\
> 	misync.h	\
> +	misyncshm.c	\
> 	misyncstr.h
> diff --git a/miext/sync/misync.c b/miext/sync/misync.c
> index f380547..3d03d1b 100644
> --- a/miext/sync/misync.c
> +++ b/miext/sync/misync.c
> @@ -29,20 +29,7 @@
> #include "misync.h"
> #include "misyncstr.h"
> 
> -static DevPrivateKeyRec syncScreenPrivateKeyRec;
> -static DevPrivateKey syncScreenPrivateKey = &syncScreenPrivateKeyRec;
> -
> -#define SYNC_SCREEN_PRIV(pScreen) 				\
> -    (SyncScreenPrivPtr) dixLookupPrivate(&pScreen->devPrivates,	\
> -					 syncScreenPrivateKey)
> -
> -typedef struct _syncScreenPriv {
> -    /* Wrappable sync-specific screen functions */
> -    SyncScreenFuncsRec funcs;
> -
> -    /* Wrapped screen functions */
> -    CloseScreenProcPtr CloseScreen;
> -} SyncScreenPrivRec, *SyncScreenPrivPtr;
> +DevPrivateKeyRec miSyncScreenPrivateKey;
> 
> /* Default implementations of the sync screen functions */
> void
> @@ -62,25 +49,25 @@ miSyncScreenDestroyFence(ScreenPtr pScreen, SyncFence * pFence)
> }
> 
> /* Default implementations of the per-object functions */
> -static void
> +void
> miSyncFenceSetTriggered(SyncFence * pFence)
> {
>     pFence->triggered = TRUE;
> }
> 
> -static void
> +void
> miSyncFenceReset(SyncFence * pFence)
> {
>     pFence->triggered = FALSE;
> }
> 
> -static Bool
> +Bool
> miSyncFenceCheckTriggered(SyncFence * pFence)
> {
>     return pFence->triggered;
> }
> 
> -static void
> +void
> miSyncFenceAddTrigger(SyncTrigger * pTrigger)
> {
>     (void) pTrigger;
> @@ -88,7 +75,7 @@ miSyncFenceAddTrigger(SyncTrigger * pTrigger)
>     return;
> }
> 
> -static void
> +void
> miSyncFenceDeleteTrigger(SyncTrigger * pTrigger)
> {
>     (void) pTrigger;
> @@ -182,8 +169,8 @@ miSyncSetup(ScreenPtr pScreen)
>         &miSyncScreenDestroyFence
>     };
> 
> -    if (!dixPrivateKeyRegistered(syncScreenPrivateKey)) {
> -        if (!dixRegisterPrivateKey(syncScreenPrivateKey, PRIVATE_SCREEN,
> +    if (!dixPrivateKeyRegistered(&miSyncScreenPrivateKey)) {
> +        if (!dixRegisterPrivateKey(&miSyncScreenPrivateKey, PRIVATE_SCREEN,
>                                    sizeof(SyncScreenPrivRec)))
>             return FALSE;
>     }
> diff --git a/miext/sync/misync.h b/miext/sync/misync.h
> index deebb82..f63ec2b 100644
> --- a/miext/sync/misync.h
> +++ b/miext/sync/misync.h
> @@ -76,4 +76,25 @@ extern _X_EXPORT SyncScreenFuncsPtr miSyncGetScreenFuncs(ScreenPtr pScreen);
> extern _X_EXPORT Bool
>  miSyncSetup(ScreenPtr pScreen);
> 
> +Bool
> +miSyncFenceCheckTriggered(SyncFence * pFence);
> +
> +void
> +miSyncFenceSetTriggered(SyncFence * pFence);
> +
> +void
> +miSyncFenceReset(SyncFence * pFence);
> +
> +void
> +miSyncFenceAddTrigger(SyncTrigger * pTrigger);
> +
> +void
> +miSyncFenceDeleteTrigger(SyncTrigger * pTrigger);
> +
> +int
> +miSyncInitFenceFromFD(DrawablePtr pDraw, SyncFence *pFence, int fd, BOOL initially_triggered);
> +
> +int
> +miSyncFDFromFence(DrawablePtr pDraw, SyncFence *pFence);
> +
> #endif                          /* _MISYNC_H_ */
> diff --git a/miext/sync/misyncshm.c b/miext/sync/misyncshm.c
> new file mode 100644
> index 0000000..ddd15ae
> --- /dev/null
> +++ b/miext/sync/misyncshm.c
> @@ -0,0 +1,176 @@
> +/*
> + * Copyright © 2013 Keith Packard
> + *
> + * 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 "scrnintstr.h"
> +#include "misync.h"
> +#include "misyncstr.h"
> +#include "misyncshm.h"
> +#include "pixmapstr.h"
> +#include <sys/mman.h>
> +#include <unistd.h>
> +#include <X11/xshmfence.h>
> +
> +static DevPrivateKeyRec syncShmFencePrivateKey;
> +
> +typedef struct _SyncShmFencePrivate {
> +    int32_t             *fence;
> +    int                 fd;
> +} SyncShmFencePrivateRec, *SyncShmFencePrivatePtr;
> +
> +#define SYNC_FENCE_PRIV(pFence) \
> +    (SyncShmFencePrivatePtr) dixLookupPrivate(&pFence->devPrivates, &syncShmFencePrivateKey)
> +
> +static void
> +miSyncShmFenceSetTriggered(SyncFence * pFence)
> +{
> +    SyncShmFencePrivatePtr      pPriv = SYNC_FENCE_PRIV(pFence);
> +
> +    if (pPriv->fence)
> +        xshmfence_trigger(pPriv->fence);
> +    miSyncFenceSetTriggered(pFence);
> +}
> +
> +static void
> +miSyncShmFenceReset(SyncFence * pFence)
> +{
> +    SyncShmFencePrivatePtr      pPriv = SYNC_FENCE_PRIV(pFence);
> +
> +    if (pPriv->fence)
> +        xshmfence_reset(pPriv->fence);
> +    miSyncFenceReset(pFence);
> +}
> +
> +static Bool
> +miSyncShmFenceCheckTriggered(SyncFence * pFence)
> +{
> +    SyncShmFencePrivatePtr      pPriv = SYNC_FENCE_PRIV(pFence);
> +
> +    if (pPriv->fence)
> +        return xshmfence_query(pPriv->fence);
> +    else
> +        return miSyncFenceCheckTriggered(pFence);
> +}
> +
> +static void
> +miSyncShmFenceAddTrigger(SyncTrigger * pTrigger)
> +{
> +    miSyncFenceAddTrigger(pTrigger);
> +}
> +
> +static void
> +miSyncShmFenceDeleteTrigger(SyncTrigger * pTrigger)
> +{
> +    miSyncFenceDeleteTrigger(pTrigger);
> +}
> +
> +static const SyncFenceFuncsRec miSyncShmFenceFuncs = {
> +    &miSyncShmFenceSetTriggered,
> +    &miSyncShmFenceReset,
> +    &miSyncShmFenceCheckTriggered,
> +    &miSyncShmFenceAddTrigger,
> +    &miSyncShmFenceDeleteTrigger
> +};
> +
> +static void
> +miSyncShmScreenCreateFence(ScreenPtr pScreen, SyncFence * pFence,
> +                        Bool initially_triggered)
> +{
> +    SyncShmFencePrivatePtr      pPriv = SYNC_FENCE_PRIV(pFence);
> +
> +    pPriv->fence = NULL;
> +    miSyncScreenCreateFence(pScreen, pFence, initially_triggered);
> +    pFence->funcs = miSyncShmFenceFuncs;
> +}
> +
> +static void
> +miSyncShmScreenDestroyFence(ScreenPtr pScreen, SyncFence * pFence)
> +{
> +    SyncShmFencePrivatePtr      pPriv = SYNC_FENCE_PRIV(pFence);
> +
> +    if (pPriv->fence) {
> +        xshmfence_trigger(pPriv->fence);
> +        xshmfence_unmap_shm(pPriv->fence);
> +        close(pPriv->fd);
> +    }
> +    miSyncScreenDestroyFence(pScreen, pFence);
> +}
> +
> +int
> +miSyncInitFenceFromFD(DrawablePtr pDraw, SyncFence *pFence, int fd, BOOL initially_triggered)
> +
> +{
> +    SyncShmFencePrivatePtr      pPriv = SYNC_FENCE_PRIV(pFence);
> +
> +    miSyncInitFence(pDraw->pScreen, pFence, initially_triggered);
> +
> +    pPriv->fence = xshmfence_map_shm(fd);
> +    if (pPriv->fence) {
> +        pPriv->fd = fd;
> +        return Success;
> +    }
> +    else
> +        close(fd);
> +    return BadValue;
> +}
> +
> +int
> +miSyncFDFromFence(DrawablePtr pDraw, SyncFence *pFence)
> +{
> +    SyncShmFencePrivatePtr      pPriv = SYNC_FENCE_PRIV(pFence);
> +
> +    if (!pPriv->fence) {
> +        pPriv->fd = xshmfence_alloc_shm();
> +        if (pPriv->fd < 0)
> +            return -1;
> +        pPriv->fence = xshmfence_map_shm(pPriv->fd);
> +        if (!pPriv->fence) {
> +            close (pPriv->fd);
> +            return -1;
> +        }
> +    }
> +    return pPriv->fd;
> +}
> +
> +_X_EXPORT Bool miSyncShmScreenInit(ScreenPtr pScreen)
> +{
> +    SyncScreenFuncsPtr  funcs;
> +
> +    if (!miSyncSetup(pScreen))
> +        return FALSE;
> +
> +    if (!dixPrivateKeyRegistered(&syncShmFencePrivateKey)) {
> +        if (!dixRegisterPrivateKey(&syncShmFencePrivateKey, PRIVATE_SYNC_FENCE,
> +                                   sizeof(SyncShmFencePrivateRec)))
> +            return FALSE;
> +    }
> +
> +    funcs = miSyncGetScreenFuncs(pScreen);
> +
> +    funcs->CreateFence = miSyncShmScreenCreateFence;
> +    funcs->DestroyFence = miSyncShmScreenDestroyFence;
> +    return TRUE;
> +}
> +
> diff --git a/miext/sync/misyncshm.h b/miext/sync/misyncshm.h
> new file mode 100644
> index 0000000..4edbb50
> --- /dev/null
> +++ b/miext/sync/misyncshm.h
> @@ -0,0 +1,28 @@
> +/*
> + * Copyright © 2013 Keith Packard
> + *
> + * 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.
> + */
> +
> +#ifndef _MISYNCSHM_H_
> +#define _MISYNCSYM_H_
> +
> +extern _X_EXPORT Bool miSyncShmScreenInit(ScreenPtr pScreen);
> +
> +#endif /* _MISYNCSHM_H_ */
> diff --git a/miext/sync/misyncstr.h b/miext/sync/misyncstr.h
> index e19256f..b5bf6fd 100644
> --- a/miext/sync/misyncstr.h
> +++ b/miext/sync/misyncstr.h
> @@ -29,6 +29,7 @@
> #define _MISYNCSTR_H_
> 
> #include "dix.h"
> +#include "scrnintstr.h"
> #include <X11/extensions/syncconst.h>
> 
> #define CARD64 XSyncValue       /* XXX temporary! need real 64 bit values for Alpha */
> @@ -79,4 +80,18 @@ typedef struct _SyncTriggerList {
>     struct _SyncTriggerList *next;
> } SyncTriggerList;
> 
> +extern DevPrivateKeyRec miSyncScreenPrivateKey;
> +
> +#define SYNC_SCREEN_PRIV(pScreen) 				\
> +    (SyncScreenPrivPtr) dixLookupPrivate(&pScreen->devPrivates,	\
> +					 &miSyncScreenPrivateKey)
> +
> +typedef struct _syncScreenPriv {
> +    /* Wrappable sync-specific screen functions */
> +    SyncScreenFuncsRec funcs;
> +
> +    /* Wrapped screen functions */
> +    CloseScreenProcPtr CloseScreen;
> +} SyncScreenPrivRec, *SyncScreenPrivPtr;
> +
> #endif                          /* _MISYNCSTR_H_ */
> diff --git a/test/Makefile.am b/test/Makefile.am
> index eff0c9d..e59c412 100644
> --- a/test/Makefile.am
> +++ b/test/Makefile.am
> @@ -19,7 +19,7 @@ AM_CPPFLAGS += -I$(top_srcdir)/hw/xfree86/parser \
> 	-I$(top_srcdir)/hw/xfree86/ddc \
> 	-I$(top_srcdir)/hw/xfree86/i2c -I$(top_srcdir)/hw/xfree86/modes \
> 	-I$(top_srcdir)/hw/xfree86/ramdac -I$(top_srcdir)/hw/xfree86/dri \
> -	-I$(top_srcdir)/hw/xfree86/dri2
> +	-I$(top_srcdir)/hw/xfree86/dri2 -I$(top_srcdir)/dri3
> endif
> TEST_LDADD=libxservertest.la $(XORG_SYS_LIBS) $(XSERVER_SYS_LIBS) $(GLX_SYS_LIBS)
> 
> @@ -64,6 +64,10 @@ if DRI2
> libxservertest_la_LIBADD += $(top_builddir)/hw/xfree86/dri2/libdri2.la
> endif
> 
> +if DRI3
> +libxservertest_la_LIBADD += $(top_builddir)/dri3/libdri3.la
> +endif
> +
> else
> nodist_libxservertest_la_SOURCES = \
>             ddxstubs.c \
> @@ -105,6 +109,11 @@ libxservertest_la_LIBADD += \
>             $(top_builddir)/record/librecord.la
> endif
> 
> +if DRI3
> +libxservertest_la_LIBADD += \
> +            $(top_builddir)/dri3/libdri3.la
> +endif
> +
> if XQUARTZ
> libxservertest_la_LIBADD += \
>             $(top_builddir)/miext/rootless/librootless.la
> commit fdec793cdc2ef9a6ea66b311cb1068a7bd4a3be3
> Author: Keith Packard <keithp at keithp.com>
> Date:   Thu Jan 17 13:46:55 2013 -0800
> 
>    Add support for MIT-SHM AttachFd request
> 
>    This passes a file descriptor from the client to the server, which is
>    then mmap'd
> 
>    Signed-off-by: Keith Packard <keithp at keithp.com>
>    Reviewed-by: Adam Jackson <ajax at redhat.com>
> 
> diff --git a/Xext/shm.c b/Xext/shm.c
> index f6995cc..1a70260 100644
> --- a/Xext/shm.c
> +++ b/Xext/shm.c
> @@ -53,6 +53,7 @@ in this Software without prior written authorization from The Open Group.
> #include "xace.h"
> #include <X11/extensions/shmproto.h>
> #include <X11/Xfuncproto.h>
> +#include <sys/mman.h>
> #include "protocol-versions.h"
> 
> /* Needed for Solaris cross-zone shared memory extension */
> @@ -382,8 +383,10 @@ ProcShmAttach(ClientPtr client)
>         client->errorValue = stuff->readOnly;
>         return BadValue;
>     }
> -    for (shmdesc = Shmsegs;
> -         shmdesc && (shmdesc->shmid != stuff->shmid); shmdesc = shmdesc->next);
> +    for (shmdesc = Shmsegs; shmdesc; shmdesc = shmdesc->next) {
> +        if (!shmdesc->is_fd && shmdesc->shmid == stuff->shmid)
> +            break;
> +    }
>     if (shmdesc) {
>         if (!stuff->readOnly && !shmdesc->writable)
>             return BadAccess;
> @@ -393,6 +396,7 @@ ProcShmAttach(ClientPtr client)
>         shmdesc = malloc(sizeof(ShmDescRec));
>         if (!shmdesc)
>             return BadAlloc;
> +        shmdesc->is_fd = FALSE;
>         shmdesc->addr = shmat(stuff->shmid, 0,
>                               stuff->readOnly ? SHM_RDONLY : 0);
>         if ((shmdesc->addr == ((char *) -1)) || SHMSTAT(stuff->shmid, &buf)) {
> @@ -431,7 +435,10 @@ ShmDetachSegment(pointer value, /* must conform to DeleteType */
> 
>     if (--shmdesc->refcnt)
>         return TRUE;
> -    shmdt(shmdesc->addr);
> +    if (shmdesc->is_fd)
> +        munmap(shmdesc->addr, shmdesc->size);
> +    else
> +        shmdt(shmdesc->addr);
>     for (prev = &Shmsegs; *prev != shmdesc; prev = &(*prev)->next);
>     *prev = shmdesc->next;
>     free(shmdesc);
> @@ -1088,6 +1095,122 @@ ProcShmCreatePixmap(ClientPtr client)
> }
> 
> static int
> +ProcShmAttachFd(ClientPtr client)
> +{
> +    int fd;
> +    ShmDescPtr shmdesc;
> +    REQUEST(xShmAttachFdReq);
> +    struct stat statb;
> +
> +    SetReqFds(client, 1);
> +    REQUEST_SIZE_MATCH(xShmAttachFdReq);
> +    LEGAL_NEW_RESOURCE(stuff->shmseg, client);
> +    if ((stuff->readOnly != xTrue) && (stuff->readOnly != xFalse)) {
> +        client->errorValue = stuff->readOnly;
> +        return BadValue;
> +    }
> +    fd = ReadFdFromClient(client);
> +    if (fd < 0)
> +        return BadMatch;
> +
> +    if (fstat(fd, &statb) < 0 || statb.st_size == 0) {
> +        close(fd);
> +        return BadMatch;
> +    }
> +
> +    shmdesc = malloc(sizeof(ShmDescRec));
> +    if (!shmdesc) {
> +        close(fd);
> +        return BadAlloc;
> +    }
> +    shmdesc->is_fd = TRUE;
> +    shmdesc->addr = mmap(NULL, statb.st_size,
> +                         stuff->readOnly ? PROT_READ : PROT_READ|PROT_WRITE,
> +                         MAP_SHARED,
> +                         fd, 0);
> +
> +    close(fd);
> +    if ((shmdesc->addr == ((char *) -1))) {
> +        free(shmdesc);
> +        return BadAccess;
> +    }
> +
> +    shmdesc->refcnt = 1;
> +    shmdesc->writable = !stuff->readOnly;
> +    shmdesc->size = statb.st_size;
> +    shmdesc->next = Shmsegs;
> +    Shmsegs = shmdesc;
> +
> +    if (!AddResource(stuff->shmseg, ShmSegType, (pointer) shmdesc))
> +        return BadAlloc;
> +    return Success;
> +}
> +
> +static int
> +ProcShmCreateSegment(ClientPtr client)
> +{
> +    int fd;
> +    ShmDescPtr shmdesc;
> +    REQUEST(xShmCreateSegmentReq);
> +    xShmCreateSegmentReply rep = {
> +        .type = X_Reply,
> +        .nfd = 1,
> +        .sequenceNumber = client->sequence,
> +        .length = 0,
> +    };
> +    char template[] = "/tmp/shm-XXXXXX";
> +
> +    REQUEST_SIZE_MATCH(xShmCreateSegmentReq);
> +    if ((stuff->readOnly != xTrue) && (stuff->readOnly != xFalse)) {
> +        client->errorValue = stuff->readOnly;
> +        return BadValue;
> +    }
> +    fd = mkstemp(template);
> +    if (fd < 0)
> +        return BadAlloc;
> +    unlink(template);
> +    if (ftruncate(fd, stuff->size) < 0) {
> +        close(fd);
> +        return BadAlloc;
> +    }
> +    shmdesc = malloc(sizeof(ShmDescRec));
> +    if (!shmdesc) {
> +        close(fd);
> +        return BadAlloc;
> +    }
> +    shmdesc->is_fd = TRUE;
> +    shmdesc->addr = mmap(NULL, stuff->size,
> +                         stuff->readOnly ? PROT_READ : PROT_READ|PROT_WRITE,
> +                         MAP_SHARED,
> +                         fd, 0);
> +
> +    if ((shmdesc->addr == ((char *) -1))) {
> +        close(fd);
> +        free(shmdesc);
> +        return BadAccess;
> +    }
> +
> +    shmdesc->refcnt = 1;
> +    shmdesc->writable = !stuff->readOnly;
> +    shmdesc->size = stuff->size;
> +    shmdesc->next = Shmsegs;
> +    Shmsegs = shmdesc;
> +
> +    if (!AddResource(stuff->shmseg, ShmSegType, (pointer) shmdesc)) {
> +        close(fd);
> +        return BadAlloc;
> +    }
> +
> +    if (WriteFdToClient(client, fd, TRUE) < 0) {
> +        FreeResource(stuff->shmseg, RT_NONE);
> +        close(fd);
> +        return BadAlloc;
> +    }
> +    WriteToClient(client, sizeof (xShmCreateSegmentReply), &rep);
> +    return Success;
> +}
> +
> +static int
> ProcShmDispatch(ClientPtr client)
> {
>     REQUEST(xReq);
> @@ -1116,6 +1239,10 @@ ProcShmDispatch(ClientPtr client)
>             return ProcPanoramiXShmCreatePixmap(client);
> #endif
>         return ProcShmCreatePixmap(client);
> +    case X_ShmAttachFd:
> +        return ProcShmAttachFd(client);
> +    case X_ShmCreateSegment:
> +        return ProcShmCreateSegment(client);
>     default:
>         return BadRequest;
>     }
> @@ -1217,6 +1344,28 @@ SProcShmCreatePixmap(ClientPtr client)
> }
> 
> static int
> +SProcShmAttachFd(ClientPtr client)
> +{
> +    REQUEST(xShmAttachFdReq);
> +    SetReqFds(client, 1);
> +    swaps(&stuff->length);
> +    REQUEST_SIZE_MATCH(xShmAttachFdReq);
> +    swapl(&stuff->shmseg);
> +    return ProcShmAttachFd(client);
> +}
> +
> +static int
> +SProcShmCreateSegment(ClientPtr client)
> +{
> +    REQUEST(xShmCreateSegmentReq);
> +    swaps(&stuff->length);
> +    REQUEST_SIZE_MATCH(xShmCreateSegmentReq);
> +    swapl(&stuff->shmseg);
> +    swapl(&stuff->size);
> +    return ProcShmCreateSegment(client);
> +}
> +
> +static int
> SProcShmDispatch(ClientPtr client)
> {
>     REQUEST(xReq);
> @@ -1233,6 +1382,10 @@ SProcShmDispatch(ClientPtr client)
>         return SProcShmGetImage(client);
>     case X_ShmCreatePixmap:
>         return SProcShmCreatePixmap(client);
> +    case X_ShmAttachFd:
> +        return SProcShmAttachFd(client);
> +    case X_ShmCreateSegment:
> +        return SProcShmCreateSegment(client);
>     default:
>         return BadRequest;
>     }
> diff --git a/Xext/shmint.h b/Xext/shmint.h
> index 9002ce5..db35fbb 100644
> --- a/Xext/shmint.h
> +++ b/Xext/shmint.h
> @@ -61,6 +61,7 @@ typedef struct _ShmDesc {
>     int shmid;
>     int refcnt;
>     char *addr;
> +    Bool is_fd;
>     Bool writable;
>     unsigned long size;
> } ShmDescRec, *ShmDescPtr;
> diff --git a/include/os.h b/include/os.h
> index b654a0d..11b2198 100644
> --- a/include/os.h
> +++ b/include/os.h
> @@ -100,6 +100,8 @@ extern _X_EXPORT int ReadRequestFromClient(ClientPtr /*client */ );
> 
> extern _X_EXPORT int ReadFdFromClient(ClientPtr client);
> 
> +extern _X_EXPORT int WriteFdToClient(ClientPtr client, int fd, Bool do_close);
> +
> extern _X_EXPORT Bool InsertFakeRequest(ClientPtr /*client */ ,
>                                         char * /*data */ ,
>                                         int /*count */ );
> diff --git a/os/io.c b/os/io.c
> index 83df6e9..a20faa5 100644
> --- a/os/io.c
> +++ b/os/io.c
> @@ -506,6 +506,14 @@ ReadFdFromClient(ClientPtr client)
>     return fd;
> }
> 
> +int
> +WriteFdToClient(ClientPtr client, int fd, Bool do_close)
> +{
> +    OsCommPtr oc = (OsCommPtr) client->osPrivate;
> +
> +    return _XSERVTransSendFd(oc->trans_conn, fd, do_close);
> +}
> +
> /*****************************************************************
>  * InsertFakeRequest
>  *    Splice a consed up (possibly partial) request in as the next request.
> commit 9fd35daa3160fd36f00ed354bfcbefefa1353cce
> Author: Keith Packard <keithp at keithp.com>
> Date:   Thu Jan 17 13:43:02 2013 -0800
> 
>    Add interfaces to get FDs from clients over the socket
> 
>    This adds two interfaces:
> 
>        void SetReqFds(ClientPtr client, int req_fds)
> 
>    	Marks the number of file descriptors expected for this
>    	request. Call this before any request processing so that
>    	any un-retrieved file descriptors will be closed
>    	automatically.
> 
>        int ReadFdFromClient(ClientPtr client)
> 
>    	Reads the next queued file descriptor from the connection. If
>    	this request is not expecting any more file descriptors, or
>    	if there are no more file descriptors available from the
>    	connection, then this will return -1.
> 
>    Signed-off-by: Keith Packard <keithp at keithp.com>
>    Reviewed-by: Adam Jackson <ajax at redhat.com>
> 
> diff --git a/include/dixstruct.h b/include/dixstruct.h
> index 7711cde..456e633 100644
> --- a/include/dixstruct.h
> +++ b/include/dixstruct.h
> @@ -110,8 +110,16 @@ typedef struct _Client {
> 
>     DeviceIntPtr clientPtr;
>     ClientIdPtr clientIds;
> +    int req_fds;
> } ClientRec;
> 
> +static inline void
> +SetReqFds(ClientPtr client, int req_fds) {
> +    if (client->req_fds != 0 && req_fds != client->req_fds)
> +        LogMessage(X_ERROR, "Mismatching number of request fds %d != %d\n", req_fds, client->req_fds);
> +    client->req_fds = req_fds;
> +}
> +
> /*
>  * Scheduling interface
>  */
> diff --git a/include/os.h b/include/os.h
> index 3840ab9..b654a0d 100644
> --- a/include/os.h
> +++ b/include/os.h
> @@ -98,6 +98,8 @@ extern _X_EXPORT int WaitForSomething(int *     /*pClientsReady */
> 
> extern _X_EXPORT int ReadRequestFromClient(ClientPtr /*client */ );
> 
> +extern _X_EXPORT int ReadFdFromClient(ClientPtr client);
> +
> extern _X_EXPORT Bool InsertFakeRequest(ClientPtr /*client */ ,
>                                         char * /*data */ ,
>                                         int /*count */ );
> diff --git a/os/io.c b/os/io.c
> index 3800366..83df6e9 100644
> --- a/os/io.c
> +++ b/os/io.c
> @@ -259,6 +259,12 @@ ReadRequestFromClient(ClientPtr client)
>         oc->input = oci;
>     }
> 
> +    /* Discard any unused file descriptors */
> +    while (client->req_fds > 0) {
> +        int req_fd = ReadFdFromClient(client);
> +        if (req_fd >= 0)
> +            close(req_fd);
> +    }
>     /* advance to start of next request */
> 
>     oci->bufptr += oci->lenLastReq;
> @@ -485,6 +491,21 @@ ReadRequestFromClient(ClientPtr client)
>     return needed;
> }
> 
> +int
> +ReadFdFromClient(ClientPtr client)
> +{
> +    int fd = -1;
> +
> +    if (client->req_fds > 0) {
> +        OsCommPtr oc = (OsCommPtr) client->osPrivate;
> +
> +        --client->req_fds;
> +        fd = _XSERVTransRecvFd(oc->trans_conn);
> +    } else
> +        LogMessage(X_ERROR, "Request asks for FD without setting req_fds\n");
> +    return fd;
> +}
> +
> /*****************************************************************
>  * InsertFakeRequest
>  *    Splice a consed up (possibly partial) request in as the next request.
> commit 264fc3abe5f18341d0cf9ddb6766e10e4154e447
> Author: Keith Packard <keithp at keithp.com>
> Date:   Thu Oct 31 13:01:46 2013 -0700
> 
>    misync: Don't smash custom screen sync functions
> 
>    There was a check to avoid smashing custom functions, but the sense
>    was backwards causing it to always smash them, and also not set them otherwise.
> 
>    Signed-off-by: Keith Packard <keithp at keithp.com>
>    Reviewed-by: Adam Jackson <ajax at redhat.com>
> 
> diff --git a/miext/sync/misync.c b/miext/sync/misync.c
> index b6914d1..f380547 100644
> --- a/miext/sync/misync.c
> +++ b/miext/sync/misync.c
> @@ -190,7 +190,7 @@ miSyncSetup(ScreenPtr pScreen)
> 
>     pScreenPriv = SYNC_SCREEN_PRIV(pScreen);
> 
> -    if (pScreenPriv->funcs.CreateFence) {
> +    if (!pScreenPriv->funcs.CreateFence) {
>         pScreenPriv->funcs = miSyncScreenFuncs;
> 
>         /* Wrap CloseScreen to clean up */
> commit 2d96948ab5c952b68875ac63844cf7d778d4bf63
> Author: Keith Packard <keithp at keithp.com>
> Date:   Thu Jul 11 16:10:34 2013 -0700
> 
>    os: Add GetTimeInMicros
> 
>    64-bit higher resolution current time value.
> 
>    Signed-off-by: Keith Packard <keithp at keithp.com>
>    Reviewed-by: Adam Jackson <ajax at redhat.com>
> 
> diff --git a/include/os.h b/include/os.h
> index c7108a5..3840ab9 100644
> --- a/include/os.h
> +++ b/include/os.h
> @@ -165,6 +165,7 @@ extern void ListenOnOpenFD(int /* fd */ , int /* noxauth */ );
> #endif
> 
> extern _X_EXPORT CARD32 GetTimeInMillis(void);
> +extern _X_EXPORT CARD64 GetTimeInMicros(void);
> 
> extern _X_EXPORT void AdjustWaitForDelay(pointer /*waitTime */ ,
>                                          unsigned long /*newdelay */ );
> diff --git a/os/utils.c b/os/utils.c
> index 97c3125..995f62a 100644
> --- a/os/utils.c
> +++ b/os/utils.c
> @@ -430,6 +430,11 @@ GetTimeInMillis(void)
> {
>     return GetTickCount();
> }
> +CARD64
> +GetTimeInMicros(void)
> +{
> +    return (CARD64) GetTickCount() * 1000;
> +}
> #else
> CARD32
> GetTimeInMillis(void)
> @@ -460,6 +465,28 @@ GetTimeInMillis(void)
>     X_GETTIMEOFDAY(&tv);
>     return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
> }
> +
> +CARD64
> +GetTimeInMicros(void)
> +{
> +    struct timeval tv;
> +#ifdef MONOTONIC_CLOCK
> +    struct timespec tp;
> +    static clockid_t clockid;
> +
> +    if (!clockid) {
> +        if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
> +            clockid = CLOCK_MONOTONIC;
> +        else
> +            clockid = ~0L;
> +    }
> +    if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
> +        return (CARD64) tp.tv_sec * (CARD64)1000000 + tp.tv_nsec / 1000;
> +#endif
> +
> +    X_GETTIMEOFDAY(&tv);
> +    return (CARD64) tv.tv_sec * (CARD64)1000000000 + (CARD64) tv.tv_usec * 1000;
> +}
> #endif
> 
> void
> commit 0c33f47281c36726848daf513fb0483cdea57bff
> Author: Keith Packard <keithp at keithp.com>
> Date:   Thu Jul 11 16:09:34 2013 -0700
> 
>    Add swapll to byte swap 64-bit datatypes
> 
>    Signed-off-by: Keith Packard <keithp at keithp.com>
>    Reviewed-by: Adam Jackson <ajax at redhat.com>
> 
> diff --git a/include/misc.h b/include/misc.h
> index 0c67f11..17de710 100644
> --- a/include/misc.h
> +++ b/include/misc.h
> @@ -305,6 +305,35 @@ __builtin_constant_p(int x)
> }
> #endif
> 
> +/* byte swap a 64-bit value */
> +static inline void
> +swap_uint64(uint64_t *x)
> +{
> +    char n;
> +
> +    n = ((char *) x)[0];
> +    ((char *) x)[0] = ((char *) x)[7];
> +    ((char *) x)[7] = n;
> +
> +    n = ((char *) x)[1];
> +    ((char *) x)[1] = ((char *) x)[6];
> +    ((char *) x)[6] = n;
> +
> +    n = ((char *) x)[2];
> +    ((char *) x)[2] = ((char *) x)[5];
> +    ((char *) x)[5] = n;
> +
> +    n = ((char *) x)[3];
> +    ((char *) x)[3] = ((char *) x)[4];
> +    ((char *) x)[4] = n;
> +}
> +
> +#define swapll(x) do { \
> +		if (sizeof(*(x)) != 8) \
> +			wrong_size(); \
> +                swap_uint64((uint64_t *)(x));   \
> +	} while (0)
> +
> /* byte swap a 32-bit value */
> static inline void
> swap_uint32(uint32_t * x)
> commit 26f013ba45b08a02bb028a461af68288a86fadb1
> Author: Keith Packard <keithp at keithp.com>
> Date:   Thu Jul 11 16:08:41 2013 -0700
> 
>    Add a RegionDuplicate function
> 
>    This allocates a new region structure and copies a source region into
>    it in a single API rather than forcing the caller to do both steps themselves.
> 
>    Signed-off-by: Keith Packard <keithp at keithp.com>
>    Reviewed-by: Adam Jackson <ajax at redhat.com>
> 
> diff --git a/dix/region.c b/dix/region.c
> index 737d2a8..15f3d01 100644
> --- a/dix/region.c
> +++ b/dix/region.c
> @@ -255,6 +255,21 @@ RegionDestroy(RegionPtr pReg)
>         free(pReg);
> }
> 
> +RegionPtr
> +RegionDuplicate(RegionPtr pOld)
> +{
> +    RegionPtr   pNew;
> +
> +    pNew = RegionCreate(&pOld->extents, 0);
> +    if (!pNew)
> +        return NULL;
> +    if (!RegionCopy(pNew, pOld)) {
> +        RegionDestroy(pNew);
> +        return NULL;
> +    }
> +    return pNew;
> +}
> +
> void
> RegionPrint(RegionPtr rgn)
> {
> diff --git a/include/regionstr.h b/include/regionstr.h
> index 805257b..4a0725d 100644
> --- a/include/regionstr.h
> +++ b/include/regionstr.h
> @@ -213,6 +213,8 @@ extern _X_EXPORT RegionPtr RegionCreate(BoxPtr /*rect */ ,
> 
> extern _X_EXPORT void RegionDestroy(RegionPtr /*pReg */ );
> 
> +extern _X_EXPORT RegionPtr RegionDuplicate(RegionPtr /* pOld */);
> +
> static inline Bool
> RegionCopy(RegionPtr dst, RegionPtr src)
> {
> commit d25c217964eb1fe54c3a54bca4cac7f47b4b9fdf
> Author: Keith Packard <keithp at keithp.com>
> Date:   Mon Jan 14 14:24:36 2013 -0800
> 
>    Clean up a couple of warnings in os/
> 
>    Signed-off-by: Keith Packard <keithp at keithp.com>
>    Reviewed-by: Adam Jackson <ajax at redhat.com>
> 
> diff --git a/os/connection.c b/os/connection.c
> index 6cd8bcf..162e1d9 100644
> --- a/os/connection.c
> +++ b/os/connection.c
> @@ -923,7 +923,7 @@ ErrorConnMax(XtransConnInfo trans_conn)
>         iov[0].iov_len = sz_xConnSetupPrefix;
>         iov[0].iov_base = (char *) &csp;
>         iov[1].iov_len = csp.lengthReason;
> -        iov[1].iov_base = NOROOM;
> +        iov[1].iov_base = (void *) NOROOM;
>         iov[2].iov_len = (4 - (csp.lengthReason & 3)) & 3;
>         iov[2].iov_base = pad;
>         (void) _XSERVTransWritev(trans_conn, iov, 3);
> diff --git a/os/xstrans.c b/os/xstrans.c
> index 6348a65..2bc79e7 100644
> --- a/os/xstrans.c
> +++ b/os/xstrans.c
> @@ -5,9 +5,11 @@
> #include <X11/Xfuncproto.h>
> 
> /* ErrorF is used by xtrans */
> +#ifndef HAVE_DIX_CONFIG_H
> extern _X_EXPORT void
> ErrorF(const char *f, ...)
> _X_ATTRIBUTE_PRINTF(1, 2);
> +#endif
> 
> #define TRANS_REOPEN
> #define TRANS_SERVER
> commit 7710f2b927ec8e3c631f72d66d494b523377b48e
> Author: Keith Packard <keithp at keithp.com>
> Date:   Fri Jan 18 21:43:40 2013 -0800
> 
>    Xext: Move MIT-SHM 'ShmDesc' to shmint.h
> 
>    This data structure is required to use shared memory objects in any
>    extension. That includes the Xv extension, which (before this patch)
>    duplicated the definition of this structure in its own code.
> 
>    Signed-off-by: Keith Packard <keithp at keithp.com>
>    Reviewed-by: Adam Jackson <ajax at redhat.com>
> 
> diff --git a/Xext/shm.c b/Xext/shm.c
> index 5596090..f6995cc 100644
> --- a/Xext/shm.c
> +++ b/Xext/shm.c
> @@ -89,15 +89,6 @@ in this Software without prior written authorization from The Open Group.
> 
> #include "extinit.h"
> 
> -typedef struct _ShmDesc {
> -    struct _ShmDesc *next;
> -    int shmid;
> -    int refcnt;
> -    char *addr;
> -    Bool writable;
> -    unsigned long size;
> -} ShmDescRec, *ShmDescPtr;
> -
> typedef struct _ShmScrPrivateRec {
>     CloseScreenProcPtr CloseScreen;
>     ShmFuncsPtr shmFuncs;
> diff --git a/Xext/shmint.h b/Xext/shmint.h
> index fa6941c..9002ce5 100644
> --- a/Xext/shmint.h
> +++ b/Xext/shmint.h
> @@ -56,6 +56,15 @@ typedef struct _ShmFuncs {
>     void (*PutImage) (XSHM_PUT_IMAGE_ARGS);
> } ShmFuncs, *ShmFuncsPtr;
> 
> +typedef struct _ShmDesc {
> +    struct _ShmDesc *next;
> +    int shmid;
> +    int refcnt;
> +    char *addr;
> +    Bool writable;
> +    unsigned long size;
> +} ShmDescRec, *ShmDescPtr;
> +
> extern _X_EXPORT void
>  ShmRegisterFuncs(ScreenPtr pScreen, ShmFuncsPtr funcs);
> 
> diff --git a/Xext/xvdisp.c b/Xext/xvdisp.c
> index 7877293..613867a 100644
> --- a/Xext/xvdisp.c
> +++ b/Xext/xvdisp.c
> @@ -43,6 +43,7 @@ SOFTWARE.
> #include "xvdix.h"
> #ifdef MITSHM
> #include <X11/extensions/shmproto.h>
> +#include "shmint.h"
> #endif
> 
> #include "xvdisp.h"
> @@ -949,18 +950,6 @@ ProcXvPutImage(ClientPtr client)
> }
> 
> #ifdef MITSHM
> -/* redefined here since it's not in any header file */
> -typedef struct _ShmDesc {
> -    struct _ShmDesc *next;
> -    int shmid;
> -    int refcnt;
> -    char *addr;
> -    Bool writable;
> -    unsigned long size;
> -} ShmDescRec, *ShmDescPtr;
> -
> -extern RESTYPE ShmSegType;
> -extern int ShmCompletionCode;
> 
> static int
> ProcXvShmPutImage(ClientPtr client)
> _______________________________________________
> xorg-commit mailing list
> xorg-commit at lists.x.org
> http://lists.x.org/mailman/listinfo/xorg-commit

-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 4136 bytes
Desc: not available
URL: <http://lists.x.org/archives/xorg-devel/attachments/20131102/6908acfa/attachment-0001.bin>


More information about the xorg-devel mailing list