xf86-video-intel: 6 commits - configure.ac Makefile.am src/common.h src/i915_video.c src/intel_batchbuffer.c src/intel_display.c src/intel_dri.c src/intel_driver.c src/intel.h src/intel_module.c src/intel_uxa.c src/Makefile.am src/sna/blt.c src/sna/kgem.c src/sna/kgem.h src/sna/Makefile.am src/sna/rop.h src/sna/sna_accel.c src/sna/sna_blt.c src/sna/sna_composite.c src/sna/sna_display.c src/sna/sna_dri.c src/sna/sna_driver.c src/sna/sna.h src/sna/sna_io.c

Chris Wilson ickle at kemper.freedesktop.org
Wed Nov 16 14:16:57 PST 2011


 Makefile.am             |    8 
 configure.ac            |   20 -
 src/Makefile.am         |   14 
 src/common.h            |    2 
 src/i915_video.c        |    1 
 src/intel.h             |    6 
 src/intel_batchbuffer.c |    2 
 src/intel_display.c     |    2 
 src/intel_dri.c         |    2 
 src/intel_driver.c      |    6 
 src/intel_module.c      |    8 
 src/intel_uxa.c         |    2 
 src/sna/Makefile.am     |    3 
 src/sna/blt.c           |   46 ++
 src/sna/kgem.c          |   38 +
 src/sna/kgem.h          |    1 
 src/sna/rop.h           |  264 +++++++++++++
 src/sna/sna.h           |   13 
 src/sna/sna_accel.c     |    2 
 src/sna/sna_blt.c       |    2 
 src/sna/sna_composite.c |    1 
 src/sna/sna_display.c   |   24 -
 src/sna/sna_dri.c       |  954 ++++++++++++++++++++++++++----------------------
 src/sna/sna_driver.c    |   36 -
 src/sna/sna_io.c        |    1 
 25 files changed, 942 insertions(+), 516 deletions(-)

New commits:
commit c259144e3fc52d078b0a78107c38f0f3d3a2bbc1
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Nov 16 10:28:23 2011 +0000

    sna: The block handler is passed an indirect pointer to the timeval
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_driver.c b/src/sna/sna_driver.c
index 4c9f298..45e8fb2 100644
--- a/src/sna/sna_driver.c
+++ b/src/sna/sna_driver.c
@@ -582,13 +582,14 @@ static void
 sna_block_handler(int i, pointer data, pointer timeout, pointer read_mask)
 {
 	struct sna *sna = data;
-	struct timeval *tv = timeout;
+	struct timeval **tv = timeout;
 
-	DBG(("%s\n", __FUNCTION__));
+	DBG(("%s (tv=%ld.%06ld)\n", __FUNCTION__,
+	     *tv ? (*tv)->tv_sec : -1, *tv ? (*tv)->tv_usec : 0));
 
 	sna->BlockHandler(i, sna->BlockData, timeout, read_mask);
 
-	if (tv == NULL || (tv->tv_usec | tv->tv_sec))
+	if (*tv == NULL || ((*tv)->tv_usec | (*tv)->tv_sec))
 		sna_accel_block_handler(sna);
 }
 
commit bfd2bb40274d1242001d295a4010211fd51b0fc3
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Nov 15 10:38:09 2011 +0000

    sna: Correct dependencies for DRI2
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/configure.ac b/configure.ac
index 2c40760..3fd28b0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -175,7 +175,7 @@ XORG_DRIVER_CHECK_EXT(DPMSExtension, xextproto)
 PKG_CHECK_MODULES(XORG, [xorg-server >= $required_xorg_xserver_version xproto fontsproto pixman-1 >= $required_pixman_version $REQUIRED_MODULES])
 PKG_CHECK_MODULES(DRM, [libdrm >= 2.4.23])
 PKG_CHECK_MODULES(DRI, [xf86driproto], , DRI=no)
-PKG_CHECK_MODULES(DRI2, [dri2proto >= 2.6])
+PKG_CHECK_MODULES(DRI2, [dri2proto >= 2.6],, DRI2=no)
 PKG_CHECK_MODULES(PCIACCESS, [pciaccess >= 0.10])
 
 sdkdir=`$PKG_CONFIG --variable=sdkdir xorg-server`
@@ -218,6 +218,10 @@ else
                 AC_MSG_ERROR([DRI requested but prerequisites not found])
         fi
 fi
+AM_CONDITIONAL(DRI2, test x$DRI2 != xno)
+if test "x$DRI2" != "xno"; then
+        AC_DEFINE(USE_DRI2,1,[Enable DRI2 driver support])
+fi
 
 if test "$XVMC" = yes; then
 	PKG_CHECK_MODULES(XVMCLIB,
diff --git a/src/sna/Makefile.am b/src/sna/Makefile.am
index 30cedc6..65e85bf 100644
--- a/src/sna/Makefile.am
+++ b/src/sna/Makefile.am
@@ -74,7 +74,7 @@ libsna_la_SOURCES = \
 	gen7_render.h \
 	$(NULL)
 
-if DRI
+if DRI2
 libsna_la_SOURCES += \
 	sna_dri.c \
 	$(NULL)
diff --git a/src/sna/sna_driver.c b/src/sna/sna_driver.c
index 19413a9..4c9f298 100644
--- a/src/sna/sna_driver.c
+++ b/src/sna/sna_driver.c
@@ -925,7 +925,7 @@ sna_screen_init(int scrnIndex, ScreenPtr screen, int argc, char **argv)
 	xf86DPMSInit(screen, xf86DPMSSet, 0);
 
 	sna_video_init(sna, screen);
-#ifdef DRI2
+#if USE_DRI2
 	sna->directRenderingOpen = sna_dri_open(sna, screen);
 	if (sna->directRenderingOpen)
 		xf86DrvMsg(scrn->scrnIndex, X_INFO,
commit 3771387ad11b5842a83e58a4b373c2acdd827bd2
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Nov 15 10:32:34 2011 +0000

    Compile out UXA if so desired
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/Makefile.am b/Makefile.am
index 29c04fd..48c3477 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -20,7 +20,13 @@
 
 ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
 
-SUBDIRS = uxa src man
+SUBDIRS = man
+
+if UXA
+SUBDIRS += uxa
+endif
+
+SUBDIRS += src
 MAINTAINERCLEANFILES = ChangeLog INSTALL
 
 if HAVE_X11
diff --git a/configure.ac b/configure.ac
index 831f6b3..2c40760 100644
--- a/configure.ac
+++ b/configure.ac
@@ -120,14 +120,13 @@ AC_ARG_ENABLE(kms-only, AS_HELP_STRING([--enable-kms-only],
               [KMS_ONLY="$enableval"],
               [KMS_ONLY=no])
 
+AC_MSG_CHECKING([whether to include SNA support])
 AC_ARG_ENABLE(sna,
 	      AS_HELP_STRING([--enable-sna],
 			     [Enable SandyBridge's New Acceleration (SNA) [default=no]]),
 	      [SNA="$enableval"],
 	      [SNA=no])
 AM_CONDITIONAL(SNA, test x$SNA != xno)
-AC_MSG_CHECKING([whether to include SNA support])
-
 required_xorg_xserver_version=1.6
 required_pixman_version=0.16
 if test "x$SNA" != "xno"; then
@@ -137,6 +136,17 @@ if test "x$SNA" != "xno"; then
 fi
 AC_MSG_RESULT([$SNA])
 
+AC_MSG_CHECKING([whether to include UXA support])
+AC_ARG_ENABLE(uxa,
+	      AS_HELP_STRING([--enable-uxa],
+			     [Enable Unified Acceleration Architecture (UXA) [default=yes]]),
+	      [UXA="$enableval"],
+	      [UXA=yes])
+AM_CONDITIONAL(UXA, test x$UXA != xno)
+if test "x$UXA" != "xno"; then
+	AC_DEFINE(USE_UXA, 1, [Enable UXA support])
+fi
+AC_MSG_RESULT([$UXA])
 
 AC_ARG_ENABLE(vmap,
 	      AS_HELP_STRING([--enable-vmap],
diff --git a/src/Makefile.am b/src/Makefile.am
index cd1bb36..e5097da 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -27,13 +27,12 @@ SUBDIRS = xvmc render_program legacy
 # TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
 
 AM_CFLAGS = @CWARNFLAGS@ @XORG_CFLAGS@ @UDEV_CFLAGS@ @DRM_CFLAGS@ @DRI_CFLAGS@ \
-	@PCIACCESS_CFLAGS@ -I$(top_srcdir)/uxa -I$(top_srcdir)/src/render_program
+	@PCIACCESS_CFLAGS@
 
 intel_drv_la_LTLIBRARIES = intel_drv.la
 intel_drv_la_LDFLAGS = -module -avoid-version
 intel_drv_ladir = @moduledir@/drivers
-intel_drv_la_LIBADD = @UDEV_LIBS@ -lm @DRM_LIBS@ -ldrm_intel ../uxa/libuxa.la legacy/liblegacy.la
-intel_drv_la_LIBADD += @PCIACCESS_LIBS@
+intel_drv_la_LIBADD = legacy/liblegacy.la @PCIACCESS_LIBS@
 
 if SNA
 SUBDIRS += sna
@@ -43,11 +42,17 @@ endif
 NULL:=#
 
 intel_drv_la_SOURCES = \
+	intel_module.c \
+	$(NULL)
+
+if UXA
+AM_CFLAGS += -I$(top_srcdir)/uxa -I$(top_srcdir)/src/render_program
+intel_drv_la_LIBADD += @UDEV_LIBS@ @DRM_LIBS@ -ldrm_intel ../uxa/libuxa.la
+intel_drv_la_SOURCES += \
          brw_defines.h \
          brw_structs.h \
          common.h \
          intel.h \
-	 intel_module.c \
          intel_batchbuffer.c \
          intel_batchbuffer.h \
 	 intel_display.c \
@@ -87,3 +92,4 @@ intel_drv_la_SOURCES += \
 	intel_hwmc.c \
 	$(NULL)
 endif
+endif
diff --git a/src/i915_video.c b/src/i915_video.c
index d46c6d1..c73615e 100644
--- a/src/i915_video.c
+++ b/src/i915_video.c
@@ -33,6 +33,7 @@
 #include "xf86_OSproc.h"
 #include "xf86xv.h"
 #include "fourcc.h"
+#include "gcstruct.h"
 
 #include "intel.h"
 #include "intel_video.h"
diff --git a/src/intel.h b/src/intel.h
index ed95063..1a002e2 100644
--- a/src/intel.h
+++ b/src/intel.h
@@ -75,7 +75,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include <libudev.h>
 #endif
 
-#include "uxa.h"
 /* XXX
  * The X server gained an *almost* identical implementation in 1.9.
  *
@@ -316,7 +315,7 @@ typedef struct intel_screen_private {
 	void (*batch_flush) (struct intel_screen_private *intel);
 	void (*batch_commit_notify) (struct intel_screen_private *intel);
 
-	uxa_driver_t *uxa_driver;
+	struct _UxaDriver *uxa_driver;
 	Bool need_sync;
 	int accel_pixmap_offset_alignment;
 	int accel_max_x;
diff --git a/src/intel_batchbuffer.c b/src/intel_batchbuffer.c
index 89a9969..2b8fbb6 100644
--- a/src/intel_batchbuffer.c
+++ b/src/intel_batchbuffer.c
@@ -40,6 +40,8 @@
 #include "i915_drm.h"
 #include "i965_reg.h"
 
+#include "uxa.h"
+
 #define DUMP_BATCHBUFFERS NULL // "/tmp/i915-batchbuffers.dump"
 
 static void intel_end_vertex(intel_screen_private *intel)
diff --git a/src/intel_dri.c b/src/intel_dri.c
index 1227dbb..135ba4e 100644
--- a/src/intel_dri.c
+++ b/src/intel_dri.c
@@ -56,8 +56,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #include "windowstr.h"
 #include "shadow.h"
-
 #include "xaarop.h"
+#include "fb.h"
 
 #include "intel.h"
 #include "i830_reg.h"
diff --git a/src/intel_driver.c b/src/intel_driver.c
index f385819..188c512 100644
--- a/src/intel_driver.c
+++ b/src/intel_driver.c
@@ -70,6 +70,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #endif
 
 #include "legacy/legacy.h"
+#include "uxa.h"
 
 #include <sys/ioctl.h>
 #include "i915_drm.h"
diff --git a/src/intel_module.c b/src/intel_module.c
index 3a0ecc9..80b5da8 100644
--- a/src/intel_module.c
+++ b/src/intel_module.c
@@ -346,8 +346,10 @@ static Bool intel_pci_probe(DriverPtr		driver,
 		default:
 #if USE_SNA
 			sna_init_scrn(scrn, entity_num);
-#else
+#elif USE_UXA
 			intel_init_scrn(scrn);
+#else
+			scrn = NULL;
 #endif
 			break;
 		}
@@ -387,8 +389,10 @@ intel_available_options(int chipid, int busid)
 	default:
 #if USE_SNA
 		return sna_available_options(chipid, busid);
-#else
+#elif USE_UXA
 		return intel_uxa_available_options(chipid, busid);
+#else
+		return NULL;
 #endif
 	}
 }
diff --git a/src/intel_uxa.c b/src/intel_uxa.c
index 8c6f754..94dfb86 100644
--- a/src/intel_uxa.c
+++ b/src/intel_uxa.c
@@ -40,6 +40,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include <string.h>
 #include <errno.h>
 
+#include "uxa.h"
+
 static const int I830CopyROP[16] = {
 	ROP_0,			/* GXclear */
 	ROP_DSa,		/* GXand */
commit edbeab8c4edf9e0e89d85add485fe659795b6350
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Nov 15 10:17:06 2011 +0000

    sna: Reduce and clarify dependencies
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/common.h b/src/common.h
index 6b9c315..f9f2300 100644
--- a/src/common.h
+++ b/src/common.h
@@ -109,7 +109,7 @@ static inline void memcpy_volatile(volatile void *dst, const void *src,
     size_t i;
 
     for (i = 0; i < len; i++)
-	((volatile char *)dst)[i] = ((volatile char *)src)[i];
+	((volatile char *)dst)[i] = ((const volatile char *)src)[i];
 }
 
 /* Memory mapped register access macros */
diff --git a/src/intel.h b/src/intel.h
index 3b3f87d..ed95063 100644
--- a/src/intel.h
+++ b/src/intel.h
@@ -57,7 +57,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "xf86Pci.h"
 #include "xf86Cursor.h"
 #include "xf86xv.h"
-#include "vgaHW.h"
 #include "xf86Crtc.h"
 #include "xf86RandR12.h"
 
@@ -636,7 +635,7 @@ intel_get_transformed_coordinates_3d(int x, int y, PictTransformPtr transform,
 				    float *x_out, float *y_out, float *z_out);
 
 static inline void
-intel_debug_fallback(ScrnInfoPtr scrn, char *format, ...)
+intel_debug_fallback(ScrnInfoPtr scrn, const char *format, ...)
 {
 	intel_screen_private *intel = intel_get_screen_private(scrn);
 	va_list ap;
diff --git a/src/intel_display.c b/src/intel_display.c
index 84c7c08..542dc20 100644
--- a/src/intel_display.c
+++ b/src/intel_display.c
@@ -42,6 +42,8 @@
 #include "intel_bufmgr.h"
 #include "xf86drmMode.h"
 #include "X11/Xatom.h"
+#include "X11/extensions/dpmsconst.h"
+#include "xf86DDC.h"
 
 struct intel_mode {
 	int fd;
diff --git a/src/intel_driver.c b/src/intel_driver.c
index 24696da..f385819 100644
--- a/src/intel_driver.c
+++ b/src/intel_driver.c
@@ -50,11 +50,11 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "xf86cmap.h"
 #include "compiler.h"
 #include "mibstore.h"
-#include "vgaHW.h"
 #include "mipointer.h"
 #include "micmap.h"
 #include "shadowfb.h"
 #include <X11/extensions/randr.h>
+#include <X11/extensions/dpmsconst.h>
 #include "fb.h"
 #include "miscstruct.h"
 #include "dixstruct.h"
@@ -1118,9 +1118,6 @@ static void I830FreeScreen(int scrnIndex, int flags)
 		free(intel);
 		scrn->driverPrivate = NULL;
 	}
-
-	if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
-		vgaHWFreeHWRec(xf86Screens[scrnIndex]);
 }
 
 static void I830LeaveVT(int scrnIndex, int flags)
diff --git a/src/sna/Makefile.am b/src/sna/Makefile.am
index ac60988..30cedc6 100644
--- a/src/sna/Makefile.am
+++ b/src/sna/Makefile.am
@@ -35,6 +35,7 @@ libsna_la_SOURCES = \
 	compiler.h \
 	kgem.c \
 	kgem.h \
+	rop.h \
 	sna.h \
 	sna_accel.c \
 	sna_blt.c \
diff --git a/src/sna/rop.h b/src/sna/rop.h
new file mode 100644
index 0000000..9db15cf
--- /dev/null
+++ b/src/sna/rop.h
@@ -0,0 +1,264 @@
+#ifndef ROP_H
+#define ROP_H
+
+#define ROP_0		0x00
+#define ROP_DPSoon	0x01
+#define ROP_DPSona	0x02
+#define ROP_PSon	0x03
+#define ROP_SDPona	0x04
+#define ROP_DPon	0x05
+#define ROP_PDSxnon	0x06
+#define ROP_PDSaon	0x07
+#define ROP_SDPnaa	0x08
+#define ROP_PDSxon	0x09
+#define ROP_DPna	0x0A
+#define ROP_PSDnaon	0x0B
+#define ROP_SPna	0x0C
+#define ROP_PDSnaon	0x0D
+#define ROP_PDSonon	0x0E
+#define ROP_Pn		0x0F
+#define ROP_PDSona	0x10
+#define ROP_DSon	0x11
+#define ROP_SDPxnon	0x12
+#define ROP_SDPaon	0x13
+#define ROP_DPSxnon	0x14
+#define ROP_DPSaon	0x15
+#define ROP_PSDPSanaxx	0x16
+#define ROP_SSPxDSxaxn	0x17
+#define ROP_SPxPDxa	0x18
+#define ROP_SDPSanaxn	0x19
+#define ROP_PDSPaox	0x1A
+#define ROP_SDPSxaxn	0x1B
+#define ROP_PSDPaox	0x1C
+#define ROP_DSPDxaxn	0x1D
+#define ROP_PDSox	0x1E
+#define ROP_PDSoan	0x1F
+#define ROP_DPSnaa	0x20
+#define ROP_SDPxon	0x21
+#define ROP_DSna	0x22
+#define ROP_SPDnaon	0x23
+#define ROP_SPxDSxa	0x24
+#define ROP_PDSPanaxn	0x25
+#define ROP_SDPSaox	0x26
+#define ROP_SDPSxnox	0x27
+#define ROP_DPSxa	0x28
+#define ROP_PSDPSaoxxn	0x29
+#define ROP_DPSana	0x2A
+#define ROP_SSPxPDxaxn	0x2B
+#define ROP_SPDSoax	0x2C
+#define ROP_PSDnox	0x2D
+#define ROP_PSDPxox	0x2E
+#define ROP_PSDnoan	0x2F
+#define ROP_PSna	0x30
+#define ROP_SDPnaon	0x31
+#define ROP_SDPSoox	0x32
+#define ROP_Sn		0x33
+#define ROP_SPDSaox	0x34
+#define ROP_SPDSxnox	0x35
+#define ROP_SDPox	0x36
+#define ROP_SDPoan	0x37
+#define ROP_PSDPoax	0x38
+#define ROP_SPDnox	0x39
+#define ROP_SPDSxox	0x3A
+#define ROP_SPDnoan	0x3B
+#define ROP_PSx		0x3C
+#define ROP_SPDSonox	0x3D
+#define ROP_SPDSnaox	0x3E
+#define ROP_PSan	0x3F
+#define ROP_PSDnaa	0x40
+#define ROP_DPSxon	0x41
+#define ROP_SDxPDxa	0x42
+#define ROP_SPDSanaxn	0x43
+#define ROP_SDna	0x44
+#define ROP_DPSnaon	0x45
+#define ROP_DSPDaox	0x46
+#define ROP_PSDPxaxn	0x47
+#define ROP_SDPxa	0x48
+#define ROP_PDSPDaoxxn	0x49
+#define ROP_DPSDoax	0x4A
+#define ROP_PDSnox	0x4B
+#define ROP_SDPana	0x4C
+#define ROP_SSPxDSxoxn	0x4D
+#define ROP_PDSPxox	0x4E
+#define ROP_PDSnoan	0x4F
+#define ROP_PDna	0x50
+#define ROP_DSPnaon	0x51
+#define ROP_DPSDaox	0x52
+#define ROP_SPDSxaxn	0x53
+#define ROP_DPSonon	0x54
+#define ROP_Dn		0x55
+#define ROP_DPSox	0x56
+#define ROP_DPSoan	0x57
+#define ROP_PDSPoax	0x58
+#define ROP_DPSnox	0x59
+#define ROP_DPx		0x5A
+#define ROP_DPSDonox	0x5B
+#define ROP_DPSDxox	0x5C
+#define ROP_DPSnoan	0x5D
+#define ROP_DPSDnaox	0x5E
+#define ROP_DPan	0x5F
+#define ROP_PDSxa	0x60
+#define ROP_DSPDSaoxxn	0x61
+#define ROP_DSPDoax	0x62
+#define ROP_SDPnox	0x63
+#define ROP_SDPSoax	0x64
+#define ROP_DSPnox	0x65
+#define ROP_DSx		0x66
+#define ROP_SDPSonox	0x67
+#define ROP_DSPDSonoxxn	0x68
+#define ROP_PDSxxn	0x69
+#define ROP_DPSax	0x6A
+#define ROP_PSDPSoaxxn	0x6B
+#define ROP_SDPax	0x6C
+#define ROP_PDSPDoaxxn	0x6D
+#define ROP_SDPSnoax	0x6E
+#define ROP_PDSxnan	0x6F
+#define ROP_PDSana	0x70
+#define ROP_SSDxPDxaxn	0x71
+#define ROP_SDPSxox	0x72
+#define ROP_SDPnoan	0x73
+#define ROP_DSPDxox	0x74
+#define ROP_DSPnoan	0x75
+#define ROP_SDPSnaox	0x76
+#define ROP_DSan	0x77
+#define ROP_PDSax	0x78
+#define ROP_DSPDSoaxxn	0x79
+#define ROP_DPSDnoax	0x7A
+#define ROP_SDPxnan	0x7B
+#define ROP_SPDSnoax	0x7C
+#define ROP_DPSxnan	0x7D
+#define ROP_SPxDSxo	0x7E
+#define ROP_DPSaan	0x7F
+#define ROP_DPSaa	0x80
+#define ROP_SPxDSxon	0x81
+#define ROP_DPSxna	0x82
+#define ROP_SPDSnoaxn	0x83
+#define ROP_SDPxna	0x84
+#define ROP_PDSPnoaxn	0x85
+#define ROP_DSPDSoaxx	0x86
+#define ROP_PDSaxn	0x87
+#define ROP_DSa		0x88
+#define ROP_SDPSnaoxn	0x89
+#define ROP_DSPnoa	0x8A
+#define ROP_DSPDxoxn	0x8B
+#define ROP_SDPnoa	0x8C
+#define ROP_SDPSxoxn	0x8D
+#define ROP_SSDxPDxax	0x8E
+#define ROP_PDSanan	0x8F
+#define ROP_PDSxna	0x90
+#define ROP_SDPSnoaxn	0x91
+#define ROP_DPSDPoaxx	0x92
+#define ROP_SPDaxn	0x93
+#define ROP_PSDPSoaxx	0x94
+#define ROP_DPSaxn	0x95
+#define ROP_DPSxx	0x96
+#define ROP_PSDPSonoxx	0x97
+#define ROP_SDPSonoxn	0x98
+#define ROP_DSxn	0x99
+#define ROP_DPSnax	0x9A
+#define ROP_SDPSoaxn	0x9B
+#define ROP_SPDnax	0x9C
+#define ROP_DSPDoaxn	0x9D
+#define ROP_DSPDSaoxx	0x9E
+#define ROP_PDSxan	0x9F
+#define ROP_DPa		0xA0
+#define ROP_PDSPnaoxn	0xA1
+#define ROP_DPSnoa	0xA2
+#define ROP_DPSDxoxn	0xA3
+#define ROP_PDSPonoxn	0xA4
+#define ROP_PDxn	0xA5
+#define ROP_DSPnax	0xA6
+#define ROP_PDSPoaxn	0xA7
+#define ROP_DPSoa	0xA8
+#define ROP_DPSoxn	0xA9
+#define ROP_D		0xAA
+#define ROP_DPSono	0xAB
+#define ROP_SPDSxax	0xAC
+#define ROP_DPSDaoxn	0xAD
+#define ROP_DSPnao	0xAE
+#define ROP_DPno	0xAF
+#define ROP_PDSnoa	0xB0
+#define ROP_PDSPxoxn	0xB1
+#define ROP_SSPxDSxox	0xB2
+#define ROP_SDPanan	0xB3
+#define ROP_PSDnax	0xB4
+#define ROP_DPSDoaxn	0xB5
+#define ROP_DPSDPaoxx	0xB6
+#define ROP_SDPxan	0xB7
+#define ROP_PSDPxax	0xB8
+#define ROP_DSPDaoxn	0xB9
+#define ROP_DPSnao	0xBA
+#define ROP_DSno	0xBB
+#define ROP_SPDSanax	0xBC
+#define ROP_SDxPDxan	0xBD
+#define ROP_DPSxo	0xBE
+#define ROP_DPSano	0xBF
+#define ROP_Psa		0xC0
+#define ROP_SPDSnaoxn	0xC1
+#define ROP_SPDSonoxn	0xC2
+#define ROP_PSxn	0xC3
+#define ROP_SPDnoa	0xC4
+#define ROP_SPDSxoxn	0xC5
+#define ROP_SDPnax	0xC6
+#define ROP_PSDPoaxn	0xC7
+#define ROP_SDPoa	0xC8
+#define ROP_SPDoxn	0xC9
+#define ROP_DPSDxax	0xCA
+#define ROP_SPDSaoxn	0xCB
+#define ROP_S		0xCC
+#define ROP_SDPono	0xCD
+#define ROP_SDPnao	0xCE
+#define ROP_SPno	0xCF
+#define ROP_PSDnoa	0xD0
+#define ROP_PSDPxoxn	0xD1
+#define ROP_PDSnax	0xD2
+#define ROP_SPDSoaxn	0xD3
+#define ROP_SSPxPDxax	0xD4
+#define ROP_DPSanan	0xD5
+#define ROP_PSDPSaoxx	0xD6
+#define ROP_DPSxan	0xD7
+#define ROP_PDSPxax	0xD8
+#define ROP_SDPSaoxn	0xD9
+#define ROP_DPSDanax	0xDA
+#define ROP_SPxDSxan	0xDB
+#define ROP_SPDnao	0xDC
+#define ROP_SDno	0xDD
+#define ROP_SDPxo	0xDE
+#define ROP_SDPano	0xDF
+#define ROP_PDSoa	0xE0
+#define ROP_PDSoxn	0xE1
+#define ROP_DSPDxax	0xE2
+#define ROP_PSDPaoxn	0xE3
+#define ROP_SDPSxax	0xE4
+#define ROP_PDSPaoxn	0xE5
+#define ROP_SDPSanax	0xE6
+#define ROP_SPxPDxan	0xE7
+#define ROP_SSPxDSxax	0xE8
+#define ROP_DSPDSanaxxn	0xE9
+#define ROP_DPSao	0xEA
+#define ROP_DPSxno	0xEB
+#define ROP_SDPao	0xEC
+#define ROP_SDPxno	0xED
+#define ROP_DSo		0xEE
+#define ROP_SDPnoo	0xEF
+#define ROP_P		0xF0
+#define ROP_PDSono	0xF1
+#define ROP_PDSnao	0xF2
+#define ROP_PSno	0xF3
+#define ROP_PSDnao	0xF4
+#define ROP_PDno	0xF5
+#define ROP_PDSxo	0xF6
+#define ROP_PDSano	0xF7
+#define ROP_PDSao	0xF8
+#define ROP_PDSxno	0xF9
+#define ROP_DPo		0xFA
+#define ROP_DPSnoo	0xFB
+#define ROP_PSo		0xFC
+#define ROP_PSDnoo	0xFD
+#define ROP_DPSoo	0xFE
+#define ROP_1		0xFF
+
+#define NO_SRC_ROP(rop) \
+   ((rop == GXnoop) || (rop == GXset) || (rop == GXclear) || (rop == GXinvert))
+
+#endif /* ROP_H */
diff --git a/src/sna/sna.h b/src/sna/sna.h
index 573fe0e..9492fc2 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -49,7 +49,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include <xf86Pci.h>
 #include <xf86Cursor.h>
 #include <xf86xv.h>
-#include <vgaHW.h>
 #include <xf86Crtc.h>
 #include <xf86RandR12.h>
 #include <gcstruct.h>
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index e0990c5..46992f6 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -31,11 +31,11 @@
 
 #include "sna.h"
 #include "sna_reg.h"
+#include "rop.h"
 
 #include <X11/fonts/font.h>
 #include <X11/fonts/fontstruct.h>
 
-#include <xaarop.h>
 #include <fb.h>
 #include <dixfontstr.h>
 
diff --git a/src/sna/sna_blt.c b/src/sna/sna_blt.c
index 0290a33..4c7beab 100644
--- a/src/sna/sna_blt.c
+++ b/src/sna/sna_blt.c
@@ -36,10 +36,10 @@
 #include "sna_render.h"
 #include "sna_render_inline.h"
 #include "sna_reg.h"
+#include "rop.h"
 
 #include <mipict.h>
 #include <fbpict.h>
-#include <xaarop.h>
 
 #if DEBUG_BLT
 #undef DBG
diff --git a/src/sna/sna_composite.c b/src/sna/sna_composite.c
index 532dd80..1d66a8d 100644
--- a/src/sna/sna_composite.c
+++ b/src/sna/sna_composite.c
@@ -726,7 +726,6 @@ fallback:
 		sna_drawable_move_to_cpu(dst->alphaMap->pDrawable, true);
 
 	if (op == PictOpSrc || op == PictOpClear) {
-		PixmapPtr pixmap = get_drawable_pixmap(dst->pDrawable);
 		int nbox = REGION_NUM_RECTS(&region);
 		BoxPtr box = REGION_RECTS(&region);
 		uint32_t pixel;
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index b1275ed..32162ef 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -39,6 +39,8 @@
 
 #include <xorgVersion.h>
 #include <X11/Xatom.h>
+#include <X11/extensions/dpmsconst.h>
+#include <xf86DDC.h>
 
 #include "sna.h"
 #include "sna_reg.h"
diff --git a/src/sna/sna_driver.c b/src/sna/sna_driver.c
index 693febc..19413a9 100644
--- a/src/sna/sna_driver.c
+++ b/src/sna/sna_driver.c
@@ -45,21 +45,11 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include <stdio.h>
 #include <errno.h>
 
-#include "xf86.h"
-#include "xf86_OSproc.h"
-#include "xf86cmap.h"
+#include <xf86cmap.h>
+#include <micmap.h>
+#include <fb.h>
+
 #include "compiler.h"
-#include "mibstore.h"
-#include "vgaHW.h"
-#include "mipointer.h"
-#include "micmap.h"
-#include "shadowfb.h"
-#include <X11/extensions/randr.h>
-#include "fb.h"
-#include "miscstruct.h"
-#include "dixstruct.h"
-#include "xf86xv.h"
-#include <X11/extensions/Xv.h>
 #include "sna.h"
 #include "sna_module.h"
 #include "sna_video.h"
@@ -973,9 +963,6 @@ static void sna_free_screen(int scrnIndex, int flags)
 	}
 
 	sna_close_drm_master(scrn);
-
-	if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
-		vgaHWFreeHWRec(xf86Screens[scrnIndex]);
 }
 
 /*
commit 78d4e99fc916e6477edb01c6f24b69ad73adc552
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Nov 15 11:06:04 2011 +0000

    sna: And keep unity happy
    
    Rewrite the DRI layer to avoid the various bugs and shortcomings of the
    Xserver and interfacing with mesa.
    
    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=38732
    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=39044
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index c854846..89caf96 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -263,7 +263,6 @@ static struct kgem_bo *__kgem_bo_init(struct kgem_bo *bo,
 	bo->handle = handle;
 	bo->size = size;
 	bo->reusable = true;
-	bo->purgeable = true;
 	bo->cpu_read = true;
 	bo->cpu_write = true;
 	list_init(&bo->request);
@@ -577,6 +576,8 @@ static void kgem_bo_free(struct kgem *kgem, struct kgem_bo *bo)
 {
 	struct kgem_bo_binding *b;
 
+	DBG(("%s: handle=%d\n", __FUNCTION__, bo->handle));
+
 	b = bo->binding.next;
 	while (b) {
 		struct kgem_bo_binding *next = b->next;
@@ -592,6 +593,8 @@ static void kgem_bo_free(struct kgem *kgem, struct kgem_bo *bo)
 
 static void __kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo)
 {
+	DBG(("%s: handle=%d\n", __FUNCTION__, bo->handle));
+
 	assert(list_is_empty(&bo->list));
 	assert(bo->refcnt == 0);
 
@@ -603,9 +606,11 @@ static void __kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo)
 	if(!bo->reusable)
 		goto destroy;
 
-	if (bo->purgeable && !bo->rq && !bo->needs_flush) {
+	if (!bo->rq && !bo->needs_flush) {
 		assert(!bo->purged);
 
+		DBG(("%s: handle=%d, purged\n", __FUNCTION__, bo->handle));
+
 		if (!gem_madvise(kgem->fd, bo->handle, I915_MADV_DONTNEED)) {
 			kgem->need_purge |= bo->gpu;
 			goto destroy;
@@ -616,10 +621,13 @@ static void __kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo)
 
 	kgem->need_expire = true;
 	if (bo->rq) {
+		DBG(("%s: handle=%d -> active\n", __FUNCTION__, bo->handle));
 		list_move(&bo->list, active(kgem, bo->size));
 	} else if (bo->purged) {
+		DBG(("%s: handle=%d -> inactive\n", __FUNCTION__, bo->handle));
 		list_move(&bo->list, inactive(kgem, bo->size));
 	} else {
+		DBG(("%s: handle=%d -> flushing\n", __FUNCTION__, bo->handle));
 		assert(list_is_empty(&bo->request));
 		list_add(&bo->request, &kgem->flushing);
 		list_move(&bo->list, active(kgem, bo->size));
@@ -651,8 +659,7 @@ bool kgem_retire(struct kgem *kgem)
 
 		DBG(("%s: moving %d from flush to inactive\n",
 		     __FUNCTION__, bo->handle));
-		if (bo->purgeable &&
-		    gem_madvise(kgem->fd, bo->handle, I915_MADV_DONTNEED)) {
+		if (gem_madvise(kgem->fd, bo->handle, I915_MADV_DONTNEED)) {
 			bo->purged = true;
 			bo->needs_flush = false;
 			bo->gpu = false;
@@ -692,7 +699,7 @@ bool kgem_retire(struct kgem *kgem)
 
 			if (bo->refcnt == 0) {
 				if (bo->reusable) {
-					if (bo->needs_flush || !bo->purgeable) {
+					if (bo->needs_flush) {
 						DBG(("%s: moving %d to flushing\n",
 						     __FUNCTION__, bo->handle));
 						list_add(&bo->request, &kgem->flushing);
@@ -813,7 +820,6 @@ static void kgem_finish_partials(struct kgem *kgem)
 			if (base) {
 				memcpy(base, &bo->base, sizeof (*base));
 				base->reusable = true;
-				base->purgeable = true;
 				list_init(&base->list);
 				list_replace(&bo->base.request, &base->request);
 				free(bo);
@@ -1269,7 +1275,6 @@ search_linear_cache(struct kgem *kgem, unsigned int size, bool use_active)
 		     use_active ? "active" : "inactive"));
 		assert(bo->refcnt == 0);
 		assert(bo->reusable);
-		assert(use_active || bo->purgeable);
 		assert(use_active || bo->gpu == 0);
 		//assert(use_active || !kgem_busy(kgem, bo->handle));
 		return bo;
@@ -1298,7 +1303,6 @@ struct kgem_bo *kgem_create_for_name(struct kgem *kgem, uint32_t name)
 	}
 
 	bo->reusable = false;
-	bo->purgeable = false;
 	return bo;
 }
 
@@ -1613,7 +1617,6 @@ skip_active_search:
 		     bo->pitch, bo->tiling, bo->handle, bo->unique_id));
 		assert(bo->refcnt == 0);
 		assert(bo->reusable);
-		assert(bo->purgeable);
 		assert((flags & CREATE_INACTIVE) == 0 || bo->gpu == 0);
 		assert((flags & CREATE_INACTIVE) == 0 ||
 		       !kgem_busy(kgem, bo->handle));
@@ -1846,7 +1849,16 @@ uint32_t kgem_bo_flink(struct kgem *kgem, struct kgem_bo *bo)
 	 * on the buffer, and *presuming* they do not pass it on to a third
 	 * party, we track the lifetime accurately.
 	 */
-	bo->purgeable = false;
+	bo->reusable = false;
+
+	/* The bo is outside of our control, so presume it is written to */
+	bo->needs_flush = true;
+	bo->gpu = true;
+	bo->cpu_read = bo->cpu_write = false;
+	bo->flush = 1;
+	if (bo->exec)
+		kgem->flush = 1;
+
 	return flink.name;
 }
 
@@ -1888,7 +1900,7 @@ struct kgem_bo *kgem_create_map(struct kgem *kgem,
 		return NULL;
 	}
 
-	bo->purgeable = bo->reusable = false;
+	bo->reusable = false;
 	bo->sync = true;
 	DBG(("%s(ptr=%p, size=%d, read_only=%d) => handle=%d\n",
 	     __FUNCTION__, ptr, size, read_only, handle));
@@ -2017,7 +2029,7 @@ struct kgem_bo *kgem_create_proxy(struct kgem_bo *target,
 	if (bo == NULL)
 		return NULL;
 
-	bo->purgeable = bo->reusable = false;
+	bo->reusable = false;
 	bo->proxy = kgem_bo_reference(target);
 	bo->delta = offset;
 	return bo;
@@ -2146,7 +2158,7 @@ struct kgem_bo *kgem_create_buffer(struct kgem *kgem,
 		bo->base.vmap = true;
 		bo->need_io = 0;
 	}
-	bo->base.purgeable = bo->base.reusable = false;
+	bo->base.reusable = false;
 
 	bo->alloc = alloc;
 	bo->used = size;
diff --git a/src/sna/kgem.h b/src/sna/kgem.h
index 0f142b7..112a91c 100644
--- a/src/sna/kgem.h
+++ b/src/sna/kgem.h
@@ -75,7 +75,6 @@ struct kgem_bo {
 	uint32_t vmap : 1;
 	uint32_t flush : 1;
 	uint32_t sync : 1;
-	uint32_t purgeable : 1;
 	uint32_t purged : 1;
 };
 
diff --git a/src/sna/sna.h b/src/sna/sna.h
index 52142cb..573fe0e 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -305,15 +305,15 @@ extern void sna_mode_fini(struct sna *sna);
 extern int sna_crtc_id(xf86CrtcPtr crtc);
 extern int sna_output_dpms_status(xf86OutputPtr output);
 
-extern int sna_do_pageflip(struct sna *sna,
-			    PixmapPtr pixmap,
-			    void *data,
-			    int ref_crtc_hw_id,
-			    uint32_t *old_fb);
+extern int sna_page_flip(struct sna *sna,
+			 struct kgem_bo *bo,
+			 void *data,
+			 int ref_crtc_hw_id,
+			 uint32_t *old_fb);
 
 extern PixmapPtr sna_set_screen_pixmap(struct sna *sna, PixmapPtr pixmap);
 
-void sna_mode_delete_fb(struct sna *sna, PixmapPtr pixmap, uint32_t fb);
+void sna_mode_delete_fb(struct sna *sna, uint32_t fb);
 
 static inline struct sna *
 to_sna(ScrnInfoPtr scrn)
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index e8d2c2a..b1275ed 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -1773,21 +1773,16 @@ PixmapPtr sna_set_screen_pixmap(struct sna *sna, PixmapPtr pixmap)
 }
 
 int
-sna_do_pageflip(struct sna *sna,
-		PixmapPtr pixmap,
-		void *data,
-		int ref_crtc_hw_id,
-		uint32_t *old_fb)
+sna_page_flip(struct sna *sna,
+	      struct kgem_bo *bo,
+	      void *data,
+	      int ref_crtc_hw_id,
+	      uint32_t *old_fb)
 {
 	ScrnInfoPtr scrn = sna->scrn;
 	struct sna_mode *mode = &sna->mode;
-	struct kgem_bo *bo;
 	int count;
 
-	bo = sna_pixmap_pin(pixmap);
-	if (!bo)
-		return 0;
-
 	*old_fb = mode->fb_id;
 
 	/*
@@ -1822,7 +1817,6 @@ sna_do_pageflip(struct sna *sna,
 	count = do_page_flip(sna, data, ref_crtc_hw_id);
 	DBG(("%s: page flipped %d crtcs\n", __FUNCTION__, count));
 	if (count) {
-		sna->mode.fb_pixmap = pixmap->drawable.serialNumber;
 		bo->cpu_read = bo->cpu_write = false;
 		bo->gpu = true;
 
@@ -1832,6 +1826,7 @@ sna_do_pageflip(struct sna *sna,
 		 * upon release.
 		 */
 		bo->needs_flush = true;
+		bo->reusable = true;
 	} else {
 		drmModeRmFB(sna->kgem.fd, mode->fb_id);
 		mode->fb_id = *old_fb;
@@ -1840,13 +1835,10 @@ sna_do_pageflip(struct sna *sna,
 	return count;
 }
 
-void sna_mode_delete_fb(struct sna *sna, PixmapPtr pixmap, uint32_t fb)
+void sna_mode_delete_fb(struct sna *sna, uint32_t fb)
 {
 	if (fb)
 		drmModeRmFB(sna->kgem.fd, fb);
-
-	if (pixmap)
-		pixmap->drawable.pScreen->DestroyPixmap(pixmap);
 }
 
 static const xf86CrtcConfigFuncsRec sna_crtc_config_funcs = {
diff --git a/src/sna/sna_dri.c b/src/sna/sna_dri.c
index 61a7b12..941da87 100644
--- a/src/sna/sna_dri.c
+++ b/src/sna/sna_dri.c
@@ -36,35 +36,17 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "config.h"
 #endif
 
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/time.h>
-#include <sys/mman.h>
-#include <time.h>
+#include <xf86.h>
+#include <xf86_OSproc.h>
 #include <errno.h>
+#include <string.h>
 
-#include "xf86.h"
-#include "xf86_OSproc.h"
-
-#include "xf86PciInfo.h"
-#include "xf86Pci.h"
-
-#include "windowstr.h"
-#include "gcstruct.h"
+#include <i915_drm.h>
+#include <dri2.h>
 
 #include "sna.h"
 #include "sna_reg.h"
 
-#include "i915_drm.h"
-
-#include "dri2.h"
-
 #if DRI2INFOREC_VERSION <= 2
 #error DRI2 version supported by the Xserver is too old
 #endif
@@ -74,8 +56,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define DBG(x) ErrorF x
 #endif
 
-#define NO_TRIPPLE_BUFFER 0
-
 enum frame_event_type {
 	DRI2_SWAP,
 	DRI2_SWAP_THROTTLE,
@@ -113,11 +93,13 @@ struct sna_dri_frame_event {
 	unsigned int fe_tv_sec;
 	unsigned int fe_tv_usec;
 
-	PixmapPtr old_front;
-	PixmapPtr next_front;
+	struct {
+		struct kgem_bo *bo;
+		uint32_t name;
+	} old_front, next_front, cache;
 	uint32_t old_fb;
 
-	struct sna_dri_frame_event *chain;
+	int off_delay;
 };
 
 static DevPrivateKeyRec sna_client_key;
@@ -128,11 +110,16 @@ to_frame_event(void *data)
 	 return (struct sna_dri_frame_event *)((uintptr_t)data & ~1);
 }
 
-static inline PixmapPtr
-get_pixmap(DRI2Buffer2Ptr buffer)
+static inline struct sna_dri_private *
+get_private(DRI2Buffer2Ptr buffer)
 {
-	struct sna_dri_private *priv = buffer->driverPrivate;
-	return priv->pixmap;
+	return (struct sna_dri_private *)(buffer+1);
+}
+
+static inline struct kgem_bo *ref(struct kgem_bo *bo)
+{
+	bo->refcnt++;
+	return bo;
 }
 
 static struct kgem_bo *sna_pixmap_set_dri(struct sna *sna,
@@ -145,29 +132,22 @@ static struct kgem_bo *sna_pixmap_set_dri(struct sna *sna,
 		return NULL;
 
 	if (priv->flush)
-		return priv->gpu_bo;
+		return ref(priv->gpu_bo);
 
 	if (priv->cpu_damage)
 		list_add(&priv->list, &sna->dirty_pixmaps);
 
-	/* The bo is outside of our control, so presume it is written to */
-	priv->gpu_bo->needs_flush = true;
-	priv->gpu_bo->gpu = true;
-
 	/* We need to submit any modifications to and reads from this
 	 * buffer before we send any reply to the Client.
 	 *
 	 * As we don't track which Client, we flush for all.
 	 */
 	priv->flush = 1;
-	priv->gpu_bo->flush = 1;
-	if (priv->gpu_bo->exec)
-		sna->kgem.flush = 1;
 
 	/* Don't allow this named buffer to be replaced */
 	priv->pinned = 1;
 
-	return priv->gpu_bo;
+	return ref(priv->gpu_bo);
 }
 
 static DRI2Buffer2Ptr
@@ -175,14 +155,12 @@ sna_dri_create_buffer(DrawablePtr drawable,
 		      unsigned int attachment,
 		      unsigned int format)
 {
-	ScreenPtr screen = drawable->pScreen;
-	ScrnInfoPtr scrn = xf86Screens[screen->myNum];
-	struct sna *sna = to_sna(scrn);
+	struct sna *sna = to_sna_from_drawable(drawable);
 	DRI2Buffer2Ptr buffer;
 	struct sna_dri_private *private;
 	PixmapPtr pixmap;
 	struct kgem_bo *bo;
-	int bpp, usage;
+	int bpp;
 
 	DBG(("%s(attachment=%d, format=%d, drawable=%dx%d)\n",
 	     __FUNCTION__, attachment, format,
@@ -191,11 +169,9 @@ sna_dri_create_buffer(DrawablePtr drawable,
 	buffer = calloc(1, sizeof *buffer + sizeof *private);
 	if (buffer == NULL)
 		return NULL;
-	private = (struct sna_dri_private *)(buffer + 1);
 
 	pixmap = NULL;
 	bo = NULL;
-	usage = SNA_CREATE_SCRATCH;
 	switch (attachment) {
 	case DRI2BufferFrontLeft:
 		pixmap = get_drawable_pixmap(drawable);
@@ -211,25 +187,14 @@ sna_dri_create_buffer(DrawablePtr drawable,
 	case DRI2BufferBackLeft:
 	case DRI2BufferBackRight:
 	case DRI2BufferFrontRight:
-		/* Allocate a normal window, perhaps flippable */
-		usage = 0;
-		if (drawable->width == sna->front->drawable.width &&
-		    drawable->height == sna->front->drawable.height &&
-		    drawable->depth == sna->front->drawable.depth)
-			usage = SNA_CREATE_FB;
-
 	case DRI2BufferFakeFrontLeft:
 	case DRI2BufferFakeFrontRight:
-		pixmap = screen->CreatePixmap(screen,
-					      drawable->width,
-					      drawable->height,
-					      drawable->depth,
-					      usage);
-		if (!pixmap)
-			goto err;
-
-		bo = sna_pixmap_set_dri(sna, pixmap);
-		bpp = pixmap->drawable.bitsPerPixel;
+		bpp = drawable->bitsPerPixel;
+		bo = kgem_create_2d(&sna->kgem,
+				    drawable->width,
+				    drawable->height,
+				    drawable->bitsPerPixel,
+				    I915_TILING_X, CREATE_EXACT);
 		break;
 
 	case DRI2BufferStencil:
@@ -282,6 +247,7 @@ sna_dri_create_buffer(DrawablePtr drawable,
 	if (bo == NULL)
 		goto err;
 
+	private = get_private(buffer);
 	buffer->attachment = attachment;
 	buffer->pitch = bo->pitch;
 	buffer->cpp = bpp / 8;
@@ -296,7 +262,7 @@ sna_dri_create_buffer(DrawablePtr drawable,
 	if (buffer->name == 0) {
 		/* failed to name buffer */
 		if (pixmap)
-			screen->DestroyPixmap(pixmap);
+			pixmap->drawable.pScreen->DestroyPixmap(pixmap);
 		else
 			kgem_bo_destroy(&sna->kgem, bo);
 		goto err;
@@ -311,12 +277,12 @@ err:
 
 static void _sna_dri_destroy_buffer(struct sna *sna, DRI2Buffer2Ptr buffer)
 {
-	struct sna_dri_private *private = buffer->driverPrivate;
+	struct sna_dri_private *private = get_private(buffer);
 
-	if (--private->refcnt == 0) {
-		private->bo->gpu = private->bo->needs_flush || private->bo->rq != NULL;
-		private->bo->flush = 0;
+	if (buffer == NULL)
+		return;
 
+	if (--private->refcnt == 0) {
 		if (private->pixmap) {
 			ScreenPtr screen = private->pixmap->drawable.pScreen;
 			struct sna_pixmap *priv = sna_pixmap(private->pixmap);
@@ -327,8 +293,12 @@ static void _sna_dri_destroy_buffer(struct sna *sna, DRI2Buffer2Ptr buffer)
 			priv->flush = 0;
 
 			screen->DestroyPixmap(private->pixmap);
-		} else
-			kgem_bo_destroy(&sna->kgem, private->bo);
+		}
+
+		private->bo->gpu =
+			private->bo->needs_flush || private->bo->rq != NULL;
+		private->bo->flush = 0;
+		kgem_bo_destroy(&sna->kgem, private->bo);
 
 		free(buffer);
 	}
@@ -336,16 +306,12 @@ static void _sna_dri_destroy_buffer(struct sna *sna, DRI2Buffer2Ptr buffer)
 
 static void sna_dri_destroy_buffer(DrawablePtr drawable, DRI2Buffer2Ptr buffer)
 {
-	if (buffer && buffer->driverPrivate)
-		_sna_dri_destroy_buffer(to_sna_from_drawable(drawable), buffer);
-	else
-		free(buffer);
+	_sna_dri_destroy_buffer(to_sna_from_drawable(drawable), buffer);
 }
 
 static void sna_dri_reference_buffer(DRI2Buffer2Ptr buffer)
 {
-	struct sna_dri_private *private = buffer->driverPrivate;
-	private->refcnt++;
+	get_private(buffer)->refcnt++;
 }
 
 static void damage(PixmapPtr pixmap, RegionPtr region)
@@ -375,65 +341,39 @@ damage_all:
 	}
 }
 
-static void damage_all(PixmapPtr pixmap)
+static void set_bo(PixmapPtr pixmap, struct kgem_bo *bo)
 {
 	struct sna_pixmap *priv;
 
 	priv = sna_pixmap(pixmap);
-	if (priv->gpu_only)
-		return;
-
-	sna_damage_all(&priv->gpu_damage,
-		       pixmap->drawable.width,
-		       pixmap->drawable.height);
-	sna_damage_destroy(&priv->cpu_damage);
+	if (!priv->gpu_only) {
+		sna_damage_all(&priv->gpu_damage,
+				pixmap->drawable.width,
+				pixmap->drawable.height);
+		sna_damage_destroy(&priv->cpu_damage);
+	}
+	assert(priv->gpu_bo->refcnt > 1);
+	priv->gpu_bo->refcnt--;
+	priv->gpu_bo = ref(bo);
 }
 
 static void
 sna_dri_copy(struct sna *sna, DrawablePtr draw, RegionPtr region,
-	     DRI2BufferPtr dst_buffer, DRI2BufferPtr src_buffer,
+	     struct kgem_bo *dst_bo,struct kgem_bo *src_bo,
 	     bool sync)
 {
-	struct sna_dri_private *src_priv = src_buffer->driverPrivate;
-	struct sna_dri_private *dst_priv = dst_buffer->driverPrivate;
-	PixmapPtr src = src_priv->pixmap;
-	PixmapPtr dst = dst_priv->pixmap;
-	struct kgem_bo *dst_bo = dst_priv->bo;
+	PixmapPtr pixmap = get_drawable_pixmap(draw);
 	pixman_region16_t clip;
 	bool flush = false;
 	BoxRec box, *boxes;
-	int16_t dx, dy, sx, sy;
+	int16_t dx, dy;
 	int n;
 
-	DBG(("%s: dst -- attachment=%d, name=%d, handle=%d [screen=%d, sync=%d]\n",
-	     __FUNCTION__,
-	     dst_buffer->attachment,
-	     dst_buffer->name,
-	     dst_priv->bo->handle,
-	     sna_pixmap_get_bo(sna->front)->handle,
-	     sync));
-	DBG(("%s: src -- attachment=%d, name=%d, handle=%d\n",
-	     __FUNCTION__,
-	     src_buffer->attachment,
-	     src_buffer->name,
-	     src_priv->bo->handle));
-	if (region) {
-		DBG(("%s: clip (%d, %d), (%d, %d) x %d\n",
-		     __FUNCTION__,
-		     region->extents.x1, region->extents.y1,
-		     region->extents.x2, region->extents.y2,
-		     REGION_NUM_RECTS(region)));
-	}
-
 	box.x1 = draw->x;
 	box.y1 = draw->y;
 	box.x2 = draw->x + draw->width;
 	box.y2 = draw->y + draw->height;
 
-	get_drawable_deltas(draw, src, &sx, &sy);
-	sx -= draw->x;
-	sy -= draw->y;
-
 	if (region) {
 		pixman_region_translate(region, draw->x, draw->y);
 		pixman_region_init_rects(&clip, &box, 1);
@@ -467,11 +407,11 @@ sna_dri_copy(struct sna *sna, DrawablePtr draw, RegionPtr region,
 			return;
 		}
 
-		if (dst == sna->front && sync)
-			flush = sna_wait_for_scanline(sna, dst, NULL,
+		if (pixmap == sna->front && sync)
+			flush = sna_wait_for_scanline(sna, pixmap, NULL,
 						      &region->extents);
 
-		get_drawable_deltas(draw, dst, &dx, &dy);
+		get_drawable_deltas(draw, pixmap, &dx, &dy);
 	}
 
 	if (sna->kgem.gen >= 60) {
@@ -490,7 +430,7 @@ sna_dri_copy(struct sna *sna, DrawablePtr draw, RegionPtr region,
 		kgem_set_mode(&sna->kgem, KGEM_RENDER);
 	}
 
-	damage(dst, region);
+	damage(pixmap, region);
 	if (region) {
 		boxes = REGION_RECTS(region);
 		n = REGION_NUM_RECTS(region);
@@ -512,8 +452,8 @@ sna_dri_copy(struct sna *sna, DrawablePtr draw, RegionPtr region,
 	 * again.
 	 */
 	sna->render.copy_boxes(sna, GXcopy,
-			       src, src_priv->bo, sx, sy,
-			       dst, dst_bo, dx, dy,
+			       pixmap, src_bo, -draw->x, -draw->y,
+			       pixmap, dst_bo, dx, dy,
 			       boxes, n);
 
 	DBG(("%s: flushing? %d\n", __FUNCTION__, flush));
@@ -521,8 +461,8 @@ sna_dri_copy(struct sna *sna, DrawablePtr draw, RegionPtr region,
 		kgem_submit(&sna->kgem);
 
 	pixman_region_translate(region, dx, dy);
-	DamageRegionAppend(&dst->drawable, region);
-	DamageRegionProcessPending(&dst->drawable);
+	DamageRegionAppend(&pixmap->drawable, region);
+	DamageRegionProcessPending(&pixmap->drawable);
 
 	if (region == &clip)
 		pixman_region_fini(&clip);
@@ -534,8 +474,32 @@ sna_dri_copy_region(DrawablePtr draw,
 		    DRI2BufferPtr dst_buffer,
 		    DRI2BufferPtr src_buffer)
 {
-	sna_dri_copy(to_sna_from_drawable(draw), draw,region,
-		     dst_buffer, src_buffer, false);
+	struct kgem_bo *src, *dst;
+
+	if (dst_buffer->attachment == DRI2BufferFrontLeft)
+		dst = sna_pixmap_get_bo(get_drawable_pixmap(draw));
+	else
+		dst = get_private(dst_buffer)->bo;
+
+	if (src_buffer->attachment == DRI2BufferFrontLeft)
+		src = sna_pixmap_get_bo(get_drawable_pixmap(draw));
+	else
+		src = get_private(src_buffer)->bo;
+
+	DBG(("%s: dst -- attachment=%d, name=%d, handle=%d [screen=%d]\n",
+	     __FUNCTION__,
+	     dst_buffer->attachment, dst_buffer->name, dst->handle,
+	     sna_pixmap_get_bo(to_sna_from_drawable(draw)->front)->handle));
+	DBG(("%s: src -- attachment=%d, name=%d, handle=%d\n",
+	     __FUNCTION__,
+	     src_buffer->attachment, src_buffer->name, src->handle));
+	DBG(("%s: clip (%d, %d), (%d, %d) x %d\n",
+	     __FUNCTION__,
+	     region->extents.x1, region->extents.y1,
+	     region->extents.x2, region->extents.y2,
+	     REGION_NUM_RECTS(region)));
+
+	sna_dri_copy(to_sna_from_drawable(draw), draw, region, dst, src, false);
 }
 
 #if DRI2INFOREC_VERSION >= 4
@@ -721,15 +685,21 @@ sna_dri_frame_event_info_free(struct sna_dri_frame_event *info)
 	list_del(&info->client_resource);
 	list_del(&info->drawable_resource);
 
-	if (info->front)
-		_sna_dri_destroy_buffer(info->sna, info->front);
-	if (info->back)
-		_sna_dri_destroy_buffer(info->sna, info->back);
+	_sna_dri_destroy_buffer(info->sna, info->front);
+	_sna_dri_destroy_buffer(info->sna, info->back);
+
+	if (info->old_front.bo)
+		kgem_bo_destroy(&info->sna->kgem, info->old_front.bo);
+	if (info->next_front.bo)
+		kgem_bo_destroy(&info->sna->kgem, info->next_front.bo);
+	if (info->cache.bo)
+		kgem_bo_destroy(&info->sna->kgem, info->cache.bo);
+
 	free(info);
 }
 
 static void
-sna_dri_exchange_buffers(DRI2BufferPtr front, DRI2BufferPtr back)
+sna_dri_exchange_attachment(DRI2BufferPtr front, DRI2BufferPtr back)
 {
 	int tmp;
 
@@ -746,20 +716,26 @@ sna_dri_exchange_buffers(DRI2BufferPtr front, DRI2BufferPtr back)
  * flipping buffers as necessary.
  */
 static Bool
-sna_dri_schedule_flip(struct sna *sna, struct sna_dri_frame_event *info)
+sna_dri_page_flip(struct sna *sna, struct sna_dri_frame_event *info)
 {
-	struct sna_dri_private *back_priv;
+	struct kgem_bo *bo = get_private(info->back)->bo;
 
 	DBG(("%s()\n", __FUNCTION__));
 
-	/* Page flip the full screen buffer */
-	back_priv = info->back->driverPrivate;
-	damage_all(back_priv->pixmap);
-	info->count = sna_do_pageflip(sna,
-				      back_priv->pixmap,
-				      info, info->pipe,
-				      &info->old_fb);
-	return info->count != 0;
+	info->count = sna_page_flip(sna, bo,
+				    info, info->pipe,
+				    &info->old_fb);
+	if (info->count == 0)
+		return FALSE;
+
+	set_bo(sna->front, bo);
+
+	info->old_front.name = info->front->name;
+	info->old_front.bo = get_private(info->front)->bo;
+
+	info->front->name = info->back->name;
+	get_private(info->front)->bo = bo;
+	return TRUE;
 }
 
 static Bool
@@ -768,14 +744,8 @@ can_flip(struct sna * sna,
 	 DRI2BufferPtr front,
 	 DRI2BufferPtr back)
 {
-	struct sna_dri_private *back_priv = back->driverPrivate;
-	struct sna_dri_private *front_priv = front->driverPrivate;
-	struct sna_pixmap *front_sna, *back_sna;
 	WindowPtr win = (WindowPtr)draw;
-	PixmapPtr front_pixmap = front_priv->pixmap;
-	PixmapPtr back_pixmap = back_priv->pixmap;
-
-	ScreenPtr screen = draw->pScreen;
+	PixmapPtr pixmap;
 
 	if (draw->type == DRAWABLE_PIXMAP)
 		return FALSE;
@@ -799,7 +769,8 @@ can_flip(struct sna * sna,
 		return FALSE;
 	}
 
-	if (front_pixmap != sna->front) {
+	pixmap = get_drawable_pixmap(draw);
+	if (pixmap != sna->front) {
 		DBG(("%s: no, window is not on the front buffer\n",
 		     __FUNCTION__));
 		return FALSE;
@@ -810,75 +781,41 @@ can_flip(struct sna * sna,
 	     win->drawable.width, win->drawable.height,
 	     win->clipList.extents.x1, win->clipList.extents.y1,
 	     win->clipList.extents.x2, win->clipList.extents.y2));
-	if (!RegionEqual(&win->clipList, &screen->root->winSize)) {
+	if (!RegionEqual(&win->clipList, &draw->pScreen->root->winSize)) {
 		DBG(("%s: no, window is clipped: clip region=(%d, %d), (%d, %d), root size=(%d, %d), (%d, %d)\n",
 		     __FUNCTION__,
 		     win->clipList.extents.x1,
 		     win->clipList.extents.y1,
 		     win->clipList.extents.x2,
 		     win->clipList.extents.y2,
-		     screen->root->winSize.extents.x1,
-		     screen->root->winSize.extents.y1,
-		     screen->root->winSize.extents.x2,
-		     screen->root->winSize.extents.y2));
+		     draw->pScreen->root->winSize.extents.x1,
+		     draw->pScreen->root->winSize.extents.y1,
+		     draw->pScreen->root->winSize.extents.x2,
+		     draw->pScreen->root->winSize.extents.y2));
 		return FALSE;
 	}
 
 	if (draw->x != 0 || draw->y != 0 ||
 #ifdef COMPOSITE
-	    draw->x != front_pixmap->screen_x ||
-	    draw->y != front_pixmap->screen_y ||
+	    draw->x != pixmap->screen_x ||
+	    draw->y != pixmap->screen_y ||
 #endif
-	    draw->width != front_pixmap->drawable.width ||
-	    draw->height != front_pixmap->drawable.height) {
+	    draw->width != pixmap->drawable.width ||
+	    draw->height != pixmap->drawable.height) {
 		DBG(("%s: no, window is not full size (%dx%d)!=(%dx%d)\n",
 		     __FUNCTION__,
 		     draw->width, draw->height,
-		     front_pixmap->drawable.width,
-		     front_pixmap->drawable.height));
-		return FALSE;
-	}
-
-	if (front_pixmap->drawable.width != back_pixmap->drawable.width) {
-		DBG(("%s -- no, size mismatch: front width=%d, back=%d\n",
-		     __FUNCTION__,
-		     front_pixmap->drawable.width,
-		     back_pixmap->drawable.width));
-		return FALSE;
-	}
-
-	if (front_pixmap->drawable.height != back_pixmap->drawable.height) {
-		DBG(("%s -- no, size mismatch: front height=%d, back=%d\n",
-		     __FUNCTION__,
-		     front_pixmap->drawable.height,
-		     back_pixmap->drawable.height));
-		return FALSE;
-	}
-
-	if (front_pixmap->drawable.depth != back_pixmap->drawable.depth) {
-		DBG(("%s -- no, depth mismatch: front bpp=%d/%d, back=%d/%d\n",
-		     __FUNCTION__,
-		     front_pixmap->drawable.depth,
-		     front_pixmap->drawable.bitsPerPixel,
-		     back_pixmap->drawable.depth,
-		     back_pixmap->drawable.bitsPerPixel));
+		     pixmap->drawable.width,
+		     pixmap->drawable.height));
 		return FALSE;
 	}
 
 	/* prevent an implicit tiling mode change */
-	front_sna = sna_pixmap(front_pixmap);
-	back_sna  = sna_pixmap(back_pixmap);
-	if (front_sna->gpu_bo->tiling != back_sna->gpu_bo->tiling) {
+	if (get_private(front)->bo->tiling != get_private(back)->bo->tiling) {
 		DBG(("%s -- no, tiling mismatch: front %d, back=%d\n",
 		     __FUNCTION__,
-		     front_sna->gpu_bo->tiling,
-		     back_sna->gpu_bo->tiling));
-		return FALSE;
-	}
-
-	if (front_sna->gpu_only != back_sna->gpu_only) {
-		DBG(("%s -- no, mismatch in gpu_only: front %d, back=%d\n",
-		     __FUNCTION__, front_sna->gpu_only, back_sna->gpu_only));
+		     get_private(front)->bo->tiling,
+		     get_private(back)->bo->tiling));
 		return FALSE;
 	}
 
@@ -913,13 +850,18 @@ static void sna_dri_vblank_handle(int fd,
 	case DRI2_FLIP:
 		/* If we can still flip... */
 		if (can_flip(sna, draw, info->front, info->back) &&
-		    sna_dri_schedule_flip(sna, info)) {
-			sna_dri_exchange_buffers(info->front, info->back);
+		    sna_dri_page_flip(sna, info)) {
+			info->back->name = info->old_front.name;
+			get_private(info->back)->bo = info->old_front.bo;
+			info->old_front.bo = NULL;
 			return;
 		}
 		/* else fall through to exchange/blit */
 	case DRI2_SWAP:
-		sna_dri_copy(sna, draw, NULL, info->front, info->back, true);
+		sna_dri_copy(sna, draw, NULL,
+			     get_private(info->front)->bo,
+			     get_private(info->back)->bo,
+			     true);
 	case DRI2_SWAP_THROTTLE:
 		DBG(("%s: %d complete, frame=%d tv=%d.%06d\n",
 		     __FUNCTION__, info->type, frame, tv_sec, tv_usec));
@@ -947,68 +889,38 @@ done:
 	sna_dri_frame_event_info_free(info);
 }
 
-static void set_pixmap(struct sna *sna, DRI2BufferPtr buffer, PixmapPtr pixmap)
-{
-	struct sna_dri_private *priv = buffer->driverPrivate;
-
-	assert(priv->pixmap->refcnt > 1);
-	priv->pixmap->refcnt--;
-	priv->pixmap = pixmap;
-	priv->bo = sna_pixmap_set_dri(sna, pixmap);
-	buffer->name = kgem_bo_flink(&sna->kgem, priv->bo);
-	buffer->pitch = priv->bo->pitch;
-}
-
 static int
-sna_dri_flip(struct sna *sna, DrawablePtr draw, struct sna_dri_frame_event *info)
+sna_dri_flip_continue(struct sna *sna,
+		      DrawablePtr draw,
+		      struct sna_dri_frame_event *info)
 {
-	struct sna_dri_frame_event *pending;
-	ScreenPtr screen = draw->pScreen;
-	PixmapPtr pixmap;
+	struct kgem_bo *bo;
+	int name;
 
-	if (NO_TRIPPLE_BUFFER)
-		return sna_dri_schedule_flip(sna, info);
+	DBG(("%s()\n", __FUNCTION__));
 
-	info->type = DRI2_FLIP_THROTTLE;
+	name = info->back->name;
+	bo = get_private(info->back)->bo;
 
-	pending = sna->dri.flip_pending[info->pipe];
-	if (pending) {
-		if (pending->type != DRI2_FLIP_THROTTLE) {
-			/* We need to first wait (one vblank) for the
-			 * async flips to complete beofore this client can
-			 * take over.
-			 */
-			info->type = DRI2_FLIP;
-			return sna_dri_schedule_flip(sna, info);
-		}
+	info->count = sna_page_flip(sna, bo, info, info->pipe, &info->old_fb);
+	if (info->count == 0)
+		return FALSE;
 
-		DBG(("%s: chaining flip\n", __FUNCTION__));
-		assert(pending->chain == NULL);
-		pending->chain = info;
-		return TRUE;
-	}
+	set_bo(sna->front, bo);
 
-	if (!sna_dri_schedule_flip(sna, info))
-		return FALSE;
+	get_private(info->back)->bo = info->old_front.bo;
+	info->back->name = info->old_front.name;
 
-	info->old_front =
-		sna_set_screen_pixmap(sna, get_pixmap(info->back));
-	sna->dri.flip_pending[info->pipe] = info;
+	info->old_front.name = info->front->name;
+	info->old_front.bo = get_private(info->front)->bo;
 
-	if ((pixmap = screen->CreatePixmap(screen,
-					   draw->width,
-					   draw->height,
-					   draw->depth,
-					   SNA_CREATE_FB))) {
-		DBG(("%s: new back buffer\n", __FUNCTION__));
-		set_pixmap(sna, info->front, pixmap);
-	}
+	info->front->name = name;
+	get_private(info->front)->bo = bo;
+
+	info->next_front.name = 0;
+
+	sna->dri.flip_pending[info->pipe] = info;
 
-	sna_dri_exchange_buffers(info->front, info->back);
-	DRI2SwapComplete(info->client, draw, 0, 0, 0,
-			 DRI2_EXCHANGE_COMPLETE,
-			 info->event_complete,
-			 info->event_data);
 	return TRUE;
 }
 
@@ -1016,8 +928,6 @@ static void sna_dri_flip_event(struct sna *sna,
 			       struct sna_dri_frame_event *flip)
 {
 	DrawablePtr drawable;
-	struct sna_dri_frame_event *chain;
-	int status;
 
 	DBG(("%s(frame=%d, tv=%d.%06d, type=%d)\n",
 	     __FUNCTION__,
@@ -1034,108 +944,119 @@ static void sna_dri_flip_event(struct sna *sna,
 		 * into account. This usually means some defective kms pageflip completion,
 		 * causing wrong (msc, ust) return values and possible visual corruption.
 		 */
-		if (flip->drawable_id) {
-			status = dixLookupDrawable(&drawable,
-						   flip->drawable_id,
-						   serverClient,
-						   M_ANY, DixWriteAccess);
-			if (status == Success) {
-				if ((flip->fe_frame < flip->frame) &&
-				    (flip->frame - flip->fe_frame < 5)) {
-					static int limit = 5;
-
-					/* XXX we are currently hitting this path with older
-					 * kernels, so make it quieter.
-					 */
-					if (limit) {
-						xf86DrvMsg(sna->scrn->scrnIndex, X_WARNING,
-							   "%s: Pageflip completion has impossible msc %d < target_msc %d\n",
-							   __func__, flip->fe_frame, flip->frame);
-						limit--;
-					}
-
-					/* All-0 values signal timestamping failure. */
-					flip->fe_frame = flip->fe_tv_sec = flip->fe_tv_usec = 0;
+		if (flip->drawable_id &&
+		    dixLookupDrawable(&drawable,
+				      flip->drawable_id,
+				      serverClient,
+				      M_ANY, DixWriteAccess) == Success) {
+			if ((flip->fe_frame < flip->frame) &&
+			    (flip->frame - flip->fe_frame < 5)) {
+				static int limit = 5;
+
+				/* XXX we are currently hitting this path with older
+				 * kernels, so make it quieter.
+				 */
+				if (limit) {
+					xf86DrvMsg(sna->scrn->scrnIndex, X_WARNING,
+						   "%s: Pageflip completion has impossible msc %d < target_msc %d\n",
+						   __func__, flip->fe_frame, flip->frame);
+					limit--;
 				}
 
-				DBG(("%s: flip complete\n", __FUNCTION__));
-				DRI2SwapComplete(flip->client, drawable,
-						 flip->fe_frame,
-						 flip->fe_tv_sec,
-						 flip->fe_tv_usec,
-						 DRI2_FLIP_COMPLETE,
-						 flip->client ? flip->event_complete : NULL,
-						 flip->event_data);
+				/* All-0 values signal timestamping failure. */
+				flip->fe_frame = flip->fe_tv_sec = flip->fe_tv_usec = 0;
 			}
+
+			DBG(("%s: flip complete\n", __FUNCTION__));
+			DRI2SwapComplete(flip->client, drawable,
+					 flip->fe_frame,
+					 flip->fe_tv_sec,
+					 flip->fe_tv_usec,
+					 DRI2_FLIP_COMPLETE,
+					 flip->client ? flip->event_complete : NULL,
+					 flip->event_data);
 		}
 
-		sna_mode_delete_fb(flip->sna, flip->old_front, flip->old_fb);
+		sna_mode_delete_fb(flip->sna, flip->old_fb);
 		sna_dri_frame_event_info_free(flip);
 		break;
 
 	case DRI2_FLIP_THROTTLE:
+		sna_mode_delete_fb(sna, flip->old_fb);
+
 		assert(sna->dri.flip_pending[flip->pipe] == flip);
 		sna->dri.flip_pending[flip->pipe] = NULL;
 
-		chain = flip->chain;
-
-		sna_mode_delete_fb(flip->sna, flip->old_front, flip->old_fb);
-		sna_dri_frame_event_info_free(flip);
-
-		if (chain) {
-			status = dixLookupDrawable(&drawable,
-						   chain->drawable_id,
-						   serverClient,
-						   M_ANY, DixWriteAccess);
-			if (status == Success) {
-				if (!(can_flip(chain->sna, drawable,
-					       chain->front, chain->back) &&
-				      sna_dri_flip(chain->sna, drawable, chain))) {
-					sna_dri_copy(sna, drawable, NULL,
-						     chain->front, chain->back, true);
-					DRI2SwapComplete(chain->client,
-							 drawable,
-							 0, 0, 0,
-							 DRI2_BLIT_COMPLETE,
-							 chain->client ? chain->event_complete : NULL,
-							 chain->event_data);
-					sna_dri_frame_event_info_free(chain);
-				}
-			} else
-				sna_dri_frame_event_info_free(chain);
+		if (flip->next_front.name &&
+		    flip->drawable_id &&
+		    dixLookupDrawable(&drawable,
+				      flip->drawable_id,
+				      serverClient,
+				      M_ANY, DixWriteAccess) == Success) {
+			if (!sna_dri_flip_continue(sna, drawable, flip)) {
+				DRI2SwapComplete(flip->client, drawable,
+						 0, 0, 0,
+						 DRI2_BLIT_COMPLETE,
+						 flip->client ? flip->event_complete : NULL,
+						 flip->event_data);
+				sna_dri_frame_event_info_free(flip);
+			} else {
+				DRI2SwapComplete(flip->client, drawable,
+						 0, 0, 0,
+						 DRI2_FLIP_COMPLETE,
+						 flip->client ? flip->event_complete : NULL,
+						 flip->event_data);
+			}
+		} else {
+			sna_dri_frame_event_info_free(flip);
 		}
 		break;
 
+#if DRI2INFOREC_VERSION >= 7
 	case DRI2_ASYNC_FLIP:
 		DBG(("%s: async swap flip completed on pipe %d, pending? %d, new? %d\n",
 		     __FUNCTION__, flip->pipe,
 		     sna->dri.flip_pending[flip->pipe] != NULL,
-		     flip->next_front != sna->front));
+		     flip->front->name != flip->old_front.name));
 		assert(sna->dri.flip_pending[flip->pipe] == flip);
 
-		sna_mode_delete_fb(flip->sna, flip->old_front, flip->old_fb);
-
-		if (sna->front != flip->next_front) {
-			PixmapPtr next = sna->front;
+		sna_mode_delete_fb(flip->sna, flip->old_fb);
 
+		if (flip->front->name != flip->next_front.name) {
 			DBG(("%s: async flip continuing\n", __FUNCTION__));
-			flip->count = sna_do_pageflip(sna, next,
-						      flip, flip->pipe,
-						      &flip->old_fb);
-			if (flip->count) {
-				flip->old_front = flip->next_front;
-				flip->next_front = next;
-				flip->next_front->refcnt++;
-			} else
+
+			flip->cache = flip->old_front;
+			flip->old_front = flip->next_front;
+			flip->next_front.bo = NULL;
+
+			flip->count = sna_page_flip(sna,
+						    get_private(flip->front)->bo,
+						    flip, flip->pipe,
+						    &flip->old_fb);
+			if (flip->count == 0)
+				goto finish_async_flip;
+
+			flip->next_front.bo = get_private(flip->front)->bo;
+			flip->next_front.name = flip->front->name;
+			flip->off_delay = 5;
+		} else if (--flip->off_delay) {
+			/* Just queue a no-op flip to trigger another event */
+			flip->count = sna_page_flip(sna,
+						    get_private(flip->front)->bo,
+						    flip, flip->pipe,
+						    &flip->old_fb);
+			if (flip->count == 0)
 				goto finish_async_flip;
 		} else {
 finish_async_flip:
+			flip->next_front.bo = NULL;
+
 			DBG(("%s: async flip completed\n", __FUNCTION__));
-			flip->next_front->drawable.pScreen->DestroyPixmap(flip->next_front);
 			sna->dri.flip_pending[flip->pipe] = NULL;
 			sna_dri_frame_event_info_free(flip);
 		}
 		break;
+#endif
 
 	default:
 		xf86DrvMsg(sna->scrn->scrnIndex, X_WARNING,
@@ -1167,6 +1088,202 @@ sna_dri_page_flip_handler(int fd, unsigned int frame, unsigned int tv_sec,
 	sna_dri_flip_event(info->sna, info);
 }
 
+static int
+sna_dri_schedule_flip(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
+		      DRI2BufferPtr back, CARD64 *target_msc, CARD64 divisor,
+		      CARD64 remainder, DRI2SwapEventPtr func, void *data)
+{
+	struct sna *sna = to_sna_from_drawable(draw);
+	struct sna_dri_frame_event *info;
+	drmVBlank vbl;
+	int pipe;
+	CARD64 current_msc;
+
+	DBG(("%s(target_msc=%llu, divisor=%llu, remainder=%llu)\n",
+	     __FUNCTION__,
+	     (long long)*target_msc,
+	     (long long)divisor,
+	     (long long)remainder));
+
+	/* Drawable not displayed... just complete the swap */
+	pipe = sna_dri_get_pipe(draw);
+	if (pipe == -1) {
+		DBG(("%s: off-screen, immediate update\n", __FUNCTION__));
+
+		sna_dri_exchange_attachment(front, back);
+		get_private(back)->pixmap = get_private(front)->pixmap;
+		get_private(front)->pixmap = NULL;
+		set_bo(get_private(back)->pixmap, get_private(back)->bo);
+		DRI2SwapComplete(client, draw, 0, 0, 0,
+				 DRI2_EXCHANGE_COMPLETE, func, data);
+		return TRUE;
+	}
+
+	/* Truncate to match kernel interfaces; means occasional overflow
+	 * misses, but that's generally not a big deal */
+	divisor &= 0xffffffff;
+	if (divisor == 0) {
+		int type = DRI2_FLIP_THROTTLE;
+
+		DBG(("%s: performing immediate swap on pipe %d, pending? %d\n",
+		     __FUNCTION__, pipe, sna->dri.flip_pending[pipe] != NULL));
+
+		info = sna->dri.flip_pending[pipe];
+		if (info) {
+			if (info->drawable_id == draw->id) {
+				DBG(("%s: chaining flip\n", __FUNCTION__));
+				info->next_front.name = 1;
+				return TRUE;
+			} else {
+				/* We need to first wait (one vblank) for the
+				 * async flips to complete before this client can
+				 * take over.
+				 */
+				type = DRI2_FLIP;
+			}
+		}
+
+		info = calloc(1, sizeof(struct sna_dri_frame_event));
+		if (!info)
+			return FALSE;
+
+		info->type = type;
+
+		info->sna = sna;
+		info->drawable_id = draw->id;
+		info->client = client;
+		info->event_complete = func;
+		info->event_data = data;
+		info->front = front;
+		info->back = back;
+		info->pipe = pipe;
+
+		if (!sna_dri_add_frame_event(info)) {
+			DBG(("%s: failed to hook up frame event\n", __FUNCTION__));
+			free(info);
+			return FALSE;
+		}
+
+		if (!sna_dri_page_flip(sna, info)) {
+			DBG(("%s: failed to queue page flip\n", __FUNCTION__));
+			free(info);
+			return FALSE;
+		}
+
+		sna_dri_reference_buffer(front);
+		sna_dri_reference_buffer(back);
+
+		get_private(info->back)->bo =
+			kgem_create_2d(&sna->kgem,
+				       draw->width,
+				       draw->height,
+				       draw->bitsPerPixel,
+				       get_private(info->front)->bo->tiling,
+				       CREATE_EXACT);
+		info->back->name = kgem_bo_flink(&sna->kgem,
+						 get_private(info->back)->bo);
+		sna->dri.flip_pending[info->pipe] = info;
+
+		DRI2SwapComplete(info->client, draw, 0, 0, 0,
+				 DRI2_EXCHANGE_COMPLETE,
+				 info->event_complete,
+				 info->event_data);
+	} else {
+		info = calloc(1, sizeof(struct sna_dri_frame_event));
+		if (info)
+			return FALSE;
+
+		info->sna = sna;
+		info->drawable_id = draw->id;
+		info->client = client;
+		info->event_complete = func;
+		info->event_data = data;
+		info->front = front;
+		info->back = back;
+		info->pipe = pipe;
+		info->type = DRI2_FLIP;
+
+		if (!sna_dri_add_frame_event(info)) {
+			DBG(("%s: failed to hook up frame event\n", __FUNCTION__));
+			free(info);
+			return FALSE;
+		}
+
+		sna_dri_reference_buffer(front);
+		sna_dri_reference_buffer(back);
+
+		/* Get current count */
+		vbl.request.type = DRM_VBLANK_RELATIVE;
+		if (pipe > 0)
+			vbl.request.type |= DRM_VBLANK_SECONDARY;
+		vbl.request.sequence = 0;
+		if (drmWaitVBlank(sna->kgem.fd, &vbl)) {
+			free(info);
+			return FALSE;
+		}
+
+		current_msc = vbl.reply.sequence;
+		*target_msc &= 0xffffffff;
+		remainder &= 0xffffffff;
+
+		vbl.request.type =
+			DRM_VBLANK_ABSOLUTE |
+			DRM_VBLANK_EVENT;
+		if (pipe > 0)
+			vbl.request.type |= DRM_VBLANK_SECONDARY;
+
+		/*
+		 * If divisor is zero, or current_msc is smaller than target_msc
+		 * we just need to make sure target_msc passes before initiating
+		 * the swap.
+		 */
+		if (current_msc < *target_msc) {
+			DBG(("%s: waiting for swap: current=%d, target=%d, divisor=%d\n",
+			     __FUNCTION__,
+			     (int)current_msc,
+			     (int)*target_msc,
+			     (int)divisor));
+			vbl.request.sequence = *target_msc;
+		} else {
+			DBG(("%s: missed target, queueing event for next: current=%d, target=%d, divisor=%d\n",
+			     __FUNCTION__,
+			     (int)current_msc,
+			     (int)*target_msc,
+			     (int)divisor));
+
+			vbl.request.sequence = current_msc - current_msc % divisor + remainder;
+
+			/*
+			 * If the calculated deadline vbl.request.sequence is smaller than
+			 * or equal to current_msc, it means we've passed the last point
+			 * when effective onset frame seq could satisfy
+			 * seq % divisor == remainder, so we need to wait for the next time
+			 * this will happen.
+			 *
+			 * This comparison takes the 1 frame swap delay in pageflipping mode
+			 * into account.
+			 */
+			if (vbl.request.sequence <= current_msc)
+				vbl.request.sequence += divisor;
+
+			/* Adjust returned value for 1 frame pageflip offset */
+			*target_msc = vbl.reply.sequence + 1;
+		}
+
+		/* Account for 1 frame extra pageflip delay */
+		vbl.request.sequence -= 1;
+		vbl.request.signal = (unsigned long)info;
+		if (drmWaitVBlank(sna->kgem.fd, &vbl)) {
+			free(info);
+			return FALSE;
+		}
+
+		info->frame = *target_msc;
+	}
+
+	return TRUE;
+}
+
 /*
  * ScheduleSwap is responsible for requesting a DRM vblank event for the
  * appropriate frame.
@@ -1196,7 +1313,7 @@ sna_dri_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 	ScrnInfoPtr scrn = xf86Screens[screen->myNum];
 	struct sna *sna = to_sna(scrn);
 	drmVBlank vbl;
-	int pipe, flip;
+	int pipe;
 	struct sna_dri_frame_event *info = NULL;
 	enum frame_event_type swap_type = DRI2_SWAP;
 	CARD64 current_msc;
@@ -1207,31 +1324,21 @@ sna_dri_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 	     (long long)divisor,
 	     (long long)remainder));
 
-	flip = 0;
 	if (can_flip(sna, draw, front, back)) {
-		DBG(("%s: can flip\n", __FUNCTION__));
-		swap_type = DRI2_FLIP;
-		flip = 1;
+		DBG(("%s: try flip\n", __FUNCTION__));
+		if (!sna_dri_schedule_flip(client, draw, front, back,
+					   target_msc, divisor, remainder,
+					   func, data))
+			goto blit_fallback;
+
+		return TRUE;
 	}
 
 	/* Drawable not displayed... just complete the swap */
 	pipe = sna_dri_get_pipe(draw);
 	if (pipe == -1) {
-		struct sna_dri_private *back_priv = back->driverPrivate;
-		PixmapPtr pixmap;
-
 		DBG(("%s: off-screen, immediate update\n", __FUNCTION__));
-
-		if (!flip)
-			goto blit_fallback;
-
-		pixmap = sna_set_screen_pixmap(sna, back_priv->pixmap);
-		assert(pixmap->refcnt > 1);
-		pixmap->refcnt--;
-		sna_dri_exchange_buffers(front, back);
-		DRI2SwapComplete(client, draw, 0, 0, 0,
-				 DRI2_EXCHANGE_COMPLETE, func, data);
-		return TRUE;
+		goto blit_fallback;
 	}
 
 	/* Truncate to match kernel interfaces; means occasional overflow
@@ -1265,10 +1372,6 @@ sna_dri_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 
 	info->type = swap_type;
 	if (divisor == 0) {
-		DBG(("%s: performing immediate swap\n", __FUNCTION__));
-		if (flip && sna_dri_flip(sna, draw, info))
-			return TRUE;
-
 		DBG(("%s: emitting immediate vsync'ed blit, throttling client\n",
 		     __FUNCTION__));
 
@@ -1287,7 +1390,10 @@ sna_dri_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 			 DRI2SwapComplete(client, draw, 0, 0, 0, DRI2_BLIT_COMPLETE, func, data);
 		 }
 
-		 sna_dri_copy(sna, draw, NULL, front, back, true);
+		 sna_dri_copy(sna, draw, NULL,
+			      get_private(front)->bo,
+			      get_private(back)->bo,
+			      true);
 		 return TRUE;
 	}
 
@@ -1297,9 +1403,6 @@ sna_dri_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 		vbl.request.type |= DRM_VBLANK_SECONDARY;
 	vbl.request.sequence = 0;
 	if (drmWaitVBlank(sna->kgem.fd, &vbl)) {
-		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
-			   "first get vblank counter failed: %s\n",
-			   strerror(errno));
 		goto blit_fallback;
 	}
 
@@ -1318,14 +1421,14 @@ sna_dri_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 		     (int)divisor));
 
 		info->frame = *target_msc;
-		info->type = flip ? DRI2_FLIP : DRI2_SWAP;
+		info->type = DRI2_SWAP;
 
 		 vbl.request.type =
 			 DRM_VBLANK_ABSOLUTE |
 			 DRM_VBLANK_EVENT;
 		 if (pipe > 0)
 			 vbl.request.type |= DRM_VBLANK_SECONDARY;
-		 vbl.request.sequence = *target_msc - flip;
+		 vbl.request.sequence = *target_msc;
 		 vbl.request.signal = (unsigned long)info;
 		 if (drmWaitVBlank(sna->kgem.fd, &vbl))
 			 goto blit_fallback;
@@ -1345,8 +1448,7 @@ sna_dri_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 		     (int)divisor));
 
 	vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
-	if (flip == 0)
-		vbl.request.type |= DRM_VBLANK_NEXTONMISS;
+	vbl.request.type |= DRM_VBLANK_NEXTONMISS;
 	if (pipe > 0)
 		vbl.request.type |= DRM_VBLANK_SECONDARY;
 
@@ -1366,25 +1468,21 @@ sna_dri_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 	if (vbl.request.sequence <= current_msc)
 		vbl.request.sequence += divisor;
 
-	/* Account for 1 frame extra pageflip delay if flip > 0 */
-	vbl.request.sequence -= flip;
-
 	vbl.request.signal = (unsigned long)info;
 	if (drmWaitVBlank(sna->kgem.fd, &vbl)) {
-		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
-			   "final get vblank counter failed: %s\n",
-			   strerror(errno));
 		goto blit_fallback;
 	}
 
-	/* Adjust returned value for 1 fame pageflip offset of flip > 0 */
-	*target_msc = vbl.reply.sequence + flip;
+	*target_msc = vbl.reply.sequence;
 	info->frame = *target_msc;
 	return TRUE;
 
 blit_fallback:
 	DBG(("%s -- blit\n", __FUNCTION__));
-	sna_dri_copy(sna, draw, NULL, front, back, true);
+	sna_dri_copy(sna, draw, NULL,
+		     get_private(front)->bo,
+		     get_private(back)->bo,
+		     true);
 	if (info)
 		sna_dri_frame_event_info_free(info);
 	DRI2SwapComplete(client, draw, 0, 0, 0, DRI2_BLIT_COMPLETE, func, data);
@@ -1392,38 +1490,46 @@ blit_fallback:
 	return TRUE;
 }
 
-#if DRI2INFOREC_VERSION >= 6
+#if DRI2INFOREC_VERSION >= 7
 static void
 sna_dri_async_swap(ClientPtr client, DrawablePtr draw,
 		   DRI2BufferPtr front, DRI2BufferPtr back,
 		   DRI2SwapEventPtr func, void *data)
 {
-	ScreenPtr screen = draw->pScreen;
-	struct sna *sna = to_sna_from_screen(screen);
-	int type = DRI2_EXCHANGE_COMPLETE;
-	struct sna_dri_private *back_priv = back->driverPrivate;
-	struct sna_dri_private *front_priv = front->driverPrivate;
+	struct sna *sna = to_sna_from_drawable(draw);
 	struct sna_dri_frame_event *info;
-	PixmapPtr pixmap;
-	int pipe;
+	struct kgem_bo *bo;
+	int name, pipe;
 
 	DBG(("%s()\n", __FUNCTION__));
 
+	pipe = sna_dri_get_pipe(draw);
+	if (pipe == -1) {
+		PixmapPtr pixmap = get_drawable_pixmap(draw);
+
+		set_bo(pixmap, get_private(back)->bo);
+		sna_dri_exchange_attachment(front, back);
+		get_private(back)->pixmap = pixmap;
+		get_private(front)->pixmap = NULL;
+
+		DRI2SwapComplete(client, draw, 0, 0, 0,
+				 DRI2_EXCHANGE_COMPLETE, func, data);
+		return;
+	}
+
 	if (!can_flip(sna, draw, front, back)) {
 blit:
-		sna_dri_copy(sna, draw, NULL, front, back, false);
+		sna_dri_copy(sna, draw, NULL,
+			     get_private(front)->bo,
+			     get_private(back)->bo,
+			     false);
 		DRI2SwapComplete(client, draw, 0, 0, 0,
 				 DRI2_BLIT_COMPLETE, func, data);
 		return;
 	}
 
-	assert(front_priv->pixmap == sna->front);
-
-	pipe = sna_dri_get_pipe(draw);
-	if (pipe == -1) {
-		/* Drawable not displayed... just complete the swap */
-		goto exchange;
-	}
+	bo = NULL;
+	name = 0;
 
 	info = sna->dri.flip_pending[pipe];
 	if (info == NULL) {
@@ -1432,71 +1538,68 @@ blit:
 
 		info = calloc(1, sizeof(struct sna_dri_frame_event));
 		if (!info)
-			goto exchange;
+			goto blit;
 
 		info->sna = sna;
+		info->client = client;
 		info->type = DRI2_ASYNC_FLIP;
 		info->pipe = pipe;
-		info->client = client;
+		info->front = front;
+		info->back = back;
 
 		if (!sna_dri_add_frame_event(info)) {
 			DBG(("%s: failed to hook up frame event\n", __FUNCTION__));
 			free(info);
 			info = NULL;
-			goto exchange;
+			goto blit;
 		}
 
-		info->count = sna_do_pageflip(sna, back_priv->pixmap,
-					      info, pipe,
-					      &info->old_fb);
-
-		if (info->count == 0) {
-			DBG(("%s: pageflip failed\n", __FUNCTION__));
+		if (!sna_dri_page_flip(sna, info)) {
 			free(info);
-			goto exchange;
+			goto blit;
 		}
 
-		info->old_front = sna->front;
-		info->old_front->refcnt++;
+		info->next_front.name = info->front->name;
+		info->next_front.bo = get_private(info->front)->bo;
+		info->off_delay = 5;
 
-		info->next_front = back_priv->pixmap;
-		info->next_front->refcnt++;
+		sna_dri_reference_buffer(front);
+		sna_dri_reference_buffer(back);
 
-		type = DRI2_FLIP_COMPLETE;
-		sna->dri.flip_pending[pipe] = info;
-
-		if ((pixmap = screen->CreatePixmap(screen,
-						   draw->width,
-						   draw->height,
-						   draw->depth,
-						   SNA_CREATE_FB))) {
-			DBG(("%s: new back buffer\n", __FUNCTION__));
-			set_pixmap(sna, front, pixmap);
-		}
 	} else if (info->type != DRI2_ASYNC_FLIP) {
 		/* A normal vsync'ed client is finishing, wait for it
-		 * to unpin the old framebuffer before taking* pver.
+		 * to unpin the old framebuffer before taking over.
 		 */
 		goto blit;
+	} else {
+		if (info->next_front.name == info->front->name) {
+			name = info->cache.name;
+			bo = info->cache.bo;
+		} else {
+			name = info->front->name;
+			bo = get_private(info->front)->bo;
+		}
+		info->front->name = info->back->name;
+		get_private(info->front)->bo = get_private(info->back)->bo;
 	}
 
-	if (front_priv->pixmap == info->next_front &&
-	    (pixmap = screen->CreatePixmap(screen,
-					   draw->width,
-					   draw->height,
-					   draw->depth,
-					   SNA_CREATE_FB))) {
-		DBG(("%s: new back buffer\n", __FUNCTION__));
-		set_pixmap(sna, front, pixmap);
-	}
+	if (bo == NULL)
+		bo = kgem_create_2d(&sna->kgem,
+				    draw->width,
+				    draw->height,
+				    draw->bitsPerPixel,
+				    I915_TILING_X, CREATE_EXACT);
+	get_private(info->back)->bo = bo;
 
-exchange:
-	damage_all(back_priv->pixmap);
-	pixmap = sna_set_screen_pixmap(sna, back_priv->pixmap);
-	screen->DestroyPixmap(pixmap);
+	if (name == 0)
+		name = kgem_bo_flink(&sna->kgem, bo);
+	info->back->name = name;
+
+	set_bo(sna->front, get_private(info->front)->bo);
+	sna->dri.flip_pending[info->pipe] = info;
 
-	sna_dri_exchange_buffers(front, back);
-	DRI2SwapComplete(client, draw, 0, 0, 0, type, func, data);
+	DRI2SwapComplete(client, draw, 0, 0, 0,
+			 DRI2_EXCHANGE_COMPLETE, func, data);
 }
 #endif
 
@@ -1698,8 +1801,7 @@ static unsigned int dri2_server_generation;
 Bool sna_dri_open(struct sna *sna, ScreenPtr screen)
 {
 	DRI2InfoRec info;
-	int dri2_major = 1;
-	int dri2_minor = 0;
+	int major = 1, minor = 0;
 #if DRI2INFOREC_VERSION >= 4
 	const char *driverNames[1];
 #endif
@@ -1713,9 +1815,9 @@ Bool sna_dri_open(struct sna *sna, ScreenPtr screen)
 	}
 
 	if (xf86LoaderCheckSymbol("DRI2Version"))
-		DRI2Version(&dri2_major, &dri2_minor);
+		DRI2Version(&major, &minor);
 
-	if (dri2_minor < 1) {
+	if (minor < 1) {
 		xf86DrvMsg(sna->scrn->scrnIndex, X_WARNING,
 			   "DRI2 requires DRI2 module version 1.1.0 or later\n");
 		return FALSE;
diff --git a/src/sna/sna_driver.c b/src/sna/sna_driver.c
index d834c0a..693febc 100644
--- a/src/sna/sna_driver.c
+++ b/src/sna/sna_driver.c
@@ -613,12 +613,12 @@ sna_wakeup_handler(int i, pointer data, unsigned long result, pointer read_mask)
 	if ((int)result < 0)
 		return;
 
-	if (FD_ISSET(sna->kgem.fd, (fd_set*)read_mask))
-		sna_dri_wakeup(sna);
-
 	sna->WakeupHandler(i, sna->WakeupData, result, read_mask);
 
 	sna_accel_wakeup_handler(sna);
+
+	if (FD_ISSET(sna->kgem.fd, (fd_set*)read_mask))
+		sna_dri_wakeup(sna);
 }
 
 #if HAVE_UDEV
diff --git a/src/sna/sna_io.c b/src/sna/sna_io.c
index cc37901..04366be 100644
--- a/src/sna/sna_io.c
+++ b/src/sna/sna_io.c
@@ -432,7 +432,6 @@ struct kgem_bo *sna_replace(struct sna *sna,
 	DBG(("%s(handle=%d, %dx%d, bpp=%d, tiling=%d)\n",
 	     __FUNCTION__, bo->handle, width, height, bpp, bo->tiling));
 
-	assert(bo->reusable);
 	if (kgem_bo_is_busy(bo)) {
 		struct kgem_bo *new_bo;
 
commit aac022cbb3342e7027301a3f8c9add8929edbad6
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Nov 14 19:49:29 2011 +0000

    sna: Optimise single pixel transfers
    
    Surprisingly frequent.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/blt.c b/src/sna/blt.c
index ca15453..1b56cc7 100644
--- a/src/sna/blt.c
+++ b/src/sna/blt.c
@@ -64,9 +64,45 @@ memcpy_blt(const void *src, void *dst, int bpp,
 		return;
 	}
 
-	do {
-		memcpy(dst_bytes, src_bytes, byte_width);
-		src_bytes += src_stride;
-		dst_bytes += dst_stride;
-	} while (--height);
+	switch (byte_width) {
+	case 1:
+		do {
+			*dst_bytes = *src_bytes;
+			src_bytes += src_stride;
+			dst_bytes += dst_stride;
+		} while (--height);
+		break;
+
+	case 2:
+		do {
+			*(uint16_t *)dst_bytes = *(uint16_t *)src_bytes;
+			src_bytes += src_stride;
+			dst_bytes += dst_stride;
+		} while (--height);
+		break;
+
+	case 4:
+		do {
+			*(uint32_t *)dst_bytes = *(uint32_t *)src_bytes;
+			src_bytes += src_stride;
+			dst_bytes += dst_stride;
+		} while (--height);
+		break;
+
+	case 8:
+		do {
+			*(uint64_t *)dst_bytes = *(uint64_t *)src_bytes;
+			src_bytes += src_stride;
+			dst_bytes += dst_stride;
+		} while (--height);
+		break;
+
+	default:
+		do {
+			memcpy(dst_bytes, src_bytes, byte_width);
+			src_bytes += src_stride;
+			dst_bytes += dst_stride;
+		} while (--height);
+		break;
+	}
 }


More information about the xorg-commit mailing list