xf86-video-intel: 54 commits - configure.ac Makefile.am src/i810_reg.h src/i830_accel.c src/i830_batchbuffer.c src/i830_batchbuffer.h src/i830_debug.c src/i830_dri.c src/i830_dri.h src/i830_driver.c src/i830_exa.c src/i830.h src/i830_memory.c src/i830_render.c src/i830_ring.h src/i830_video.c src/i915_3d.h src/i915_render.c src/i915_video.c src/i965_render.c src/Makefile.am src/reg_dumper/.gitignore src/reg_dumper/idle.c src/reg_dumper/Makefile.am src/reg_dumper/reg_dumper.h src/reg_dumper/statuspage.c src/reg_dumper/util.c src/xvmc/Makefile.am uxa/Makefile.am uxa/uxa-accel.c uxa/uxa.c uxa/uxa-glyphs.c uxa/uxa.h uxa/uxa-priv.h uxa/uxa-render.c uxa/uxa-unaccel.c

Jesse Barnes jbarnes at kemper.freedesktop.org
Wed Aug 6 12:55:37 PDT 2008


 Makefile.am                 |    2 
 configure.ac                |   15 
 src/Makefile.am             |   12 
 src/i810_reg.h              |   11 
 src/i830.h                  |   76 ++-
 src/i830_accel.c            |  132 ++++-
 src/i830_batchbuffer.c      |  167 +++++++
 src/i830_batchbuffer.h      |  148 ++++++
 src/i830_debug.c            |   15 
 src/i830_dri.c              |  128 ++---
 src/i830_dri.h              |    1 
 src/i830_driver.c           |  344 ++++++++++----
 src/i830_exa.c              |  336 +++++++++++---
 src/i830_memory.c           |  192 ++++----
 src/i830_render.c           |   21 
 src/i830_ring.h             |    5 
 src/i830_video.c            |    4 
 src/i915_3d.h               |   10 
 src/i915_render.c           |   16 
 src/i915_video.c            |    2 
 src/i965_render.c           |   20 
 src/reg_dumper/.gitignore   |    1 
 src/reg_dumper/Makefile.am  |    8 
 src/reg_dumper/idle.c       |    8 
 src/reg_dumper/reg_dumper.h |    1 
 src/reg_dumper/statuspage.c |   81 +++
 src/reg_dumper/util.c       |   86 +++
 src/xvmc/Makefile.am        |    5 
 uxa/Makefile.am             |   20 
 uxa/uxa-accel.c             | 1032 ++++++++++++++++++++++++++++++++++++++++++++
 uxa/uxa-glyphs.c            |  880 +++++++++++++++++++++++++++++++++++++
 uxa/uxa-priv.h              |  443 ++++++++++++++++++
 uxa/uxa-render.c            | 1015 +++++++++++++++++++++++++++++++++++++++++++
 uxa/uxa-unaccel.c           |  370 +++++++++++++++
 uxa/uxa.c                   |  510 +++++++++++++++++++++
 uxa/uxa.h                   |  528 ++++++++++++++++++++++
 36 files changed, 6192 insertions(+), 453 deletions(-)

New commits:
commit f9504eff31eb3c9c6c6b33dced9875866ff8307e
Merge: f911347... 5c9a62a...
Author: Jesse Barnes <jbarnes at virtuousgeek.org>
Date:   Wed Aug 6 12:40:47 2008 -0700

    Merge branch 'drm-gem'

commit 5c9a62a29f62a9ecce37fae98cb01f8217eaba15
Author: Jesse Barnes <jbarnes at virtuousgeek.org>
Date:   Wed Aug 6 12:39:03 2008 -0700

    Revert "Switch to using a buffer object for the vertex buffer"
    
    This reverts commit 1abf4d3a7a203ff5d6e5ceda29573e7fd69ddf8e.
    
    Conflicts:
    
    	src/i965_render.c - flushing was removed, keep it that way

diff --git a/src/i965_render.c b/src/i965_render.c
index 62d0035..391e063 100644
--- a/src/i965_render.c
+++ b/src/i965_render.c
@@ -37,7 +37,6 @@
 #include "xf86.h"
 #include "i830.h"
 #include "i915_reg.h"
-#include "i915_drm.h"
 
 /* bring in brw structs */
 #include "brw_defines.h"
@@ -61,7 +60,7 @@ do { 							\
 #endif
 
 #define MAX_VERTEX_PER_COMPOSITE    24
-#define VERTEX_BUFFER_SIZE	    (16 * MAX_VERTEX_PER_COMPOSITE)
+#define MAX_VERTEX_BUFFERS	    256
 
 struct blendinfo {
     Bool dst_alpha;
@@ -503,14 +502,14 @@ typedef struct _gen4_state {
 				     [BRW_BLENDFACTOR_COUNT];
     struct brw_cc_viewport cc_viewport;
     PAD64 (brw_cc_viewport, 0);
+
+    float vb[MAX_VERTEX_PER_COMPOSITE * MAX_VERTEX_BUFFERS];
 } gen4_state_t;
 
 /** Private data for gen4 render accel implementation. */
 struct gen4_render_state {
     gen4_state_t *card_state;
     uint32_t card_state_offset;
-    dri_bo *vb_bo;
-    int vb_bo_busy;
 
     int binding_table_index;
     int surface_state_index;
@@ -1271,11 +1270,12 @@ i965_composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
 {
     ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
+    gen4_state_t *card_state = pI830->gen4_render_state->card_state;
     struct gen4_render_state *render_state = pI830->gen4_render_state;
     Bool has_mask;
     Bool is_affine_src, is_affine_mask, is_affine;
     float src_x[3], src_y[3], src_w[3], mask_x[3], mask_y[3], mask_w[3];
-    float *vb;
+    float *vb = card_state->vb;
     int i;
 
     is_affine_src = i830_transform_is_affine (pI830->transform[0]);
@@ -1352,25 +1352,11 @@ i965_composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
 	}
     }
 
-    /* Arrange for a buffer object with sufficient space for our
-     * vertices, and that isn't "busy", that is, it is not already
-     * referenced by a batch that has been flushed. */
-    if (! render_state->vb_bo || render_state->vb_bo_busy ||
-	render_state->vb_offset + MAX_VERTEX_PER_COMPOSITE > VERTEX_BUFFER_SIZE)
-    {
-	if (render_state->vb_bo)
-	    dri_bo_unreference (render_state->vb_bo);
-
-	render_state->vb_bo = dri_bo_alloc (pI830->bufmgr, "vb",
-					    VERTEX_BUFFER_SIZE * sizeof (float),
-					    4096);
+    if (render_state->vb_offset + MAX_VERTEX_PER_COMPOSITE >= ARRAY_SIZE(card_state->vb)) {
+	i830WaitSync(pScrn);
 	render_state->vb_offset = 0;
     }
 
-    /* Map the vertex buffer object so we can write to it. */
-    dri_bo_map (render_state->vb_bo, 1);
-    vb = render_state->vb_bo->virtual;
-
     i = render_state->vb_offset;
     /* rect (x2,y2) */
     vb[i++] = (float)(dstX + w);
@@ -1413,9 +1399,7 @@ i965_composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
 	if (!is_affine)
 	    vb[i++] = mask_w[0];
     }
-    assert (i <= VERTEX_BUFFER_SIZE);
-
-    dri_bo_unmap (render_state->vb_bo);
+    assert (i * 4 <= sizeof(card_state->vb));
 
     BEGIN_BATCH(12);
     OUT_BATCH(MI_FLUSH);
@@ -1424,7 +1408,7 @@ i965_composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
     OUT_BATCH((0 << VB0_BUFFER_INDEX_SHIFT) |
 	      VB0_VERTEXDATA |
 	      (render_state->vertex_size << VB0_BUFFER_PITCH_SHIFT));
-    OUT_RELOC(render_state->vb_bo, I915_GEM_DOMAIN_VERTEX, 0,
+    OUT_BATCH(render_state->card_state_offset + offsetof(gen4_state_t, vb) +
 	      render_state->vb_offset * 4);
     OUT_BATCH(3);
     OUT_BATCH(0); // ignore for VERTEXDATA, but still there
commit fc3e287e6b6db21b113aa40ec4d397802c067f8b
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Aug 5 22:50:01 2008 -0700

    [uxa] Remove unused pixmap size limits.
    
    All size-related rendering limits should be managed by the driver in the
    pixmap_is_offscreen call. There's no need for uxa to even know these values.

diff --git a/src/i830_exa.c b/src/i830_exa.c
index 87a7e6c..2041741 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -720,9 +720,6 @@ i830_uxa_init (ScreenPtr pScreen)
     i830->uxa_driver->uxa_major = 1;
     i830->uxa_driver->uxa_minor = 0;
 
-    i830->uxa_driver->max_x = i830->accel_max_x;
-    i830->uxa_driver->max_y = i830->accel_max_y;
-
     /* Solid fill */
     i830->uxa_driver->prepare_solid = I830EXAPrepareSolid;
     i830->uxa_driver->solid = I830EXASolid;
diff --git a/uxa/uxa.c b/uxa/uxa.c
index c76cb1d..aac3d68 100644
--- a/uxa/uxa.c
+++ b/uxa/uxa.c
@@ -408,20 +408,6 @@ uxa_driver_init(ScreenPtr screen, uxa_driver_t *uxa_driver)
 	return FALSE;
     }
 
-    /* If the driver doesn't set any max pitch values, we'll just assume
-     * that there's a limitation by pixels, and that it's the same as
-     * maxX.
-     *
-     * We want max_pitch_pixels or max_pitch_bytes to be set so we can check
-     * pixmaps against the max pitch in uxaCreatePixmap() -- it matters
-     * whether a pixmap is rejected because of its pitch or
-     * because of its width.
-     */
-    if (!uxa_driver->max_pitch_pixels && !uxa_driver->max_pitch_bytes)
-    {
-        uxa_driver->max_pitch_pixels = uxa_driver->max_x;
-    }
-
 #ifdef RENDER
     ps = GetPictureScreenIfSet(screen);
 #endif
diff --git a/uxa/uxa.h b/uxa/uxa.h
index 22889b7..f1c1cfa 100644
--- a/uxa/uxa.h
+++ b/uxa/uxa.h
@@ -68,26 +68,6 @@ typedef struct _UxaDriver {
      */
     int flags;
 
-    /** @{ */
-    /**
-     * max_x controls the X coordinate limitation for rendering from the card.
-     * The driver should never receive a request for rendering beyond max_x
-     * in the X direction from the origin of a pixmap.
-     */
-    int max_x;
-
-    /**
-     * max_y controls the Y coordinate limitation for rendering from the card.
-     * The driver should never receive a request for rendering beyond max_y
-     * in the Y direction from the origin of a pixmap.
-     */
-    int max_y;
-    /** @} */
-
-    /* private */
-    Bool	      needsSync;
-    int               lastMarker;
-
     /** @name solid
      * @{
      */
@@ -510,36 +490,6 @@ typedef struct _UxaDriver {
      */
     Bool	(*pixmap_is_offscreen)(PixmapPtr pPix);
 
-    /**
-     * max_pitch_pixels controls the pitch limitation for rendering from
-     * the card.
-     * The driver should never receive a request for rendering a pixmap
-     * that has a pitch (in pixels) beyond max_pitch_pixels.
-     *
-     * Setting this field is optional -- if your hardware doesn't have
-     * a pitch limitation in pixels, don't set this. If neither this value
-     * nor max_pitch_bytes is set, then max_pitch_pixels is set to max_x.
-     * If set, it must not be smaller than max_x.
-     *
-     * @sa max_pitch_bytes
-     */
-    int max_pitch_pixels;
-
-    /**
-     * max_pitch_bytes controls the pitch limitation for rendering from
-     * the card.
-     * The driver should never receive a request for rendering a pixmap
-     * that has a pitch (in bytes) beyond max_pitch_bytes.
-     *
-     * Setting this field is optional -- if your hardware doesn't have
-     * a pitch limitation in bytes, don't set this.
-     * If set, it must not be smaller than max_x * 4.
-     * There's no default value for max_pitch_bytes.
-     *
-     * @sa max_pitch_pixels
-     */
-    int max_pitch_bytes;
-
     /** @} */
 } uxa_driver_t;
 
commit 68f0872db6ec4d5dc3b524ee08ecad0aa125acd9
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Aug 5 22:36:03 2008 -0700

    [uxa] Check xalloc returns and deal with failure
    
    Failing xalloc in a rendering function means just dropping the drawing on
    the floor (that's what we've always done).

diff --git a/uxa/uxa-accel.c b/uxa/uxa-accel.c
index edc68f2..b25a8fa 100644
--- a/uxa/uxa-accel.c
+++ b/uxa/uxa-accel.c
@@ -508,6 +508,8 @@ uxa_poly_point(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
     }
 
     prect = xalloc(sizeof(xRectangle) * npt);
+    if (!prect)
+	return;
     for (i = 0; i < npt; i++) {
 	prect[i].x = ppt[i].x;
 	prect[i].y = ppt[i].y;
@@ -543,6 +545,8 @@ uxa_poly_lines(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
     }
 
     prect = xalloc(sizeof(xRectangle) * (npt - 1));
+    if (!prect)
+	return;
     x1 = ppt[0].x;
     y1 = ppt[0].y;
     /* If we have any non-horizontal/vertical, fall back. */
@@ -612,6 +616,8 @@ uxa_poly_segment (DrawablePtr pDrawable, GCPtr pGC, int nseg,
     }
 
     prect = xalloc(sizeof(xRectangle) * nseg);
+    if (!prect)
+	return;
     for (i = 0; i < nseg; i++) {
 	if (pSeg[i].x1 < pSeg[i].x2) {
 	    prect[i].x = pSeg[i].x1;
commit 8f10bfb127bfe73d83d58f1f306fb9a4dfd825d6
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Aug 5 22:34:24 2008 -0700

    Use EXA by default instead of UXA until we have GTT mapping

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 6b8f998..6cc2352 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1582,12 +1582,12 @@ I830PreInit(ScrnInfoPtr pScrn, int flags)
 #ifdef I830_USE_XAA
       pI830->accel = ACCEL_XAA;
 #endif
-#ifdef I830_USE_EXA
-      pI830->accel = ACCEL_EXA;
-#endif
 #ifdef I830_USE_UXA
       pI830->accel = ACCEL_UXA;
 #endif
+#ifdef I830_USE_EXA
+      pI830->accel = ACCEL_EXA;
+#endif
 #if I830_USE_XAA + I830_USE_EXA + I830_USE_UXA >= 2
        from = X_DEFAULT;
        if ((s = (char *)xf86GetOptValString(pI830->Options,
commit b2d058d80ccd08d9e02ef866ee7a95b58686f6a3
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Aug 4 23:43:13 2008 -0700

    Rename uxa using _ instead of caps

diff --git a/src/i830.h b/src/i830.h
index dbcf3c0..d87e5d9 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -538,6 +538,7 @@ typedef struct _I830Rec {
 #ifdef I830_USE_UXA
    uxa_driver_t *uxa_driver;
    Bool need_flush;
+   Bool need_sync;
 #endif
 #if defined(I830_USE_EXA) || defined(I830_USE_UXA)
    PixmapPtr pSrcPixmap;
diff --git a/src/i830_driver.c b/src/i830_driver.c
index bef3bb8..6b8f998 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -3887,9 +3887,9 @@ i830WaitSync(ScrnInfoPtr pScrn)
 #endif
 #ifdef I830_USE_UXA
    case ACCEL_UXA:
-      if (pI830->uxa_driver) {
-	 ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
-	 uxa_wait_sync(pScreen);
+      if (pI830->uxa_driver && pI830->need_sync) {
+	 pI830->need_sync = FALSE;
+	 I830Sync(pScrn);
       }
       break;
 #endif
@@ -3920,10 +3920,8 @@ i830MarkSync(ScrnInfoPtr pScrn)
 #endif
 #ifdef I830_USE_UXA
    case ACCEL_UXA:
-      if (pI830->uxa_driver) {
-	 ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
-	 exaMarkSync(pScreen);
-      }
+      if (pI830->uxa_driver)
+	 pI830->need_sync = TRUE;
       break;
 #endif
    default:
diff --git a/src/i830_exa.c b/src/i830_exa.c
index 08d73b5..87a7e6c 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -42,6 +42,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #endif
 
 #define ALWAYS_SYNC		0
+#define ALWAYS_FLUSH		0
 
 #ifdef DEBUG_I830FALLBACK
 #define I830FALLBACK(s, arg...)				\
@@ -247,11 +248,16 @@ I830EXASolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
 static void
 I830EXADoneSolid(PixmapPtr pPixmap)
 {
-#if ALWAYS_SYNC
+#if ALWAYS_SYNC || ALWAYS_FLUSH || 1
     ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
 
+#if ALWAYS_FLUSH || 1
+    intel_batch_flush(pScrn);
+#endif
+#if ALWAYS_SYNC
     I830Sync(pScrn);
 #endif
+#endif
 }
 
 /**
@@ -343,11 +349,37 @@ I830EXACopy(PixmapPtr pDstPixmap, int src_x1, int src_y1, int dst_x1,
 static void
 I830EXADoneCopy(PixmapPtr pDstPixmap)
 {
-#if ALWAYS_SYNC
+#if ALWAYS_SYNC || ALWAYS_FLUSH
     ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
 
+#if ALWAYS_FLUSH
+    intel_batch_flush(pScrn);
+#endif
+#if ALWAYS_SYNC
+    I830Sync(pScrn);
+#endif
+#endif
+}
+
+
+/**
+ * Do any cleanup from the Composite operation.
+ *
+ * This is shared between i830 through i965.
+ */
+void
+i830_done_composite(PixmapPtr pDst)
+{
+#if ALWAYS_SYNC || ALWAYS_FLUSH
+    ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
+
+#if ALWAYS_FLUSH
+    intel_batch_flush(pScrn);
+#endif
+#if ALWAYS_SYNC
     I830Sync(pScrn);
 #endif
+#endif
 }
 
 #define xFixedToFloat(val) \
@@ -558,7 +590,15 @@ i830_uxa_prepare_access (PixmapPtr pixmap, uxa_access_t access)
     dri_bo *bo = i830_uxa_get_pixmap_bo (pixmap);
 
     if (bo) {
-	intel_batch_flush(xf86Screens[pixmap->drawable.pScreen->myNum]);
+	ScreenPtr screen = pixmap->drawable.pScreen;
+	ScrnInfoPtr scrn = xf86Screens[screen->myNum];
+	I830Ptr i830 = I830PTR(scrn);
+	
+	intel_batch_flush(scrn);
+	if (i830->need_sync) {
+	    I830Sync(scrn);
+	    i830->need_sync = FALSE;
+	}
 	if (dri_bo_map (bo, access == UXA_ACCESS_RW) != 0)
 	    return FALSE;
         pixmap->devPrivate.ptr = bo->virtual;
@@ -680,47 +720,42 @@ i830_uxa_init (ScreenPtr pScreen)
     i830->uxa_driver->uxa_major = 1;
     i830->uxa_driver->uxa_minor = 0;
 
-    i830->uxa_driver->maxX = i830->accel_max_x;
-    i830->uxa_driver->maxY = i830->accel_max_y;
-
-    /* Sync */
-    i830->uxa_driver->WaitMarker = I830EXASync;
+    i830->uxa_driver->max_x = i830->accel_max_x;
+    i830->uxa_driver->max_y = i830->accel_max_y;
 
     /* Solid fill */
-    i830->uxa_driver->PrepareSolid = I830EXAPrepareSolid;
-    i830->uxa_driver->Solid = I830EXASolid;
-    i830->uxa_driver->DoneSolid = I830EXADoneSolid;
+    i830->uxa_driver->prepare_solid = I830EXAPrepareSolid;
+    i830->uxa_driver->solid = I830EXASolid;
+    i830->uxa_driver->done_solid = I830EXADoneSolid;
 
     /* Copy */
-    i830->uxa_driver->PrepareCopy = I830EXAPrepareCopy;
-    i830->uxa_driver->Copy = I830EXACopy;
-    i830->uxa_driver->DoneCopy = I830EXADoneCopy;
+    i830->uxa_driver->prepare_copy = I830EXAPrepareCopy;
+    i830->uxa_driver->copy = I830EXACopy;
+    i830->uxa_driver->done_copy = I830EXADoneCopy;
 
-#if 0
     /* Composite */
     if (!IS_I9XX(i830)) {
-    	i830->uxa_driver->CheckComposite = i830_check_composite;
-    	i830->uxa_driver->PrepareComposite = i830_prepare_composite;
-    	i830->uxa_driver->Composite = i830_composite;
-    	i830->uxa_driver->DoneComposite = i830_done_composite;
+    	i830->uxa_driver->check_composite = i830_check_composite;
+    	i830->uxa_driver->prepare_composite = i830_prepare_composite;
+    	i830->uxa_driver->composite = i830_composite;
+    	i830->uxa_driver->done_composite = i830_done_composite;
     } else if (IS_I915G(i830) || IS_I915GM(i830) ||
 	       IS_I945G(i830) || IS_I945GM(i830) || IS_G33CLASS(i830))
     {
-	i830->uxa_driver->CheckComposite = i915_check_composite;
-   	i830->uxa_driver->PrepareComposite = i915_prepare_composite;
-    	i830->uxa_driver->Composite = i830_composite;
-    	i830->uxa_driver->DoneComposite = i830_done_composite;
+	i830->uxa_driver->check_composite = i915_check_composite;
+   	i830->uxa_driver->prepare_composite = i915_prepare_composite;
+    	i830->uxa_driver->composite = i830_composite;
+    	i830->uxa_driver->done_composite = i830_done_composite;
     } else {
- 	i830->uxa_driver->CheckComposite = i965_check_composite;
- 	i830->uxa_driver->PrepareComposite = i965_prepare_composite;
- 	i830->uxa_driver->Composite = i965_composite;
- 	i830->uxa_driver->DoneComposite = i830_done_composite;
+ 	i830->uxa_driver->check_composite = i965_check_composite;
+ 	i830->uxa_driver->prepare_composite = i965_prepare_composite;
+ 	i830->uxa_driver->composite = i965_composite;
+ 	i830->uxa_driver->done_composite = i830_done_composite;
     }
-#endif
 
-    i830->uxa_driver->PrepareAccess = i830_uxa_prepare_access;
-    i830->uxa_driver->FinishAccess = i830_uxa_finish_access;
-    i830->uxa_driver->PixmapIsOffscreen = i830_uxa_pixmap_is_offscreen;
+    i830->uxa_driver->prepare_access = i830_uxa_prepare_access;
+    i830->uxa_driver->finish_access = i830_uxa_finish_access;
+    i830->uxa_driver->pixmap_is_offscreen = i830_uxa_pixmap_is_offscreen;
 
     if(!uxa_driver_init(pScreen, i830->uxa_driver)) {
 	xf86DrvMsg(scrn->scrnIndex, X_INFO,
diff --git a/src/i830_render.c b/src/i830_render.c
index 4b42ea3..c1ce856 100644
--- a/src/i830_render.c
+++ b/src/i830_render.c
@@ -733,14 +733,3 @@ i830_composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
 
     ADVANCE_BATCH();
 }
-
-/**
- * Do any cleanup from the Composite operation.
- *
- * This is shared between i830 through i965.
- */
-void
-i830_done_composite(PixmapPtr pDst)
-{
-    /* NO-OP */
-}
diff --git a/uxa/uxa-accel.c b/uxa/uxa-accel.c
index 20a5657..edc68f2 100644
--- a/uxa/uxa-accel.c
+++ b/uxa/uxa-accel.c
@@ -37,7 +37,7 @@
 
 static void
 uxa_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int n,
-	     DDXPointPtr ppt, int *pwidth, int fSorted)
+	       DDXPointPtr ppt, int *pwidth, int fSorted)
 {
     ScreenPtr	    pScreen = pDrawable->pScreen;
     uxa_screen_t    *uxa_screen = uxa_get_screen(pScreen);
@@ -52,10 +52,10 @@ uxa_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int n,
 
     if (uxa_screen->swappedOut || pGC->fillStyle != FillSolid ||
 	!(pPixmap = uxa_get_offscreen_pixmap (pDrawable, &off_x, &off_y)) ||
-	!(*uxa_screen->info->PrepareSolid) (pPixmap,
-					 pGC->alu,
-					 pGC->planemask,
-					 pGC->fgPixel))
+	!(*uxa_screen->info->prepare_solid) (pPixmap,
+					     pGC->alu,
+					     pGC->planemask,
+					     pGC->fgPixel))
     {
 	uxa_check_fill_spans (pDrawable, pGC, n, ppt, pwidth, fSorted);
 	return;
@@ -89,9 +89,9 @@ uxa_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int n,
 	nbox = REGION_NUM_RECTS (pClip);
 	if (nbox == 1)
 	{
-	    (*uxa_screen->info->Solid) (pPixmap,
-				     fullX1 + off_x, fullY1 + off_y,
-				     fullX2 + off_x, fullY1 + 1 + off_y);
+	    (*uxa_screen->info->solid) (pPixmap,
+					fullX1 + off_x, fullY1 + off_y,
+					fullX2 + off_x, fullY1 + 1 + off_y);
 	}
 	else
 	{
@@ -107,22 +107,21 @@ uxa_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int n,
 		    if (partX2 > fullX2)
 			partX2 = fullX2;
 		    if (partX2 > partX1) {
-			(*uxa_screen->info->Solid) (pPixmap,
-						 partX1 + off_x, fullY1 + off_y,
-						 partX2 + off_x, fullY1 + 1 + off_y);
+			(*uxa_screen->info->solid) (pPixmap,
+						    partX1 + off_x, fullY1 + off_y,
+						    partX2 + off_x, fullY1 + 1 + off_y);
 		    }
 		}
 		pbox++;
 	    }
 	}
     }
-    (*uxa_screen->info->DoneSolid) (pPixmap);
-    uxa_mark_sync(pScreen);
+    (*uxa_screen->info->done_solid) (pPixmap);
 }
 
 static Bool
 uxa_do_put_image (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
-	       int w, int h, int format, char *bits, int src_stride)
+		  int w, int h, int format, char *bits, int src_stride)
 {
     uxa_screen_t    *uxa_screen = uxa_get_screen(pDrawable->pScreen);
     PixmapPtr pPix = uxa_get_drawable_pixmap (pDrawable);
@@ -146,7 +145,7 @@ uxa_do_put_image (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
 
     pPix = uxa_get_offscreen_pixmap (pDrawable, &xoff, &yoff);
 
-    if (!pPix || !uxa_screen->info->UploadToScreen)
+    if (!pPix || !uxa_screen->info->put_image)
 	return FALSE;
 
     x += pDrawable->x;
@@ -177,8 +176,8 @@ uxa_do_put_image (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
 	    continue;
 
 	src = bits + (y1 - y) * src_stride + (x1 - x) * (bpp / 8);
-	ok = uxa_screen->info->UploadToScreen(pPix, x1 + xoff, y1 + yoff,
-					      x2 - x1, y2 - y1, src, src_stride);
+	ok = uxa_screen->info->put_image(pPix, x1 + xoff, y1 + yoff,
+					 x2 - x1, y2 - y1, src, src_stride);
 	/* If we fail to accelerate the upload, fall back to using unaccelerated
 	 * fb calls.
 	 */
@@ -210,8 +209,6 @@ uxa_do_put_image (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
 
     if (access_prepared)
 	uxa_finish_access(pDrawable);
-    else
-	uxa_mark_sync(pDrawable->pScreen);
 
     return TRUE;
 }
@@ -226,8 +223,8 @@ uxa_do_shm_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth,
     int src_stride = PixmapBytePad(w, depth);
 
     if (uxa_do_put_image(pDrawable, pGC, depth, dx, dy, sw, sh, format, data +
-		      sy * src_stride + sx * BitsPerPixel(depth) / 8,
-		      src_stride))
+			 sy * src_stride + sx * BitsPerPixel(depth) / 8,
+			 src_stride))
 	return TRUE;
 
     if (format == ZPixmap)
@@ -235,12 +232,12 @@ uxa_do_shm_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth,
 	PixmapPtr pPixmap;
 
 	pPixmap = GetScratchPixmapHeader(pDrawable->pScreen, w, h, depth,
-		BitsPerPixel(depth), PixmapBytePad(w, depth), (pointer)data);
+					 BitsPerPixel(depth), PixmapBytePad(w, depth),
+					 (pointer)data);
 	if (!pPixmap)
 	    return FALSE;
 
         uxa_prepare_access (pDrawable, UXA_ACCESS_RW);
-
 	fbCopyArea((DrawablePtr)pPixmap, pDrawable, pGC, sx, sy, sw, sh, dx, dy);
 	uxa_finish_access(pDrawable);
 
@@ -260,11 +257,11 @@ uxa_do_shm_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth,
  */
 void
 uxa_shm_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth, unsigned int format,
-	       int w, int h, int sx, int sy, int sw, int sh, int dx, int dy,
-	       char *data)
+		  int w, int h, int sx, int sy, int sw, int sh, int dx, int dy,
+		  char *data)
 {
     if (!uxa_do_shm_put_image(pDrawable, pGC, depth, format, w, h, sx, sy, sw, sh,
-			  dx, dy, data)) {
+			      dx, dy, data)) {
 	uxa_prepare_access (pDrawable, UXA_ACCESS_RW);
 	fbShmPutImage(pDrawable, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy,
 		      data);
@@ -316,9 +313,9 @@ uxa_copy_n_to_n_two_dir (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
 	    /* Do a xdir = ydir = -1 blit instead. */
 	    if (dirsetup != -1) {
 		if (dirsetup != 0)
-		    uxa_screen->info->DoneCopy(pDstPixmap);
+		    uxa_screen->info->done_copy(pDstPixmap);
 		dirsetup = -1;
-		if (!(*uxa_screen->info->PrepareCopy)(pSrcPixmap,
+		if (!(*uxa_screen->info->prepare_copy)(pSrcPixmap,
 						   pDstPixmap,
 						   -1, -1,
 						   pGC ? pGC->alu : GXcopy,
@@ -326,7 +323,7 @@ uxa_copy_n_to_n_two_dir (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
 							 FB_ALLONES))
 		    return FALSE;
 	    }
-	    (*uxa_screen->info->Copy)(pDstPixmap,
+	    (*uxa_screen->info->copy)(pDstPixmap,
 				   src_off_x + pbox->x1 + dx,
 				   src_off_y + pbox->y1 + dy,
 				   dst_off_x + pbox->x1,
@@ -337,9 +334,9 @@ uxa_copy_n_to_n_two_dir (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
 	    /* Do a xdir = ydir = 1 blit instead. */
 	    if (dirsetup != 1) {
 		if (dirsetup != 0)
-		    uxa_screen->info->DoneCopy(pDstPixmap);
+		    uxa_screen->info->done_copy(pDstPixmap);
 		dirsetup = 1;
-		if (!(*uxa_screen->info->PrepareCopy)(pSrcPixmap,
+		if (!(*uxa_screen->info->prepare_copy)(pSrcPixmap,
 						   pDstPixmap,
 						   1, 1,
 						   pGC ? pGC->alu : GXcopy,
@@ -347,7 +344,7 @@ uxa_copy_n_to_n_two_dir (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
 							 FB_ALLONES))
 		    return FALSE;
 	    }
-	    (*uxa_screen->info->Copy)(pDstPixmap,
+	    (*uxa_screen->info->copy)(pDstPixmap,
 				   src_off_x + pbox->x1 + dx,
 				   src_off_y + pbox->y1 + dy,
 				   dst_off_x + pbox->x1,
@@ -362,9 +359,9 @@ uxa_copy_n_to_n_two_dir (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
 	    int i;
 	    if (dirsetup != 1) {
 		if (dirsetup != 0)
-		    uxa_screen->info->DoneCopy(pDstPixmap);
+		    uxa_screen->info->done_copy(pDstPixmap);
 		dirsetup = 1;
-		if (!(*uxa_screen->info->PrepareCopy)(pSrcPixmap,
+		if (!(*uxa_screen->info->prepare_copy)(pSrcPixmap,
 						   pDstPixmap,
 						   1, 1,
 						   pGC ? pGC->alu : GXcopy,
@@ -373,7 +370,7 @@ uxa_copy_n_to_n_two_dir (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
 		    return FALSE;
 	    }
 	    for (i = pbox->y2 - pbox->y1 - 1; i >= 0; i--)
-		(*uxa_screen->info->Copy)(pDstPixmap,
+		(*uxa_screen->info->copy)(pDstPixmap,
 				       src_off_x + pbox->x1 + dx,
 				       src_off_y + pbox->y1 + dy + i,
 				       dst_off_x + pbox->x1,
@@ -387,9 +384,9 @@ uxa_copy_n_to_n_two_dir (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
 	    int i;
 	    if (dirsetup != -1) {
 		if (dirsetup != 0)
-		    uxa_screen->info->DoneCopy(pDstPixmap);
+		    uxa_screen->info->done_copy(pDstPixmap);
 		dirsetup = -1;
-		if (!(*uxa_screen->info->PrepareCopy)(pSrcPixmap,
+		if (!(*uxa_screen->info->prepare_copy)(pSrcPixmap,
 						   pDstPixmap,
 						   -1, -1,
 						   pGC ? pGC->alu : GXcopy,
@@ -398,7 +395,7 @@ uxa_copy_n_to_n_two_dir (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
 		    return FALSE;
 	    }
 	    for (i = 0; i < pbox->y2 - pbox->y1; i++)
-		(*uxa_screen->info->Copy)(pDstPixmap,
+		(*uxa_screen->info->copy)(pDstPixmap,
 				       src_off_x + pbox->x1 + dx,
 				       src_off_y + pbox->y1 + dy + i,
 				       dst_off_x + pbox->x1,
@@ -407,8 +404,7 @@ uxa_copy_n_to_n_two_dir (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
 	}
     }
     if (dirsetup != 0)
-	uxa_screen->info->DoneCopy(pDstPixmap);
-    uxa_mark_sync(pDstDrawable->pScreen);
+	uxa_screen->info->done_copy(pDstPixmap);
     return TRUE;
 }
 
@@ -447,7 +443,7 @@ uxa_copy_n_to_n (DrawablePtr    pSrcDrawable,
 
     if (!uxa_pixmap_is_offscreen(pSrcPixmap) ||
 	!uxa_pixmap_is_offscreen(pDstPixmap) ||
-	!(*uxa_screen->info->PrepareCopy) (pSrcPixmap, pDstPixmap, reverse ? -1 : 1,
+	!(*uxa_screen->info->prepare_copy) (pSrcPixmap, pDstPixmap, reverse ? -1 : 1,
 					   upsidedown ? -1 : 1,
 					   pGC ? pGC->alu : GXcopy,
 					   pGC ? pGC->planemask : FB_ALLONES)) {
@@ -456,7 +452,7 @@ uxa_copy_n_to_n (DrawablePtr    pSrcDrawable,
 
     while (nbox--)
     {
-	(*uxa_screen->info->Copy) (pDstPixmap,
+	(*uxa_screen->info->copy) (pDstPixmap,
 				   pbox->x1 + dx + src_off_x,
 				   pbox->y1 + dy + src_off_y,
 				   pbox->x1 + dst_off_x, pbox->y1 + dst_off_y,
@@ -464,8 +460,7 @@ uxa_copy_n_to_n (DrawablePtr    pSrcDrawable,
 	pbox++;
     }
 
-    (*uxa_screen->info->DoneCopy) (pDstPixmap);
-    uxa_mark_sync (pDstDrawable->pScreen);
+    (*uxa_screen->info->done_copy) (pDstPixmap);
 
     return;
 
@@ -704,7 +699,7 @@ uxa_poly_fill_rect(DrawablePtr pDrawable,
     }
 
     if (!uxa_pixmap_is_offscreen (pPixmap) ||
-	!(*uxa_screen->info->PrepareSolid) (pPixmap,
+	!(*uxa_screen->info->prepare_solid) (pPixmap,
 					 pGC->alu,
 					 pGC->planemask,
 					 pGC->fgPixel))
@@ -747,7 +742,7 @@ fallback:
 	n = REGION_NUM_RECTS (pClip);
 	if (n == 1)
 	{
-	    (*uxa_screen->info->Solid) (pPixmap,
+	    (*uxa_screen->info->solid) (pPixmap,
 				     fullX1 + xoff, fullY1 + yoff,
 				     fullX2 + xoff, fullY2 + yoff);
 	}
@@ -777,15 +772,14 @@ fallback:
 		pbox++;
 
 		if (partX1 < partX2 && partY1 < partY2) {
-		    (*uxa_screen->info->Solid) (pPixmap,
+		    (*uxa_screen->info->solid) (pPixmap,
 					     partX1 + xoff, partY1 + yoff,
 					     partX2 + xoff, partY2 + yoff);
 		}
 	    }
 	}
     }
-    (*uxa_screen->info->DoneSolid) (pPixmap);
-    uxa_mark_sync(pDrawable->pScreen);
+    (*uxa_screen->info->done_solid) (pPixmap);
 
 out:
     REGION_UNINIT(pScreen, pReg);
@@ -858,7 +852,7 @@ uxa_fill_region_solid (DrawablePtr	pDrawable,
     REGION_TRANSLATE(pScreen, pRegion, xoff, yoff);
 
     if (uxa_pixmap_is_offscreen (pPixmap) &&
-	(*uxa_screen->info->PrepareSolid) (pPixmap, alu, planemask, pixel))
+	(*uxa_screen->info->prepare_solid) (pPixmap, alu, planemask, pixel))
     {
 	int nbox;
 	BoxPtr pBox;
@@ -868,12 +862,11 @@ uxa_fill_region_solid (DrawablePtr	pDrawable,
 
 	while (nbox--)
 	{
-	    (*uxa_screen->info->Solid) (pPixmap, pBox->x1, pBox->y1, pBox->x2,
+	    (*uxa_screen->info->solid) (pPixmap, pBox->x1, pBox->y1, pBox->x2,
 				     pBox->y2);
 	    pBox++;
 	}
-	(*uxa_screen->info->DoneSolid) (pPixmap);
-	uxa_mark_sync(pDrawable->pScreen);
+	(*uxa_screen->info->done_solid) (pPixmap);
 
 	ret = TRUE;
     }
@@ -906,7 +899,7 @@ uxa_fill_region_tiled (DrawablePtr	pDrawable,
     tileHeight = pTile->drawable.height;
 
     /* If we're filling with a solid color, grab it out and go to
-     * FillRegionSolid, saving numerous copies.
+     * FillRegionsolid, saving numerous copies.
      */
     if (tileWidth == 1 && tileHeight == 1)
 	return uxa_fill_region_solid(pDrawable, pRegion,
@@ -922,7 +915,7 @@ uxa_fill_region_tiled (DrawablePtr	pDrawable,
     if (!pPixmap || !uxa_pixmap_is_offscreen(pTile))
 	goto out;
 
-    if ((*uxa_screen->info->PrepareCopy) (pTile, pPixmap, 1, 1, alu, planemask))
+    if ((*uxa_screen->info->prepare_copy) (pTile, pPixmap, 1, 1, alu, planemask))
     {
 	while (nbox--)
 	{
@@ -951,7 +944,7 @@ uxa_fill_region_tiled (DrawablePtr	pDrawable,
 			w = width;
 		    width -= w;
 
-		    (*uxa_screen->info->Copy) (pPixmap, tileX, tileY, dstX, dstY,
+		    (*uxa_screen->info->copy) (pPixmap, tileX, tileY, dstX, dstY,
 					    w, h);
 		    dstX += w;
 		    tileX = 0;
@@ -961,8 +954,7 @@ uxa_fill_region_tiled (DrawablePtr	pDrawable,
 	    }
 	    pBox++;
 	}
-	(*uxa_screen->info->DoneCopy) (pPixmap);
-	uxa_mark_sync(pDrawable->pScreen);
+	(*uxa_screen->info->done_copy) (pPixmap);
 
 	ret = TRUE;
     }
@@ -1003,7 +995,7 @@ uxa_get_image (DrawablePtr pDrawable, int x, int y, int w, int h,
 
     pPix = uxa_get_offscreen_pixmap (pDrawable, &xoff, &yoff);
 
-    if (pPix == NULL || uxa_screen->info->DownloadFromScreen == NULL)
+    if (pPix == NULL || uxa_screen->info->get_image == NULL)
 	goto fallback;
 
     /* Only cover the ZPixmap, solid copy case. */
@@ -1016,13 +1008,11 @@ uxa_get_image (DrawablePtr pDrawable, int x, int y, int w, int h,
     if (pDrawable->bitsPerPixel < 8)
 	goto fallback;
 
-    ok = uxa_screen->info->DownloadFromScreen(pPix, pDrawable->x + x + xoff,
+    ok = uxa_screen->info->get_image(pPix, pDrawable->x + x + xoff,
 					   pDrawable->y + y + yoff, w, h, d,
 					   PixmapBytePad(w, pDrawable->depth));
-    if (ok) {
-	uxa_wait_sync(pDrawable->pScreen);
-	goto out;
-    }
+    if (ok)
+	return;
 
 fallback:
     UXA_FALLBACK(("from %p (%c)\n", pDrawable,
@@ -1032,6 +1022,5 @@ fallback:
     fbGetImage (pDrawable, x, y, w, h, format, planeMask, d);
     uxa_finish_access (pDrawable);
 
-out:
    return;
 }
diff --git a/uxa/uxa-glyphs.c b/uxa/uxa-glyphs.c
index 3c44640..364fcfb 100644
--- a/uxa/uxa-glyphs.c
+++ b/uxa/uxa-glyphs.c
@@ -362,7 +362,7 @@ uxa_glyph_cache_upload_glyph(ScreenPtr		    pScreen,
     PixmapPtr	    pCachePixmap = (PixmapPtr)cache->picture->pDrawable;
     int		    cacheXoff, cacheYoff;
 
-    if (!uxa_screen->info->UploadToScreen || uxa_screen->swappedOut)
+    if (!uxa_screen->info->put_image || uxa_screen->swappedOut)
 	return FALSE;
 
     /* If the glyph pixmap is already uploaded, no point in doing
@@ -378,13 +378,13 @@ uxa_glyph_cache_upload_glyph(ScreenPtr		    pScreen,
     if (!pCachePixmap)
 	return FALSE;
 
-    if (!uxa_screen->info->UploadToScreen(pCachePixmap,
-					  CACHE_X(pos) + cacheXoff,
-					  CACHE_Y(pos) + cacheYoff,
-					  pGlyph->info.width,
-					  pGlyph->info.height,
-					  (char *)pGlyphPixmap->devPrivate.ptr,
-					  pGlyphPixmap->devKind))
+    if (!uxa_screen->info->put_image(pCachePixmap,
+				     CACHE_X(pos) + cacheXoff,
+				     CACHE_Y(pos) + cacheYoff,
+				     pGlyph->info.width,
+				     pGlyph->info.height,
+				     (char *)pGlyphPixmap->devPrivate.ptr,
+				     pGlyphPixmap->devKind))
 	return FALSE;
 
     return TRUE;
diff --git a/uxa/uxa-priv.h b/uxa/uxa-priv.h
index 1e4f4ea..c50ab3a 100644
--- a/uxa/uxa-priv.h
+++ b/uxa/uxa-priv.h
@@ -117,7 +117,6 @@ typedef struct {
 
 #define UXA_NUM_GLYPH_CACHES 4
 
-typedef void (*EnableDisableFBAccessProcPtr)(int, Bool);
 typedef struct {
     uxa_driver_t		*info;
     CreateGCProcPtr 		 SavedCreateGC;
diff --git a/uxa/uxa-render.c b/uxa/uxa-render.c
index 9c79fce..94e18a5 100644
--- a/uxa/uxa-render.c
+++ b/uxa/uxa-render.c
@@ -291,7 +291,7 @@ uxa_try_driver_solid_fill(PicturePtr	pSrc,
 	return -1;
     }
 
-    if (!(*uxa_screen->info->PrepareSolid) (pDstPix, GXcopy, 0xffffffff, pixel))
+    if (!(*uxa_screen->info->prepare_solid) (pDstPix, GXcopy, 0xffffffff, pixel))
     {
 	REGION_UNINIT(pDst->pDrawable->pScreen, &region);
 	return -1;
@@ -302,60 +302,46 @@ uxa_try_driver_solid_fill(PicturePtr	pSrc,
 
     while (nbox--)
     {
-	(*uxa_screen->info->Solid) (pDstPix, pbox->x1, pbox->y1, pbox->x2, pbox->y2);
+	(*uxa_screen->info->solid) (pDstPix, pbox->x1, pbox->y1, pbox->x2, pbox->y2);
 	pbox++;
     }
 
-    (*uxa_screen->info->DoneSolid) (pDstPix);
-    uxa_mark_sync(pDst->pDrawable->pScreen);
+    (*uxa_screen->info->done_solid) (pDstPix);
 
     REGION_UNINIT(pDst->pDrawable->pScreen, &region);
     return 1;
 }
 
 static int
-uxa_try_driver_composite_rects(CARD8	       op,
-			   PicturePtr	       pSrc,
-			   PicturePtr	       pDst,
-			   int                 nrect,
-			   uxa_composite_rect_t *rects)
+uxa_try_driver_composite_rects(CARD8		    op,
+			       PicturePtr	    pSrc,
+			       PicturePtr	    pDst,
+			       int		    nrect,
+			       uxa_composite_rect_t *rects)
 {
     uxa_screen_t    *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen);
     int src_off_x, src_off_y, dst_off_x, dst_off_y;
     PixmapPtr pSrcPix, pDstPix;
-    struct _Pixmap scratch;
 
-    if (!uxa_screen->info->PrepareComposite)
+    if (!uxa_screen->info->prepare_composite)
 	return -1;
 
-    pSrcPix = uxa_get_drawable_pixmap(pSrc->pDrawable);
-
-    pDstPix = uxa_get_drawable_pixmap(pDst->pDrawable);
-
-    if (uxa_screen->info->CheckComposite &&
-	!(*uxa_screen->info->CheckComposite) (op, pSrc, NULL, pDst))
+    if (uxa_screen->info->check_composite &&
+	!(*uxa_screen->info->check_composite) (op, pSrc, NULL, pDst))
     {
 	return -1;
     }
     
-    uxa_get_drawable_deltas (pDst->pDrawable, pDstPix, &dst_off_x, &dst_off_y);
-	
-    pSrcPix = uxa_get_offscreen_pixmap (pSrc->pDrawable, &src_off_x, &src_off_y);
-    if (!uxa_pixmap_is_offscreen(pDstPix))
+    pDstPix = uxa_get_offscreen_pixmap(pDst->pDrawable, &dst_off_x, &dst_off_y);
+    if (!pDstPix)
 	return 0;
-    
-    if (!pSrcPix && uxa_screen->info->UploadToScratch)
-    {
-	pSrcPix = uxa_get_drawable_pixmap (pSrc->pDrawable);
-	if ((*uxa_screen->info->UploadToScratch) (pSrcPix, &scratch))
-	    pSrcPix = &scratch;
-    }
 
+    pSrcPix = uxa_get_offscreen_pixmap(pSrc->pDrawable, &src_off_x, &src_off_y);
     if (!pSrcPix)
 	return 0;
 
-    if (!(*uxa_screen->info->PrepareComposite) (op, pSrc, NULL, pDst, pSrcPix,
-					     NULL, pDstPix))
+    if (!(*uxa_screen->info->prepare_composite) (op, pSrc, NULL, pDst, pSrcPix,
+						 NULL, pDstPix))
 	return -1;
 
     while (nrect--)
@@ -384,14 +370,14 @@ uxa_try_driver_composite_rects(CARD8	       op,
 	
 	while (nbox--)
 	{
-	    (*uxa_screen->info->Composite) (pDstPix,
-					 pbox->x1 + xSrc,
-					 pbox->y1 + ySrc,
-					 0, 0,
-					 pbox->x1,
-					 pbox->y1,
-					 pbox->x2 - pbox->x1,
-					 pbox->y2 - pbox->y1);
+	    (*uxa_screen->info->composite) (pDstPix,
+					    pbox->x1 + xSrc,
+					    pbox->y1 + ySrc,
+					    0, 0,
+					    pbox->x1,
+					    pbox->y1,
+					    pbox->x2 - pbox->x1,
+					    pbox->y2 - pbox->y1);
 	    pbox++;
 	}
 
@@ -400,9 +386,7 @@ uxa_try_driver_composite_rects(CARD8	       op,
 
 	rects++;
     }
-    
-    (*uxa_screen->info->DoneComposite) (pDstPix);
-    uxa_mark_sync(pDst->pDrawable->pScreen);
+    (*uxa_screen->info->done_composite) (pDstPix);
 	
     return 1;
 }
@@ -467,12 +451,6 @@ uxa_try_driver_composite(CARD8		op,
     int nbox;
     int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y;
     PixmapPtr pSrcPix, pMaskPix = NULL, pDstPix;
-    struct _Pixmap scratch;
-
-    pSrcPix = uxa_get_drawable_pixmap(pSrc->pDrawable);
-    pDstPix = uxa_get_drawable_pixmap(pDst->pDrawable);
-    if (pMask)
-	pMaskPix = uxa_get_drawable_pixmap(pMask->pDrawable);
 
     xDst += pDst->pDrawable->x;
     yDst += pDst->pDrawable->y;
@@ -485,8 +463,8 @@ uxa_try_driver_composite(CARD8		op,
     xSrc += pSrc->pDrawable->x;
     ySrc += pSrc->pDrawable->y;
 
-    if (uxa_screen->info->CheckComposite &&
-	!(*uxa_screen->info->CheckComposite) (op, pSrc, pMask, pDst))
+    if (uxa_screen->info->check_composite &&
+	!(*uxa_screen->info->check_composite) (op, pSrc, pMask, pDst))
     {
 	return -1;
     }
@@ -496,37 +474,23 @@ uxa_try_driver_composite(CARD8		op,
 				   width, height))
 	return 1;
 
-    uxa_get_drawable_deltas (pDst->pDrawable, pDstPix, &dst_off_x, &dst_off_y);
-
-    REGION_TRANSLATE(pScreen, &region, dst_off_x, dst_off_y);
+    pDstPix = uxa_get_offscreen_pixmap (pDst->pDrawable, &dst_off_x, &dst_off_y);
 
     pSrcPix = uxa_get_offscreen_pixmap (pSrc->pDrawable, &src_off_x, &src_off_y);
+
     if (pMask)
 	pMaskPix = uxa_get_offscreen_pixmap (pMask->pDrawable, &mask_off_x,
-					  &mask_off_y);
+					     &mask_off_y);
 
-    if (!uxa_pixmap_is_offscreen(pDstPix)) {
+    if (!pDstPix || !pSrcPix || (pMask && !pMaskPix)) {
 	REGION_UNINIT(pDst->pDrawable->pScreen, &region);
 	return 0;
     }
 
-    if (!pSrcPix && (!pMask || pMaskPix) && uxa_screen->info->UploadToScratch) {
-	pSrcPix = uxa_get_drawable_pixmap (pSrc->pDrawable);
-	if ((*uxa_screen->info->UploadToScratch) (pSrcPix, &scratch))
-	    pSrcPix = &scratch;
-    } else if (pSrcPix && pMask && !pMaskPix && uxa_screen->info->UploadToScratch) {
-	pMaskPix = uxa_get_drawable_pixmap (pMask->pDrawable);
-	if ((*uxa_screen->info->UploadToScratch) (pMaskPix, &scratch))
-	    pMaskPix = &scratch;
-    }
-
-    if (!pSrcPix || (pMask && !pMaskPix)) {
-	REGION_UNINIT(pDst->pDrawable->pScreen, &region);
-	return 0;
-    }
+    REGION_TRANSLATE(pScreen, &region, dst_off_x, dst_off_y);
 
-    if (!(*uxa_screen->info->PrepareComposite) (op, pSrc, pMask, pDst, pSrcPix,
-					     pMaskPix, pDstPix))
+    if (!(*uxa_screen->info->prepare_composite) (op, pSrc, pMask, pDst, pSrcPix,
+						 pMaskPix, pDstPix))
     {
 	REGION_UNINIT(pDst->pDrawable->pScreen, &region);
 	return -1;
@@ -543,19 +507,18 @@ uxa_try_driver_composite(CARD8		op,
 
     while (nbox--)
     {
-	(*uxa_screen->info->Composite) (pDstPix,
-				     pbox->x1 + xSrc,
-				     pbox->y1 + ySrc,
-				     pbox->x1 + xMask,
-				     pbox->y1 + yMask,
-				     pbox->x1,
-				     pbox->y1,
-				     pbox->x2 - pbox->x1,
-				     pbox->y2 - pbox->y1);
+	(*uxa_screen->info->composite) (pDstPix,
+					pbox->x1 + xSrc,
+					pbox->y1 + ySrc,
+					pbox->x1 + xMask,
+					pbox->y1 + yMask,
+					pbox->x1,
+					pbox->y1,
+					pbox->x2 - pbox->x1,
+					pbox->y2 - pbox->y1);
 	pbox++;
     }
-    (*uxa_screen->info->DoneComposite) (pDstPix);
-    uxa_mark_sync(pDst->pDrawable->pScreen);
+    (*uxa_screen->info->done_composite) (pDstPix);
 
     REGION_UNINIT(pDst->pDrawable->pScreen, &region);
     return 1;
@@ -628,10 +591,10 @@ uxa_try_magic_two_pass_composite_helper(CARD8 op,
 
     assert(op == PictOpOver);
 
-    if (uxa_screen->info->CheckComposite &&
-	(!(*uxa_screen->info->CheckComposite)(PictOpOutReverse, pSrc, pMask,
+    if (uxa_screen->info->check_composite &&
+	(!(*uxa_screen->info->check_composite)(PictOpOutReverse, pSrc, pMask,
 					   pDst) ||
-	 !(*uxa_screen->info->CheckComposite)(PictOpAdd, pSrc, pMask, pDst)))
+	 !(*uxa_screen->info->check_composite)(PictOpAdd, pSrc, pMask, pDst)))
     {
 	return -1;
     }
@@ -735,7 +698,7 @@ uxa_composite(CARD8	op,
 		DDXPointRec patOrg;
 
 		/* Let's see if the driver can do the repeat in one go */
-		if (uxa_screen->info->PrepareComposite && !pSrc->alphaMap &&
+		if (uxa_screen->info->prepare_composite && !pSrc->alphaMap &&
 		    !pDst->alphaMap)
 		{
 		    ret = uxa_try_driver_composite(op, pSrc, pMask, pDst, xSrc,
@@ -779,7 +742,7 @@ uxa_composite(CARD8	op,
 	(yMask + height) <= pMask->pDrawable->height)
 	    pMask->repeat = 0;
 
-    if (uxa_screen->info->PrepareComposite &&
+    if (uxa_screen->info->prepare_composite &&
 	!pSrc->alphaMap && (!pMask || !pMask->alphaMap) && !pDst->alphaMap)
     {
 	Bool isSrcSolid;
diff --git a/uxa/uxa.c b/uxa/uxa.c
index 5fe0f32..c76cb1d 100644
--- a/uxa/uxa.c
+++ b/uxa/uxa.c
@@ -100,8 +100,8 @@ uxa_pixmap_is_offscreen(PixmapPtr p)
     ScreenPtr	    pScreen = p->drawable.pScreen;
     uxa_screen_t    *uxa_screen = uxa_get_screen(pScreen);
 
-    if (uxa_screen->info->PixmapIsOffscreen)
-	return uxa_screen->info->PixmapIsOffscreen(p);
+    if (uxa_screen->info->pixmap_is_offscreen)
+	return uxa_screen->info->pixmap_is_offscreen(p);
 
     return FALSE;
 }
@@ -151,14 +151,14 @@ uxa_prepare_access(DrawablePtr pDrawable, uxa_access_t access)
     if (!offscreen)
 	return;
 
-    if (uxa_screen->info->PrepareAccess)
-	(*uxa_screen->info->PrepareAccess) (pPixmap, access);
+    if (uxa_screen->info->prepare_access)
+	(*uxa_screen->info->prepare_access) (pPixmap, access);
 }
 
 /**
- * uxa_finish_access() is UXA's wrapper for the driver's FinishAccess() handler.
+ * uxa_finish_access() is UXA's wrapper for the driver's finish_access() handler.
  *
- * It deals with calling the driver's FinishAccess() only if necessary.
+ * It deals with calling the driver's finish_access() only if necessary.
  */
 void
 uxa_finish_access(DrawablePtr pDrawable)
@@ -167,13 +167,13 @@ uxa_finish_access(DrawablePtr pDrawable)
     uxa_screen_t    *uxa_screen = uxa_get_screen(pScreen);
     PixmapPtr	    pPixmap = uxa_get_drawable_pixmap (pDrawable);
 
-    if (uxa_screen->info->FinishAccess == NULL)
+    if (uxa_screen->info->finish_access == NULL)
 	return;
 
     if (!uxa_pixmap_is_offscreen (pPixmap))
 	return;
 
-    (*uxa_screen->info->FinishAccess) (pPixmap);
+    (*uxa_screen->info->finish_access) (pPixmap);
 }
 
 /**
@@ -185,7 +185,7 @@ uxa_validate_gc (GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
 {
     /* fbValidateGC will do direct access to pixmaps if the tiling has changed.
      * Preempt fbValidateGC by doing its work and masking the change out, so
-     * that we can do the Prepare/FinishAccess.
+     * that we can do the Prepare/finish_access.
      */
 #ifdef FB_24_32BIT
     if ((changes & GCTile) && fbGetRotatedPixmap(pGC)) {
@@ -396,20 +396,14 @@ uxa_driver_init(ScreenPtr screen, uxa_driver_t *uxa_driver)
 	return FALSE;
     }
 
-    if (!uxa_driver->PrepareSolid) {
-	LogMessage(X_ERROR, "UXA(%d): uxa_driver_t::PrepareSolid must be "
+    if (!uxa_driver->prepare_solid) {
+	LogMessage(X_ERROR, "UXA(%d): uxa_driver_t::prepare_solid must be "
 		   "non-NULL\n", screen->myNum);
 	return FALSE;
     }
 
-    if (!uxa_driver->PrepareCopy) {
-	LogMessage(X_ERROR, "UXA(%d): uxa_driver_t::PrepareCopy must be "
-		   "non-NULL\n", screen->myNum);
-	return FALSE;
-    }
-
-    if (!uxa_driver->WaitMarker) {
-	LogMessage(X_ERROR, "UXA(%d): uxa_driver_t::WaitMarker must be "
+    if (!uxa_driver->prepare_copy) {
+	LogMessage(X_ERROR, "UXA(%d): uxa_driver_t::prepare_copy must be "
 		   "non-NULL\n", screen->myNum);
 	return FALSE;
     }
@@ -418,14 +412,14 @@ uxa_driver_init(ScreenPtr screen, uxa_driver_t *uxa_driver)
      * that there's a limitation by pixels, and that it's the same as
      * maxX.
      *
-     * We want maxPitchPixels or maxPitchBytes to be set so we can check
+     * We want max_pitch_pixels or max_pitch_bytes to be set so we can check
      * pixmaps against the max pitch in uxaCreatePixmap() -- it matters
      * whether a pixmap is rejected because of its pitch or
      * because of its width.
      */
-    if (!uxa_driver->maxPitchPixels && !uxa_driver->maxPitchBytes)
+    if (!uxa_driver->max_pitch_pixels && !uxa_driver->max_pitch_bytes)
     {
-        uxa_driver->maxPitchPixels = uxa_driver->maxX;
+        uxa_driver->max_pitch_pixels = uxa_driver->max_x;
     }
 
 #ifdef RENDER
@@ -501,18 +495,18 @@ uxa_driver_init(ScreenPtr screen, uxa_driver_t *uxa_driver)
 
     LogMessage(X_INFO, "UXA(%d): Driver registered support for the following"
 	       " operations:\n", screen->myNum);
-    assert(uxa_driver->PrepareSolid != NULL);
-    LogMessage(X_INFO, "        Solid\n");
-    assert(uxa_driver->PrepareCopy != NULL);
-    LogMessage(X_INFO, "        Copy\n");
-    if (uxa_driver->PrepareComposite != NULL) {
-	LogMessage(X_INFO, "        Composite (RENDER acceleration)\n");
+    assert(uxa_driver->prepare_solid != NULL);
+    LogMessage(X_INFO, "        solid\n");
+    assert(uxa_driver->prepare_copy != NULL);
+    LogMessage(X_INFO, "        copy\n");
+    if (uxa_driver->prepare_composite != NULL) {
+	LogMessage(X_INFO, "        composite (RENDER acceleration)\n");
     }
-    if (uxa_driver->UploadToScreen != NULL) {
-	LogMessage(X_INFO, "        UploadToScreen\n");
+    if (uxa_driver->put_image != NULL) {
+	LogMessage(X_INFO, "        put_image\n");
     }
-    if (uxa_driver->DownloadFromScreen != NULL) {
-	LogMessage(X_INFO, "        DownloadFromScreen\n");
+    if (uxa_driver->get_image != NULL) {
+	LogMessage(X_INFO, "        get_image\n");
     }
 
     return TRUE;
@@ -528,43 +522,3 @@ uxa_driver_fini (ScreenPtr pScreen)
 {
     /*right now does nothing*/
 }
-
-/**
- * uxa_mark_sync() should be called after any asynchronous drawing by the hardware.
- *
- * @param pScreen screen which drawing occurred on
- *
- * uxa_mark_sync() sets a flag to indicate that some asynchronous drawing has
- * happened and a WaitSync() will be necessary before relying on the contents of
- * offscreen memory from the CPU's perspective.  It also calls an optional
- * driver MarkSync() callback, the return value of which may be used to do partial
- * synchronization with the hardware in the future.
- */
-void uxa_mark_sync(ScreenPtr pScreen)
-{
-    uxa_screen_t    *uxa_screen = uxa_get_screen(pScreen);
-
-    uxa_screen->info->needsSync = TRUE;
-    if (uxa_screen->info->MarkSync != NULL) {
-        uxa_screen->info->lastMarker = (*uxa_screen->info->MarkSync)(pScreen);
-    }
-}
-
-/**
- * uxa_wait_sync() ensures that all drawing has been completed.
- *
- * @param pScreen screen being synchronized.
- *
- * Calls down into the driver to ensure that all previous drawing has completed.
- * It should always be called before relying on the framebuffer contents
- * reflecting previous drawing, from a CPU perspective.
- */
-void uxa_wait_sync(ScreenPtr pScreen)
-{
-    uxa_screen_t    *uxa_screen = uxa_get_screen(pScreen);
-
-    if (uxa_screen->info->needsSync && !uxa_screen->swappedOut) {
-        (*uxa_screen->info->WaitMarker)(pScreen, uxa_screen->info->lastMarker);
-        uxa_screen->info->needsSync = FALSE;
-    }
-}
diff --git a/uxa/uxa.h b/uxa/uxa.h
index 32d5a5a..22889b7 100644
--- a/uxa/uxa.h
+++ b/uxa/uxa.h
@@ -70,36 +70,36 @@ typedef struct _UxaDriver {
 
     /** @{ */
     /**
-     * maxX controls the X coordinate limitation for rendering from the card.
-     * The driver should never receive a request for rendering beyond maxX
+     * max_x controls the X coordinate limitation for rendering from the card.
+     * The driver should never receive a request for rendering beyond max_x
      * in the X direction from the origin of a pixmap.
      */
-    int maxX;
+    int max_x;
 
     /**
-     * maxY controls the Y coordinate limitation for rendering from the card.
-     * The driver should never receive a request for rendering beyond maxY
+     * max_y controls the Y coordinate limitation for rendering from the card.
+     * The driver should never receive a request for rendering beyond max_y
      * in the Y direction from the origin of a pixmap.
      */
-    int maxY;
+    int max_y;
     /** @} */
 
     /* private */
     Bool	      needsSync;
     int               lastMarker;
 
-    /** @name Solid
+    /** @name solid
      * @{
      */
     /**
-     * PrepareSolid() sets up the driver for doing a solid fill.
+     * prepare_solid() sets up the driver for doing a solid fill.
      * @param pPixmap Destination pixmap
      * @param alu raster operation
      * @param planemask write mask for the fill
      * @param fg "foreground" color for the fill
      *
      * This call should set up the driver for doing a series of solid fills
-     * through the Solid() call.  The alu raster op is one of the GX*
+     * through the solid() call.  The alu raster op is one of the GX*
      * graphics functions listed in X.h, and typically maps to a similar
      * single-byte "ROP" setting in all hardware.  The planemask controls
      * which bits of the destination should be affected, and will only represent
@@ -109,16 +109,16 @@ typedef struct _UxaDriver {
      * Note that many drivers will need to store some of the data in the driver
      * private record, for sending to the hardware with each drawing command.
      *
-     * The PrepareSolid() call is required of all drivers, but it may fail for any
+     * The prepare_solid() call is required of all drivers, but it may fail for any
      * reason.  Failure results in a fallback to software rendering.
      */
-    Bool        (*PrepareSolid) (PixmapPtr      pPixmap,
+    Bool        (*prepare_solid) (PixmapPtr      pPixmap,
                                  int            alu,
                                  Pixel          planemask,
                                  Pixel          fg);
 
     /**
-     * Solid() performs a solid fill set up in the last PrepareSolid() call.
+     * solid() performs a solid fill set up in the last prepare_solid() call.
      *
      * @param pPixmap destination pixmap
      * @param x1 left coordinate
@@ -126,37 +126,37 @@ typedef struct _UxaDriver {
      * @param x2 right coordinate
      * @param y2 bottom coordinate
      *
-     * Performs the fill set up by the last PrepareSolid() call, covering the
+     * Performs the fill set up by the last prepare_solid() call, covering the
      * area from (x1,y1) to (x2,y2) in pPixmap.  Note that the coordinates are
      * in the coordinate space of the destination pixmap, so the driver will
      * need to set up the hardware's offset and pitch for the destination
      * coordinates according to the pixmap's offset and pitch within
      * framebuffer.
      *
-     * This call is required if PrepareSolid() ever succeeds.
+     * This call is required if prepare_solid() ever succeeds.
      */
-    void        (*Solid) (PixmapPtr      pPixmap, int x1, int y1, int x2, int y2);
+    void        (*solid) (PixmapPtr      pPixmap, int x1, int y1, int x2, int y2);
 
     /**
-     * DoneSolid() finishes a set of solid fills.
+     * done_solid() finishes a set of solid fills.
      *
      * @param pPixmap destination pixmap.
      *
-     * The DoneSolid() call is called at the end of a series of consecutive
-     * Solid() calls following a successful PrepareSolid().  This allows drivers
+     * The done_solid() call is called at the end of a series of consecutive
+     * solid() calls following a successful prepare_solid().  This allows drivers
      * to finish up emitting drawing commands that were buffered, or clean up
-     * state from PrepareSolid().
+     * state from prepare_solid().
      *
-     * This call is required if PrepareSolid() ever succeeds.
+     * This call is required if prepare_solid() ever succeeds.
      */
-    void        (*DoneSolid) (PixmapPtr      pPixmap);
+    void        (*done_solid) (PixmapPtr      pPixmap);
     /** @} */
 
-    /** @name Copy
+    /** @name copy
      * @{
      */
     /**
-     * PrepareCopy() sets up the driver for doing a copy within video 
+     * prepare_copy() sets up the driver for doing a copy within video 
      * memory.
      *
      * @param pSrcPixmap source pixmap
@@ -173,7 +173,7 @@ typedef struct _UxaDriver {
      * is to deal with self-overlapping copies when pSrcPixmap == pDstPixmap.
      * If your hardware can only support blits that are (left to right, top to
      * bottom) or (right to left, bottom to top), then you should set
-     * #UXA_TWO_BITBLT_DIRECTIONS, and UXA will break down Copy operations to
+     * #UXA_TWO_BITBLT_DIRECTIONS, and UXA will break down copy operations to
      * ones that meet those requirements.  The alu raster op is one of the GX*
      * graphics functions listed in X.h, and typically maps to a similar
      * single-byte "ROP" setting in all hardware.  The planemask controls which
@@ -183,10 +183,10 @@ typedef struct _UxaDriver {
      * Note that many drivers will need to store some of the data in the driver
      * private record, for sending to the hardware with each drawing command.
      *
-     * The PrepareCopy() call is required of all drivers, but it may fail for any
+     * The prepare_copy() call is required of all drivers, but it may fail for any
      * reason.  Failure results in a fallback to software rendering.
      */
-    Bool        (*PrepareCopy) (PixmapPtr       pSrcPixmap,
+    Bool        (*prepare_copy) (PixmapPtr       pSrcPixmap,
                                 PixmapPtr       pDstPixmap,
                                 int             dx,
                                 int             dy,
@@ -194,7 +194,7 @@ typedef struct _UxaDriver {
                                 Pixel           planemask);
 
     /**
-     * Copy() performs a copy set up in the last PrepareCopy call.
+     * copy() performs a copy set up in the last prepare_copy call.
      *
      * @param pDstPixmap destination pixmap
      * @param srcX source X coordinate
@@ -204,20 +204,20 @@ typedef struct _UxaDriver {
      * @param width width of the rectangle to be copied
      * @param height height of the rectangle to be copied.
      *
-     * Performs the copy set up by the last PrepareCopy() call, copying the
+     * Performs the copy set up by the last prepare_copy() call, copying the
      * rectangle from (srcX, srcY) to (srcX + width, srcY + width) in the source
      * pixmap to the same-sized rectangle at (dstX, dstY) in the destination
      * pixmap.  Those rectangles may overlap in memory, if
      * pSrcPixmap == pDstPixmap.  Note that this call does not receive the
      * pSrcPixmap as an argument -- if it's needed in this function, it should
-     * be stored in the driver private during PrepareCopy().  As with Solid(),
+     * be stored in the driver private during prepare_copy().  As with solid(),
      * the coordinates are in the coordinate space of each pixmap, so the driver
      * will need to set up source and destination pitches and offsets from those
      * pixmaps, probably using uxaGetPixmapOffset() and uxa_get_pixmap_pitch().
      *
-     * This call is required if PrepareCopy ever succeeds.
+     * This call is required if prepare_copy ever succeeds.
      */
-    void        (*Copy) (PixmapPtr       pDstPixmap,
+    void        (*copy) (PixmapPtr       pDstPixmap,
                          int    srcX,
                          int    srcY,
                          int    dstX,
@@ -226,25 +226,25 @@ typedef struct _UxaDriver {
                          int    height);
 
     /**
-     * DoneCopy() finishes a set of copies.
+     * done_copy() finishes a set of copies.
      *
      * @param pPixmap destination pixmap.
      *
-     * The DoneCopy() call is called at the end of a series of consecutive
-     * Copy() calls following a successful PrepareCopy().  This allows drivers
+     * The done_copy() call is called at the end of a series of consecutive
+     * copy() calls following a successful prepare_copy().  This allows drivers
      * to finish up emitting drawing commands that were buffered, or clean up
-     * state from PrepareCopy().
+     * state from prepare_copy().
      *
-     * This call is required if PrepareCopy() ever succeeds.
+     * This call is required if prepare_copy() ever succeeds.
      */
-    void        (*DoneCopy) (PixmapPtr       pDstPixmap);
+    void        (*done_copy) (PixmapPtr       pDstPixmap);
     /** @} */
 
-    /** @name Composite
+    /** @name composite
      * @{
      */
     /**
-     * CheckComposite() checks to see if a composite operation could be
+     * check_composite() checks to see if a composite operation could be
      * accelerated.
      *
      * @param op Render operation
@@ -252,25 +252,25 @@ typedef struct _UxaDriver {
      * @param pMaskPicture mask picture
      * @param pDstPicture destination Picture
      *
-     * The CheckComposite() call checks if the driver could handle acceleration
+     * The check_composite() call checks if the driver could handle acceleration
      * of op with the given source, mask, and destination pictures.  This allows
      * drivers to check source and destination formats, supported operations,
      * transformations, and component alpha state, and send operations it can't
      * support to software rendering early on.
      *
-     * See PrepareComposite() for more details on likely issues that drivers
-     * will have in accelerating Composite operations.
+     * See prepare_composite() for more details on likely issues that drivers
+     * will have in accelerating composite operations.
      *
-     * The CheckComposite() call is recommended if PrepareComposite() is
+     * The check_composite() call is recommended if prepare_composite() is
      * implemented, but is not required.
      */
-    Bool        (*CheckComposite) (int          op,
+    Bool        (*check_composite) (int          op,
                                    PicturePtr   pSrcPicture,
                                    PicturePtr   pMaskPicture,
                                    PicturePtr   pDstPicture);
 
     /**
-     * PrepareComposite() sets up the driver for doing a Composite operation
+     * prepare_composite() sets up the driver for doing a composite operation
      * described in the Render extension protocol spec.
      *
      * @param op Render operation
@@ -281,7 +281,7 @@ typedef struct _UxaDriver {
      * @param pMask mask pixmap
      * @param pDst destination pixmap
      *
-     * This call should set up the driver for doing a series of Composite
+     * This call should set up the driver for doing a series of composite
      * operations, as described in the Render protocol spec, with the given
      * pSrcPicture, pMaskPicture, and pDstPicture.  The pSrc, pMask, and
      * pDst are the pixmaps containing the pixel data, and should be used for
@@ -295,7 +295,7 @@ typedef struct _UxaDriver {
      *   operation is simply src OP dst instead of src IN mask OP dst, and
      *   mask coordinates should be ignored.
      * - pMarkPicture may have componentAlpha set, which greatly changes
-     *   the behavior of the Composite operation.  componentAlpha has no effect
+     *   the behavior of the composite operation.  componentAlpha has no effect
      *   when set on pSrcPicture or pDstPicture.
      * - The source and mask Pictures may have a transformation set
      *   (Picture->transform != NULL), which means that the source coordinates
@@ -306,7 +306,7 @@ typedef struct _UxaDriver {
      * - The source and mask pictures may have a filter set.  PictFilterNearest
      *   and PictFilterBilinear are defined in the Render protocol, but others
      *   may be encountered, and must be handled correctly (usually by
-     *   PrepareComposite failing, and falling back to software).  Filters have
+     *   prepare_composite failing, and falling back to software).  Filters have
      *   no effect on Pictures when used as a destination.
      * - The source and mask Pictures may have repeating set, which must be
      *   respected.  Many chipsets will be unable to support repeating on
@@ -318,12 +318,12 @@ typedef struct _UxaDriver {
      * Note that many drivers will need to store some of the data in the driver
      * private record, for sending to the hardware with each drawing command.
      *
-     * The PrepareComposite() call is not required.  However, it is highly
+     * The prepare_composite() call is not required.  However, it is highly
      * recommended for performance of antialiased font rendering and performance
      * of cairo applications.  Failure results in a fallback to software
      * rendering.
      */
-    Bool        (*PrepareComposite) (int                op,
+    Bool        (*prepare_composite) (int                op,
                                      PicturePtr         pSrcPicture,
                                      PicturePtr         pMaskPicture,
                                      PicturePtr         pDstPicture,
@@ -332,8 +332,8 @@ typedef struct _UxaDriver {
                                      PixmapPtr          pDst);
 
     /**
-     * Composite() performs a Composite operation set up in the last
-     * PrepareComposite() call.
+     * composite() performs a composite operation set up in the last
+     * prepare_composite() call.
      *
      * @param pDstPixmap destination pixmap
      * @param srcX source X coordinate
@@ -345,7 +345,7 @@ typedef struct _UxaDriver {
      * @param width destination rectangle width
      * @param height destination rectangle height
      *
-     * Performs the Composite operation set up by the last PrepareComposite()
+     * Performs the composite operation set up by the last prepare_composite()
      * call, to the rectangle from (dstX, dstY) to (dstX + width, dstY + height)
      * in the destination Pixmap.  Note that if a transformation was set on
      * the source or mask Pictures, the source rectangles may not be the same
@@ -353,9 +353,9 @@ typedef struct _UxaDriver {
      * transformation right at the subpixel level can be tricky, and rendercheck
      * can test this for you.
      *
-     * This call is required if PrepareComposite() ever succeeds.
+     * This call is required if prepare_composite() ever succeeds.
      */
-    void        (*Composite) (PixmapPtr         pDst,
+    void        (*composite) (PixmapPtr         pDst,
                               int       srcX,
                               int        srcY,
                               int        maskX,
@@ -366,22 +366,22 @@ typedef struct _UxaDriver {
                               int        height);
 
     /**
-     * DoneComposite() finishes a set of Composite operations.
+     * done_composite() finishes a set of composite operations.
      *
      * @param pPixmap destination pixmap.
      *
-     * The DoneComposite() call is called at the end of a series of consecutive
-     * Composite() calls following a successful PrepareComposite().  This allows
+     * The done_composite() call is called at the end of a series of consecutive
+     * composite() calls following a successful prepare_composite().  This allows
      * drivers to finish up emitting drawing commands that were buffered, or
-     * clean up state from PrepareComposite().
+     * clean up state from prepare_composite().
      *
-     * This call is required if PrepareComposite() ever succeeds.
+     * This call is required if prepare_composite() ever succeeds.
      */
-    void        (*DoneComposite) (PixmapPtr         pDst);
+    void        (*done_composite) (PixmapPtr         pDst);
     /** @} */
 
     /**
-     * UploadToScreen() loads a rectangle of data from src into pDst.
+     * put_image() loads a rectangle of data from src into pDst.
      *
      * @param pDst destination pixmap
      * @param x destination X coordinate.
@@ -391,27 +391,23 @@ typedef struct _UxaDriver {
      * @param src pointer to the beginning of the source data
      * @param src_pitch pitch (in bytes) of the lines of source data.
      *
-     * UploadToScreen() copies data in system memory beginning at src (with
+     * put_image() copies data in system memory beginning at src (with
      * pitch src_pitch) into the destination pixmap from (x, y) to
      * (x + width, y + height).  This is typically done with hostdata uploads,
      * where the CPU sets up a blit command on the hardware with instructions
      * that the blit data will be fed through some sort of aperture on the card.
      *
-     * If UploadToScreen() is performed asynchronously, it is up to the driver
-     * to call uxa_mark_sync().  This is in contrast to most other acceleration
-     * calls in UXA.
-     *
-     * UploadToScreen() can aid in pixmap migration, but is most important for
-     * the performance of uxa_glyphs() (antialiased font drawing) by allowing
-     * pipelining of data uploads, avoiding a sync of the card after each glyph.
+     * put_image() is most important for the performance of uxa_glyphs()
+     * (antialiased font drawing) by allowing pipelining of data uploads,
+     * avoiding a sync of the card after each glyph.
      * 
      * @return TRUE if the driver successfully uploaded the data.  FALSE
      * indicates that UXA should fall back to doing the upload in software.
      *
-     * UploadToScreen() is not required, but is recommended if Composite
+     * put_image() is not required, but is recommended if composite
      * acceleration is supported.
      */
-    Bool        (*UploadToScreen) (PixmapPtr            pDst,
+    Bool        (*put_image) (PixmapPtr            pDst,
 				   int                  x,
 				   int                  y,
 				   int                  w,
@@ -420,33 +416,7 @@ typedef struct _UxaDriver {
                                    int                  src_pitch);
 
     /**
-     * UploadToScratch() is used to upload a pixmap to a scratch area for
-     * acceleration.
-     *
-     * @param pSrc source pixmap in host memory
-     * @param pDst fake, scratch pixmap to be set up in offscreen memory.
-     *
-     * The UploadToScratch() call was added to support Xati before Xati had
-     * support for hostdata uploads and before uxa_glyphs() was written.  It
-     * behaves incorrectly (uses an invalid pixmap as pDst),
-     * and UploadToScreen() should be implemented instead.
-     *
-     * Drivers implementing UploadToScratch() had to set up space (likely in a
-     * statically allocated area) in offscreen memory, copy pSrc to that
-     * scratch area, and adust pDst->devKind for the pitch and
-     * pDst->devPrivate.ptr for the pointer to that scratch area.  The driver
-     * was responsible for syncing (as it was implemented using memcpy() in
-     * Xati), and only the data from the last UploadToScratch() was guaranteed
-     * to be valid at any given time.
-     *
-     * UploadToScratch() should not be implemented by drivers, and will likely
-     * be removed in a future version of UXA.
-     */
-    Bool        (*UploadToScratch) (PixmapPtr           pSrc,
-                                    PixmapPtr           pDst);
-
-    /**
-     * DownloadFromScreen() loads a rectangle of data from pSrc into dst
+     * get_image() loads a rectangle of data from pSrc into dst
      *
      * @param pSrc source pixmap
      * @param x source X coordinate.
@@ -456,108 +426,72 @@ typedef struct _UxaDriver {
      * @param dst pointer to the beginning of the destination data
      * @param dst_pitch pitch (in bytes) of the lines of destination data.
      *
-     * DownloadFromScreen() copies data from offscreen memory in pSrc from
+     * get_image() copies data from offscreen memory in pSrc from
      * (x, y) to (x + width, y + height), to system memory starting at
      * dst (with pitch dst_pitch).  This would usually be done
      * using scatter-gather DMA, supported by a DRM call, or by blitting to AGP
      * and then synchronously reading from AGP.  Because the implementation
      * might be synchronous, UXA leaves it up to the driver to call
-     * uxa_mark_sync() if DownloadFromScreen() was asynchronous.  This is in
+     * uxa_mark_sync() if get_image() was asynchronous.  This is in
      * contrast to most other acceleration calls in UXA.
      *
-     * DownloadFromScreen() can aid in the largest bottleneck in pixmap
-     * migration, which is the read from framebuffer when evicting pixmaps from
-     * framebuffer memory.  Thus, it is highly recommended, even though
-     * implementations are typically complicated.
-     * 
      * @return TRUE if the driver successfully downloaded the data.  FALSE
      * indicates that UXA should fall back to doing the download in software.
      *
-     * DownloadFromScreen() is not required, but is highly recommended.
+     * get_image() is not required, but is highly recommended.
      */
-    Bool (*DownloadFromScreen)(PixmapPtr pSrc,
+    Bool (*get_image)(PixmapPtr pSrc,
                                int x,  int y,
                                int w,  int h,
                                char *dst,  int dst_pitch);
 
-    /**
-     * MarkSync() requests that the driver mark a synchronization point,
-     * returning an driver-defined integer marker which could be requested for
-     * synchronization to later in WaitMarker().  This might be used in the
-     * future to avoid waiting for full hardware stalls before accessing pixmap
-     * data with the CPU, but is not important in the current incarnation of
-     * UXA.
-     *
-     * Note that drivers should call uxa_mark_sync() when they have done some
-     * acceleration, rather than their own MarkSync() handler, as otherwise UXA
-     * will be unaware of the driver's acceleration and not sync to it during
-     * fallbacks.
-     *
-     * MarkSync() is optional.
-     */
-    int		(*MarkSync)   (ScreenPtr pScreen);
-
-    /**
-     * WaitMarker() waits for all rendering before the given marker to have
-     * completed.  If the driver does not implement MarkSync(), marker is
-     * meaningless, and all rendering by the hardware should be completed before
-     * WaitMarker() returns.
-     *
-     * Note that drivers should call uxa_wait_sync() to wait for all acceleration
-     * to finish, as otherwise UXA will be unaware of the driver having
-     * synchronized, resulting in excessive WaitMarker() calls.
-     *
-     * WaitMarker() is required of all drivers.
-     */
-    void	(*WaitMarker) (ScreenPtr pScreen, int marker);
-
     /** @{ */
     /**
-     * PrepareAccess() is called before CPU access to an offscreen pixmap.
+     * prepare_access() is called before CPU access to an offscreen pixmap.
      *
      * @param pPix the pixmap being accessed
      * @param index the index of the pixmap being accessed.
      *
-     * PrepareAccess() will be called before CPU access to an offscreen pixmap.
+     * prepare_access() will be called before CPU access to an offscreen pixmap.
      * This can be used to set up hardware surfaces for byteswapping or
      * untiling, or to adjust the pixmap's devPrivate.ptr for the purpose of
      * making CPU access use a different aperture.
      *
      * The index is one of #UXA_PREPARE_DEST, #UXA_PREPARE_SRC, or
      * #UXA_PREPARE_MASK, indicating which pixmap is in question.  Since only up
-     * to three pixmaps will have PrepareAccess() called on them per operation,
+     * to three pixmaps will have prepare_access() called on them per operation,
      * drivers can have a small, statically-allocated space to maintain state
-     * for PrepareAccess() and FinishAccess() in.  Note that the same pixmap may
-     * have PrepareAccess() called on it more than once, for uxample when doing
-     * a copy within the same pixmap (so it gets PrepareAccess as()
+     * for prepare_access() and finish_access() in.  Note that the same pixmap may
+     * have prepare_access() called on it more than once, for uxample when doing
+     * a copy within the same pixmap (so it gets prepare_access as()
      * #UXA_PREPARE_DEST and then as #UXA_PREPARE_SRC).
      *
-     * PrepareAccess() may fail.  An uxample might be the case of hardware that
-     * can set up 1 or 2 surfaces for CPU access, but not 3.  If PrepareAccess()
+     * prepare_access() may fail.  An uxample might be the case of hardware that
+     * can set up 1 or 2 surfaces for CPU access, but not 3.  If prepare_access()
      * fails, UXA will migrate the pixmap to system memory.
-     * DownloadFromScreen() must be implemented and must not fail if a driver
-     * wishes to fail in PrepareAccess().  PrepareAccess() must not fail when
+     * get_image() must be implemented and must not fail if a driver
+     * wishes to fail in prepare_access().  prepare_access() must not fail when
      * pPix is the visible screen, because the visible screen can not be
      * migrated.
      *
-     * @return TRUE if PrepareAccess() successfully prepared the pixmap for CPU
+     * @return TRUE if prepare_access() successfully prepared the pixmap for CPU
      * drawing.
-     * @return FALSE if PrepareAccess() is unsuccessful and UXA should use
-     * DownloadFromScreen() to migate the pixmap out.
+     * @return FALSE if prepare_access() is unsuccessful and UXA should use
+     * get_image() to migate the pixmap out.
      */
-    Bool	(*PrepareAccess)(PixmapPtr pPix, uxa_access_t access);
+    Bool	(*prepare_access)(PixmapPtr pPix, uxa_access_t access);
 
     /**
-     * FinishAccess() is called after CPU access to an offscreen pixmap.
+     * finish_access() is called after CPU access to an offscreen pixmap.
      *
      * @param pPix the pixmap being accessed
      * @param index the index of the pixmap being accessed.
      *
-     * FinishAccess() will be called after finishing CPU access of an offscreen
-     * pixmap set up by PrepareAccess().  Note that the FinishAccess() will not be
-     * called if PrepareAccess() failed.
+     * finish_access() will be called after finishing CPU access of an offscreen
+     * pixmap set up by prepare_access().  Note that the finish_access() will not be
+     * called if prepare_access() failed.
      */
-    void	(*FinishAccess)(PixmapPtr pPix);
+    void	(*finish_access)(PixmapPtr pPix);
 
     /**
      * PixmapIsOffscreen() is an optional driver replacement to
@@ -569,42 +503,42 @@ typedef struct _UxaDriver {
      *
      * uxa_pixmap_is_offscreen() is used to determine if a pixmap is in offscreen
      * memory, meaning that acceleration could probably be done to it, and that it
-     * will need to be wrapped by PrepareAccess()/FinishAccess() when accessing it
+     * will need to be wrapped by prepare_access()/finish_access() when accessing it
      * with the CPU.
      *
      *
      */
-    Bool	(*PixmapIsOffscreen)(PixmapPtr pPix);
+    Bool	(*pixmap_is_offscreen)(PixmapPtr pPix);
 
     /**
-     * maxPitchPixels controls the pitch limitation for rendering from
+     * max_pitch_pixels controls the pitch limitation for rendering from
      * the card.
      * The driver should never receive a request for rendering a pixmap
-     * that has a pitch (in pixels) beyond maxPitchPixels.
+     * that has a pitch (in pixels) beyond max_pitch_pixels.
      *
      * Setting this field is optional -- if your hardware doesn't have
      * a pitch limitation in pixels, don't set this. If neither this value
-     * nor maxPitchBytes is set, then maxPitchPixels is set to maxX.
-     * If set, it must not be smaller than maxX.
+     * nor max_pitch_bytes is set, then max_pitch_pixels is set to max_x.
+     * If set, it must not be smaller than max_x.
      *
-     * @sa maxPitchBytes
+     * @sa max_pitch_bytes
      */
-    int maxPitchPixels;
+    int max_pitch_pixels;
 
     /**
-     * maxPitchBytes controls the pitch limitation for rendering from
+     * max_pitch_bytes controls the pitch limitation for rendering from
      * the card.
      * The driver should never receive a request for rendering a pixmap
-     * that has a pitch (in bytes) beyond maxPitchBytes.
+     * that has a pitch (in bytes) beyond max_pitch_bytes.
      *
      * Setting this field is optional -- if your hardware doesn't have
      * a pitch limitation in bytes, don't set this.
-     * If set, it must not be smaller than maxX * 4.
-     * There's no default value for maxPitchBytes.
+     * If set, it must not be smaller than max_x * 4.
+     * There's no default value for max_pitch_bytes.
      *
-     * @sa maxPitchPixels
+     * @sa max_pitch_pixels
      */
-    int maxPitchBytes;
+    int max_pitch_bytes;
 
     /** @} */
 } uxa_driver_t;
@@ -630,15 +564,6 @@ uxa_driver_init(ScreenPtr screen, uxa_driver_t *uxa_driver);
 void
 uxa_driver_fini(ScreenPtr pScreen);
 
-void
-uxa_mark_sync(ScreenPtr pScreen);
-
-void
-uxa_wait_sync(ScreenPtr pScreen);
-
-void
-uxaEnableDisableFBAccess (int index, Bool enable);
-
 CARD32
 uxa_get_pixmap_first_pixel (PixmapPtr pPixmap);
 
commit fc4d9c55a7fa8001786c1e4da10f005406c57ece
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Aug 4 18:17:20 2008 -0700

    Change PrepareAccess to take access mode rather than index

diff --git a/src/i830_exa.c b/src/i830_exa.c
index 7609239..08d73b5 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -553,33 +553,21 @@ i830_uxa_get_pixmap_bo (PixmapPtr pixmap)
 }
 
 static Bool
-i830_uxa_prepare_access (PixmapPtr pixmap, int index)
+i830_uxa_prepare_access (PixmapPtr pixmap, uxa_access_t access)
 {
     dri_bo *bo = i830_uxa_get_pixmap_bo (pixmap);
 
     if (bo) {
 	intel_batch_flush(xf86Screens[pixmap->drawable.pScreen->myNum]);
-	if (dri_bo_map (bo, index == UXA_PREPARE_DEST) != 0)
+	if (dri_bo_map (bo, access == UXA_ACCESS_RW) != 0)
 	    return FALSE;
         pixmap->devPrivate.ptr = bo->virtual;
     }
     return TRUE;
 }
 
-void
-i830_uxa_block_handler (ScreenPtr screen)
-{
-    ScrnInfoPtr scrn = xf86Screens[screen->myNum];
-    I830Ptr i830 = I830PTR(scrn);
-
-    if (i830->need_flush) {
-	dri_bo_wait_rendering (i830->front_buffer->bo);
-	i830->need_flush = FALSE;
-    }
-}
-
 static void
-i830_uxa_finish_access (PixmapPtr pixmap, int index)
+i830_uxa_finish_access (PixmapPtr pixmap)
 {
     dri_bo *bo = i830_uxa_get_pixmap_bo (pixmap);
 
@@ -589,11 +577,24 @@ i830_uxa_finish_access (PixmapPtr pixmap, int index)
 	I830Ptr i830 = I830PTR(scrn);
 	
 	dri_bo_unmap (bo);
+	pixmap->devPrivate.ptr = NULL;
 	if (bo == i830->front_buffer->bo)
 	    i830->need_flush = TRUE;
     }
 }
 
+void
+i830_uxa_block_handler (ScreenPtr screen)
+{
+    ScrnInfoPtr scrn = xf86Screens[screen->myNum];
+    I830Ptr i830 = I830PTR(scrn);
+
+    if (i830->need_flush) {
+	dri_bo_wait_rendering (i830->front_buffer->bo);
+	i830->need_flush = FALSE;
+    }
+}
+
 static Bool
 i830_uxa_pixmap_is_offscreen(PixmapPtr pixmap)
 {
@@ -626,16 +627,8 @@ i830_uxa_create_pixmap (ScreenPtr screen, int w, int h, int depth, unsigned usag
 	    return NullPixmap;
 	}
 	
-	if (dri_bo_map (bo, FALSE) != 0) {
-	    fbDestroyPixmap (pixmap);
-	    dri_bo_unreference (bo);
-	    return NullPixmap;
-	}
-	    
-	screen->ModifyPixmapHeader (pixmap, w, h, 0, 0, stride,
-				    (pointer) bo->virtual);
+	screen->ModifyPixmapHeader (pixmap, w, h, 0, 0, stride, NULL);
     
-	dri_bo_unmap (bo);
 	i830_uxa_set_pixmap_bo (pixmap, bo);
     }
 
@@ -648,10 +641,8 @@ i830_uxa_destroy_pixmap (PixmapPtr pixmap)
     if (pixmap->refcnt == 1) {
 	dri_bo  *bo = i830_uxa_get_pixmap_bo (pixmap);
     
-	if (bo) {
-	    dri_bo_unmap (bo);
+	if (bo)
 	    dri_bo_unreference (bo);
-	}
     }
     fbDestroyPixmap (pixmap);
     return TRUE;
@@ -705,6 +696,7 @@ i830_uxa_init (ScreenPtr pScreen)
     i830->uxa_driver->Copy = I830EXACopy;
     i830->uxa_driver->DoneCopy = I830EXADoneCopy;
 
+#if 0
     /* Composite */
     if (!IS_I9XX(i830)) {
     	i830->uxa_driver->CheckComposite = i830_check_composite;
@@ -724,6 +716,7 @@ i830_uxa_init (ScreenPtr pScreen)
  	i830->uxa_driver->Composite = i965_composite;
  	i830->uxa_driver->DoneComposite = i830_done_composite;
     }
+#endif
 
     i830->uxa_driver->PrepareAccess = i830_uxa_prepare_access;
     i830->uxa_driver->FinishAccess = i830_uxa_finish_access;
diff --git a/uxa/uxa-accel.c b/uxa/uxa-accel.c
index 7c7b3e9..20a5657 100644
--- a/uxa/uxa-accel.c
+++ b/uxa/uxa-accel.c
@@ -189,8 +189,7 @@ uxa_do_put_image (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
 	    int	dstXoff, dstYoff;
 
 	    if (!access_prepared) {
-		uxa_prepare_access(pDrawable, UXA_PREPARE_DEST);
-
+		uxa_prepare_access(pDrawable, UXA_ACCESS_RW);
 		access_prepared = TRUE;
 	    }
 
@@ -210,7 +209,7 @@ uxa_do_put_image (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
     }
 
     if (access_prepared)
-	uxa_finish_access(pDrawable, UXA_PREPARE_DEST);
+	uxa_finish_access(pDrawable);
     else
 	uxa_mark_sync(pDrawable->pScreen);
 
@@ -240,10 +239,10 @@ uxa_do_shm_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth,
 	if (!pPixmap)
 	    return FALSE;
 
-        uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+        uxa_prepare_access (pDrawable, UXA_ACCESS_RW);
 
 	fbCopyArea((DrawablePtr)pPixmap, pDrawable, pGC, sx, sy, sw, sh, dx, dy);
-	uxa_finish_access(pDrawable, UXA_PREPARE_DEST);
+	uxa_finish_access(pDrawable);
 
 	FreeScratchPixmapHeader(pPixmap);
 
@@ -266,10 +265,10 @@ uxa_shm_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth, unsigned int form
 {
     if (!uxa_do_shm_put_image(pDrawable, pGC, depth, format, w, h, sx, sy, sw, sh,
 			  dx, dy, data)) {
-	uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+	uxa_prepare_access (pDrawable, UXA_ACCESS_RW);
 	fbShmPutImage(pDrawable, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy,
 		      data);
-	uxa_finish_access(pDrawable, UXA_PREPARE_DEST);
+	uxa_finish_access(pDrawable);
     }
 }
 
@@ -474,12 +473,12 @@ fallback:
     UXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrcDrawable, pDstDrawable,
 		  uxa_drawable_location(pSrcDrawable),
 		  uxa_drawable_location(pDstDrawable)));
-    uxa_prepare_access (pDstDrawable, UXA_PREPARE_DEST);
-    uxa_prepare_access (pSrcDrawable, UXA_PREPARE_SRC);
+    uxa_prepare_access (pDstDrawable, UXA_ACCESS_RW);
+    uxa_prepare_access (pSrcDrawable, UXA_ACCESS_RO);
     fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy, reverse,
 		upsidedown, bitplane, closure);
-    uxa_finish_access (pSrcDrawable, UXA_PREPARE_SRC);
-    uxa_finish_access (pDstDrawable, UXA_PREPARE_DEST);
+    uxa_finish_access (pSrcDrawable);
+    uxa_finish_access (pDstDrawable);
 }
 
 RegionPtr
@@ -1029,9 +1028,9 @@ fallback:
     UXA_FALLBACK(("from %p (%c)\n", pDrawable,
 		  uxa_drawable_location(pDrawable)));
 
-    uxa_prepare_access (pDrawable, UXA_PREPARE_SRC);
+    uxa_prepare_access (pDrawable, UXA_ACCESS_RO);
     fbGetImage (pDrawable, x, y, w, h, format, planeMask, d);
-    uxa_finish_access (pDrawable, UXA_PREPARE_SRC);
+    uxa_finish_access (pDrawable);
 
 out:
    return;
diff --git a/uxa/uxa-priv.h b/uxa/uxa-priv.h
index acc82bb..1e4f4ea 100644
--- a/uxa/uxa-priv.h
+++ b/uxa/uxa-priv.h
@@ -350,10 +350,10 @@ uxa_check_composite (CARD8      op,
 
 /* uxa.c */
 void
-uxa_prepare_access(DrawablePtr pDrawable, int index);
+uxa_prepare_access(DrawablePtr pDrawable, uxa_access_t access);
 
 void
-uxa_finish_access(DrawablePtr pDrawable, int index);
+uxa_finish_access(DrawablePtr pDrawable);
 
 void
 uxa_get_drawable_deltas (DrawablePtr pDrawable, PixmapPtr pPixmap,
diff --git a/uxa/uxa-render.c b/uxa/uxa-render.c
index 38e6088..9c79fce 100644
--- a/uxa/uxa-render.c
+++ b/uxa/uxa-render.c
@@ -926,12 +926,12 @@ uxa_trapezoids (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
 	xoff += pDraw->x;
 	yoff += pDraw->y;
 
-	uxa_prepare_access(pDraw, UXA_PREPARE_DEST);
+	uxa_prepare_access(pDraw, UXA_ACCESS_RW);
 
 	for (; ntrap; ntrap--, traps++)
 	    (*ps->RasterizeTrapezoid) (pDst, traps, 0, 0);
 
-	uxa_finish_access(pDraw, UXA_PREPARE_DEST);
+	uxa_finish_access(pDraw);
     }
     else if (maskFormat)
     {
@@ -948,11 +948,11 @@ uxa_trapezoids (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
 	if (!pPicture)
 	    return;
 
-	uxa_prepare_access(pPicture->pDrawable, UXA_PREPARE_DEST);
+	uxa_prepare_access(pPicture->pDrawable, UXA_ACCESS_RW);
 	for (; ntrap; ntrap--, traps++)
 	    (*ps->RasterizeTrapezoid) (pPicture, traps,
 				       -bounds.x1, -bounds.y1);
-	uxa_finish_access(pPicture->pDrawable, UXA_PREPARE_DEST);
+	uxa_finish_access(pPicture->pDrawable);
 
 	xRel = bounds.x1 + xSrc - xDst;
 	yRel = bounds.y1 + ySrc - yDst;
@@ -1009,9 +1009,9 @@ uxa_triangles (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
     if (direct)
     {
 	DrawablePtr pDraw = pDst->pDrawable;
-	uxa_prepare_access(pDraw, UXA_PREPARE_DEST);
+	uxa_prepare_access(pDraw, UXA_ACCESS_RW);
 	(*ps->AddTriangles) (pDst, 0, 0, ntri, tris);
-	uxa_finish_access(pDraw, UXA_PREPARE_DEST);
+	uxa_finish_access(pDraw);
     }
     else if (maskFormat)
     {
@@ -1028,9 +1028,9 @@ uxa_triangles (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
 	if (!pPicture)
 	    return;
 
-	uxa_prepare_access(pPicture->pDrawable, UXA_PREPARE_DEST);
+	uxa_prepare_access(pPicture->pDrawable, UXA_ACCESS_RW);
 	(*ps->AddTriangles) (pPicture, -bounds.x1, -bounds.y1, ntri, tris);
-	uxa_finish_access(pPicture->pDrawable, UXA_PREPARE_DEST);
+	uxa_finish_access(pPicture->pDrawable);
 	
 	xRel = bounds.x1 + xSrc - xDst;
 	yRel = bounds.y1 + ySrc - yDst;
diff --git a/uxa/uxa-unaccel.c b/uxa/uxa-unaccel.c
index 2719420..01c1322 100644
--- a/uxa/uxa-unaccel.c
+++ b/uxa/uxa-unaccel.c
@@ -45,9 +45,9 @@ void
 uxa_prepare_access_gc(GCPtr pGC)
 {
     if (pGC->stipple)
-        uxa_prepare_access(&pGC->stipple->drawable, UXA_PREPARE_MASK);
+        uxa_prepare_access(&pGC->stipple->drawable, UXA_ACCESS_RO);
     if (pGC->fillStyle == FillTiled)
-	uxa_prepare_access(&pGC->tile.pixmap->drawable, UXA_PREPARE_SRC);
+	uxa_prepare_access(&pGC->tile.pixmap->drawable, UXA_ACCESS_RO);
 }
 
 /**
@@ -57,9 +57,9 @@ void
 uxa_finish_access_gc(GCPtr pGC)
 {
     if (pGC->fillStyle == FillTiled)
-	uxa_finish_access(&pGC->tile.pixmap->drawable, UXA_PREPARE_MASK);
+	uxa_finish_access(&pGC->tile.pixmap->drawable);
     if (pGC->stipple)
-        uxa_finish_access(&pGC->stipple->drawable, UXA_PREPARE_SRC);
+        uxa_finish_access(&pGC->stipple->drawable);
 }
 
 #if DEBUG_TRACE_FALL
@@ -75,11 +75,11 @@ uxa_check_fill_spans (DrawablePtr pDrawable, GCPtr pGC, int nspans,
 		   DDXPointPtr ppt, int *pwidth, int fSorted)
 {
     UXA_FALLBACK(("to %p (%c)\n", pDrawable, uxa_drawable_location(pDrawable)));
-    uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+    uxa_prepare_access (pDrawable, UXA_ACCESS_RW);
     uxa_prepare_access_gc (pGC);
     fbFillSpans (pDrawable, pGC, nspans, ppt, pwidth, fSorted);
     uxa_finish_access_gc (pGC);
-    uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+    uxa_finish_access (pDrawable);
 }
 
 void
@@ -87,9 +87,9 @@ uxa_check_set_spans (DrawablePtr pDrawable, GCPtr pGC, char *psrc,
 		 DDXPointPtr ppt, int *pwidth, int nspans, int fSorted)
 {
     UXA_FALLBACK(("to %p (%c)\n", pDrawable, uxa_drawable_location(pDrawable)));
-    uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+    uxa_prepare_access (pDrawable, UXA_ACCESS_RW);
     fbSetSpans (pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted);
-    uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+    uxa_finish_access (pDrawable);
 }
 
 void
@@ -98,9 +98,9 @@ uxa_check_put_image (DrawablePtr pDrawable, GCPtr pGC, int depth,
 		 char *bits)
 {
     UXA_FALLBACK(("to %p (%c)\n", pDrawable, uxa_drawable_location(pDrawable)));
-    uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+    uxa_prepare_access (pDrawable, UXA_ACCESS_RW);
     fbPutImage (pDrawable, pGC, depth, x, y, w, h, leftPad, format, bits);
-    uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+    uxa_finish_access (pDrawable);
 }
 
 RegionPtr
@@ -111,11 +111,11 @@ uxa_check_copy_area (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
 
     UXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst,
 		  uxa_drawable_location(pSrc), uxa_drawable_location(pDst)));
-    uxa_prepare_access (pDst, UXA_PREPARE_DEST);
-    uxa_prepare_access (pSrc, UXA_PREPARE_SRC);
+    uxa_prepare_access (pDst, UXA_ACCESS_RW);
+    uxa_prepare_access (pSrc, UXA_ACCESS_RO);
     ret = fbCopyArea (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty);
-    uxa_finish_access (pSrc, UXA_PREPARE_SRC);
-    uxa_finish_access (pDst, UXA_PREPARE_DEST);
+    uxa_finish_access (pSrc);
+    uxa_finish_access (pDst);
 
     return ret;
 }
@@ -129,12 +129,12 @@ uxa_check_copy_plane (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
 
     UXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst,
 		  uxa_drawable_location(pSrc), uxa_drawable_location(pDst)));
-    uxa_prepare_access (pDst, UXA_PREPARE_DEST);
-    uxa_prepare_access (pSrc, UXA_PREPARE_SRC);
+    uxa_prepare_access (pDst, UXA_ACCESS_RW);
+    uxa_prepare_access (pSrc, UXA_ACCESS_RO);
     ret = fbCopyPlane (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty,
 		       bitPlane);
-    uxa_finish_access (pSrc, UXA_PREPARE_SRC);
-    uxa_finish_access (pDst, UXA_PREPARE_DEST);
+    uxa_finish_access (pSrc);
+    uxa_finish_access (pDst);
 
     return ret;
 }
@@ -144,9 +144,9 @@ uxa_check_poly_point (DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
 		  DDXPointPtr pptInit)
 {
     UXA_FALLBACK(("to %p (%c)\n", pDrawable, uxa_drawable_location(pDrawable)));
-    uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+    uxa_prepare_access (pDrawable, UXA_ACCESS_RW);
     fbPolyPoint (pDrawable, pGC, mode, npt, pptInit);
-    uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+    uxa_finish_access (pDrawable);
 }
 
 void
@@ -158,11 +158,11 @@ uxa_check_poly_lines (DrawablePtr pDrawable, GCPtr pGC,
 		  pGC->lineWidth, mode, npt));
 
     if (pGC->lineWidth == 0) {
-	uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+	uxa_prepare_access (pDrawable, UXA_ACCESS_RW);
 	uxa_prepare_access_gc (pGC);
 	fbPolyLine (pDrawable, pGC, mode, npt, ppt);
 	uxa_finish_access_gc (pGC);
-	uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+	uxa_finish_access (pDrawable);
 	return;
     }
     /* fb calls mi functions in the lineWidth != 0 case. */
@@ -176,11 +176,11 @@ uxa_check_poly_segment (DrawablePtr pDrawable, GCPtr pGC,
     UXA_FALLBACK(("to %p (%c) width %d, count %d\n", pDrawable,
 		  uxa_drawable_location(pDrawable), pGC->lineWidth, nsegInit));
     if (pGC->lineWidth == 0) {
-	uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+	uxa_prepare_access (pDrawable, UXA_ACCESS_RW);
 	uxa_prepare_access_gc (pGC);
 	fbPolySegment (pDrawable, pGC, nsegInit, pSegInit);
 	uxa_finish_access_gc (pGC);
-	uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+	uxa_finish_access (pDrawable);
 	return;
     }
     /* fb calls mi functions in the lineWidth != 0 case. */
@@ -200,11 +200,11 @@ uxa_check_poly_arc (DrawablePtr pDrawable, GCPtr pGC,
 #if 0
     if (pGC->lineWidth == 0)
     {
-	uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+	uxa_prepare_access (pDrawable, UXA_ACCESS_RW);
 	uxa_prepare_access_gc (pGC);
 	fbPolyArc (pDrawable, pGC, narcs, pArcs);
 	uxa_finish_access_gc (pGC);
-	uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+	uxa_finish_access (pDrawable);
 	return;
     }
 #endif
@@ -217,11 +217,11 @@ uxa_check_poly_fill_rect (DrawablePtr pDrawable, GCPtr pGC,
 {
     UXA_FALLBACK(("to %p (%c)\n", pDrawable, uxa_drawable_location(pDrawable)));
 
-    uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+    uxa_prepare_access (pDrawable, UXA_ACCESS_RW);
     uxa_prepare_access_gc (pGC);
     fbPolyFillRect (pDrawable, pGC, nrect, prect);
     uxa_finish_access_gc (pGC);
-    uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+    uxa_finish_access (pDrawable);
 }
 
 void
@@ -231,11 +231,11 @@ uxa_check_image_glyph_blt (DrawablePtr pDrawable, GCPtr pGC,
 {
     UXA_FALLBACK(("to %p (%c)\n", pDrawable,
 		  uxa_drawable_location(pDrawable)));
-    uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+    uxa_prepare_access (pDrawable, UXA_ACCESS_RW);
     uxa_prepare_access_gc (pGC);
     fbImageGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
     uxa_finish_access_gc (pGC);
-    uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+    uxa_finish_access (pDrawable);
 }
 
 void
@@ -245,11 +245,11 @@ uxa_check_poly_glyph_blt (DrawablePtr pDrawable, GCPtr pGC,
 {
     UXA_FALLBACK(("to %p (%c), style %d alu %d\n", pDrawable,
 		  uxa_drawable_location(pDrawable), pGC->fillStyle, pGC->alu));
-    uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+    uxa_prepare_access (pDrawable, UXA_ACCESS_RW);
     uxa_prepare_access_gc (pGC);
     fbPolyGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
     uxa_finish_access_gc (pGC);
-    uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+    uxa_finish_access (pDrawable);
 }
 
 void
@@ -260,13 +260,13 @@ uxa_check_push_pixels (GCPtr pGC, PixmapPtr pBitmap,
     UXA_FALLBACK(("from %p to %p (%c,%c)\n", pBitmap, pDrawable,
 		  uxa_drawable_location(&pBitmap->drawable),
 		  uxa_drawable_location(pDrawable)));
-    uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
-    uxa_prepare_access (&pBitmap->drawable, UXA_PREPARE_SRC);
+    uxa_prepare_access (pDrawable, UXA_ACCESS_RW);
+    uxa_prepare_access (&pBitmap->drawable, UXA_ACCESS_RO);
     uxa_prepare_access_gc (pGC);
     fbPushPixels (pGC, pBitmap, pDrawable, w, h, x, y);
     uxa_finish_access_gc (pGC);
-    uxa_finish_access (&pBitmap->drawable, UXA_PREPARE_SRC);
-    uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+    uxa_finish_access (&pBitmap->drawable);
+    uxa_finish_access (pDrawable);
 }
 
 void
@@ -278,9 +278,9 @@ uxa_check_get_spans (DrawablePtr pDrawable,
 		 char *pdstStart)
 {
     UXA_FALLBACK(("from %p (%c)\n", pDrawable, uxa_drawable_location(pDrawable)));
-    uxa_prepare_access (pDrawable, UXA_PREPARE_SRC);
+    uxa_prepare_access (pDrawable, UXA_ACCESS_RO);
     fbGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
-    uxa_finish_access (pDrawable, UXA_PREPARE_SRC);
+    uxa_finish_access (pDrawable);
 }
 
 void
@@ -300,11 +300,11 @@ uxa_check_composite (CARD8      op,
     UXA_FALLBACK(("from picts %p/%p to pict %p\n",
 		 pSrc, pMask, pDst));
 
-    uxa_prepare_access (pDst->pDrawable, UXA_PREPARE_DEST);
+    uxa_prepare_access (pDst->pDrawable, UXA_ACCESS_RW);
     if (pSrc->pDrawable != NULL)
-	uxa_prepare_access (pSrc->pDrawable, UXA_PREPARE_SRC);
+	uxa_prepare_access (pSrc->pDrawable, UXA_ACCESS_RO);
     if (pMask && pMask->pDrawable != NULL)
-	uxa_prepare_access (pMask->pDrawable, UXA_PREPARE_MASK);
+	uxa_prepare_access (pMask->pDrawable, UXA_ACCESS_RO);
     fbComposite (op,
                  pSrc,
                  pMask,
@@ -318,10 +318,10 @@ uxa_check_composite (CARD8      op,
                  width,
                  height);
     if (pMask && pMask->pDrawable != NULL)
-	uxa_finish_access (pMask->pDrawable, UXA_PREPARE_MASK);
+	uxa_finish_access (pMask->pDrawable);
     if (pSrc->pDrawable != NULL)
-	uxa_finish_access (pSrc->pDrawable, UXA_PREPARE_SRC);
-    uxa_finish_access (pDst->pDrawable, UXA_PREPARE_DEST);
+	uxa_finish_access (pSrc->pDrawable);
+    uxa_finish_access (pDst->pDrawable);
 }
 
 void
@@ -333,9 +333,9 @@ uxa_check_add_traps (PicturePtr	pPicture,
 {
     UXA_FALLBACK(("to pict %p (%c)\n",
 		  uxa_drawable_location(pPicture->pDrawable)));
-    uxa_prepare_access(pPicture->pDrawable, UXA_PREPARE_DEST);
+    uxa_prepare_access(pPicture->pDrawable, UXA_ACCESS_RW);
     fbAddTraps (pPicture, x_off, y_off, ntrap, traps);
-    uxa_finish_access(pPicture->pDrawable, UXA_PREPARE_DEST);
+    uxa_finish_access(pPicture->pDrawable);
 }
 
 /**
@@ -350,7 +350,7 @@ uxa_get_pixmap_first_pixel (PixmapPtr pPixmap)
     CARD32 pixel;
     void *fb;
 
-    uxa_prepare_access (&pPixmap->drawable, UXA_PREPARE_SRC);
+    uxa_prepare_access (&pPixmap->drawable, UXA_ACCESS_RO);
     fb = pPixmap->devPrivate.ptr;
 
     switch (pPixmap->drawable.bitsPerPixel) {
@@ -364,7 +364,7 @@ uxa_get_pixmap_first_pixel (PixmapPtr pPixmap)
 	pixel = *(CARD8 *)fb;
 	break;
     }
-    uxa_finish_access(&pPixmap->drawable, UXA_PREPARE_SRC);
+    uxa_finish_access(&pPixmap->drawable);
 
     return pixel;
 }
diff --git a/uxa/uxa.c b/uxa/uxa.c
index 7201e7c..5fe0f32 100644
--- a/uxa/uxa.c
+++ b/uxa/uxa.c
@@ -141,7 +141,7 @@ uxa_get_offscreen_pixmap (DrawablePtr drawable, int *xp, int *yp)
  * PrepareAccess() is necessary, and working around PrepareAccess() failure.
  */
 void
-uxa_prepare_access(DrawablePtr pDrawable, int index)
+uxa_prepare_access(DrawablePtr pDrawable, uxa_access_t access)
 {
     ScreenPtr	    pScreen = pDrawable->pScreen;
     uxa_screen_t    *uxa_screen = uxa_get_screen(pScreen);
@@ -152,7 +152,7 @@ uxa_prepare_access(DrawablePtr pDrawable, int index)
 	return;
 
     if (uxa_screen->info->PrepareAccess)
-	(*uxa_screen->info->PrepareAccess) (pPixmap, index);
+	(*uxa_screen->info->PrepareAccess) (pPixmap, access);
 }
 
 /**
@@ -161,7 +161,7 @@ uxa_prepare_access(DrawablePtr pDrawable, int index)
  * It deals with calling the driver's FinishAccess() only if necessary.
  */
 void
-uxa_finish_access(DrawablePtr pDrawable, int index)
+uxa_finish_access(DrawablePtr pDrawable)
 {
     ScreenPtr	    pScreen = pDrawable->pScreen;
     uxa_screen_t    *uxa_screen = uxa_get_screen(pScreen);
@@ -173,7 +173,7 @@ uxa_finish_access(DrawablePtr pDrawable, int index)
     if (!uxa_pixmap_is_offscreen (pPixmap))
 	return;
 
-    (*uxa_screen->info->FinishAccess) (pPixmap, index);
+    (*uxa_screen->info->FinishAccess) (pPixmap);
 }
 
 /**
@@ -209,10 +209,10 @@ uxa_validate_gc (GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
 		 * allocated pixmap.  This isn't a problem yet, since we don't
 		 * put pixmaps in FB until at least one accelerated UXA op.
 		 */
-		uxa_prepare_access(&pOldTile->drawable, UXA_PREPARE_SRC);
+		uxa_prepare_access(&pOldTile->drawable, UXA_ACCESS_RO);
 		pNewTile = fb24_32ReformatTile (pOldTile,
 						pDrawable->bitsPerPixel);
-		uxa_finish_access(&pOldTile->drawable, UXA_PREPARE_SRC);
+		uxa_finish_access(&pOldTile->drawable);
 	    }
 	    if (pNewTile)
 	    {
@@ -227,9 +227,9 @@ uxa_validate_gc (GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
 	if (!pGC->tileIsPixel && FbEvenTile (pGC->tile.pixmap->drawable.width *
 					     pDrawable->bitsPerPixel))
 	{
-	    uxa_prepare_access(&pGC->tile.pixmap->drawable, UXA_PREPARE_SRC);
+	    uxa_prepare_access(&pGC->tile.pixmap->drawable, UXA_ACCESS_RW);
 	    fbPadPixmap (pGC->tile.pixmap);
-	    uxa_finish_access(&pGC->tile.pixmap->drawable, UXA_PREPARE_SRC);
+	    uxa_finish_access(&pGC->tile.pixmap->drawable);
 	}
 	/* Mask out the GCTile change notification, now that we've done FB's
 	 * job for it.
@@ -273,20 +273,20 @@ void
 uxa_prepare_access_window(WindowPtr pWin)
 {
     if (pWin->backgroundState == BackgroundPixmap) 
-        uxa_prepare_access(&pWin->background.pixmap->drawable, UXA_PREPARE_SRC);
+        uxa_prepare_access(&pWin->background.pixmap->drawable, UXA_ACCESS_RO);
 
     if (pWin->borderIsPixel == FALSE)
-        uxa_prepare_access(&pWin->border.pixmap->drawable, UXA_PREPARE_SRC);
+        uxa_prepare_access(&pWin->border.pixmap->drawable, UXA_ACCESS_RO);
 }
 
 void
 uxa_finish_access_window(WindowPtr pWin)
 {
     if (pWin->backgroundState == BackgroundPixmap) 
-        uxa_finish_access(&pWin->background.pixmap->drawable, UXA_PREPARE_SRC);
+        uxa_finish_access(&pWin->background.pixmap->drawable);
 
     if (pWin->borderIsPixel == FALSE)
-        uxa_finish_access(&pWin->border.pixmap->drawable, UXA_PREPARE_SRC);
+        uxa_finish_access(&pWin->border.pixmap->drawable);
 }
 
 static Bool
@@ -304,9 +304,9 @@ static RegionPtr
 uxa_bitmap_to_region(PixmapPtr pPix)
 {
   RegionPtr ret;
-  uxa_prepare_access(&pPix->drawable, UXA_PREPARE_SRC);
+  uxa_prepare_access(&pPix->drawable, UXA_ACCESS_RO);
   ret = fbPixmapToRegion(pPix);
-  uxa_finish_access(&pPix->drawable, UXA_PREPARE_SRC);
+  uxa_finish_access(&pPix->drawable);
   return ret;
 }
 
diff --git a/uxa/uxa.h b/uxa/uxa.h
index 57e84f3..32d5a5a 100644
--- a/uxa/uxa.h
+++ b/uxa/uxa.h
@@ -43,6 +43,11 @@
 #define UXA_VERSION_MINOR   0
 #define UXA_VERSION_RELEASE 0
 
+typedef enum {
+	UXA_ACCESS_RO,
+	UXA_ACCESS_RW
+} uxa_access_t;
+
 /**
  * The UxaDriver structure is allocated through uxa_driver_alloc(), and then
  * fllled in by drivers.
@@ -251,11 +256,7 @@ typedef struct _UxaDriver {
      * of op with the given source, mask, and destination pictures.  This allows
      * drivers to check source and destination formats, supported operations,
      * transformations, and component alpha state, and send operations it can't
-     * support to software rendering early on.  This avoids costly pixmap
-     * migration to the wrong places when the driver can't accelerate
-     * operations.  Note that because migration hasn't happened, the driver
-     * can't know during CheckComposite() what the offsets and pitches of the
-     * pixmaps are going to be.
+     * support to software rendering early on.
      *
      * See PrepareComposite() for more details on likely issues that drivers
      * will have in accelerating Composite operations.
@@ -544,7 +545,7 @@ typedef struct _UxaDriver {
      * @return FALSE if PrepareAccess() is unsuccessful and UXA should use
      * DownloadFromScreen() to migate the pixmap out.
      */
-    Bool	(*PrepareAccess)(PixmapPtr pPix, int index);
+    Bool	(*PrepareAccess)(PixmapPtr pPix, uxa_access_t access);
 
     /**
      * FinishAccess() is called after CPU access to an offscreen pixmap.
@@ -554,9 +555,9 @@ typedef struct _UxaDriver {
      *
      * FinishAccess() will be called after finishing CPU access of an offscreen
      * pixmap set up by PrepareAccess().  Note that the FinishAccess() will not be
-     * called if PrepareAccess() failed and the pixmap was migrated out.
+     * called if PrepareAccess() failed.
      */
-    void	(*FinishAccess)(PixmapPtr pPix, int index);
+    void	(*FinishAccess)(PixmapPtr pPix);
 
     /**
      * PixmapIsOffscreen() is an optional driver replacement to
@@ -575,25 +576,6 @@ typedef struct _UxaDriver {
      */
     Bool	(*PixmapIsOffscreen)(PixmapPtr pPix);
 
-	/** @name PrepareAccess() and FinishAccess() indices
-	 * @{
-	 */
-	/**
-	 * UXA_PREPARE_DEST is the index for a pixmap that may be drawn to or
-	 * read from.
-	 */ 
-	#define UXA_PREPARE_DEST	0
-	/**
-	 * UXA_PREPARE_SRC is the index for a pixmap that may be read from
-	 */
-	#define UXA_PREPARE_SRC		1
-	/**
-	 * UXA_PREPARE_SRC is the index for a second pixmap that may be read
-	 * from.
-	 */
-	#define UXA_PREPARE_MASK	2
-	/** @} */
-
     /**
      * maxPitchPixels controls the pitch limitation for rendering from
      * the card.
commit c155bb3cb17a3bd3b2e90be52cd1fc90147c4e17
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Aug 4 04:11:13 2008 -0700

    Add batch flush in i830_uxa_prepare_access

diff --git a/src/i830_exa.c b/src/i830_exa.c
index 72a1e8d..7609239 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -179,7 +179,6 @@ I830EXAPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg)
     I830Ptr pI830 = I830PTR(pScrn);
     unsigned long pitch;
 
-    I830FALLBACK("solid");
     if (!EXA_PM_IS_SOLID(&pPixmap->drawable, planemask))
 	I830FALLBACK("planemask is not solid");
 
@@ -266,7 +265,6 @@ I830EXAPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
     ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
 
-    I830FALLBACK("copy");
     if (!EXA_PM_IS_SOLID(&pSrcPixmap->drawable, planemask))
 	I830FALLBACK("planemask is not solid");
 
@@ -560,10 +558,10 @@ i830_uxa_prepare_access (PixmapPtr pixmap, int index)
     dri_bo *bo = i830_uxa_get_pixmap_bo (pixmap);
 
     if (bo) {
+	intel_batch_flush(xf86Screens[pixmap->drawable.pScreen->myNum]);
 	if (dri_bo_map (bo, index == UXA_PREPARE_DEST) != 0)
 	    return FALSE;
-	assert (pixmap->devPrivate.ptr == bo->virtual);
-	pixmap->devPrivate.ptr = bo->virtual;
+        pixmap->devPrivate.ptr = bo->virtual;
     }
     return TRUE;
 }
@@ -597,9 +595,9 @@ i830_uxa_finish_access (PixmapPtr pixmap, int index)
 }
 
 static Bool
-i830_uxa_pixmap_is_offscreen(PixmapPtr pPixmap)
+i830_uxa_pixmap_is_offscreen(PixmapPtr pixmap)
 {
-    return i830_uxa_get_pixmap_bo (pPixmap) != NULL;
+    return i830_uxa_get_pixmap_bo (pixmap) != NULL;
 }
 
 static PixmapPtr
@@ -667,9 +665,6 @@ void i830_uxa_create_screen_resources(ScreenPtr pScreen)
 
     if (bo != NULL) {
 	PixmapPtr   pixmap = pScreen->GetScreenPixmap(pScreen);
-	dri_bo_map (bo, i830->front_buffer->alignment);
-	pixmap->devPrivate.ptr = bo->virtual;
-	dri_bo_unmap (bo);
 	i830_uxa_set_pixmap_bo (pixmap, bo);
     }
 }
diff --git a/src/i915_render.c b/src/i915_render.c
index 7837635..970c42a 100644
--- a/src/i915_render.c
+++ b/src/i915_render.c
@@ -322,8 +322,6 @@ i915_prepare_composite(int op, PicturePtr pSrcPicture,
     Bool is_affine_src, is_affine_mask;
     Bool is_nearest = FALSE;
 
-    return FALSE;
-
     i830_exa_check_pitch_3d(pSrc);
     if (pMask)
 	i830_exa_check_pitch_3d(pMask);
commit 66706718553cd272eab6f817b5a059df3e0a4347
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Aug 4 04:10:21 2008 -0700

    Add throttling

diff --git a/src/i830_driver.c b/src/i830_driver.c
index a810f11..bef3bb8 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2531,6 +2531,10 @@ I830BlockHandler(int i,
 	* fashion.
 	*/
        intel_batch_flush(pScrn);
+#ifdef XF86DRI
+       if (pI830->memory_manager)
+	 drmCommandNone(pI830->drmSubFD, DRM_I915_GEM_THROTTLE);
+#endif
 
        pI830->need_mi_flush = FALSE;
 #ifdef XF86DRI
commit 12df8f40d2fb41f5446db1b49beeb442da18bee2
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Aug 4 01:43:44 2008 -0700

    Use dri_bo for all object allocations, including pixmaps under uxa

diff --git a/src/i830.h b/src/i830.h
index fe25919..dbcf3c0 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -80,15 +80,22 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #endif
 #include "dri_bufmgr.h"
 #include "intel_bufmgr.h"
+#include "i915_drm.h"
 
 #ifdef I830_USE_EXA
 #include "exa.h"
-#include "uxa.h"
 Bool I830EXAInit(ScreenPtr pScreen);
-Bool i830_uxa_init(ScreenPtr pScreen);
 unsigned long long I830TexOffsetStart(PixmapPtr pPix);
 #endif
 
+#ifdef I830_USE_UXA
+#include "uxa.h"
+Bool i830_uxa_init(ScreenPtr pScreen);
+dri_bo *i830_uxa_get_pixmap_bo (PixmapPtr pixmap);
+void i830_uxa_create_screen_resources(ScreenPtr pScreen);
+void i830_uxa_block_handler (ScreenPtr pScreen);
+#endif
+
 #ifdef I830_USE_XAA
 Bool I830XAAInit(ScreenPtr pScreen);
 #endif
@@ -194,7 +201,7 @@ struct _i830_memory {
     i830_memory *prev;
     /** @} */
 
-    uint32_t gem_handle;
+    dri_bo *bo;
     uint32_t alignment;
     uint32_t gem_name;
     Bool lifetime_fixed_offset;
@@ -530,6 +537,7 @@ typedef struct _I830Rec {
 #endif
 #ifdef I830_USE_UXA
    uxa_driver_t *uxa_driver;
+   Bool need_flush;
 #endif
 #if defined(I830_USE_EXA) || defined(I830_USE_UXA)
    PixmapPtr pSrcPixmap;
@@ -818,6 +826,7 @@ Bool i830_allocate_2d_memory(ScrnInfoPtr pScrn);
 Bool i830_allocate_texture_memory(ScrnInfoPtr pScrn);
 Bool i830_allocate_pwrctx(ScrnInfoPtr pScrn);
 Bool i830_allocate_3d_memory(ScrnInfoPtr pScrn);
+void i830_init_bufmgr(ScrnInfoPtr pScrn);
 #ifdef INTEL_XVMC
 Bool i830_allocate_xvmc_buffer(ScrnInfoPtr pScrn, const char *name,
                                i830_memory **buffer, unsigned long size, int flags);
diff --git a/src/i830_accel.c b/src/i830_accel.c
index 0ef565b..a301818 100644
--- a/src/i830_accel.c
+++ b/src/i830_accel.c
@@ -67,7 +67,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 unsigned long
 intel_get_pixmap_offset(PixmapPtr pPix)
 {
-#ifdef I830_USE_EXA
+#if defined(I830_USE_EXA) || defined(I830_USE_UXA)
     ScreenPtr pScreen = pPix->drawable.pScreen;
     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
diff --git a/src/i830_batchbuffer.h b/src/i830_batchbuffer.h
index c9b8421..4c1198d 100644
--- a/src/i830_batchbuffer.h
+++ b/src/i830_batchbuffer.h
@@ -74,12 +74,24 @@ intel_batch_emit_reloc (I830Ptr  pI830,
 }
 
 static inline void
-intel_batch_emit_reloc_pixmap(I830Ptr pI830, PixmapPtr pPixmap, uint32_t delta)
+intel_batch_emit_reloc_pixmap(I830Ptr pI830, PixmapPtr pPixmap,
+			      uint32_t read_domains, uint32_t write_domain,
+			      uint32_t delta)
 {
+#if I830_USE_UXA
+    dri_bo *bo = i830_uxa_get_pixmap_bo(pPixmap);
+#endif
+    uint32_t offset;
     assert(pI830->batch_ptr != NULL);
     assert(intel_batch_space(pI830) >= 4);
-    *(uint32_t *)(pI830->batch_ptr + pI830->batch_used) =
-	intel_get_pixmap_offset(pPixmap) + delta;
+#if I830_USE_UXA
+    if (bo) {
+	intel_batch_emit_reloc(pI830, bo, read_domains, write_domain, delta);
+	return;
+    }
+#endif
+    offset = intel_get_pixmap_offset(pPixmap);
+    *(uint32_t *)(pI830->batch_ptr + pI830->batch_used) = offset + delta;
     pI830->batch_used += 4;
 }
 
@@ -88,8 +100,8 @@ intel_batch_emit_reloc_pixmap(I830Ptr pI830, PixmapPtr pPixmap, uint32_t delta)
 #define OUT_RELOC(bo, read_domains, write_domains, delta) \
 	intel_batch_emit_reloc (pI830, bo, read_domains, write_domains, delta)
 
-#define OUT_RELOC_PIXMAP(pPixmap, delta)	\
-	intel_batch_emit_reloc_pixmap(pI830, pPixmap, delta)
+#define OUT_RELOC_PIXMAP(pPixmap, reads, write, delta)	\
+	intel_batch_emit_reloc_pixmap(pI830, pPixmap, reads, write, delta)
 
 union intfloat {
 	float f;
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 0e5d81d..d40ada5 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -1514,23 +1514,18 @@ I830DRIClipNotify(ScreenPtr pScreen, WindowPtr *ppWin, int num)
 static int
 i830_name_buffer (ScrnInfoPtr pScrn, i830_memory *mem)
 {
-    if (mem && mem->gem_handle)
+    if (mem && mem->bo)
     {
-	I830Ptr			pI830 = I830PTR(pScrn);
-	struct drm_gem_flink	flink;
-	int			ret;
-	
 	if (!mem->gem_name)
 	{
-	    flink.handle = mem->gem_handle;
-	    ret = ioctl(pI830->drmSubFD, DRM_IOCTL_GEM_FLINK, &flink);
+	    int ret;
+	    ret = intel_bo_flink(mem->bo, &mem->gem_name);
 	    if (ret != 0)
 	    {
 		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 			   "[drm] failed to name buffer %d\n", -errno);
 		return -1;
 	    }
-	    mem->gem_name = flink.name;
 	}
 	return mem->gem_name;
     }
diff --git a/src/i830_dri.h b/src/i830_dri.h
index b6a8366..83ddd85 100644
--- a/src/i830_dri.h
+++ b/src/i830_dri.h
@@ -59,5 +59,4 @@ typedef struct {
    int dummy;
 } I830DRIContextRec, *I830DRIContextPtr;
 
-
 #endif
diff --git a/src/i830_driver.c b/src/i830_driver.c
index ed974ce..a810f11 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -849,7 +849,7 @@ i830_update_front_offset(ScrnInfoPtr pScrn)
    /* If we are still in ScreenInit, there is no screen pixmap to be updated
     * yet.  We'll fix it up at CreateScreenResources.
     */
-   if (!pI830->starting) {
+   if (!pI830->starting && pI830->accel != ACCEL_UXA) {
       if (!pScreen->ModifyPixmapHeader(pScreen->GetScreenPixmap(pScreen),
 				       -1, -1, -1, -1, -1,
 				       (pointer)(pI830->FbBase +
@@ -876,6 +876,10 @@ i830CreateScreenResources(ScreenPtr pScreen)
 
    i830_update_front_offset(pScrn);
 
+#ifdef I830_USE_UXA
+   if (pI830->accel == ACCEL_UXA)
+      i830_uxa_create_screen_resources(pScreen);
+#endif
    return TRUE;
 }
 
@@ -2534,6 +2538,8 @@ I830BlockHandler(int i,
 #endif
     }
 
+    if (pI830->accel == ACCEL_UXA)
+	i830_uxa_block_handler (pScreen);
     /*
      * Check for FIFO underruns at block time (which amounts to just
      * periodically).  If this happens, it means our DSPARB or some other
@@ -2774,12 +2780,13 @@ i830_fake_fence_wait(void *priv, unsigned int fence)
    return 0;
 }
 
-static void
+void
 i830_init_bufmgr(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830 = I830PTR(pScrn);
 
-   assert(pI830->FbBase != NULL);
+   if (pI830->bufmgr) return;
+
    if (pI830->memory_manager) {
       int batch_size;
 
@@ -2792,6 +2799,7 @@ i830_init_bufmgr(ScrnInfoPtr pScrn)
       pI830->bufmgr = intel_bufmgr_gem_init(pI830->drmSubFD, batch_size);
       intel_bufmgr_gem_enable_reuse(pI830->bufmgr);
    } else {
+      assert(pI830->FbBase != NULL);
       pI830->bufmgr = intel_bufmgr_fake_init(pI830->fake_bufmgr_mem->offset,
 					     pI830->FbBase +
 					     pI830->fake_bufmgr_mem->offset,
@@ -3412,7 +3420,7 @@ I830LeaveVT(int scrnIndex, int flags)
    }
 #endif /* XF86DRI */
 
-   if (pI830->useEXA && IS_I965G(pI830))
+   if ((pI830->accel == ACCEL_EXA || pI830->accel == ACCEL_UXA) && IS_I965G(pI830))
       gen4_render_state_cleanup(pScrn);
 
    if (pI830->AccelInfoRec)
@@ -3465,7 +3473,7 @@ I830EnterVT(int scrnIndex, int flags)
 
    intel_batch_init(pScrn);
 
-   if (pI830->useEXA && IS_I965G(pI830))
+   if ((pI830->accel == ACCEL_EXA || pI830->accel == ACCEL_UXA) && IS_I965G(pI830))
       gen4_render_state_init(pScrn);
 
    if (i830_check_error_state(pScrn)) {
diff --git a/src/i830_exa.c b/src/i830_exa.c
index f00e4f9..72a1e8d 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -179,6 +179,7 @@ I830EXAPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg)
     I830Ptr pI830 = I830PTR(pScrn);
     unsigned long pitch;
 
+    I830FALLBACK("solid");
     if (!EXA_PM_IS_SOLID(&pPixmap->drawable, planemask))
 	I830FALLBACK("planemask is not solid");
 
@@ -238,7 +239,7 @@ I830EXASolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
 	OUT_BATCH(pI830->BR[13] | pitch);
 	OUT_BATCH((y1 << 16) | (x1 & 0xffff));
 	OUT_BATCH((y2 << 16) | (x2 & 0xffff));
-	OUT_RELOC_PIXMAP(pPixmap, 0);
+	OUT_RELOC_PIXMAP(pPixmap, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
 	OUT_BATCH(pI830->BR[16]);
 	ADVANCE_BATCH();
     }
@@ -265,6 +266,7 @@ I830EXAPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
     ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
 
+    I830FALLBACK("copy");
     if (!EXA_PM_IS_SOLID(&pSrcPixmap->drawable, planemask))
 	I830FALLBACK("planemask is not solid");
 
@@ -331,10 +333,10 @@ I830EXACopy(PixmapPtr pDstPixmap, int src_x1, int src_y1, int dst_x1,
 	OUT_BATCH(pI830->BR[13] | dst_pitch);
 	OUT_BATCH((dst_y1 << 16) | (dst_x1 & 0xffff));
 	OUT_BATCH((dst_y2 << 16) | (dst_x2 & 0xffff));
-	OUT_RELOC_PIXMAP(pDstPixmap, 0);
+	OUT_RELOC_PIXMAP(pDstPixmap, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
 	OUT_BATCH((src_y1 << 16) | (src_x1 & 0xffff));
 	OUT_BATCH(src_pitch);
-	OUT_RELOC_PIXMAP(pI830->pSrcPixmap, 0);
+	OUT_RELOC_PIXMAP(pI830->pSrcPixmap, I915_GEM_DOMAIN_RENDER, 0, 0);
 
 	ADVANCE_BATCH();
     }
@@ -538,129 +540,212 @@ I830EXAInit(ScreenPtr pScreen)
     return TRUE;
 }
 
+static DevPrivateKey	uxa_pixmap_key = &uxa_pixmap_key;
+
+static void
+i830_uxa_set_pixmap_bo (PixmapPtr pixmap, dri_bo *bo)
+{
+    dixSetPrivate(&pixmap->devPrivates, uxa_pixmap_key, bo);
+}
+
+dri_bo *
+i830_uxa_get_pixmap_bo (PixmapPtr pixmap)
+{
+    return dixLookupPrivate(&pixmap->devPrivates, uxa_pixmap_key);
+}
+
+static Bool
+i830_uxa_prepare_access (PixmapPtr pixmap, int index)
+{
+    dri_bo *bo = i830_uxa_get_pixmap_bo (pixmap);
+
+    if (bo) {
+	if (dri_bo_map (bo, index == UXA_PREPARE_DEST) != 0)
+	    return FALSE;
+	assert (pixmap->devPrivate.ptr == bo->virtual);
+	pixmap->devPrivate.ptr = bo->virtual;
+    }
+    return TRUE;
+}
+
+void
+i830_uxa_block_handler (ScreenPtr screen)
+{
+    ScrnInfoPtr scrn = xf86Screens[screen->myNum];
+    I830Ptr i830 = I830PTR(scrn);
+
+    if (i830->need_flush) {
+	dri_bo_wait_rendering (i830->front_buffer->bo);
+	i830->need_flush = FALSE;
+    }
+}
+
+static void
+i830_uxa_finish_access (PixmapPtr pixmap, int index)
+{
+    dri_bo *bo = i830_uxa_get_pixmap_bo (pixmap);
+
+    if (bo) {
+	ScreenPtr screen = pixmap->drawable.pScreen;
+	ScrnInfoPtr scrn = xf86Screens[screen->myNum];
+	I830Ptr i830 = I830PTR(scrn);
+	
+	dri_bo_unmap (bo);
+	if (bo == i830->front_buffer->bo)
+	    i830->need_flush = TRUE;
+    }
+}
+
 static Bool
 i830_uxa_pixmap_is_offscreen(PixmapPtr pPixmap)
 {
-    ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
-    I830Ptr pI830 = I830PTR(pScrn);
+    return i830_uxa_get_pixmap_bo (pPixmap) != NULL;
+}
 
-    /* XXX for now, eventually we'll support 'real' off-screen pixmaps */
-    if ((void *)pPixmap->devPrivate.ptr >= (void *)pI830->FbBase &&
-	(void *)pPixmap->devPrivate.ptr <
-	(void *)(pI830->FbBase + pI830->FbMapSize))
+static PixmapPtr
+i830_uxa_create_pixmap (ScreenPtr screen, int w, int h, int depth, unsigned usage)
+{
+    ScrnInfoPtr scrn = xf86Screens[screen->myNum];
+    I830Ptr i830 = I830PTR(scrn);
+    dri_bo *bo;
+    int stride;
+    PixmapPtr pixmap;
+    
+    if (w > 32767 || h > 32767)
+	return NullPixmap;
+
+    pixmap = fbCreatePixmap (screen, 0, 0, depth, usage);
+    
+    if (w && h)
     {
-	return TRUE;
-    } else {
-	return FALSE;
+	stride = ROUND_TO((w * pixmap->drawable.bitsPerPixel + 7) / 8,
+			  i830->accel_pixmap_pitch_alignment);
+    
+	bo = dri_bo_alloc (i830->bufmgr, "pixmap", stride * h, 
+			   i830->accel_pixmap_offset_alignment);
+	if (!bo) {
+	    fbDestroyPixmap (pixmap);
+	    return NullPixmap;
+	}
+	
+	if (dri_bo_map (bo, FALSE) != 0) {
+	    fbDestroyPixmap (pixmap);
+	    dri_bo_unreference (bo);
+	    return NullPixmap;
+	}
+	    
+	screen->ModifyPixmapHeader (pixmap, w, h, 0, 0, stride,
+				    (pointer) bo->virtual);
+    
+	dri_bo_unmap (bo);
+	i830_uxa_set_pixmap_bo (pixmap, bo);
     }
+
+    return pixmap;
 }
 
+static Bool
+i830_uxa_destroy_pixmap (PixmapPtr pixmap)
+{
+    if (pixmap->refcnt == 1) {
+	dri_bo  *bo = i830_uxa_get_pixmap_bo (pixmap);
+    
+	if (bo) {
+	    dri_bo_unmap (bo);
+	    dri_bo_unreference (bo);
+	}
+    }
+    fbDestroyPixmap (pixmap);
+    return TRUE;
+}
+
+void i830_uxa_create_screen_resources(ScreenPtr pScreen)
+{
+    ScrnInfoPtr scrn = xf86Screens[pScreen->myNum];
+    I830Ptr i830 = I830PTR(scrn);
+    dri_bo *bo = i830->front_buffer->bo;
+
+    if (bo != NULL) {
+	PixmapPtr   pixmap = pScreen->GetScreenPixmap(pScreen);
+	dri_bo_map (bo, i830->front_buffer->alignment);
+	pixmap->devPrivate.ptr = bo->virtual;
+	dri_bo_unmap (bo);
+	i830_uxa_set_pixmap_bo (pixmap, bo);
+    }
+}
 
 Bool
 i830_uxa_init (ScreenPtr pScreen)
 {
-    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
-    I830Ptr pI830 = I830PTR(pScrn);
+    ScrnInfoPtr scrn = xf86Screens[pScreen->myNum];
+    I830Ptr i830 = I830PTR(scrn);
 
-    pI830->uxa_driver = uxa_driver_alloc();
-    if (pI830->uxa_driver == NULL) {
-	pI830->accel = ACCEL_NONE;
+    if (!dixRequestPrivate(uxa_pixmap_key, 0))
+	return FALSE;
+    
+    i830->uxa_driver = uxa_driver_alloc();
+    if (i830->uxa_driver == NULL) {
+	i830->accel = ACCEL_NONE;
 	return FALSE;
     }
-    memset(pI830->uxa_driver, 0, sizeof(*pI830->uxa_driver));
+    memset(i830->uxa_driver, 0, sizeof(*i830->uxa_driver));
 
-    pI830->bufferOffset = 0;
-    pI830->uxa_driver->uxa_major = 1;
-    pI830->uxa_driver->uxa_minor = 0;
-
-    /* Limits are described in the BLT engine chapter under Graphics Data Size
-     * Limitations, and the descriptions of SURFACE_STATE, 3DSTATE_BUFFER_INFO,
-     * 3DSTATE_DRAWING_RECTANGLE, 3DSTATE_MAP_INFO, and 3DSTATE_MAP_INFO.
-     *
-     * i845 through i965 limits 2D rendering to 65536 lines and pitch of 32768.
-     *
-     * i965 limits 3D surface to (2*element size)-aligned offset if un-tiled.
-     * i965 limits 3D surface to 4kB-aligned offset if tiled.
-     * i965 limits 3D surfaces to w,h of ?,8192.
-     * i965 limits 3D surface to pitch of 1B - 128kB.
-     * i965 limits 3D surface pitch alignment to 1 or 2 times the element size.
-     * i965 limits 3D surface pitch alignment to 512B if tiled.
-     * i965 limits 3D destination drawing rect to w,h of 8192,8192.
-     *
-     * i915 limits 3D textures to 4B-aligned offset if un-tiled.
-     * i915 limits 3D textures to ~4kB-aligned offset if tiled.
-     * i915 limits 3D textures to width,height of 2048,2048.
-     * i915 limits 3D textures to pitch of 16B - 8kB, in dwords.
-     * i915 limits 3D destination to ~4kB-aligned offset if tiled.
-     * i915 limits 3D destination to pitch of 16B - 8kB, in dwords, if un-tiled.
-     * i915 limits 3D destination to pitch of 512B - 8kB, in tiles, if tiled.
-     * i915 limits 3D destination to POT aligned pitch if tiled.
-     * i915 limits 3D destination drawing rect to w,h of 2048,2048.
-     *
-     * i845 limits 3D textures to 4B-aligned offset if un-tiled.
-     * i845 limits 3D textures to ~4kB-aligned offset if tiled.
-     * i845 limits 3D textures to width,height of 2048,2048.
-     * i845 limits 3D textures to pitch of 4B - 8kB, in dwords.
-     * i845 limits 3D destination to 4B-aligned offset if un-tiled.
-     * i845 limits 3D destination to ~4kB-aligned offset if tiled.
-     * i845 limits 3D destination to pitch of 8B - 8kB, in dwords.
-     * i845 limits 3D destination drawing rect to w,h of 2048,2048.
-     *
-     * For the tiled issues, the only tiled buffer we draw to should be
-     * the front, which will have an appropriate pitch/offset already set up,
-     * so EXA doesn't need to worry.
-     */
-    if (IS_I965G(pI830)) {
-	pI830->uxa_driver->maxX = 8192;
-	pI830->uxa_driver->maxY = 8192;
-    } else {
-	pI830->uxa_driver->maxX = 2048;
-	pI830->uxa_driver->maxY = 2048;
-    }
+    i830->bufferOffset = 0;
+    i830->uxa_driver->uxa_major = 1;
+    i830->uxa_driver->uxa_minor = 0;
+
+    i830->uxa_driver->maxX = i830->accel_max_x;
+    i830->uxa_driver->maxY = i830->accel_max_y;
 
     /* Sync */
-    pI830->uxa_driver->WaitMarker = I830EXASync;
+    i830->uxa_driver->WaitMarker = I830EXASync;
 
     /* Solid fill */
-    pI830->uxa_driver->PrepareSolid = I830EXAPrepareSolid;
-    pI830->uxa_driver->Solid = I830EXASolid;
-    pI830->uxa_driver->DoneSolid = I830EXADoneSolid;
+    i830->uxa_driver->PrepareSolid = I830EXAPrepareSolid;
+    i830->uxa_driver->Solid = I830EXASolid;
+    i830->uxa_driver->DoneSolid = I830EXADoneSolid;
 
     /* Copy */
-    pI830->uxa_driver->PrepareCopy = I830EXAPrepareCopy;
-    pI830->uxa_driver->Copy = I830EXACopy;
-    pI830->uxa_driver->DoneCopy = I830EXADoneCopy;
+    i830->uxa_driver->PrepareCopy = I830EXAPrepareCopy;
+    i830->uxa_driver->Copy = I830EXACopy;
+    i830->uxa_driver->DoneCopy = I830EXADoneCopy;
 
     /* Composite */
-    if (!IS_I9XX(pI830)) {
-    	pI830->uxa_driver->CheckComposite = i830_check_composite;
-    	pI830->uxa_driver->PrepareComposite = i830_prepare_composite;
-    	pI830->uxa_driver->Composite = i830_composite;
-    	pI830->uxa_driver->DoneComposite = i830_done_composite;
-    } else if (IS_I915G(pI830) || IS_I915GM(pI830) ||
-	       IS_I945G(pI830) || IS_I945GM(pI830) || IS_G33CLASS(pI830))
+    if (!IS_I9XX(i830)) {
+    	i830->uxa_driver->CheckComposite = i830_check_composite;
+    	i830->uxa_driver->PrepareComposite = i830_prepare_composite;
+    	i830->uxa_driver->Composite = i830_composite;
+    	i830->uxa_driver->DoneComposite = i830_done_composite;
+    } else if (IS_I915G(i830) || IS_I915GM(i830) ||
+	       IS_I945G(i830) || IS_I945GM(i830) || IS_G33CLASS(i830))
     {
-	pI830->uxa_driver->CheckComposite = i915_check_composite;
-   	pI830->uxa_driver->PrepareComposite = i915_prepare_composite;
-    	pI830->uxa_driver->Composite = i830_composite;
-    	pI830->uxa_driver->DoneComposite = i830_done_composite;
+	i830->uxa_driver->CheckComposite = i915_check_composite;
+   	i830->uxa_driver->PrepareComposite = i915_prepare_composite;
+    	i830->uxa_driver->Composite = i830_composite;
+    	i830->uxa_driver->DoneComposite = i830_done_composite;
     } else {
- 	pI830->uxa_driver->CheckComposite = i965_check_composite;
- 	pI830->uxa_driver->PrepareComposite = i965_prepare_composite;
- 	pI830->uxa_driver->Composite = i965_composite;
- 	pI830->uxa_driver->DoneComposite = i830_done_composite;
+ 	i830->uxa_driver->CheckComposite = i965_check_composite;
+ 	i830->uxa_driver->PrepareComposite = i965_prepare_composite;
+ 	i830->uxa_driver->Composite = i965_composite;
+ 	i830->uxa_driver->DoneComposite = i830_done_composite;
     }
-    pI830->uxa_driver->PixmapIsOffscreen = i830_uxa_pixmap_is_offscreen;
 
-    if(!uxa_driver_init(pScreen, pI830->uxa_driver)) {
-	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+    i830->uxa_driver->PrepareAccess = i830_uxa_prepare_access;
+    i830->uxa_driver->FinishAccess = i830_uxa_finish_access;
+    i830->uxa_driver->PixmapIsOffscreen = i830_uxa_pixmap_is_offscreen;
+
+    if(!uxa_driver_init(pScreen, i830->uxa_driver)) {
+	xf86DrvMsg(scrn->scrnIndex, X_INFO,
 		   "UXA initialization failed\n");
-	xfree(pI830->uxa_driver);
-	pI830->accel = ACCEL_NONE;
+	xfree(i830->uxa_driver);
+	i830->accel = ACCEL_NONE;
 	return FALSE;
     }
 
-    I830SelectBuffer(pScrn, I830_SELECT_FRONT);
+    pScreen->CreatePixmap = i830_uxa_create_pixmap;
+    pScreen->DestroyPixmap = i830_uxa_destroy_pixmap;
+
+    I830SelectBuffer(scrn, I830_SELECT_FRONT);
 
     return TRUE;
 }
diff --git a/src/i830_memory.c b/src/i830_memory.c
index c1748b3..ff5def6 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -166,24 +166,16 @@ i830_bind_memory(ScrnInfoPtr pScrn, i830_memory *mem)
 	return TRUE;
 
 #ifdef XF86DRI
-    if (mem->gem_handle != 0) {
-	I830Ptr pI830 = I830PTR(pScrn);
-	struct drm_i915_gem_pin pin;
-	int ret;
-
-	pin.handle = mem->gem_handle;
-	pin.alignment = mem->alignment;
-
-	ret = ioctl(pI830->drmSubFD, DRM_IOCTL_I915_GEM_PIN, &pin);
-	if (ret != 0) {
-		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-			   "Failed to pin %s: %s\n",
-			   mem->name, strerror(errno));
+    if (mem->bo != NULL) {
+	if (intel_bo_pin (mem->bo, mem->alignment) != 0) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "Failed to pin %s: %s\n",
+		       mem->name, strerror(errno));
 	    return FALSE;
 	}
 
 	mem->bound = TRUE;
-	mem->offset = pin.offset;
+	mem->offset = mem->bo->offset;
 	mem->end = mem->offset + mem->size;
     }
 #endif
@@ -219,15 +211,8 @@ i830_unbind_memory(ScrnInfoPtr pScrn, i830_memory *mem)
 	i830_clear_tiling(pScrn, mem->fence_nr);
 
 #ifdef XF86DRI
-    if (mem->gem_handle != 0) {
-	I830Ptr pI830 = I830PTR(pScrn);
-	struct drm_i915_gem_unpin unpin;
-	int ret;
-
-	unpin.handle = mem->gem_handle;
-	ret = ioctl(pI830->drmSubFD, DRM_IOCTL_I915_GEM_UNPIN, &unpin);
-
-	if (ret == 0) {
+    if (mem->bo != NULL) {
+	if (intel_bo_unpin (mem->bo) == 0) {
 	    mem->bound = FALSE;
 	    /* Give buffer obviously wrong offset/end until it's re-pinned. */
 	    mem->offset = -1;
@@ -257,12 +242,9 @@ i830_free_memory(ScrnInfoPtr pScrn, i830_memory *mem)
     i830_unbind_memory(pScrn, mem);
 
 #ifdef XF86DRI
-    if (mem->gem_handle != 0) {
+    if (mem->bo != NULL) {
 	I830Ptr pI830 = I830PTR(pScrn);
-	struct drm_gem_close close;
-
-	close.handle = mem->gem_handle;
-	ioctl(pI830->drmSubFD, DRM_IOCTL_GEM_CLOSE, &close);
+	dri_bo_unreference (mem->bo);
 	if (pI830->bo_list == mem) {
 	    pI830->bo_list = mem->next;
 	    if (mem->next)
@@ -493,6 +475,7 @@ i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset, unsigned long size)
 		i830_free_memory(pScrn, pI830->memory_manager);
 		pI830->memory_manager = NULL;
 	    }
+	    i830_init_bufmgr(pScrn);
 	} else {
 	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		       "Failed to allocate space for kernel memory manager\n");
@@ -735,8 +718,6 @@ i830_allocate_memory_bo(ScrnInfoPtr pScrn, const char *name,
 {
     I830Ptr pI830 = I830PTR(pScrn);
     i830_memory *mem;
-    int ret;
-    struct drm_i915_gem_create create;
 
     assert((flags & NEED_PHYSICAL_ADDR) == 0);
 
@@ -754,16 +735,13 @@ i830_allocate_memory_bo(ScrnInfoPtr pScrn, const char *name,
 	return NULL;
     }
 
-    memset(&create, 0, sizeof(create));
-    create.size = size;
+    mem->bo = dri_bo_alloc (pI830->bufmgr, name, size, align);
 
-    ret = ioctl(pI830->drmSubFD, DRM_IOCTL_I915_GEM_CREATE, &create);
-    if (ret) {
+    if (!mem->bo) {
 	xfree(mem->name);
 	xfree(mem);
 	return NULL;
     }
-    mem->gem_handle = create.handle;
 
     /* Give buffer obviously wrong offset/end until it's pinned. */
     mem->offset = -1;
@@ -777,10 +755,7 @@ i830_allocate_memory_bo(ScrnInfoPtr pScrn, const char *name,
     /* Bind it if we currently control the VT */
     if (pScrn->vtSema) {
 	if (!i830_bind_memory(pScrn, mem)) {
-	    struct drm_gem_close close;
-
-	    close.handle = mem->gem_handle;
-	    ioctl(pI830->drmSubFD, DRM_IOCTL_GEM_CLOSE, &close);
+	    dri_bo_unreference (mem->bo);
 	    xfree(mem->name);
 	    xfree(mem);
 	    return NULL;
@@ -908,19 +883,17 @@ i830_allocate_memory_tiled(ScrnInfoPtr pScrn, const char *name,
     mem->fence_nr = -1;
 
 #ifdef XF86DRI
-    if (mem->gem_handle != 0) {
-	struct drm_i915_gem_set_tiling set_tiling;
-	int ret;
+    if (mem->bo != 0) {
+	uint32_t    tiling_mode = I915_TILING_NONE;
+	int	    ret;
 
-	set_tiling.handle = mem->gem_handle;
 	if (tile_format == TILE_XMAJOR)
-	    set_tiling.tiling_mode = I915_TILING_X;
+	    tiling_mode = I915_TILING_X;
 	else
-	    set_tiling.tiling_mode = I915_TILING_Y;
+	    tiling_mode = I915_TILING_Y;
 
-	ret = ioctl(pI830->drmSubFD, DRM_IOCTL_I915_GEM_SET_TILING,
-		    &set_tiling);
-	if (ret != 0 || set_tiling.tiling_mode == I915_TILING_NONE) {
+	ret = intel_bo_set_tiling (mem->bo, &tiling_mode);
+	if (ret != 0 || tiling_mode == I915_TILING_NONE) {
 		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 			   "Failed to set tiling on %s: %s\n",
 			   mem->name,
diff --git a/src/i830_render.c b/src/i830_render.c
index d5cab3f..4b42ea3 100644
--- a/src/i830_render.c
+++ b/src/i830_render.c
@@ -313,7 +313,7 @@ i830_texture_setup(PicturePtr pPict, PixmapPtr pPix, int unit)
 
 	BEGIN_BATCH(10);
 	OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | LOAD_TEXTURE_MAP(unit) | 4);
-	OUT_RELOC_PIXMAP(pPix, TM0S0_USE_FENCE);
+	OUT_RELOC_PIXMAP(pPix, I915_GEM_DOMAIN_SAMPLER, 0, TM0S0_USE_FENCE);
 	OUT_BATCH(((pPix->drawable.height - 1) << TM0S1_HEIGHT_SHIFT) |
 		  ((pPix->drawable.width - 1) << TM0S1_WIDTH_SHIFT) | format);
 	OUT_BATCH((pitch/4 - 1) << TM0S2_PITCH_SHIFT | TM0S2_MAP_2D);
@@ -444,7 +444,7 @@ i830_prepare_composite(int op, PicturePtr pSrcPicture,
 	OUT_BATCH(_3DSTATE_BUF_INFO_CMD);
 	OUT_BATCH(BUF_3D_ID_COLOR_BACK| BUF_3D_USE_FENCE |
 		  BUF_3D_PITCH(dst_pitch));
-	OUT_RELOC_PIXMAP(pDst, 0);
+	OUT_RELOC_PIXMAP(pDst, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
 	OUT_BATCH(MI_NOOP);
 
 	OUT_BATCH(_3DSTATE_DST_BUF_VARS_CMD);
diff --git a/src/i915_render.c b/src/i915_render.c
index 54197bf..7837635 100644
--- a/src/i915_render.c
+++ b/src/i915_render.c
@@ -322,6 +322,8 @@ i915_prepare_composite(int op, PicturePtr pSrcPicture,
     Bool is_affine_src, is_affine_mask;
     Bool is_nearest = FALSE;
 
+    return FALSE;
+
     i830_exa_check_pitch_3d(pSrc);
     if (pMask)
 	i830_exa_check_pitch_3d(pMask);
@@ -360,7 +362,7 @@ i915_prepare_composite(int op, PicturePtr pSrcPicture,
 	BEGIN_BATCH(10);
 	OUT_BATCH(_3DSTATE_MAP_STATE | 3);
 	OUT_BATCH(0x00000001); /* map 0 */
-	OUT_RELOC_PIXMAP(pSrc, 0);
+	OUT_RELOC_PIXMAP(pSrc, I915_GEM_DOMAIN_SAMPLER, 0, 0);
 	OUT_BATCH(pI830->mapstate[1]);
 	OUT_BATCH(pI830->mapstate[2]);
 
@@ -374,10 +376,10 @@ i915_prepare_composite(int op, PicturePtr pSrcPicture,
 	BEGIN_BATCH(16);
 	OUT_BATCH(_3DSTATE_MAP_STATE | 6);
 	OUT_BATCH(0x00000003); /* map 0,1 */
-	OUT_RELOC_PIXMAP(pSrc, 0);
+	OUT_RELOC_PIXMAP(pSrc, I915_GEM_DOMAIN_SAMPLER, 0, 0);
 	OUT_BATCH(pI830->mapstate[1]);
 	OUT_BATCH(pI830->mapstate[2]);
-	OUT_RELOC_PIXMAP(pMask, 0);
+	OUT_RELOC_PIXMAP(pMask, I915_GEM_DOMAIN_SAMPLER, 0, 0);
 	OUT_BATCH(pI830->mapstate[4]);
 	OUT_BATCH(pI830->mapstate[5]);
 
@@ -398,7 +400,7 @@ i915_prepare_composite(int op, PicturePtr pSrcPicture,
 	OUT_BATCH(_3DSTATE_BUF_INFO_CMD);
 	OUT_BATCH(BUF_3D_ID_COLOR_BACK| BUF_3D_USE_FENCE|
 		  BUF_3D_PITCH(dst_pitch));
-	OUT_RELOC_PIXMAP(pDst, 0);
+	OUT_RELOC_PIXMAP(pDst, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
 
 	OUT_BATCH(_3DSTATE_DST_BUF_VARS_CMD);
 	OUT_BATCH(dst_format);
diff --git a/src/i915_video.c b/src/i915_video.c
index e2954a7..7761a45 100644
--- a/src/i915_video.c
+++ b/src/i915_video.c
@@ -130,7 +130,7 @@ I915DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id,
    OUT_BATCH(_3DSTATE_BUF_INFO_CMD);
    OUT_BATCH(BUF_3D_ID_COLOR_BACK | BUF_3D_USE_FENCE |
 	     BUF_3D_PITCH(intel_get_pixmap_pitch(pPixmap)));
-   OUT_RELOC_PIXMAP(pPixmap, 0);
+   OUT_RELOC_PIXMAP(pPixmap, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
    ADVANCE_BATCH();
 
    if (!planar) {
commit 4cc20b7f6e25f4be4598f8edbe0077117126b4ee
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Aug 4 01:42:48 2008 -0700

    Don't call sync on prepare_access -- just let the driver deal with it.
    
    Let the driver do whatever sync is necessary from the prepare_access hook
    rather than forcing a full sync.

diff --git a/uxa/uxa.c b/uxa/uxa.c
index 9745f8b..7201e7c 100644
--- a/uxa/uxa.c
+++ b/uxa/uxa.c
@@ -151,9 +151,6 @@ uxa_prepare_access(DrawablePtr pDrawable, int index)
     if (!offscreen)
 	return;
 
-    /* XXX should be pPixmap eventually */
-    uxa_wait_sync (pScreen);
-
     if (uxa_screen->info->PrepareAccess)
 	(*uxa_screen->info->PrepareAccess) (pPixmap, index);
 }
commit b0b0998b5d52d105eb1e631f688aa8f1bd55ef39
Author: Keith Packard <keithp at keithp.com>
Date:   Wed Jul 30 16:15:37 2008 -0700

    Make EXA functions work for UXA as well
    
    EXA and UXA have the same acceleration interface, but UXA doesn't provide
    pixmap stride information as it doesn't manage pixmaps. Move all of that
    into the driver structure so that the acceleration functions needn't
    reference the EXA structure.

diff --git a/src/i830.h b/src/i830.h
index 2fb8efa..fe25919 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -527,9 +527,17 @@ typedef struct _I830Rec {
 
 #ifdef I830_USE_EXA
    ExaDriverPtr	EXADriverPtr;
+#endif
+#ifdef I830_USE_UXA
    uxa_driver_t *uxa_driver;
+#endif
+#if defined(I830_USE_EXA) || defined(I830_USE_UXA)
    PixmapPtr pSrcPixmap;
 #endif
+   int accel_pixmap_pitch_alignment;
+   int accel_pixmap_offset_alignment;
+   int accel_max_x;
+   int accel_max_y;
 
    I830WriteIndexedByteFunc writeControl;
    I830ReadIndexedByteFunc readControl;
diff --git a/src/i830_accel.c b/src/i830_accel.c
index 579de31..0ef565b 100644
--- a/src/i830_accel.c
+++ b/src/i830_accel.c
@@ -282,6 +282,54 @@ I830AccelInit(ScreenPtr pScreen)
     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
 
+    /* Limits are described in the BLT engine chapter under Graphics Data Size
+     * Limitations, and the descriptions of SURFACE_STATE, 3DSTATE_BUFFER_INFO,
+     * 3DSTATE_DRAWING_RECTANGLE, 3DSTATE_MAP_INFO, and 3DSTATE_MAP_INFO.
+     *
+     * i845 through i965 limits 2D rendering to 65536 lines and pitch of 32768.
+     *
+     * i965 limits 3D surface to (2*element size)-aligned offset if un-tiled.
+     * i965 limits 3D surface to 4kB-aligned offset if tiled.
+     * i965 limits 3D surfaces to w,h of ?,8192.
+     * i965 limits 3D surface to pitch of 1B - 128kB.
+     * i965 limits 3D surface pitch alignment to 1 or 2 times the element size.
+     * i965 limits 3D surface pitch alignment to 512B if tiled.
+     * i965 limits 3D destination drawing rect to w,h of 8192,8192.
+     *
+     * i915 limits 3D textures to 4B-aligned offset if un-tiled.
+     * i915 limits 3D textures to ~4kB-aligned offset if tiled.
+     * i915 limits 3D textures to width,height of 2048,2048.
+     * i915 limits 3D textures to pitch of 16B - 8kB, in dwords.
+     * i915 limits 3D destination to ~4kB-aligned offset if tiled.
+     * i915 limits 3D destination to pitch of 16B - 8kB, in dwords, if un-tiled.
+     * i915 limits 3D destination to pitch of 512B - 8kB, in tiles, if tiled.
+     * i915 limits 3D destination to POT aligned pitch if tiled.
+     * i915 limits 3D destination drawing rect to w,h of 2048,2048.
+     *
+     * i845 limits 3D textures to 4B-aligned offset if un-tiled.
+     * i845 limits 3D textures to ~4kB-aligned offset if tiled.
+     * i845 limits 3D textures to width,height of 2048,2048.
+     * i845 limits 3D textures to pitch of 4B - 8kB, in dwords.
+     * i845 limits 3D destination to 4B-aligned offset if un-tiled.
+     * i845 limits 3D destination to ~4kB-aligned offset if tiled.
+     * i845 limits 3D destination to pitch of 8B - 8kB, in dwords.
+     * i845 limits 3D destination drawing rect to w,h of 2048,2048.
+     *
+     * For the tiled issues, the only tiled buffer we draw to should be
+     * the front, which will have an appropriate pitch/offset already set up,
+     * so EXA doesn't need to worry.
+     */
+    if (IS_I965G(pI830)) {
+	pI830->accel_pixmap_offset_alignment = 4 * 2;
+	pI830->accel_pixmap_pitch_alignment = 16;
+	pI830->accel_max_x = 8192;
+	pI830->accel_max_y = 8192;
+    } else {
+	pI830->accel_pixmap_offset_alignment = 4;
+	pI830->accel_pixmap_pitch_alignment = 16;
+	pI830->accel_max_x = 2048;
+	pI830->accel_max_y = 2048;
+    }
     switch (pI830->accel) {
 #ifdef I830_USE_UXA
     case ACCEL_UXA:
diff --git a/src/i830_exa.c b/src/i830_exa.c
index a6705f4..f00e4f9 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -121,6 +121,21 @@ i830_pixmap_tiled(PixmapPtr pPixmap)
     return FALSE;
 }
 
+static unsigned long
+i830_pixmap_pitch(PixmapPtr pixmap)
+{
+    return pixmap->devKind;
+}
+
+static int
+i830_pixmap_pitch_is_aligned(PixmapPtr pixmap)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pixmap->drawable.pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    return i830_pixmap_pitch(pixmap) % pI830->accel_pixmap_pitch_alignment == 0;
+}
+
 static Bool
 i830_exa_pixmap_is_offscreen(PixmapPtr pPixmap)
 {
@@ -172,9 +187,9 @@ I830EXAPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg)
 
     i830_exa_check_pitch_2d(pPixmap);
 
-    pitch = exaGetPixmapPitch(pPixmap);
+    pitch = i830_pixmap_pitch(pPixmap);
 
-    if (pitch % pI830->EXADriverPtr->pixmapPitchAlign != 0)
+    if (!i830_pixmap_pitch_is_aligned(pPixmap))
 	I830FALLBACK("pixmap pitch not aligned");
 
     pI830->BR[13] = (I830PatternROP[alu] & 0xff) << 16 ;
@@ -202,7 +217,7 @@ I830EXASolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
     unsigned long pitch;
     uint32_t cmd;
 
-    pitch = exaGetPixmapPitch(pPixmap);
+    pitch = i830_pixmap_pitch(pPixmap);
 
     {
 	BEGIN_BATCH(6);
@@ -286,8 +301,8 @@ I830EXACopy(PixmapPtr pDstPixmap, int src_x1, int src_y1, int dst_x1,
     dst_x2 = dst_x1 + w;
     dst_y2 = dst_y1 + h;
 
-    dst_pitch = exaGetPixmapPitch(pDstPixmap);
-    src_pitch = exaGetPixmapPitch(pI830->pSrcPixmap);
+    dst_pitch = i830_pixmap_pitch(pDstPixmap);
+    src_pitch = i830_pixmap_pitch(pI830->pSrcPixmap);
 
     {
 	BEGIN_BATCH(8);
@@ -466,55 +481,10 @@ I830EXAInit(ScreenPtr pScreen)
 	    pI830->EXADriverPtr->offScreenBase,
 	    pI830->EXADriverPtr->memorySize);
 
-
-    /* Limits are described in the BLT engine chapter under Graphics Data Size
-     * Limitations, and the descriptions of SURFACE_STATE, 3DSTATE_BUFFER_INFO,
-     * 3DSTATE_DRAWING_RECTANGLE, 3DSTATE_MAP_INFO, and 3DSTATE_MAP_INFO.
-     *
-     * i845 through i965 limits 2D rendering to 65536 lines and pitch of 32768.
-     *
-     * i965 limits 3D surface to (2*element size)-aligned offset if un-tiled.
-     * i965 limits 3D surface to 4kB-aligned offset if tiled.
-     * i965 limits 3D surfaces to w,h of ?,8192.
-     * i965 limits 3D surface to pitch of 1B - 128kB.
-     * i965 limits 3D surface pitch alignment to 1 or 2 times the element size.
-     * i965 limits 3D surface pitch alignment to 512B if tiled.
-     * i965 limits 3D destination drawing rect to w,h of 8192,8192.
-     *
-     * i915 limits 3D textures to 4B-aligned offset if un-tiled.
-     * i915 limits 3D textures to ~4kB-aligned offset if tiled.
-     * i915 limits 3D textures to width,height of 2048,2048.
-     * i915 limits 3D textures to pitch of 16B - 8kB, in dwords.
-     * i915 limits 3D destination to ~4kB-aligned offset if tiled.
-     * i915 limits 3D destination to pitch of 16B - 8kB, in dwords, if un-tiled.
-     * i915 limits 3D destination to pitch of 512B - 8kB, in tiles, if tiled.
-     * i915 limits 3D destination to POT aligned pitch if tiled.
-     * i915 limits 3D destination drawing rect to w,h of 2048,2048.
-     *
-     * i845 limits 3D textures to 4B-aligned offset if un-tiled.
-     * i845 limits 3D textures to ~4kB-aligned offset if tiled.
-     * i845 limits 3D textures to width,height of 2048,2048.
-     * i845 limits 3D textures to pitch of 4B - 8kB, in dwords.
-     * i845 limits 3D destination to 4B-aligned offset if un-tiled.
-     * i845 limits 3D destination to ~4kB-aligned offset if tiled.
-     * i845 limits 3D destination to pitch of 8B - 8kB, in dwords.
-     * i845 limits 3D destination drawing rect to w,h of 2048,2048.
-     *
-     * For the tiled issues, the only tiled buffer we draw to should be
-     * the front, which will have an appropriate pitch/offset already set up,
-     * so EXA doesn't need to worry.
-     */
-    if (IS_I965G(pI830)) {
-	pI830->EXADriverPtr->pixmapOffsetAlign = 4 * 2;
-	pI830->EXADriverPtr->pixmapPitchAlign = 16;
-	pI830->EXADriverPtr->maxX = 8192;
-	pI830->EXADriverPtr->maxY = 8192;
-    } else {
-	pI830->EXADriverPtr->pixmapOffsetAlign = 4;
-	pI830->EXADriverPtr->pixmapPitchAlign = 16;
-	pI830->EXADriverPtr->maxX = 2048;
-	pI830->EXADriverPtr->maxY = 2048;
-    }
+    pI830->EXADriverPtr->pixmapOffsetAlign = pI830->accel_pixmap_offset_alignment;
+    pI830->EXADriverPtr->pixmapPitchAlign = pI830->accel_pixmap_pitch_alignment;
+    pI830->EXADriverPtr->maxX = pI830->accel_max_x;
+    pI830->EXADriverPtr->maxY = pI830->accel_max_y;
 
     /* Sync */
     pI830->EXADriverPtr->WaitMarker = I830EXASync;
commit 59774e9aca2d743e82d616bb644d20ff6d60d492
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Jul 29 22:57:09 2008 -0700

    Add UXA - the unified memory acceleration architecture.
    
    This eliminates the cost of EXA migration management while providing full
    pixmap allocation control to the driver. The goal is to make something
    useful for UMA drivers.

diff --git a/Makefile.am b/Makefile.am
index b2398a8..5db07de 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -19,7 +19,7 @@
 #  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 AUTOMAKE_OPTIONS = foreign
-SUBDIRS = src man
+SUBDIRS = uxa src man
 
 EXTRA_DIST = README
 DISTCLEANFILES = doltcompile
diff --git a/configure.ac b/configure.ac
index db16c35..b24a154 100644
--- a/configure.ac
+++ b/configure.ac
@@ -251,6 +251,7 @@ XORG_CHECK_LINUXDOC
 
 AC_OUTPUT([
 	Makefile
+	uxa/Makefile
 	src/Makefile
 	src/xvmc/Makefile
 	src/bios_reader/Makefile
diff --git a/src/Makefile.am b/src/Makefile.am
index 2932233..dd92c8d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -31,13 +31,13 @@ SUBDIRS = xvmc bios_reader ch7017 ch7xxx ivch sil164 tfp410 $(REGDUMPER)
 # TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
 
 AM_CFLAGS = @WARN_CFLAGS@ @XORG_CFLAGS@ @DRM_CFLAGS@ @DRI_CFLAGS@ \
-	@PCIACCESS_CFLAGS@ \
-	@XMODES_CFLAGS@ -DI830_XV -DI830_USE_XAA -DI830_USE_EXA
+	@PCIACCESS_CFLAGS@ -I../uxa \
+	@XMODES_CFLAGS@ -DI830_XV -DI830_USE_XAA -DI830_USE_EXA	-DI830_USE_UXA
 
 intel_drv_la_LTLIBRARIES = intel_drv.la
 intel_drv_la_LDFLAGS = -module -avoid-version
 intel_drv_ladir = @moduledir@/drivers
-intel_drv_la_LIBADD = -lm
+intel_drv_la_LIBADD = -lm ../uxa/libuxa.la
 if XSERVER_LIBPCIACCESS
 intel_drv_la_LIBADD += @PCIACCESS_LIBS@
 endif
diff --git a/src/i830.h b/src/i830.h
index a8ab8c6..2fb8efa 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -83,7 +83,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #ifdef I830_USE_EXA
 #include "exa.h"
+#include "uxa.h"
 Bool I830EXAInit(ScreenPtr pScreen);
+Bool i830_uxa_init(ScreenPtr pScreen);
 unsigned long long I830TexOffsetStart(PixmapPtr pPix);
 #endif
 
@@ -355,6 +357,14 @@ enum backlight_control {
     BCM_KERNEL,
 };
 
+typedef enum accel_method {
+    ACCEL_UNINIT = 0,
+    ACCEL_NONE,
+    ACCEL_XAA,
+    ACCEL_EXA,
+    ACCEL_UXA
+} accel_method_t;
+
 typedef struct _I830Rec {
    unsigned char *MMIOBase;
    unsigned char *GTTBase;
@@ -496,8 +506,7 @@ typedef struct _I830Rec {
 
    Bool fence_used[FENCE_NEW_NR];
 
-   Bool useEXA;
-   Bool noAccel;
+   accel_method_t accel;
    Bool SWCursor;
 #ifdef I830_USE_XAA
    XAAInfoRecPtr AccelInfoRec;
@@ -518,6 +527,7 @@ typedef struct _I830Rec {
 
 #ifdef I830_USE_EXA
    ExaDriverPtr	EXADriverPtr;
+   uxa_driver_t *uxa_driver;
    PixmapPtr pSrcPixmap;
 #endif
 
@@ -902,7 +912,7 @@ static inline int i830_fb_compression_supported(I830Ptr pI830)
     /* fbc depends on tiled surface. And we don't support tiled
      * front buffer with XAA now.
      */
-    if (!pI830->tiling || (IS_I965G(pI830) && !pI830->useEXA))
+    if (!pI830->tiling || (IS_I965G(pI830) && pI830->accel <= ACCEL_XAA))
 	return FALSE;
     return TRUE;
 }
diff --git a/src/i830_accel.c b/src/i830_accel.c
index c3cd08e..579de31 100644
--- a/src/i830_accel.c
+++ b/src/i830_accel.c
@@ -67,12 +67,12 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 unsigned long
 intel_get_pixmap_offset(PixmapPtr pPix)
 {
+#ifdef I830_USE_EXA
     ScreenPtr pScreen = pPix->drawable.pScreen;
     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
 
-#ifdef I830_USE_EXA
-    if (pI830->useEXA)
+    if (pI830->accel == ACCEL_EXA)
 	return exaGetPixmapOffset(pPix);
 #endif
     return (unsigned long)pPix->devPrivate.ptr - (unsigned long)pI830->FbBase;
@@ -81,17 +81,15 @@ intel_get_pixmap_offset(PixmapPtr pPix)
 unsigned long
 intel_get_pixmap_pitch(PixmapPtr pPix)
 {
+#ifdef I830_USE_EXA
     ScreenPtr pScreen = pPix->drawable.pScreen;
     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
 
-#ifdef I830_USE_EXA
-    if (pI830->useEXA)
+    if (pI830->accel == ACCEL_EXA)
 	return exaGetPixmapPitch(pPix);
 #endif
-#ifdef I830_USE_XAA
     return (unsigned long)pPix->devKind;
-#endif
 }
 
 int
@@ -151,6 +149,9 @@ I830WaitLpRing(ScrnInfoPtr pScrn, int n, int timeout_millis)
 #ifdef I830_USE_EXA
 	 pI830->EXADriverPtr = NULL;
 #endif
+#ifdef I830_USE_UXA
+	pI830->uxa_driver = NULL;
+#endif
 	 FatalError("lockup\n");
       }
 
@@ -176,7 +177,7 @@ I830Sync(ScrnInfoPtr pScrn)
    if (I810_DEBUG & (DEBUG_VERBOSE_ACCEL | DEBUG_VERBOSE_SYNC))
       ErrorF("I830Sync\n");
 
-   if (pI830->noAccel)
+   if (pI830->accel == ACCEL_NONE)
        return;
 
 #ifdef XF86DRI
@@ -278,15 +279,25 @@ I830SelectBuffer(ScrnInfoPtr pScrn, int buffer)
 Bool
 I830AccelInit(ScreenPtr pScreen)
 {
-#ifdef I830_USE_EXA
     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
 
-    if (pI830->useEXA)
+    switch (pI830->accel) {
+#ifdef I830_USE_UXA
+    case ACCEL_UXA:
+	return i830_uxa_init(pScreen);
+#endif
+#ifdef I830_USE_EXA
+    case ACCEL_EXA:
 	return I830EXAInit(pScreen);
 #endif
 #ifdef I830_USE_XAA
-    return I830XAAInit(pScreen);
+    case ACCEL_XAA:
+	return I830XAAInit(pScreen);
 #endif
+    case ACCEL_UNINIT:
+    case ACCEL_NONE:
+	break;
+    }
     return FALSE;
 }
diff --git a/src/i830_debug.c b/src/i830_debug.c
index 1671e25..f1205cc 100644
--- a/src/i830_debug.c
+++ b/src/i830_debug.c
@@ -1314,6 +1314,8 @@ i830_valid_command (uint32_t cmd)
 	if (!mi_cmds[opcode])
 	    return -1;
 	break;
+    case 1:
+	return -1;
     case 2:			    /* 2D */
 	count = (cmd & 0x1f) + 2;
 	opcode = (cmd >> 22) & 0x7f;
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 4678372..0e5d81d 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -589,7 +589,7 @@ I830DRIScreenInit(ScreenPtr pScreen)
 
 #if DRIINFO_MAJOR_VERSION > 5 || \
     (DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 3)
-      if (pI830->useEXA)
+      if (pI830->accel == ACCEL_EXA)
 	 pDRIInfo->texOffsetStart = I830TexOffsetStart;
 #endif
 
diff --git a/src/i830_driver.c b/src/i830_driver.c
index b6fac9f..ed974ce 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -290,9 +290,7 @@ static PciChipsets I830PciChipsets[] = {
  */
 
 typedef enum {
-#if defined(I830_USE_XAA) && defined(I830_USE_EXA)
    OPTION_ACCELMETHOD,
-#endif
    OPTION_NOACCEL,
    OPTION_SW_CURSOR,
    OPTION_CACHE_LINES,
@@ -318,9 +316,7 @@ typedef enum {
 } I830Opts;
 
 static OptionInfoRec I830Options[] = {
-#if defined(I830_USE_XAA) && defined(I830_USE_EXA)
    {OPTION_ACCELMETHOD,	"AccelMethod",	OPTV_ANYSTR,	{0},	FALSE},
-#endif
    {OPTION_NOACCEL,	"NoAccel",	OPTV_BOOLEAN,	{0},	FALSE},
    {OPTION_SW_CURSOR,	"SWcursor",	OPTV_BOOLEAN,	{0},	FALSE},
    {OPTION_CACHE_LINES,	"CacheLines",	OPTV_INTEGER,	{0},	FALSE},
@@ -1338,6 +1334,15 @@ i830_detect_chipset(ScrnInfoPtr pScrn)
     return TRUE;
 }
 
+static const char *accel_name[] = 
+{
+   "unspecified",
+   "no",
+   "XAA",
+   "EXA",
+   "UXA",
+};
+
 /**
  * This is called per zaphod head (so usually just once) to do initialization
  * before the Screen is created.
@@ -1554,7 +1559,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags)
 	      num_pipe, num_pipe > 1 ? "s" : "");
 
    if (xf86ReturnOptValBool(pI830->Options, OPTION_NOACCEL, FALSE)) {
-      pI830->noAccel = TRUE;
+      pI830->accel = ACCEL_NONE;
    }
 
    /*
@@ -1568,29 +1573,38 @@ I830PreInit(ScrnInfoPtr pScrn, int flags)
     * All this *could* go away if we removed XAA support from this driver,
     * for example. :)
     */
-   if (!pI830->noAccel) {
+   if (pI830->accel == ACCEL_UNINIT) {
+      pI830->accel = ACCEL_NONE;
+#ifdef I830_USE_XAA
+      pI830->accel = ACCEL_XAA;
+#endif
 #ifdef I830_USE_EXA
-       pI830->useEXA = TRUE;
-#else
-       pI830->useEXA = FALSE;
+      pI830->accel = ACCEL_EXA;
+#endif
+#ifdef I830_USE_UXA
+      pI830->accel = ACCEL_UXA;
 #endif
-#if defined(I830_USE_XAA) && defined(I830_USE_EXA)
+#if I830_USE_XAA + I830_USE_EXA + I830_USE_UXA >= 2
        from = X_DEFAULT;
        if ((s = (char *)xf86GetOptValString(pI830->Options,
 					    OPTION_ACCELMETHOD))) {
 	   if (!xf86NameCmp(s, "EXA")) {
 	       from = X_CONFIG;
-	       pI830->useEXA = TRUE;
+	       pI830->accel = ACCEL_EXA;
 	   }
 	   else if (!xf86NameCmp(s, "XAA")) {
 	       from = X_CONFIG;
-	       pI830->useEXA = FALSE;
+	       pI830->accel = ACCEL_XAA;
+	   }
+	   else if (!xf86NameCmp(s, "UXA")) {
+	       from = X_CONFIG;
+	       pI830->accel = ACCEL_UXA;
 	   }
        }
 #endif
-       xf86DrvMsg(pScrn->scrnIndex, from, "Using %s for acceleration\n",
-		  pI830->useEXA ? "EXA" : "XAA");
    }
+   xf86DrvMsg(pScrn->scrnIndex, from, "Using %s acceleration\n",
+	      accel_name[pI830->accel]);
 
    if (xf86ReturnOptValBool(pI830->Options, OPTION_SW_CURSOR, FALSE)) {
       pI830->SWCursor = TRUE;
@@ -1601,7 +1615,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags)
 
 #ifdef XF86DRI
    if (!pI830->directRenderingDisabled) {
-      if (pI830->noAccel || pI830->SWCursor) {
+      if (pI830->accel == ACCEL_NONE || pI830->SWCursor) {
 	 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "DRI is disabled because it "
 		    "needs HW cursor and 2D acceleration.\n");
 	 pI830->directRenderingDisabled = TRUE;
@@ -1774,7 +1788,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags)
 
    if (!IS_I965G(pI830) && pScrn->virtualY > 2048) {
       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot support > 2048 vertical lines. disabling acceleration.\n");
-      pI830->noAccel = TRUE;
+      pI830->accel = ACCEL_NONE;
    }
 
    /* Set display resolution */
@@ -1788,18 +1802,19 @@ I830PreInit(ScrnInfoPtr pScrn, int flags)
 
    xf86LoaderReqSymLists(I810fbSymbols, NULL);
 
+   switch (pI830->accel) {
 #ifdef I830_USE_XAA
-   if (!pI830->noAccel && !pI830->useEXA) {
+   case ACCEL_XAA:
       if (!xf86LoadSubModule(pScrn, "xaa")) {
 	 PreInitCleanup(pScrn);
 	 return FALSE;
       }
       xf86LoaderReqSymLists(I810xaaSymbols, NULL);
-   }
+      break;
 #endif
 
 #ifdef I830_USE_EXA
-   if (!pI830->noAccel && pI830->useEXA) {
+   case ACCEL_EXA: {
       XF86ModReqInfo req;
       int errmaj, errmin;
 
@@ -1817,8 +1832,12 @@ I830PreInit(ScrnInfoPtr pScrn, int flags)
 	 return FALSE;
       }
       xf86LoaderReqSymLists(I830exaSymbols, NULL);
+      break;
    }
 #endif
+   default:
+      break;
+   }
    if (!pI830->SWCursor) {
       if (!xf86LoadSubModule(pScrn, "ramdac")) {
 	 PreInitCleanup(pScrn);
@@ -1878,7 +1897,7 @@ i830_stop_ring(ScrnInfoPtr pScrn, Bool flush)
       pI830->entityPrivate->RingRunning = 0;
 
    /* Flush the ring buffer (if enabled), then disable it. */
-   if (!pI830->noAccel) {
+   if (pI830->accel != ACCEL_NONE) {
       temp = INREG(LP_RING + RING_LEN);
       if (temp & RING_VALID) {
 	 i830_refresh_ring(pScrn);
@@ -1900,7 +1919,7 @@ i830_start_ring(ScrnInfoPtr pScrn)
 
    DPRINTF(PFX, "SetRingRegs\n");
 
-   if (pI830->noAccel)
+   if (pI830->accel == ACCEL_NONE)
       return;
 
    if (!I830IsPrimary(pScrn)) return;
@@ -2441,7 +2460,7 @@ IntelEmitInvarientState(ScrnInfoPtr pScrn)
    I830Ptr pI830 = I830PTR(pScrn);
    uint32_t ctx_addr;
 
-   if (pI830->noAccel)
+   if (pI830->accel == ACCEL_NONE)
       return;
 
 #ifdef XF86DRI
@@ -2496,12 +2515,12 @@ I830BlockHandler(int i,
     pI830->BlockHandler = pScreen->BlockHandler;
     pScreen->BlockHandler = I830BlockHandler;
 
-    if (pScrn->vtSema && !pI830->noAccel) {
+    if (pScrn->vtSema && pI830->accel != ACCEL_NONE) {
        /* Emit a flush of the rendering cache, or on the 965 and beyond
 	* rendering results may not hit the framebuffer until significantly
 	* later.
 	*/
-       if (!pI830->noAccel && (pI830->need_mi_flush || pI830->batch_used))
+       if (pI830->accel != ACCEL_NONE && (pI830->need_mi_flush || pI830->batch_used))
 	  I830EmitFlush(pScrn);
 
        /* Flush the batch, so that any rendering is executed in a timely
@@ -3001,12 +3020,12 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
    pI830->XvEnabled = !pI830->XvDisabled;
    if (pI830->XvEnabled) {
       if (!I830IsPrimary(pScrn)) {
-         if (!pI8301->XvEnabled || pI830->noAccel) {
+         if (!pI8301->XvEnabled || pI830->accel == ACCEL_NONE) {
             pI830->XvEnabled = FALSE;
 	    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Xv is disabled.\n");
          }
       } else
-      if (pI830->noAccel || pI830->StolenOnly) {
+      if (pI830->accel == ACCEL_NONE || pI830->StolenOnly) {
 	 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Xv is disabled because it "
 		    "needs 2D accel and AGPGART.\n");
 	 pI830->XvEnabled = FALSE;
@@ -3016,18 +3035,18 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
    pI830->XvEnabled = FALSE;
 #endif
 
-   if (!pI830->noAccel) {
+   if (pI830->accel != ACCEL_NONE) {
       if (pI830->memory_manager == NULL && pI830->LpRing->mem->size == 0) {
 	  xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		     "Disabling acceleration because the ring buffer "
 		      "allocation failed.\n");
-	   pI830->noAccel = TRUE;
+	   pI830->accel = ACCEL_NONE;
       }
    }
 
 #ifdef I830_XV
    if (pI830->XvEnabled) {
-      if (pI830->noAccel) {
+      if (pI830->accel == ACCEL_NONE) {
 	 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Disabling Xv because it "
 		    "needs 2D acceleration.\n");
 	 pI830->XvEnabled = FALSE;
@@ -3049,7 +3068,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
     */
 
    if (pI830->directRenderingEnabled) {
-      if (pI830->noAccel || pI830->SWCursor || (pI830->StolenOnly && I830IsPrimary(pScrn))) {
+      if (pI830->accel == ACCEL_NONE || pI830->SWCursor || (pI830->StolenOnly && I830IsPrimary(pScrn))) {
 	 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DRI is disabled because it "
 		    "needs HW cursor, 2D accel and AGPGART.\n");
 	 pI830->directRenderingEnabled = FALSE;
@@ -3123,7 +3142,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
 
    DPRINTF(PFX, "assert( if(!I830EnterVT(scrnIndex, 0)) )\n");
 
-   if (!pI830->useEXA) {
+   if (pI830->accel <= ACCEL_XAA) {
       if (I830IsPrimary(pScrn)) {
 	 if (!I830InitFBManager(pScreen, &(pI830->FbMemBox))) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
@@ -3171,7 +3190,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
    DPRINTF(PFX,
 	   "assert( if(!I830InitFBManager(pScreen, &(pI830->FbMemBox))) )\n");
 
-   if (!pI830->noAccel) {
+   if (pI830->accel != ACCEL_NONE) {
       if (!I830AccelInit(pScreen)) {
 	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		    "Hardware acceleration initialization failed\n");
@@ -3596,12 +3615,19 @@ I830CloseScreen(int scrnIndex, ScreenPtr pScreen)
    }
 #endif
 #ifdef I830_USE_EXA
-   if (pI830->useEXA && pI830->EXADriverPtr) {
+   if (pI830->EXADriverPtr) {
        exaDriverFini(pScreen);
        xfree(pI830->EXADriverPtr);
        pI830->EXADriverPtr = NULL;
    }
 #endif
+#ifdef I830_USE_UXA
+   if (pI830->uxa_driver) {
+       uxa_driver_fini (pScreen);
+       xfree (pI830->uxa_driver);
+       pI830->uxa_driver = NULL;
+   }
+#endif
    xf86_cursors_fini (pScreen);
 
    i830_allocator_fini(pScrn);
@@ -3830,19 +3856,34 @@ i830WaitSync(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830 = I830PTR(pScrn);
 
+   switch (pI830->accel) {
 #ifdef I830_USE_XAA
-   if (!pI830->noAccel && !pI830->useEXA && pI830->AccelInfoRec 
-	&& pI830->AccelInfoRec->NeedToSync) {
-      (*pI830->AccelInfoRec->Sync)(pScrn);
-      pI830->AccelInfoRec->NeedToSync = FALSE;
-   }
+   case ACCEL_XAA:
+      if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) {
+	 (*pI830->AccelInfoRec->Sync)(pScrn);
+	 pI830->AccelInfoRec->NeedToSync = FALSE;
+      }
+      break;
 #endif
 #ifdef I830_USE_EXA
-   if (!pI830->noAccel && pI830->useEXA && pI830->EXADriverPtr) {
-	ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
-	exaWaitSync(pScreen);
-   }
+   case ACCEL_EXA:
+      if (pI830->EXADriverPtr) {
+	 ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
+	 exaWaitSync(pScreen);
+      }
+      break;
 #endif
+#ifdef I830_USE_UXA
+   case ACCEL_UXA:
+      if (pI830->uxa_driver) {
+	 ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
+	 uxa_wait_sync(pScreen);
+      }
+      break;
+#endif
+   default:
+      break;
+   }
 }
 
 void
@@ -3850,16 +3891,32 @@ i830MarkSync(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830 = I830PTR(pScrn);
 
+   switch (pI830->accel) {
 #ifdef I830_USE_XAA
-   if (!pI830->useEXA && pI830->AccelInfoRec)
-      pI830->AccelInfoRec->NeedToSync = TRUE;
+   case ACCEL_XAA:
+      if (pI830->AccelInfoRec)
+	 pI830->AccelInfoRec->NeedToSync = TRUE;
+      break;
 #endif
 #ifdef I830_USE_EXA
-   if (pI830->useEXA && pI830->EXADriverPtr) {
-      ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
-      exaMarkSync(pScreen);
-   }
+   case ACCEL_EXA:
+      if (pI830->EXADriverPtr) {
+	 ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
+	 exaMarkSync(pScreen);
+      }
+      break;
+#endif
+#ifdef I830_USE_UXA
+   case ACCEL_UXA:
+      if (pI830->uxa_driver) {
+	 ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
+	 exaMarkSync(pScreen);
+      }
+      break;
 #endif
+   default:
+      break;
+   }
 }
 
 void
diff --git a/src/i830_exa.c b/src/i830_exa.c
index 75ccd74..a6705f4 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -430,7 +430,7 @@ I830EXAInit(ScreenPtr pScreen)
 
     pI830->EXADriverPtr = exaDriverAlloc();
     if (pI830->EXADriverPtr == NULL) {
-	pI830->noAccel = TRUE;
+	pI830->accel = ACCEL_NONE;
 	return FALSE;
     }
     memset(pI830->EXADriverPtr, 0, sizeof(*pI830->EXADriverPtr));
@@ -558,7 +558,7 @@ I830EXAInit(ScreenPtr pScreen)
 	pI830->EXADriverPtr->exa_minor = 0;
 	if(!exaDriverInit(pScreen, pI830->EXADriverPtr)) {
 	    xfree(pI830->EXADriverPtr);
-	    pI830->noAccel = TRUE;
+	    pI830->accel = ACCEL_NONE;
 	    return FALSE;
 	}
     }
@@ -568,6 +568,133 @@ I830EXAInit(ScreenPtr pScreen)
     return TRUE;
 }
 
+static Bool
+i830_uxa_pixmap_is_offscreen(PixmapPtr pPixmap)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    /* XXX for now, eventually we'll support 'real' off-screen pixmaps */
+    if ((void *)pPixmap->devPrivate.ptr >= (void *)pI830->FbBase &&
+	(void *)pPixmap->devPrivate.ptr <
+	(void *)(pI830->FbBase + pI830->FbMapSize))
+    {
+	return TRUE;
+    } else {
+	return FALSE;
+    }
+}
+
+
+Bool
+i830_uxa_init (ScreenPtr pScreen)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    pI830->uxa_driver = uxa_driver_alloc();
+    if (pI830->uxa_driver == NULL) {
+	pI830->accel = ACCEL_NONE;
+	return FALSE;
+    }
+    memset(pI830->uxa_driver, 0, sizeof(*pI830->uxa_driver));
+
+    pI830->bufferOffset = 0;
+    pI830->uxa_driver->uxa_major = 1;
+    pI830->uxa_driver->uxa_minor = 0;
+
+    /* Limits are described in the BLT engine chapter under Graphics Data Size
+     * Limitations, and the descriptions of SURFACE_STATE, 3DSTATE_BUFFER_INFO,
+     * 3DSTATE_DRAWING_RECTANGLE, 3DSTATE_MAP_INFO, and 3DSTATE_MAP_INFO.
+     *
+     * i845 through i965 limits 2D rendering to 65536 lines and pitch of 32768.
+     *
+     * i965 limits 3D surface to (2*element size)-aligned offset if un-tiled.
+     * i965 limits 3D surface to 4kB-aligned offset if tiled.
+     * i965 limits 3D surfaces to w,h of ?,8192.
+     * i965 limits 3D surface to pitch of 1B - 128kB.
+     * i965 limits 3D surface pitch alignment to 1 or 2 times the element size.
+     * i965 limits 3D surface pitch alignment to 512B if tiled.
+     * i965 limits 3D destination drawing rect to w,h of 8192,8192.
+     *
+     * i915 limits 3D textures to 4B-aligned offset if un-tiled.
+     * i915 limits 3D textures to ~4kB-aligned offset if tiled.
+     * i915 limits 3D textures to width,height of 2048,2048.
+     * i915 limits 3D textures to pitch of 16B - 8kB, in dwords.
+     * i915 limits 3D destination to ~4kB-aligned offset if tiled.
+     * i915 limits 3D destination to pitch of 16B - 8kB, in dwords, if un-tiled.
+     * i915 limits 3D destination to pitch of 512B - 8kB, in tiles, if tiled.
+     * i915 limits 3D destination to POT aligned pitch if tiled.
+     * i915 limits 3D destination drawing rect to w,h of 2048,2048.
+     *
+     * i845 limits 3D textures to 4B-aligned offset if un-tiled.
+     * i845 limits 3D textures to ~4kB-aligned offset if tiled.
+     * i845 limits 3D textures to width,height of 2048,2048.
+     * i845 limits 3D textures to pitch of 4B - 8kB, in dwords.
+     * i845 limits 3D destination to 4B-aligned offset if un-tiled.
+     * i845 limits 3D destination to ~4kB-aligned offset if tiled.
+     * i845 limits 3D destination to pitch of 8B - 8kB, in dwords.
+     * i845 limits 3D destination drawing rect to w,h of 2048,2048.
+     *
+     * For the tiled issues, the only tiled buffer we draw to should be
+     * the front, which will have an appropriate pitch/offset already set up,
+     * so EXA doesn't need to worry.
+     */
+    if (IS_I965G(pI830)) {
+	pI830->uxa_driver->maxX = 8192;
+	pI830->uxa_driver->maxY = 8192;
+    } else {
+	pI830->uxa_driver->maxX = 2048;
+	pI830->uxa_driver->maxY = 2048;
+    }
+
+    /* Sync */
+    pI830->uxa_driver->WaitMarker = I830EXASync;
+
+    /* Solid fill */
+    pI830->uxa_driver->PrepareSolid = I830EXAPrepareSolid;
+    pI830->uxa_driver->Solid = I830EXASolid;
+    pI830->uxa_driver->DoneSolid = I830EXADoneSolid;
+
+    /* Copy */
+    pI830->uxa_driver->PrepareCopy = I830EXAPrepareCopy;
+    pI830->uxa_driver->Copy = I830EXACopy;
+    pI830->uxa_driver->DoneCopy = I830EXADoneCopy;
+
+    /* Composite */
+    if (!IS_I9XX(pI830)) {
+    	pI830->uxa_driver->CheckComposite = i830_check_composite;
+    	pI830->uxa_driver->PrepareComposite = i830_prepare_composite;
+    	pI830->uxa_driver->Composite = i830_composite;
+    	pI830->uxa_driver->DoneComposite = i830_done_composite;
+    } else if (IS_I915G(pI830) || IS_I915GM(pI830) ||
+	       IS_I945G(pI830) || IS_I945GM(pI830) || IS_G33CLASS(pI830))
+    {
+	pI830->uxa_driver->CheckComposite = i915_check_composite;
+   	pI830->uxa_driver->PrepareComposite = i915_prepare_composite;
+    	pI830->uxa_driver->Composite = i830_composite;
+    	pI830->uxa_driver->DoneComposite = i830_done_composite;
+    } else {
+ 	pI830->uxa_driver->CheckComposite = i965_check_composite;
+ 	pI830->uxa_driver->PrepareComposite = i965_prepare_composite;
+ 	pI830->uxa_driver->Composite = i965_composite;
+ 	pI830->uxa_driver->DoneComposite = i830_done_composite;
+    }
+    pI830->uxa_driver->PixmapIsOffscreen = i830_uxa_pixmap_is_offscreen;
+
+    if(!uxa_driver_init(pScreen, pI830->uxa_driver)) {
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		   "UXA initialization failed\n");
+	xfree(pI830->uxa_driver);
+	pI830->accel = ACCEL_NONE;
+	return FALSE;
+    }
+
+    I830SelectBuffer(pScrn, I830_SELECT_FRONT);
+
+    return TRUE;
+}
+
 #ifdef XF86DRI
 
 #ifndef ExaOffscreenMarkUsed
diff --git a/src/i830_memory.c b/src/i830_memory.c
index b62bda0..c1748b3 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -449,7 +449,7 @@ i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset, unsigned long size)
 	mmsize = size;
 
 	/* EXA area is fixed. */
-	if (pI830->useEXA) {
+	if (pI830->accel == ACCEL_EXA) {
 	    mmsize -= ROUND_TO_PAGE(3 * pScrn->displayWidth * pI830->cpp *
 				    pScrn->virtualY);
 	}
@@ -1022,7 +1022,7 @@ i830_allocate_ringbuffer(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
 
-    if (pI830->noAccel || pI830->memory_manager || pI830->LpRing->mem != NULL)
+    if (pI830->accel == ACCEL_NONE || pI830->memory_manager || pI830->LpRing->mem != NULL)
 	return TRUE;
 
     /* We don't have any mechanism in the DRM yet to alert it that we've moved
@@ -1167,7 +1167,7 @@ i830_allocate_framebuffer(ScrnInfoPtr pScrn, I830Ptr pI830, BoxPtr FbMemBox,
     minspace = pitch * pScrn->virtualY;
     avail = pScrn->videoRam * 1024;
 
-    if (!pI830->useEXA) {
+    if (pI830->accel == ACCEL_XAA) {
 	maxCacheLines = (avail - minspace) / pitch;
 	/* This shouldn't happen. */
 	if (maxCacheLines < 0) {
@@ -1198,7 +1198,7 @@ i830_allocate_framebuffer(ScrnInfoPtr pScrn, I830Ptr pI830, BoxPtr FbMemBox,
 		   "Allocating %d scanlines for pixmap cache\n",
 		   cacheLines);
     } else {
-	/* For EXA, we have a separate allocation for the linear allocator
+	/* For non-XAA, we have a separate allocation for the linear allocator
 	 * which also does the pixmap cache.
 	 */
 	cacheLines = 0;
@@ -1213,7 +1213,7 @@ i830_allocate_framebuffer(ScrnInfoPtr pScrn, I830Ptr pI830, BoxPtr FbMemBox,
      * acceleration operations (non-XY COLOR_BLT) can't be done to tiled
      * buffers.
      */
-    if (!pI830->useEXA && IS_I965G(pI830))
+    if (pI830->accel <= ACCEL_XAA && IS_I965G(pI830))
 	tiling = FALSE;
     else
 	tiling = pI830->tiling;
@@ -1412,7 +1412,7 @@ i830_allocate_2d_memory(ScrnInfoPtr pScrn)
     }
 
     /* even in XAA, 965G needs state mem buffer for rendering */
-    if (IS_I965G(pI830) && !pI830->noAccel &&
+    if (IS_I965G(pI830) && pI830->accel != ACCEL_NONE &&
 	pI830->gen4_render_state_mem == NULL)
     {
 	pI830->gen4_render_state_mem =
@@ -1450,7 +1450,7 @@ i830_allocate_2d_memory(ScrnInfoPtr pScrn)
 	return FALSE;
 
 #ifdef I830_USE_EXA
-    if (pI830->useEXA) {
+    if (pI830->accel == ACCEL_EXA) {
 	if (pI830->exa_offscreen == NULL) {
 	    /* Default EXA to having 3 screens worth of offscreen memory space
 	     * (for pixmaps).
@@ -1478,7 +1478,7 @@ i830_allocate_2d_memory(ScrnInfoPtr pScrn)
     }
 #endif /* I830_USE_EXA */
 
-    if (!pI830->noAccel && !pI830->useEXA) {
+    if (pI830->accel == ACCEL_XAA) {
 	/* The lifetime fixed offset of xaa scratch is probably not required,
 	 * but we do some setup using it at XAAInit() time.  And XAA may not
 	 * end up being supported with GEM anyway.
diff --git a/src/i830_video.c b/src/i830_video.c
index 486f670..1719835 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -2460,13 +2460,13 @@ I830PutImage(ScrnInfoPtr pScrn,
     }
 
 #ifdef I830_USE_EXA
-    if (pPriv->textured && pI830->useEXA) {
+    if (pPriv->textured && pI830->accel == ACCEL_EXA) {
 	/* Force the pixmap into framebuffer so we can draw to it. */
 	exaMoveInPixmap(pPixmap);
     }
 #endif
 
-    if (pPriv->textured && !pI830->useEXA &&
+    if (pPriv->textured && pI830->accel <= ACCEL_XAA &&
 	    (((char *)pPixmap->devPrivate.ptr < (char *)pI830->FbBase) ||
 	     ((char *)pPixmap->devPrivate.ptr >= (char *)pI830->FbBase +
 	      pI830->FbMapSize))) {
diff --git a/uxa/Makefile.am b/uxa/Makefile.am
new file mode 100644
index 0000000..641b414
--- /dev/null
+++ b/uxa/Makefile.am
@@ -0,0 +1,20 @@
+noinst_LTLIBRARIES = libuxa.la
+
+# Override these since UXA doesn't need them and the needed files aren't
+# built (in hw/xfree86/os-support/solaris) until after UXA is built
+SOLARIS_ASM_CFLAGS=""
+
+INCLUDES = \
+	$(XORG_INCS)
+
+AM_CFLAGS = $(WARN_CFLAGS) $(XORG_CFLAGS) $(DIX_CFLAGS)
+
+libuxa_la_SOURCES = \
+	uxa.c \
+	uxa.h \
+	uxa-accel.c \
+	uxa-glyphs.c \
+	uxa-render.c \
+	uxa-priv.h \
+	uxa-unaccel.c
+
diff --git a/uxa/uxa-accel.c b/uxa/uxa-accel.c
new file mode 100644
index 0000000..7c7b3e9
--- /dev/null
+++ b/uxa/uxa-accel.c
@@ -0,0 +1,1038 @@
+/*
+ * Copyright © 2001 Keith Packard
+ *
+ * Partly based on code that is Copyright © The XFree86 Project Inc.
+ *
+ * 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 Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  Keith Packard makes no
+ * representations about the suitability of this software for any purpose.  It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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.
+ *
+ * Authors:
+ *    Eric Anholt <eric at anholt.net>
+ *    Michel Dänzer <michel at tungstengraphics.com>
+ *
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+#include "uxa-priv.h"
+#include <X11/fonts/fontstruct.h>
+#include "dixfontstr.h"
+#include "uxa.h"
+
+static void
+uxa_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int n,
+	     DDXPointPtr ppt, int *pwidth, int fSorted)
+{
+    ScreenPtr	    pScreen = pDrawable->pScreen;
+    uxa_screen_t    *uxa_screen = uxa_get_screen(pScreen);
+    RegionPtr	    pClip = fbGetCompositeClip(pGC);
+    PixmapPtr	    pPixmap = uxa_get_drawable_pixmap (pDrawable);
+    BoxPtr	    pextent, pbox;
+    int		    nbox;
+    int		    extentX1, extentX2, extentY1, extentY2;
+    int		    fullX1, fullX2, fullY1;
+    int		    partX1, partX2;
+    int		    off_x, off_y;
+
+    if (uxa_screen->swappedOut || pGC->fillStyle != FillSolid ||
+	!(pPixmap = uxa_get_offscreen_pixmap (pDrawable, &off_x, &off_y)) ||
+	!(*uxa_screen->info->PrepareSolid) (pPixmap,
+					 pGC->alu,
+					 pGC->planemask,
+					 pGC->fgPixel))
+    {
+	uxa_check_fill_spans (pDrawable, pGC, n, ppt, pwidth, fSorted);
+	return;
+    }
+
+    pextent = REGION_EXTENTS(pGC->pScreen, pClip);
+    extentX1 = pextent->x1;
+    extentY1 = pextent->y1;
+    extentX2 = pextent->x2;
+    extentY2 = pextent->y2;
+    while (n--)
+    {
+	fullX1 = ppt->x;
+	fullY1 = ppt->y;
+	fullX2 = fullX1 + (int) *pwidth;
+	ppt++;
+	pwidth++;
+
+	if (fullY1 < extentY1 || extentY2 <= fullY1)
+	    continue;
+
+	if (fullX1 < extentX1)
+	    fullX1 = extentX1;
+
+	if (fullX2 > extentX2)
+	    fullX2 = extentX2;
+
+	if (fullX1 >= fullX2)
+	    continue;
+
+	nbox = REGION_NUM_RECTS (pClip);
+	if (nbox == 1)
+	{
+	    (*uxa_screen->info->Solid) (pPixmap,
+				     fullX1 + off_x, fullY1 + off_y,
+				     fullX2 + off_x, fullY1 + 1 + off_y);
+	}
+	else
+	{
+	    pbox = REGION_RECTS(pClip);
+	    while(nbox--)
+	    {
+		if (pbox->y1 <= fullY1 && fullY1 < pbox->y2)
+		{
+		    partX1 = pbox->x1;
+		    if (partX1 < fullX1)
+			partX1 = fullX1;
+		    partX2 = pbox->x2;
+		    if (partX2 > fullX2)
+			partX2 = fullX2;
+		    if (partX2 > partX1) {
+			(*uxa_screen->info->Solid) (pPixmap,
+						 partX1 + off_x, fullY1 + off_y,
+						 partX2 + off_x, fullY1 + 1 + off_y);
+		    }
+		}
+		pbox++;
+	    }
+	}
+    }
+    (*uxa_screen->info->DoneSolid) (pPixmap);
+    uxa_mark_sync(pScreen);
+}
+
+static Bool
+uxa_do_put_image (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
+	       int w, int h, int format, char *bits, int src_stride)
+{
+    uxa_screen_t    *uxa_screen = uxa_get_screen(pDrawable->pScreen);
+    PixmapPtr pPix = uxa_get_drawable_pixmap (pDrawable);
+    RegionPtr pClip;
+    BoxPtr pbox;
+    int nbox;
+    int xoff, yoff;
+    int bpp = pDrawable->bitsPerPixel;
+    Bool access_prepared = FALSE;
+
+    /* Don't bother with under 8bpp, XYPixmaps. */
+    if (format != ZPixmap || bpp < 8)
+	return FALSE;
+
+    /* Only accelerate copies: no rop or planemask. */
+    if (!UXA_PM_IS_SOLID(pDrawable, pGC->planemask) || pGC->alu != GXcopy)
+	return FALSE;
+
+    if (uxa_screen->swappedOut)
+	return FALSE;
+
+    pPix = uxa_get_offscreen_pixmap (pDrawable, &xoff, &yoff);
+
+    if (!pPix || !uxa_screen->info->UploadToScreen)
+	return FALSE;
+
+    x += pDrawable->x;
+    y += pDrawable->y;
+
+    pClip = fbGetCompositeClip(pGC);
+    for (nbox = REGION_NUM_RECTS(pClip),
+	 pbox = REGION_RECTS(pClip);
+	 nbox--;
+	 pbox++)
+    {
+	int x1 = x;
+	int y1 = y;
+	int x2 = x + w;
+	int y2 = y + h;
+	char *src;
+	Bool ok;
+
+	if (x1 < pbox->x1)
+	    x1 = pbox->x1;
+	if (y1 < pbox->y1)
+	    y1 = pbox->y1;
+	if (x2 > pbox->x2)
+	    x2 = pbox->x2;
+	if (y2 > pbox->y2)
+	    y2 = pbox->y2;
+	if (x1 >= x2 || y1 >= y2)
+	    continue;
+
+	src = bits + (y1 - y) * src_stride + (x1 - x) * (bpp / 8);
+	ok = uxa_screen->info->UploadToScreen(pPix, x1 + xoff, y1 + yoff,
+					      x2 - x1, y2 - y1, src, src_stride);
+	/* If we fail to accelerate the upload, fall back to using unaccelerated
+	 * fb calls.
+	 */
+	if (!ok) {
+	    FbStip *dst;
+	    FbStride dst_stride;
+	    int	dstBpp;
+	    int	dstXoff, dstYoff;
+
+	    if (!access_prepared) {
+		uxa_prepare_access(pDrawable, UXA_PREPARE_DEST);
+
+		access_prepared = TRUE;
+	    }
+
+	    fbGetStipDrawable(pDrawable, dst, dst_stride, dstBpp,
+			      dstXoff, dstYoff);
+
+	    fbBltStip((FbStip *)bits + (y1 - y) * (src_stride / sizeof(FbStip)),
+		      src_stride / sizeof(FbStip),
+		      (x1 - x) * dstBpp,
+		      dst + (y1 + dstYoff) * dst_stride,
+		      dst_stride,
+		      (x1 + dstXoff) * dstBpp,
+		      (x2 - x1) * dstBpp,
+		      y2 - y1,
+		      GXcopy, FB_ALLONES, dstBpp);
+	}
+    }
+
+    if (access_prepared)
+	uxa_finish_access(pDrawable, UXA_PREPARE_DEST);
+    else
+	uxa_mark_sync(pDrawable->pScreen);
+
+    return TRUE;
+}
+
+#ifdef MITSHM
+
+static Bool
+uxa_do_shm_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth,
+		 unsigned int format, int w, int h, int sx, int sy, int sw,
+		 int sh, int dx, int dy, char *data)
+{
+    int src_stride = PixmapBytePad(w, depth);
+
+    if (uxa_do_put_image(pDrawable, pGC, depth, dx, dy, sw, sh, format, data +
+		      sy * src_stride + sx * BitsPerPixel(depth) / 8,
+		      src_stride))
+	return TRUE;
+
+    if (format == ZPixmap)
+    {
+	PixmapPtr pPixmap;
+
+	pPixmap = GetScratchPixmapHeader(pDrawable->pScreen, w, h, depth,
+		BitsPerPixel(depth), PixmapBytePad(w, depth), (pointer)data);
+	if (!pPixmap)
+	    return FALSE;
+
+        uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+
+	fbCopyArea((DrawablePtr)pPixmap, pDrawable, pGC, sx, sy, sw, sh, dx, dy);
+	uxa_finish_access(pDrawable, UXA_PREPARE_DEST);
+
+	FreeScratchPixmapHeader(pPixmap);
+
+	return TRUE;
+    }
+
+    return FALSE;
+}
+
+/* The actual ShmPutImage isn't wrapped by the damage layer, so we need to
+ * inform any interested parties of the damage incurred to the drawable.
+ *
+ * We also need to set the pending damage to ensure correct migration in all
+ * cases.
+ */
+void
+uxa_shm_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth, unsigned int format,
+	       int w, int h, int sx, int sy, int sw, int sh, int dx, int dy,
+	       char *data)
+{
+    if (!uxa_do_shm_put_image(pDrawable, pGC, depth, format, w, h, sx, sy, sw, sh,
+			  dx, dy, data)) {
+	uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+	fbShmPutImage(pDrawable, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy,
+		      data);
+	uxa_finish_access(pDrawable, UXA_PREPARE_DEST);
+    }
+}
+
+ShmFuncs uxa_shm_funcs = { NULL, uxa_shm_put_image };
+
+#endif
+
+static void
+uxa_put_image (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
+	     int w, int h, int leftPad, int format, char *bits)
+{
+#ifdef MITSHM
+    if (!uxa_do_shm_put_image(pDrawable, pGC, depth, format, w, h, 0, 0, w, h, x, y,
+			  bits))
+#else
+    if (!uxa_do_put_image(pDrawable, pGC, depth, x, y, w, h, format, bits,
+		       PixmapBytePad(w, pDrawable->depth)))
+#endif
+	uxa_check_put_image(pDrawable, pGC, depth, x, y, w, h, leftPad, format,
+			 bits);
+}
+
+static Bool inline
+uxa_copy_n_to_n_two_dir (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
+		   GCPtr pGC, BoxPtr pbox, int nbox, int dx, int dy)
+{
+    uxa_screen_t *uxa_screen = uxa_get_screen(pDstDrawable->pScreen);
+    PixmapPtr pSrcPixmap, pDstPixmap;
+    int src_off_x, src_off_y, dst_off_x, dst_off_y;
+    int dirsetup;
+
+    /* Need to get both pixmaps to call the driver routines */
+    pSrcPixmap = uxa_get_offscreen_pixmap (pSrcDrawable, &src_off_x, &src_off_y);
+    pDstPixmap = uxa_get_offscreen_pixmap (pDstDrawable, &dst_off_x, &dst_off_y);
+    if (!pSrcPixmap || !pDstPixmap)
+	return FALSE;
+
+    /*
+     * Now the case of a chip that only supports xdir = ydir = 1 or
+     * xdir = ydir = -1, but we have xdir != ydir.
+     */
+    dirsetup = 0;	/* No direction set up yet. */
+    for (; nbox; pbox++, nbox--) {
+	if (dx >= 0 && (src_off_y + pbox->y1 + dy) != pbox->y1) {
+	    /* Do a xdir = ydir = -1 blit instead. */
+	    if (dirsetup != -1) {
+		if (dirsetup != 0)
+		    uxa_screen->info->DoneCopy(pDstPixmap);
+		dirsetup = -1;
+		if (!(*uxa_screen->info->PrepareCopy)(pSrcPixmap,
+						   pDstPixmap,
+						   -1, -1,
+						   pGC ? pGC->alu : GXcopy,
+						   pGC ? pGC->planemask :
+							 FB_ALLONES))
+		    return FALSE;
+	    }
+	    (*uxa_screen->info->Copy)(pDstPixmap,
+				   src_off_x + pbox->x1 + dx,
+				   src_off_y + pbox->y1 + dy,
+				   dst_off_x + pbox->x1,
+				   dst_off_y + pbox->y1,
+				   pbox->x2 - pbox->x1,
+				   pbox->y2 - pbox->y1);
+	} else if (dx < 0 && (src_off_y + pbox->y1 + dy) != pbox->y1) {
+	    /* Do a xdir = ydir = 1 blit instead. */
+	    if (dirsetup != 1) {
+		if (dirsetup != 0)
+		    uxa_screen->info->DoneCopy(pDstPixmap);
+		dirsetup = 1;
+		if (!(*uxa_screen->info->PrepareCopy)(pSrcPixmap,
+						   pDstPixmap,
+						   1, 1,
+						   pGC ? pGC->alu : GXcopy,
+						   pGC ? pGC->planemask :
+							 FB_ALLONES))
+		    return FALSE;
+	    }
+	    (*uxa_screen->info->Copy)(pDstPixmap,
+				   src_off_x + pbox->x1 + dx,
+				   src_off_y + pbox->y1 + dy,
+				   dst_off_x + pbox->x1,
+				   dst_off_y + pbox->y1,
+				   pbox->x2 - pbox->x1,
+				   pbox->y2 - pbox->y1);
+	} else if (dx >= 0) {
+	    /*
+	     * xdir = 1, ydir = -1.
+	     * Perform line-by-line xdir = ydir = 1 blits, going up.
+	     */
+	    int i;
+	    if (dirsetup != 1) {
+		if (dirsetup != 0)
+		    uxa_screen->info->DoneCopy(pDstPixmap);
+		dirsetup = 1;
+		if (!(*uxa_screen->info->PrepareCopy)(pSrcPixmap,
+						   pDstPixmap,
+						   1, 1,
+						   pGC ? pGC->alu : GXcopy,
+						   pGC ? pGC->planemask :
+							 FB_ALLONES))
+		    return FALSE;
+	    }
+	    for (i = pbox->y2 - pbox->y1 - 1; i >= 0; i--)
+		(*uxa_screen->info->Copy)(pDstPixmap,
+				       src_off_x + pbox->x1 + dx,
+				       src_off_y + pbox->y1 + dy + i,
+				       dst_off_x + pbox->x1,
+				       dst_off_y + pbox->y1 + i,
+				       pbox->x2 - pbox->x1, 1);
+	} else {
+	    /*
+	     * xdir = -1, ydir = 1.
+	     * Perform line-by-line xdir = ydir = -1 blits, going down.
+	     */
+	    int i;
+	    if (dirsetup != -1) {
+		if (dirsetup != 0)
+		    uxa_screen->info->DoneCopy(pDstPixmap);
+		dirsetup = -1;
+		if (!(*uxa_screen->info->PrepareCopy)(pSrcPixmap,
+						   pDstPixmap,
+						   -1, -1,
+						   pGC ? pGC->alu : GXcopy,
+						   pGC ? pGC->planemask :
+							 FB_ALLONES))
+		    return FALSE;
+	    }
+	    for (i = 0; i < pbox->y2 - pbox->y1; i++)
+		(*uxa_screen->info->Copy)(pDstPixmap,
+				       src_off_x + pbox->x1 + dx,
+				       src_off_y + pbox->y1 + dy + i,
+				       dst_off_x + pbox->x1,
+				       dst_off_y + pbox->y1 + i,
+				       pbox->x2 - pbox->x1, 1);
+	}
+    }
+    if (dirsetup != 0)
+	uxa_screen->info->DoneCopy(pDstPixmap);
+    uxa_mark_sync(pDstDrawable->pScreen);
+    return TRUE;
+}
+
+void
+uxa_copy_n_to_n (DrawablePtr    pSrcDrawable,
+		 DrawablePtr    pDstDrawable,
+		 GCPtr		pGC,
+		 BoxPtr		pbox,
+		 int		nbox,
+		 int		dx,
+		 int		dy,
+		 Bool		reverse,
+		 Bool		upsidedown,
+		 Pixel		bitplane,
+		 void		*closure)
+{
+    uxa_screen_t    *uxa_screen = uxa_get_screen(pDstDrawable->pScreen);
+    int		    src_off_x, src_off_y;
+    int		    dst_off_x, dst_off_y;
+    PixmapPtr	    pSrcPixmap, pDstPixmap;
+
+    pSrcPixmap = uxa_get_drawable_pixmap (pSrcDrawable);
+    pDstPixmap = uxa_get_drawable_pixmap (pDstDrawable);
+
+    uxa_get_drawable_deltas (pSrcDrawable, pSrcPixmap, &src_off_x, &src_off_y);
+    uxa_get_drawable_deltas (pDstDrawable, pDstPixmap, &dst_off_x, &dst_off_y);
+
+    /* Mixed directions must be handled specially if the card is lame */
+    if ((uxa_screen->info->flags & UXA_TWO_BITBLT_DIRECTIONS) &&
+	reverse != upsidedown) {
+	if (uxa_copy_n_to_n_two_dir(pSrcDrawable, pDstDrawable, pGC, pbox, nbox,
+			       dx, dy))
+	    return;
+	goto fallback;
+    }
+
+    if (!uxa_pixmap_is_offscreen(pSrcPixmap) ||
+	!uxa_pixmap_is_offscreen(pDstPixmap) ||
+	!(*uxa_screen->info->PrepareCopy) (pSrcPixmap, pDstPixmap, reverse ? -1 : 1,
+					   upsidedown ? -1 : 1,
+					   pGC ? pGC->alu : GXcopy,
+					   pGC ? pGC->planemask : FB_ALLONES)) {
+	goto fallback;
+    }
+
+    while (nbox--)
+    {
+	(*uxa_screen->info->Copy) (pDstPixmap,
+				   pbox->x1 + dx + src_off_x,
+				   pbox->y1 + dy + src_off_y,
+				   pbox->x1 + dst_off_x, pbox->y1 + dst_off_y,
+				   pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
+	pbox++;
+    }
+
+    (*uxa_screen->info->DoneCopy) (pDstPixmap);
+    uxa_mark_sync (pDstDrawable->pScreen);
+
+    return;
+
+fallback:
+    UXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrcDrawable, pDstDrawable,
+		  uxa_drawable_location(pSrcDrawable),
+		  uxa_drawable_location(pDstDrawable)));
+    uxa_prepare_access (pDstDrawable, UXA_PREPARE_DEST);
+    uxa_prepare_access (pSrcDrawable, UXA_PREPARE_SRC);
+    fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy, reverse,
+		upsidedown, bitplane, closure);
+    uxa_finish_access (pSrcDrawable, UXA_PREPARE_SRC);
+    uxa_finish_access (pDstDrawable, UXA_PREPARE_DEST);
+}
+
+RegionPtr
+uxa_copy_area(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
+	    int srcx, int srcy, int width, int height, int dstx, int dsty)
+{
+    uxa_screen_t    *uxa_screen = uxa_get_screen(pDstDrawable->pScreen);
+
+    if (uxa_screen->swappedOut) {
+        return  uxa_check_copy_area(pSrcDrawable, pDstDrawable, pGC,
+                                 srcx, srcy, width, height, dstx, dsty);
+    }
+
+    return  fbDoCopy (pSrcDrawable, pDstDrawable, pGC,
+                      srcx, srcy, width, height,
+                      dstx, dsty, uxa_copy_n_to_n, 0, NULL);
+}
+
+static void
+uxa_poly_point(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
+	     DDXPointPtr ppt)
+{
+    int i;
+    xRectangle *prect;
+
+    /* If we can't reuse the current GC as is, don't bother accelerating the
+     * points.
+     */
+    if (pGC->fillStyle != FillSolid) {
+	uxa_check_poly_point(pDrawable, pGC, mode, npt, ppt);
+	return;
+    }
+
+    prect = xalloc(sizeof(xRectangle) * npt);
+    for (i = 0; i < npt; i++) {
+	prect[i].x = ppt[i].x;
+	prect[i].y = ppt[i].y;
+	if (i > 0 && mode == CoordModePrevious) {
+	    prect[i].x += prect[i - 1].x;
+	    prect[i].y += prect[i - 1].y;
+	}
+	prect[i].width = 1;
+	prect[i].height = 1;
+    }
+    pGC->ops->PolyFillRect(pDrawable, pGC, npt, prect);
+    xfree(prect);
+}
+
+/**
+ * uxa_poly_lines() checks if it can accelerate the lines as a group of
+ * horizontal or vertical lines (rectangles), and uses existing rectangle fill
+ * acceleration if so.
+ */
+static void
+uxa_poly_lines(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
+	       DDXPointPtr ppt)
+{
+    xRectangle *prect;
+    int x1, x2, y1, y2;
+    int i;
+
+    /* Don't try to do wide lines or non-solid fill style. */
+    if (pGC->lineWidth != 0 || pGC->lineStyle != LineSolid ||
+	pGC->fillStyle != FillSolid) {
+	uxa_check_poly_lines(pDrawable, pGC, mode, npt, ppt);
+	return;
+    }
+
+    prect = xalloc(sizeof(xRectangle) * (npt - 1));
+    x1 = ppt[0].x;
+    y1 = ppt[0].y;
+    /* If we have any non-horizontal/vertical, fall back. */
+    for (i = 0; i < npt - 1; i++) {
+	if (mode == CoordModePrevious) {
+	    x2 = x1 + ppt[i + 1].x;
+	    y2 = y1 + ppt[i + 1].y;
+	} else {
+	    x2 = ppt[i + 1].x;
+	    y2 = ppt[i + 1].y;
+	}
+
+	if (x1 != x2 && y1 != y2) {
+	    xfree(prect);
+	    uxa_check_poly_lines(pDrawable, pGC, mode, npt, ppt);
+	    return;
+	}
+
+	if (x1 < x2) {
+	    prect[i].x = x1;
+	    prect[i].width = x2 - x1 + 1;
+	} else {
+	    prect[i].x = x2;
+	    prect[i].width = x1 - x2 + 1;
+	}
+	if (y1 < y2) {
+	    prect[i].y = y1;
+	    prect[i].height = y2 - y1 + 1;
+	} else {
+	    prect[i].y = y2;
+	    prect[i].height = y1 - y2 + 1;
+	}
+
+	x1 = x2;
+	y1 = y2;
+    }
+    pGC->ops->PolyFillRect(pDrawable, pGC, npt - 1, prect);
+    xfree(prect);
+}
+
+/**
+ * uxa_poly_segment() checks if it can accelerate the lines as a group of
+ * horizontal or vertical lines (rectangles), and uses existing rectangle fill
+ * acceleration if so.
+ */
+static void
+uxa_poly_segment (DrawablePtr pDrawable, GCPtr pGC, int nseg,
+		xSegment *pSeg)
+{
+    xRectangle *prect;
+    int i;
+
+    /* Don't try to do wide lines or non-solid fill style. */
+    if (pGC->lineWidth != 0 || pGC->lineStyle != LineSolid ||
+	pGC->fillStyle != FillSolid)
+    {
+	uxa_check_poly_segment(pDrawable, pGC, nseg, pSeg);
+	return;
+    }
+
+    /* If we have any non-horizontal/vertical, fall back. */
+    for (i = 0; i < nseg; i++) {
+	if (pSeg[i].x1 != pSeg[i].x2 && pSeg[i].y1 != pSeg[i].y2) {
+	    uxa_check_poly_segment(pDrawable, pGC, nseg, pSeg);
+	    return;
+	}
+    }
+
+    prect = xalloc(sizeof(xRectangle) * nseg);
+    for (i = 0; i < nseg; i++) {
+	if (pSeg[i].x1 < pSeg[i].x2) {
+	    prect[i].x = pSeg[i].x1;
+	    prect[i].width = pSeg[i].x2 - pSeg[i].x1 + 1;
+	} else {
+	    prect[i].x = pSeg[i].x2;
+	    prect[i].width = pSeg[i].x1 - pSeg[i].x2 + 1;
+	}
+	if (pSeg[i].y1 < pSeg[i].y2) {
+	    prect[i].y = pSeg[i].y1;
+	    prect[i].height = pSeg[i].y2 - pSeg[i].y1 + 1;
+	} else {
+	    prect[i].y = pSeg[i].y2;
+	    prect[i].height = pSeg[i].y1 - pSeg[i].y2 + 1;
+	}
+
+	/* don't paint last pixel */
+	if (pGC->capStyle == CapNotLast) {
+	    if (prect[i].width == 1)
+		prect[i].height--;
+	    else
+		prect[i].width--;
+	}
+    }
+    pGC->ops->PolyFillRect(pDrawable, pGC, nseg, prect);
+    xfree(prect);
+}
+
+static Bool uxa_fill_region_solid (DrawablePtr pDrawable, RegionPtr pRegion,
+				Pixel pixel, CARD32 planemask, CARD32 alu);
+
+static void
+uxa_poly_fill_rect(DrawablePtr pDrawable,
+		GCPtr	    pGC,
+		int	    nrect,
+		xRectangle  *prect)
+{
+    uxa_screen_t    *uxa_screen = uxa_get_screen(pDrawable->pScreen);
+    RegionPtr	    pClip = fbGetCompositeClip(pGC);
+    PixmapPtr	    pPixmap = uxa_get_drawable_pixmap(pDrawable);
+    register BoxPtr pbox;
+    BoxPtr	    pextent;
+    int		    extentX1, extentX2, extentY1, extentY2;
+    int		    fullX1, fullX2, fullY1, fullY2;
+    int		    partX1, partX2, partY1, partY2;
+    int		    xoff, yoff;
+    int		    xorg, yorg;
+    int		    n;
+    RegionPtr pReg = RECTS_TO_REGION(pScreen, nrect, prect, CT_UNSORTED);
+
+    /* Compute intersection of rects and clip region */
+    REGION_TRANSLATE(pScreen, pReg, pDrawable->x, pDrawable->y);
+    REGION_INTERSECT(pScreen, pReg, pClip, pReg);
+
+    if (!REGION_NUM_RECTS(pReg))
+	goto out;
+
+    uxa_get_drawable_deltas(pDrawable, pPixmap, &xoff, &yoff);
+
+    if (uxa_screen->swappedOut)
+	goto fallback;
+
+    /* For ROPs where overlaps don't matter, convert rectangles to region and
+     * call uxa_fill_region_{solid,tiled}.
+     */
+    if ((pGC->fillStyle == FillSolid || pGC->fillStyle == FillTiled) &&
+	(nrect == 1 || pGC->alu == GXcopy || pGC->alu == GXclear ||
+	 pGC->alu == GXnoop || pGC->alu == GXcopyInverted ||
+	 pGC->alu == GXset)) {
+	if (((pGC->fillStyle == FillSolid || pGC->tileIsPixel) &&
+	     uxa_fill_region_solid(pDrawable, pReg, pGC->fillStyle == FillSolid ?
+				pGC->fgPixel : pGC->tile.pixel,	pGC->planemask,
+				pGC->alu)) ||
+	    (pGC->fillStyle == FillTiled && !pGC->tileIsPixel &&
+	     uxa_fill_region_tiled(pDrawable, pReg, pGC->tile.pixmap, &pGC->patOrg,
+				pGC->planemask, pGC->alu))) {
+	    goto out;
+	}
+    }
+
+    if (pGC->fillStyle != FillSolid &&
+	!(pGC->tileIsPixel && pGC->fillStyle == FillTiled))
+    {
+	goto fallback;
+    }
+
+    if (!uxa_pixmap_is_offscreen (pPixmap) ||
+	!(*uxa_screen->info->PrepareSolid) (pPixmap,
+					 pGC->alu,
+					 pGC->planemask,
+					 pGC->fgPixel))
+    {
+fallback:
+	uxa_check_poly_fill_rect (pDrawable, pGC, nrect, prect);
+	goto out;
+    }
+
+    xorg = pDrawable->x;
+    yorg = pDrawable->y;
+
+    pextent = REGION_EXTENTS(pGC->pScreen, pClip);
+    extentX1 = pextent->x1;
+    extentY1 = pextent->y1;
+    extentX2 = pextent->x2;
+    extentY2 = pextent->y2;
+    while (nrect--)
+    {
+	fullX1 = prect->x + xorg;
+	fullY1 = prect->y + yorg;
+	fullX2 = fullX1 + (int) prect->width;
+	fullY2 = fullY1 + (int) prect->height;
+	prect++;
+
+	if (fullX1 < extentX1)
+	    fullX1 = extentX1;
+
+	if (fullY1 < extentY1)
+	    fullY1 = extentY1;
+
+	if (fullX2 > extentX2)
+	    fullX2 = extentX2;
+
+	if (fullY2 > extentY2)
+	    fullY2 = extentY2;
+
+	if ((fullX1 >= fullX2) || (fullY1 >= fullY2))
+	    continue;
+	n = REGION_NUM_RECTS (pClip);
+	if (n == 1)
+	{
+	    (*uxa_screen->info->Solid) (pPixmap,
+				     fullX1 + xoff, fullY1 + yoff,
+				     fullX2 + xoff, fullY2 + yoff);
+	}
+	else
+	{
+	    pbox = REGION_RECTS(pClip);
+	    /*
+	     * clip the rectangle to each box in the clip region
+	     * this is logically equivalent to calling Intersect(),
+	     * but rectangles may overlap each other here.
+	     */
+	    while(n--)
+	    {
+		partX1 = pbox->x1;
+		if (partX1 < fullX1)
+		    partX1 = fullX1;
+		partY1 = pbox->y1;
+		if (partY1 < fullY1)
+		    partY1 = fullY1;
+		partX2 = pbox->x2;
+		if (partX2 > fullX2)
+		    partX2 = fullX2;
+		partY2 = pbox->y2;
+		if (partY2 > fullY2)
+		    partY2 = fullY2;
+
+		pbox++;
+
+		if (partX1 < partX2 && partY1 < partY2) {
+		    (*uxa_screen->info->Solid) (pPixmap,
+					     partX1 + xoff, partY1 + yoff,
+					     partX2 + xoff, partY2 + yoff);
+		}
+	    }
+	}
+    }
+    (*uxa_screen->info->DoneSolid) (pPixmap);
+    uxa_mark_sync(pDrawable->pScreen);
+
+out:
+    REGION_UNINIT(pScreen, pReg);
+    REGION_DESTROY(pScreen, pReg);
+}
+
+const GCOps uxa_ops = {
+    uxa_fill_spans,
+    uxa_check_set_spans,
+    uxa_put_image,
+    uxa_copy_area,
+    uxa_check_copy_plane,
+    uxa_poly_point,
+    uxa_poly_lines,
+    uxa_poly_segment,
+    miPolyRectangle,
+    uxa_check_poly_arc,
+    miFillPolygon,
+    uxa_poly_fill_rect,
+    miPolyFillArc,
+    miPolyText8,
+    miPolyText16,
+    miImageText8,
+    miImageText16,
+    uxa_check_image_glyph_blt,
+    uxa_check_poly_glyph_blt,
+    uxa_check_push_pixels,
+};
+
+void
+uxa_copy_window(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
+{
+    RegionRec	rgnDst;
+    int		dx, dy;
+    PixmapPtr	pPixmap = (*pWin->drawable.pScreen->GetWindowPixmap) (pWin);
+
+    dx = ptOldOrg.x - pWin->drawable.x;
+    dy = ptOldOrg.y - pWin->drawable.y;
+    REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy);
+
+    REGION_INIT (pWin->drawable.pScreen, &rgnDst, NullBox, 0);
+
+    REGION_INTERSECT(pWin->drawable.pScreen, &rgnDst, &pWin->borderClip, prgnSrc);
+#ifdef COMPOSITE
+    if (pPixmap->screen_x || pPixmap->screen_y)
+	REGION_TRANSLATE (pWin->drawable.pScreen, &rgnDst,
+			  -pPixmap->screen_x, -pPixmap->screen_y);
+#endif
+
+    fbCopyRegion (&pPixmap->drawable, &pPixmap->drawable,
+		  NULL,
+		  &rgnDst, dx, dy, uxa_copy_n_to_n, 0, NULL);
+
+    REGION_UNINIT(pWin->drawable.pScreen, &rgnDst);
+}
+
+static Bool
+uxa_fill_region_solid (DrawablePtr	pDrawable,
+		    RegionPtr	pRegion,
+		    Pixel	pixel,
+		    CARD32	planemask,
+		    CARD32	alu)
+{
+    uxa_screen_t    *uxa_screen = uxa_get_screen(pDrawable->pScreen);
+    PixmapPtr	    pPixmap = uxa_get_drawable_pixmap (pDrawable);
+    int		    xoff, yoff;
+    Bool	    ret = FALSE;
+
+    uxa_get_drawable_deltas(pDrawable, pPixmap, &xoff, &yoff);
+    REGION_TRANSLATE(pScreen, pRegion, xoff, yoff);
+
+    if (uxa_pixmap_is_offscreen (pPixmap) &&
+	(*uxa_screen->info->PrepareSolid) (pPixmap, alu, planemask, pixel))
+    {
+	int nbox;
+	BoxPtr pBox;
+
+	nbox = REGION_NUM_RECTS (pRegion);
+	pBox = REGION_RECTS (pRegion);
+
+	while (nbox--)
+	{
+	    (*uxa_screen->info->Solid) (pPixmap, pBox->x1, pBox->y1, pBox->x2,
+				     pBox->y2);
+	    pBox++;
+	}
+	(*uxa_screen->info->DoneSolid) (pPixmap);
+	uxa_mark_sync(pDrawable->pScreen);
+
+	ret = TRUE;
+    }
+
+    REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff);
+
+    return ret;
+}
+
+/* Try to do an accelerated tile of the pTile into pRegion of pDrawable.
+ * Based on fbFillRegionTiled(), fbTile().
+ */
+Bool
+uxa_fill_region_tiled (DrawablePtr	pDrawable,
+		       RegionPtr	pRegion,
+		       PixmapPtr	pTile,
+		       DDXPointPtr	pPatOrg,
+		       CARD32		planemask,
+		       CARD32		alu)
+{
+    uxa_screen_t    *uxa_screen = uxa_get_screen(pDrawable->pScreen);
+    PixmapPtr	    pPixmap;
+    int		    xoff, yoff;
+    int		    tileWidth, tileHeight;
+    int		    nbox = REGION_NUM_RECTS (pRegion);
+    BoxPtr	    pBox = REGION_RECTS (pRegion);
+    Bool	    ret = FALSE;
+
+    tileWidth = pTile->drawable.width;
+    tileHeight = pTile->drawable.height;
+
+    /* If we're filling with a solid color, grab it out and go to
+     * FillRegionSolid, saving numerous copies.
+     */
+    if (tileWidth == 1 && tileHeight == 1)
+	return uxa_fill_region_solid(pDrawable, pRegion,
+				     uxa_get_pixmap_first_pixel (pTile), planemask,
+				     alu);
+
+    pPixmap = uxa_get_drawable_pixmap (pDrawable);
+    uxa_get_drawable_deltas(pDrawable, pPixmap, &xoff, &yoff);
+    REGION_TRANSLATE(pScreen, pRegion, xoff, yoff);
+
+    pPixmap = uxa_get_offscreen_pixmap (pDrawable, &xoff, &yoff);
+
+    if (!pPixmap || !uxa_pixmap_is_offscreen(pTile))
+	goto out;
+
+    if ((*uxa_screen->info->PrepareCopy) (pTile, pPixmap, 1, 1, alu, planemask))
+    {
+	while (nbox--)
+	{
+	    int height = pBox->y2 - pBox->y1;
+	    int dstY = pBox->y1;
+	    int tileY;
+
+	    modulus(dstY - yoff - pDrawable->y - pPatOrg->y, tileHeight, tileY);
+
+	    while (height > 0) {
+		int width = pBox->x2 - pBox->x1;
+		int dstX = pBox->x1;
+		int tileX;
+		int h = tileHeight - tileY;
+
+		if (h > height)
+		    h = height;
+		height -= h;
+
+		modulus(dstX - xoff - pDrawable->x - pPatOrg->x, tileWidth,
+			tileX);
+
+		while (width > 0) {
+		    int w = tileWidth - tileX;
+		    if (w > width)
+			w = width;
+		    width -= w;
+
+		    (*uxa_screen->info->Copy) (pPixmap, tileX, tileY, dstX, dstY,
+					    w, h);
+		    dstX += w;
+		    tileX = 0;
+		}
+		dstY += h;
+		tileY = 0;
+	    }
+	    pBox++;
+	}
+	(*uxa_screen->info->DoneCopy) (pPixmap);
+	uxa_mark_sync(pDrawable->pScreen);
+
+	ret = TRUE;
+    }
+
+out:
+    REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff);
+
+    return ret;
+}
+
+
+/**
+ * Accelerates GetImage for solid ZPixmap downloads from framebuffer memory.
+ *
+ * This is probably the only case we actually care about.  The rest fall through
+ * to migration and fbGetImage, which hopefully will result in migration pushing
+ * the pixmap out of framebuffer.
+ */
+void
+uxa_get_image (DrawablePtr pDrawable, int x, int y, int w, int h,
+	       unsigned int format, unsigned long planeMask, char *d)
+{
+    uxa_screen_t    *uxa_screen = uxa_get_screen(pDrawable->pScreen);
+    BoxRec	    Box;
+    PixmapPtr	    pPix = uxa_get_drawable_pixmap (pDrawable);
+    int		    xoff, yoff;
+    Bool	    ok;
+
+    uxa_get_drawable_deltas (pDrawable, pPix, &xoff, &yoff);
+
+    Box.x1 = pDrawable->y + x + xoff;
+    Box.y1 = pDrawable->y + y + yoff;
+    Box.x2 = Box.x1 + w;
+    Box.y2 = Box.y1 + h;
+
+    if (uxa_screen->swappedOut)
+	goto fallback;
+
+    pPix = uxa_get_offscreen_pixmap (pDrawable, &xoff, &yoff);
+
+    if (pPix == NULL || uxa_screen->info->DownloadFromScreen == NULL)
+	goto fallback;
+
+    /* Only cover the ZPixmap, solid copy case. */
+    if (format != ZPixmap || !UXA_PM_IS_SOLID(pDrawable, planeMask))
+	goto fallback;
+
+    /* Only try to handle the 8bpp and up cases, since we don't want to think
+     * about <8bpp.
+     */
+    if (pDrawable->bitsPerPixel < 8)
+	goto fallback;
+
+    ok = uxa_screen->info->DownloadFromScreen(pPix, pDrawable->x + x + xoff,
+					   pDrawable->y + y + yoff, w, h, d,
+					   PixmapBytePad(w, pDrawable->depth));
+    if (ok) {
+	uxa_wait_sync(pDrawable->pScreen);
+	goto out;
+    }
+
+fallback:
+    UXA_FALLBACK(("from %p (%c)\n", pDrawable,
+		  uxa_drawable_location(pDrawable)));
+
+    uxa_prepare_access (pDrawable, UXA_PREPARE_SRC);
+    fbGetImage (pDrawable, x, y, w, h, format, planeMask, d);
+    uxa_finish_access (pDrawable, UXA_PREPARE_SRC);
+
+out:
+   return;
+}
diff --git a/uxa/uxa-glyphs.c b/uxa/uxa-glyphs.c
new file mode 100644
index 0000000..3c44640
--- /dev/null
+++ b/uxa/uxa-glyphs.c
@@ -0,0 +1,880 @@
+/*
+ * Copyright © 2008 Red Hat, Inc.
+ * Partly based on code Copyright © 2000 SuSE, Inc.
+ *
+ * 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 Red Hat not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  Red Hat makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ *
+ * Red Hat DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL Red Hat
+ * 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.
+ *
+ * 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 SuSE not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  SuSE makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ *
+ * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
+ * 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.
+ *
+ * Author: Owen Taylor <otaylor at fishsoup.net>
+ * Based on code by: Keith Packard
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <stdlib.h>
+
+#include "uxa-priv.h"
+
+#include "mipict.h"
+
+#if DEBUG_GLYPH_CACHE
+#define DBG_GLYPH_CACHE(a) ErrorF a
+#else
+#define DBG_GLYPH_CACHE(a)
+#endif
+
+/* Width of the pixmaps we use for the caches; this should be less than
+ * max texture size of the driver; this may need to actually come from
+ * the driver.
+ */
+#define CACHE_PICTURE_WIDTH 1024
+
+/* Maximum number of glyphs we buffer on the stack before flushing
+ * rendering to the mask or destination surface.
+ */
+#define GLYPH_BUFFER_SIZE 256
+
+typedef struct {
+    PicturePtr source;
+    uxa_composite_rect_t rects[GLYPH_BUFFER_SIZE];
+    int count;
+} uxa_glyph_buffer_t;
+
+typedef enum {
+    UXA_GLYPH_SUCCESS,    /* Glyph added to render buffer */
+    UXA_GLYPH_FAIL,       /* out of memory, etc */
+    UXA_GLYPH_NEED_FLUSH, /* would evict a glyph already in the buffer */
+} uxa_glyph_cache_result_t;
+
+void
+uxa_glyphs_init(ScreenPtr pScreen)
+{
+    uxa_screen_t    *uxa_screen = uxa_get_screen(pScreen);
+    int		    i = 0;
+
+    memset(uxa_screen->glyphCaches, 0, sizeof(uxa_screen->glyphCaches));
+
+    uxa_screen->glyphCaches[i].format = PICT_a8;
+    uxa_screen->glyphCaches[i].glyphWidth = uxa_screen->glyphCaches[i].glyphHeight = 16;
+    i++;
+    uxa_screen->glyphCaches[i].format = PICT_a8;
+    uxa_screen->glyphCaches[i].glyphWidth = uxa_screen->glyphCaches[i].glyphHeight = 32;
+    i++;
+    uxa_screen->glyphCaches[i].format = PICT_a8r8g8b8;
+    uxa_screen->glyphCaches[i].glyphWidth = uxa_screen->glyphCaches[i].glyphHeight = 16;
+    i++;
+    uxa_screen->glyphCaches[i].format = PICT_a8r8g8b8;
+    uxa_screen->glyphCaches[i].glyphWidth = uxa_screen->glyphCaches[i].glyphHeight = 32;
+    i++;
+
+    assert(i == UXA_NUM_GLYPH_CACHES);
+    
+    for (i = 0; i < UXA_NUM_GLYPH_CACHES; i++) {
+	uxa_screen->glyphCaches[i].columns = CACHE_PICTURE_WIDTH / uxa_screen->glyphCaches[i].glyphWidth;
+	uxa_screen->glyphCaches[i].size = 256;
+	uxa_screen->glyphCaches[i].hashSize = 557;
+    }
+}
+
+static void
+uxa_unrealize_glyph_caches(ScreenPtr    pScreen,
+			   unsigned int format)
+{
+    uxa_screen_t    *uxa_screen = uxa_get_screen(pScreen);
+    int		    i;
+
+    for (i = 0; i < UXA_NUM_GLYPH_CACHES; i++) {
+	uxa_glyph_cache_t *cache = &uxa_screen->glyphCaches[i];
+	
+	if (cache->format != format)
+	    continue;
+
+	if (cache->picture) {
+	    FreePicture ((pointer) cache->picture, (XID) 0);
+	    cache->picture = NULL;
+	}
+
+	if (cache->hashEntries) {
+	    xfree(cache->hashEntries);
+	    cache->hashEntries = NULL;
+	}
+	
+	if (cache->glyphs) {
+	    xfree(cache->glyphs);
+	    cache->glyphs = NULL;
+	}
+	cache->glyphCount = 0;
+    }
+}
+
+/* All caches for a single format share a single pixmap for glyph storage,
+ * allowing mixing glyphs of different sizes without paying a penalty
+ * for switching between source pixmaps. (Note that for a size of font
+ * right at the border between two sizes, we might be switching for almost
+ * every glyph.)
+ *
+ * This function allocates the storage pixmap, and then fills in the
+ * rest of the allocated structures for all caches with the given format.
+ */
+static Bool
+uxa_realize_glyph_caches(ScreenPtr    pScreen,
+			 unsigned int format)
+{
+    uxa_screen_t    *uxa_screen = uxa_get_screen(pScreen);
+    int		    depth = PIXMAN_FORMAT_DEPTH(format);
+    PictFormatPtr   pPictFormat;
+    PixmapPtr	    pPixmap;
+    PicturePtr	    pPicture;
+    int		    height;
+    int		    i;
+    int		    error;
+
+    pPictFormat = PictureMatchFormat(pScreen, depth, format);
+    if (!pPictFormat)
+	return FALSE;
+    
+    /* Compute the total vertical size needed for the format */
+
+    height = 0;
+    for (i = 0; i < UXA_NUM_GLYPH_CACHES; i++) {
+	uxa_glyph_cache_t *cache = &uxa_screen->glyphCaches[i];
+	int rows;
+
+	if (cache->format != format)
+	    continue;
+
+	cache->yOffset = height;
+
+	rows = (cache->size + cache->columns - 1) / cache->columns;
+	height += rows * cache->glyphHeight;
+    }
+
+    /* Now allocate the pixmap and picture */
+       
+    pPixmap = (*pScreen->CreatePixmap) (pScreen,
+					CACHE_PICTURE_WIDTH,
+					height, depth, 0);
+    if (!pPixmap)
+	return FALSE;
+
+    pPicture = CreatePicture(0, &pPixmap->drawable, pPictFormat,
+			     0, 0, serverClient, &error);
+
+    (*pScreen->DestroyPixmap) (pPixmap); /* picture holds a refcount */
+
+    if (!pPicture)
+	return FALSE;
+
+    /* And store the picture in all the caches for the format */
+    
+    for (i = 0; i < UXA_NUM_GLYPH_CACHES; i++) {
+	uxa_glyph_cache_t *cache = &uxa_screen->glyphCaches[i];
+	int j;
+
+	if (cache->format != format)
+	    continue;
+
+	cache->picture = pPicture;
+	cache->picture->refcnt++;
+	cache->hashEntries = xalloc(sizeof(int) * cache->hashSize);
+	cache->glyphs = xalloc(sizeof(uxa_cached_glyph_t) * cache->size);
+	cache->glyphCount = 0;
+
+	if (!cache->hashEntries || !cache->glyphs)
+	    goto bail;
+
+	for (j = 0; j < cache->hashSize; j++)
+	    cache->hashEntries[j] = -1;
+	
+	cache->evictionPosition = rand() % cache->size;
+    }
+
+    /* Each cache references the picture individually */
+    FreePicture ((pointer) pPicture, (XID) 0);
+    return TRUE;
+
+bail:
+    uxa_unrealize_glyph_caches(pScreen, format);
+    return FALSE;
+}
+
+void
+uxa_glyphs_fini (ScreenPtr pScreen)
+{
+    uxa_screen_t    *uxa_screen = uxa_get_screen(pScreen);
+    int		    i;
+
+    for (i = 0; i < UXA_NUM_GLYPH_CACHES; i++) {
+	uxa_glyph_cache_t *cache = &uxa_screen->glyphCaches[i];
+
+	if (cache->picture)
+	    uxa_unrealize_glyph_caches(pScreen, cache->format);
+    }
+}
+
+static int
+uxa_glyph_cache_hash_lookup(uxa_glyph_cache_t *cache, GlyphPtr pGlyph)
+{
+    int slot;
+
+    slot = (*(CARD32 *) pGlyph->sha1) % cache->hashSize;
+    
+    while (TRUE) { /* hash table can never be full */
+	int entryPos = cache->hashEntries[slot];
+	if (entryPos == -1)
+	    return -1;
+
+	if (memcmp(pGlyph->sha1, cache->glyphs[entryPos].sha1, sizeof(pGlyph->sha1)) == 0){
+	    return entryPos;
+	}
+	    
+	slot--;
+	if (slot < 0)
+	    slot = cache->hashSize - 1;
+    }
+}
+
+static void
+uxa_glyph_cache_hash_insert(uxa_glyph_cache_t *cache,
+			GlyphPtr         pGlyph,
+			int              pos)
+{
+    int slot;
+
+    memcpy(cache->glyphs[pos].sha1, pGlyph->sha1, sizeof(pGlyph->sha1));
+    
+    slot = (*(CARD32 *) pGlyph->sha1) % cache->hashSize;
+    
+    while (TRUE) { /* hash table can never be full */
+	if (cache->hashEntries[slot] == -1) {
+	    cache->hashEntries[slot] = pos;
+	    return;
+	}
+	    
+	slot--;
+	if (slot < 0)
+	    slot = cache->hashSize - 1;
+    }
+}
+
+static void
+uxa_glyph_cache_hash_remove(uxa_glyph_cache_t *cache,
+			int              pos)
+{
+    int slot;
+    int emptiedSlot = -1;
+
+    slot = (*(CARD32 *) cache->glyphs[pos].sha1) % cache->hashSize;
+
+    while (TRUE) { /* hash table can never be full */
+	int entryPos = cache->hashEntries[slot];
+	
+	if (entryPos == -1)
+	    return;
+
+	if (entryPos == pos) {
+	    cache->hashEntries[slot] = -1;
+	    emptiedSlot = slot;
+	} else if (emptiedSlot != -1) {
+	    /* See if we can move this entry into the emptied slot, we can't
+	     * do that if if entry would have hashed between the current position
+	     * and the emptied slot. (taking wrapping into account). Bad positions
+	     * are:
+	     *
+	     * |   XXXXXXXXXX             |
+	     *     i         j            
+	     *                            
+	     * |XXX                   XXXX|
+	     *     j                  i
+	     *
+	     * i - slot, j - emptiedSlot
+	     *
+	     * (Knuth 6.4R)
+	     */
+	    
+	    int entrySlot = (*(CARD32 *) cache->glyphs[entryPos].sha1) % cache->hashSize;
+
+	    if (!((entrySlot >= slot && entrySlot < emptiedSlot) ||
+		  (emptiedSlot < slot && (entrySlot < emptiedSlot || entrySlot >= slot)))) 
+	    {
+		cache->hashEntries[emptiedSlot] = entryPos;
+		cache->hashEntries[slot] = -1;
+		emptiedSlot = slot;
+	    }
+	}
+	
+	slot--;
+	if (slot < 0)
+	    slot = cache->hashSize - 1;
+    }
+}
+
+#define CACHE_X(pos) (((pos) % cache->columns) * cache->glyphWidth)
+#define CACHE_Y(pos) (cache->yOffset + ((pos) / cache->columns) * cache->glyphHeight)
+
+/* The most efficient thing to way to upload the glyph to the screen
+ * is to use the UploadToScreen() driver hook; this allows us to
+ * pipeline glyph uploads and to avoid creating offscreen pixmaps for
+ * glyphs that we'll never use again.
+ */
+static Bool
+uxa_glyph_cache_upload_glyph(ScreenPtr		    pScreen,
+			     uxa_glyph_cache_t	    *cache,
+			     int		    pos,
+			     GlyphPtr		    pGlyph)
+{
+    uxa_screen_t    *uxa_screen = uxa_get_screen(pScreen);
+    PicturePtr	    pGlyphPicture = GlyphPicture(pGlyph)[pScreen->myNum];
+    PixmapPtr	    pGlyphPixmap = (PixmapPtr)pGlyphPicture->pDrawable;
+    PixmapPtr	    pCachePixmap = (PixmapPtr)cache->picture->pDrawable;
+    int		    cacheXoff, cacheYoff;
+
+    if (!uxa_screen->info->UploadToScreen || uxa_screen->swappedOut)
+	return FALSE;
+
+    /* If the glyph pixmap is already uploaded, no point in doing
+     * things this way */
+    if (uxa_pixmap_is_offscreen(pGlyphPixmap))
+	return FALSE;
+
+    /* UploadToScreen only works if bpp match */
+    if (pGlyphPixmap->drawable.bitsPerPixel != pCachePixmap->drawable.bitsPerPixel)
+	return FALSE;
+
+    pCachePixmap = uxa_get_offscreen_pixmap ((DrawablePtr)pCachePixmap, &cacheXoff, &cacheYoff);
+    if (!pCachePixmap)
+	return FALSE;
+
+    if (!uxa_screen->info->UploadToScreen(pCachePixmap,
+					  CACHE_X(pos) + cacheXoff,
+					  CACHE_Y(pos) + cacheYoff,
+					  pGlyph->info.width,
+					  pGlyph->info.height,
+					  (char *)pGlyphPixmap->devPrivate.ptr,
+					  pGlyphPixmap->devKind))
+	return FALSE;
+
+    return TRUE;
+}
+
+static uxa_glyph_cache_result_t
+uxa_glyph_cache_buffer_glyph(ScreenPtr		pScreen,
+			     uxa_glyph_cache_t	*cache,
+			     uxa_glyph_buffer_t *buffer,
+			     GlyphPtr		pGlyph,
+			     int		xGlyph,
+			     int		yGlyph)
+{
+    uxa_composite_rect_t    *rect;
+    int			    pos;
+    
+    if (buffer->source && buffer->source != cache->picture)
+	return UXA_GLYPH_NEED_FLUSH;
+
+    if (!cache->picture) {
+	if (!uxa_realize_glyph_caches(pScreen, cache->format))
+	    return UXA_GLYPH_FAIL;
+    }
+
+    DBG_GLYPH_CACHE(("(%d,%d,%s): buffering glyph %lx\n",
+		     cache->glyphWidth, cache->glyphHeight, cache->format == PICT_a8 ? "A" : "ARGB",
+		     (long)*(CARD32 *) pGlyph->sha1));
+   
+    pos = uxa_glyph_cache_hash_lookup(cache, pGlyph);
+    if (pos != -1) {
+	DBG_GLYPH_CACHE(("  found existing glyph at %d\n", pos));
+    } else {
+	if (cache->glyphCount < cache->size) {
+	    /* Space remaining; we fill from the start */
+	    pos = cache->glyphCount;
+	    cache->glyphCount++;
+	    DBG_GLYPH_CACHE(("  storing glyph in free space at %d\n", pos));
+
+	    uxa_glyph_cache_hash_insert(cache, pGlyph, pos);
+
+	} else {
+	    /* Need to evict an entry. We have to see if any glyphs
+	     * already in the output buffer were at this position in
+	     * the cache
+	     */
+	    
+	    pos = cache->evictionPosition;
+	    DBG_GLYPH_CACHE(("  evicting glyph at %d\n", pos));
+	    if (buffer->count) {
+		int x, y;
+		int i;
+		
+		x = CACHE_X(pos);
+		y = CACHE_Y(pos);
+
+		for (i = 0; i < buffer->count; i++) {
+		    if (buffer->rects[i].xSrc == x && buffer->rects[i].ySrc == y) {
+			DBG_GLYPH_CACHE(("  must flush buffer\n"));
+			return UXA_GLYPH_NEED_FLUSH;
+		    }
+		}
+	    }
+
+	    /* OK, we're all set, swap in the new glyph */
+	    uxa_glyph_cache_hash_remove(cache, pos);
+	    uxa_glyph_cache_hash_insert(cache, pGlyph, pos);
+
+	    /* And pick a new eviction position */
+	    cache->evictionPosition = rand() % cache->size;
+	}
+
+	/* Now actually upload the glyph into the cache picture; if
+	 * we can't do it with UploadToScreen (because the glyph is
+	 * offscreen, etc), we fall back to CompositePicture.
+	 */
+	if (!uxa_glyph_cache_upload_glyph(pScreen, cache, pos, pGlyph)) {
+	    CompositePicture (PictOpSrc,
+			      GlyphPicture(pGlyph)[pScreen->myNum],
+			      None,
+			      cache->picture,
+			      0, 0,
+			      0, 0,
+			      CACHE_X(pos),
+			      CACHE_Y(pos),
+			      pGlyph->info.width,
+			      pGlyph->info.height);
+	}
+
+    }
+    
+
+    buffer->source = cache->picture;
+	    
+    rect = &buffer->rects[buffer->count];
+    rect->xSrc = CACHE_X(pos);
+    rect->ySrc = CACHE_Y(pos);
+    rect->xDst = xGlyph - pGlyph->info.x;
+    rect->yDst = yGlyph - pGlyph->info.y;
+    rect->width = pGlyph->info.width;
+    rect->height = pGlyph->info.height;
+	    
+    buffer->count++;
+
+    return UXA_GLYPH_SUCCESS;
+}
+
+#undef CACHE_X
+#undef CACHE_Y
+
+static uxa_glyph_cache_result_t
+uxa_buffer_glyph(ScreenPtr	    pScreen,
+		 uxa_glyph_buffer_t *buffer,
+		 GlyphPtr	    pGlyph,
+		 int		    xGlyph,
+		 int		    yGlyph)
+{
+    uxa_screen_t    *uxa_screen = uxa_get_screen(pScreen);
+    unsigned int    format = (GlyphPicture(pGlyph)[pScreen->myNum])->format;
+    int		    width = pGlyph->info.width;
+    int		    height = pGlyph->info.height;
+    uxa_composite_rect_t    *rect;
+    PicturePtr	    source;
+    int		     i;
+
+    if (buffer->count == GLYPH_BUFFER_SIZE)
+	return UXA_GLYPH_NEED_FLUSH;
+
+    if (PICT_FORMAT_BPP(format) == 1)
+	format = PICT_a8;
+    
+    for (i = 0; i < UXA_NUM_GLYPH_CACHES; i++) {
+	uxa_glyph_cache_t *cache = &uxa_screen->glyphCaches[i];
+
+	if (format == cache->format &&
+	    width <= cache->glyphWidth &&
+	    height <= cache->glyphHeight) {
+	    uxa_glyph_cache_result_t result = uxa_glyph_cache_buffer_glyph(pScreen, &uxa_screen->glyphCaches[i],
+									   buffer,
+									   pGlyph, xGlyph, yGlyph);
+	    switch (result) {
+	    case UXA_GLYPH_FAIL:
+		break;
+	    case UXA_GLYPH_SUCCESS:
+	    case UXA_GLYPH_NEED_FLUSH:
+		return result;
+	    }
+	}
+    }
+
+    /* Couldn't find the glyph in the cache, use the glyph picture directly */
+
+    source = GlyphPicture(pGlyph)[pScreen->myNum];
+    if (buffer->source && buffer->source != source)
+	return UXA_GLYPH_NEED_FLUSH;
+
+    buffer->source = source;
+    
+    rect = &buffer->rects[buffer->count];
+    rect->xSrc = 0;
+    rect->ySrc = 0;
+    rect->xDst = xGlyph - pGlyph->info.x;
+    rect->yDst = yGlyph - pGlyph->info.y;
+    rect->width = pGlyph->info.width;
+    rect->height = pGlyph->info.height;
+
+    buffer->count++;
+
+    return UXA_GLYPH_SUCCESS;
+}
+
+static void
+uxa_glyphs_to_mask(PicturePtr		pMask,
+		   uxa_glyph_buffer_t	*buffer)
+{
+    uxa_composite_rects(PictOpAdd, buffer->source, pMask,
+		      buffer->count, buffer->rects);
+    
+    buffer->count = 0;
+    buffer->source = NULL;
+}
+
+static void
+uxa_glyphs_to_dst(CARD8			op,
+		  PicturePtr		pSrc,
+		  PicturePtr		pDst,
+		  uxa_glyph_buffer_t	*buffer,
+		  INT16			xSrc,
+		  INT16			ySrc,
+		  INT16			xDst,
+		  INT16			yDst)
+{
+    int i;
+
+    for (i = 0; i < buffer->count; i++) {
+	uxa_composite_rect_t	*rect = &buffer->rects[i];
+	
+	CompositePicture (op,
+			  pSrc,
+			  buffer->source,
+			  pDst,
+			  xSrc + rect->xDst - xDst,
+			  ySrc + rect->yDst - yDst,
+			  rect->xSrc,
+			  rect->ySrc,
+			  rect->xDst,
+			  rect->yDst,
+			  rect->width,
+			  rect->height);
+    }
+    
+    buffer->count = 0;
+    buffer->source = NULL;
+}
+
+/* Cut and paste from render/glyph.c - probably should export it instead */
+static void
+uxa_glyph_extents (int		nlist,
+	      GlyphListPtr	list,
+	      GlyphPtr	       *glyphs,
+	      BoxPtr		extents)
+{
+    int		x1, x2, y1, y2;
+    int		n;
+    GlyphPtr	glyph;
+    int		x, y;
+    
+    x = 0;
+    y = 0;
+    extents->x1 = MAXSHORT;
+    extents->x2 = MINSHORT;
+    extents->y1 = MAXSHORT;
+    extents->y2 = MINSHORT;
+    while (nlist--)
+    {
+	x += list->xOff;
+	y += list->yOff;
+	n = list->len;
+	list++;
+	while (n--)
+	{
+	    glyph = *glyphs++;
+	    x1 = x - glyph->info.x;
+	    if (x1 < MINSHORT)
+		x1 = MINSHORT;
+	    y1 = y - glyph->info.y;
+	    if (y1 < MINSHORT)
+		y1 = MINSHORT;
+	    x2 = x1 + glyph->info.width;
+	    if (x2 > MAXSHORT)
+		x2 = MAXSHORT;
+	    y2 = y1 + glyph->info.height;
+	    if (y2 > MAXSHORT)
+		y2 = MAXSHORT;
+	    if (x1 < extents->x1)
+		extents->x1 = x1;
+	    if (x2 > extents->x2)
+		extents->x2 = x2;
+	    if (y1 < extents->y1)
+		extents->y1 = y1;
+	    if (y2 > extents->y2)
+		extents->y2 = y2;
+	    x += glyph->info.xOff;
+	    y += glyph->info.yOff;
+	}
+    }
+}
+
+/**
+ * Returns TRUE if the glyphs in the lists intersect.  Only checks based on
+ * bounding box, which appears to be good enough to catch most cases at least.
+ */
+static Bool
+uxa_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr *glyphs)
+{
+    int x1, x2, y1, y2;
+    int n;
+    GlyphPtr glyph;
+    int x, y;
+    BoxRec extents;
+    Bool first = TRUE;
+
+    x = 0;
+    y = 0;
+    while (nlist--) {
+       x += list->xOff;
+       y += list->yOff;
+       n = list->len;
+       list++;
+       while (n--) {
+           glyph = *glyphs++;
+
+           if (glyph->info.width == 0 || glyph->info.height == 0) {
+               x += glyph->info.xOff;
+               y += glyph->info.yOff;
+               continue;
+           }
+
+           x1 = x - glyph->info.x;
+           if (x1 < MINSHORT)
+               x1 = MINSHORT;
+           y1 = y - glyph->info.y;
+           if (y1 < MINSHORT)
+               y1 = MINSHORT;
+           x2 = x1 + glyph->info.width;
+           if (x2 > MAXSHORT)
+               x2 = MAXSHORT;
+           y2 = y1 + glyph->info.height;
+           if (y2 > MAXSHORT)
+               y2 = MAXSHORT;
+
+           if (first) {
+               extents.x1 = x1;
+               extents.y1 = y1;
+               extents.x2 = x2;
+               extents.y2 = y2;
+               first = FALSE;
+           } else {
+               if (x1 < extents.x2 && x2 > extents.x1 &&
+                   y1 < extents.y2 && y2 > extents.y1)
+               {
+                   return TRUE;
+               }
+
+               if (x1 < extents.x1)
+                  extents.x1 = x1;
+               if (x2 > extents.x2)
+                   extents.x2 = x2;
+               if (y1 < extents.y1)
+                   extents.y1 = y1;
+               if (y2 > extents.y2)
+                   extents.y2 = y2;
+           }
+           x += glyph->info.xOff;
+           y += glyph->info.yOff;
+       }
+    }
+
+    return FALSE;
+}
+
+#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0)
+
+void
+uxa_glyphs (CARD8 	 op,
+	   PicturePtr	 pSrc,
+	   PicturePtr	 pDst,
+	   PictFormatPtr maskFormat,
+	   INT16	 xSrc,
+	   INT16	 ySrc,
+	   int		 nlist,
+	   GlyphListPtr	 list,
+	   GlyphPtr	*glyphs)
+{
+    PicturePtr	pPicture;
+    PixmapPtr   pMaskPixmap = 0;
+    PicturePtr  pMask;
+    ScreenPtr   pScreen = pDst->pDrawable->pScreen;
+    int		width = 0, height = 0;
+    int		x, y;
+    int		xDst = list->xOff, yDst = list->yOff;
+    int		n;
+    GlyphPtr	glyph;
+    int		error;
+    BoxRec	extents = {0, 0, 0, 0};
+    CARD32	component_alpha;
+    uxa_glyph_buffer_t buffer;
+
+    /* If we don't have a mask format but all the glyphs have the same format
+     * and don't intersect, use the glyph format as mask format for the full
+     * benefits of the glyph cache.
+     */
+    if (!maskFormat) {
+       Bool sameFormat = TRUE;
+       int i;
+
+       maskFormat = list[0].format;
+
+       for (i = 0; i < nlist; i++) {
+           if (maskFormat->format != list[i].format->format) {
+               sameFormat = FALSE;
+               break;
+           }
+       }
+
+       if (!sameFormat || (maskFormat->depth != 1 &&
+			   uxa_glyphs_intersect(nlist, list, glyphs))) {
+	   maskFormat = NULL;
+       }
+    }
+
+    if (maskFormat)
+    {
+	GCPtr	    pGC;
+	xRectangle  rect;
+
+	uxa_glyph_extents (nlist, list, glyphs, &extents);
+
+	if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1)
+	    return;
+	width = extents.x2 - extents.x1;
+	height = extents.y2 - extents.y1;
+
+	if (maskFormat->depth == 1) {
+	    PictFormatPtr a8Format = PictureMatchFormat (pScreen, 8, PICT_a8);
+
+	    if (a8Format)
+		maskFormat = a8Format;
+	}
+
+	pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
+						maskFormat->depth,
+						CREATE_PIXMAP_USAGE_SCRATCH);
+	if (!pMaskPixmap)
+	    return;
+	component_alpha = NeedsComponent(maskFormat->format);
+	pMask = CreatePicture (0, &pMaskPixmap->drawable,
+			       maskFormat, CPComponentAlpha, &component_alpha,
+			       serverClient, &error);
+	if (!pMask)
+	{
+	    (*pScreen->DestroyPixmap) (pMaskPixmap);
+	    return;
+	}
+	pGC = GetScratchGC (pMaskPixmap->drawable.depth, pScreen);
+	ValidateGC (&pMaskPixmap->drawable, pGC);
+	rect.x = 0;
+	rect.y = 0;
+	rect.width = width;
+	rect.height = height;
+	(*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, &rect);
+	FreeScratchGC (pGC);
+	x = -extents.x1;
+	y = -extents.y1;
+    }
+    else
+    {
+	pMask = pDst;
+	x = 0;
+	y = 0;
+    }
+    buffer.count = 0;
+    buffer.source = NULL;
+    while (nlist--)
+    {
+	x += list->xOff;
+	y += list->yOff;
+	n = list->len;
+	while (n--)
+	{
+	    glyph = *glyphs++;
+	    pPicture = GlyphPicture (glyph)[pScreen->myNum];
+
+	    if (glyph->info.width > 0 && glyph->info.height > 0 &&
+		uxa_buffer_glyph(pScreen, &buffer, glyph, x, y) == UXA_GLYPH_NEED_FLUSH)
+	    {
+		if (maskFormat)
+		    uxa_glyphs_to_mask(pMask, &buffer);
+		else
+		    uxa_glyphs_to_dst(op, pSrc, pDst, &buffer,
+				   xSrc, ySrc, xDst, yDst);
+
+		uxa_buffer_glyph(pScreen, &buffer, glyph, x, y);
+	    }
+
+	    x += glyph->info.xOff;
+	    y += glyph->info.yOff;
+	}
+	list++;
+    }
+    
+    if (maskFormat)
+	uxa_glyphs_to_mask(pMask, &buffer);
+    else
+	uxa_glyphs_to_dst(op, pSrc, pDst, &buffer,
+		       xSrc, ySrc, xDst, yDst);
+    
+    if (maskFormat)
+    {
+	x = extents.x1;
+	y = extents.y1;
+	CompositePicture (op,
+			  pSrc,
+			  pMask,
+			  pDst,
+			  xSrc + x - xDst,
+			  ySrc + y - yDst,
+			  0, 0,
+			  x, y,
+			  width, height);
+	FreePicture ((pointer) pMask, (XID) 0);
+	(*pScreen->DestroyPixmap) (pMaskPixmap);
+    }
+}
diff --git a/uxa/uxa-priv.h b/uxa/uxa-priv.h
new file mode 100644
index 0000000..acc82bb
--- /dev/null
+++ b/uxa/uxa-priv.h
@@ -0,0 +1,444 @@
+/*
+ *
+ * Copyright © 2000,2008 Keith Packard
+ *             2005 Zack Rusin, Trolltech
+ *
+ * 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 Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  Keith Packard makes 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 UXAPRIV_H
+#define UXAPRIV_H
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#else
+#include <xorg-server.h>
+#endif
+
+#include "uxa.h"
+
+#include <X11/X.h>
+#define NEED_EVENTS
+#include <X11/Xproto.h>
+#ifdef MITSHM
+#define _XSHM_SERVER_
+#include <X11/extensions/shmstr.h>
+#endif
+#include "scrnintstr.h"
+#include "pixmapstr.h"
+#include "windowstr.h"
+#include "servermd.h"
+#include "mibstore.h"
+#include "colormapst.h"
+#include "gcstruct.h"
+#include "input.h"
+#include "mipointer.h"
+#include "mi.h"
+#include "dix.h"
+#include "fb.h"
+#include "fboverlay.h"
+#ifdef RENDER
+//#include "fbpict.h"
+#include "glyphstr.h"
+#endif
+#include "damage.h"
+
+#define DEBUG_TRACE_FALL	0
+#define DEBUG_MIGRATE		0
+#define DEBUG_PIXMAP		0
+#define DEBUG_OFFSCREEN		0
+#define DEBUG_GLYPH_CACHE	0
+
+#if DEBUG_TRACE_FALL
+#define UXA_FALLBACK(x)     					\
+do {								\
+	ErrorF("UXA fallback at %s: ", __FUNCTION__);		\
+	ErrorF x;						\
+} while (0)
+
+char
+uxa_drawable_location(DrawablePtr pDrawable);
+#else
+#define UXA_FALLBACK(x)
+#endif
+
+#if DEBUG_PIXMAP
+#define DBG_PIXMAP(a) ErrorF a
+#else
+#define DBG_PIXMAP(a)
+#endif
+
+typedef struct {
+    unsigned char sha1[20];
+} uxa_cached_glyph_t;
+
+typedef struct {
+    /* The identity of the cache, statically configured at initialization */
+    unsigned int format;
+    int glyphWidth;
+    int glyphHeight;
+
+    int size; /* Size of cache; eventually this should be dynamically determined */
+
+    /* Hash table mapping from glyph sha1 to position in the glyph; we use
+     * open addressing with a hash table size determined based on size and large
+     * enough so that we always have a good amount of free space, so we can
+     * use linear probing. (Linear probing is preferrable to double hashing
+     * here because it allows us to easily remove entries.)
+     */
+    int *hashEntries;
+    int hashSize;
+    
+    uxa_cached_glyph_t *glyphs;
+    int glyphCount; /* Current number of glyphs */
+    
+    PicturePtr picture;   /* Where the glyphs of the cache are stored */
+    int yOffset;          /* y location within the picture where the cache starts */
+    int columns;          /* Number of columns the glyphs are layed out in */
+    int evictionPosition; /* Next random position to evict a glyph */
+} uxa_glyph_cache_t;
+
+#define UXA_NUM_GLYPH_CACHES 4
+
+typedef void (*EnableDisableFBAccessProcPtr)(int, Bool);
+typedef struct {
+    uxa_driver_t		*info;
+    CreateGCProcPtr 		 SavedCreateGC;
+    CloseScreenProcPtr 		 SavedCloseScreen;
+    GetImageProcPtr 		 SavedGetImage;
+    GetSpansProcPtr 		 SavedGetSpans;
+    CreatePixmapProcPtr 	 SavedCreatePixmap;
+    DestroyPixmapProcPtr 	 SavedDestroyPixmap;
+    CopyWindowProcPtr 		 SavedCopyWindow;
+    ChangeWindowAttributesProcPtr SavedChangeWindowAttributes;
+    BitmapToRegionProcPtr        SavedBitmapToRegion;
+#ifdef RENDER
+    CompositeProcPtr             SavedComposite;
+    TrianglesProcPtr		 SavedTriangles;
+    GlyphsProcPtr                SavedGlyphs;
+    TrapezoidsProcPtr            SavedTrapezoids;
+    AddTrapsProcPtr		 SavedAddTraps;
+#endif
+  
+    Bool			 swappedOut;
+    unsigned			 disableFbCount;
+    unsigned			 offScreenCounter;
+
+    uxa_glyph_cache_t             glyphCaches[UXA_NUM_GLYPH_CACHES];
+} uxa_screen_t;
+
+/*
+ * This is the only completely portable way to
+ * compute this info.
+ */
+#ifndef BitsPerPixel
+#define BitsPerPixel(d) (\
+    PixmapWidthPaddingInfo[d].notPower2 ? \
+    (PixmapWidthPaddingInfo[d].bytesPerPixel * 8) : \
+    ((1 << PixmapWidthPaddingInfo[d].padBytesLog2) * 8 / \
+    (PixmapWidthPaddingInfo[d].padRoundUp+1)))
+#endif
+
+extern DevPrivateKey uxa_screen_key;
+#define uxa_get_screen(s) ((uxa_screen_t *)dixLookupPrivate(&(s)->devPrivates, uxa_screen_key))
+
+/** Align an offset to an arbitrary alignment */
+#define UXA_ALIGN(offset, align) (((offset) + (align) - 1) - \
+	(((offset) + (align) - 1) % (align)))
+/** Align an offset to a power-of-two alignment */
+#define UXA_ALIGN2(offset, align) (((offset) + (align) - 1) & ~((align) - 1))
+
+typedef struct {
+    INT16 xSrc;
+    INT16 ySrc;
+    INT16 xDst;
+    INT16 yDst;
+    INT16 width;
+    INT16 height;
+} uxa_composite_rect_t;
+
+/**
+ * exaDDXDriverInit must be implemented by the DDX using EXA, and is the place
+ * to set EXA options or hook in screen functions to handle using EXA as the AA.
+  */
+void exaDDXDriverInit (ScreenPtr pScreen);
+
+void
+uxa_prepare_access_window(WindowPtr pWin);
+
+void
+uxa_finish_access_window(WindowPtr pWin);
+
+/* uxa-unaccel.c */
+void
+uxa_prepare_access_gc(GCPtr pGC);
+
+void
+uxa_finish_access_gc(GCPtr pGC);
+
+void
+uxa_check_fill_spans  (DrawablePtr pDrawable, GCPtr pGC, int nspans,
+		   DDXPointPtr ppt, int *pwidth, int fSorted);
+
+void
+uxa_check_set_spans (DrawablePtr pDrawable, GCPtr pGC, char *psrc,
+		 DDXPointPtr ppt, int *pwidth, int nspans, int fSorted);
+
+void
+uxa_check_put_image (DrawablePtr pDrawable, GCPtr pGC, int depth,
+		 int x, int y, int w, int h, int leftPad, int format,
+		 char *bits);
+
+RegionPtr
+uxa_check_copy_area (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
+		 int srcx, int srcy, int w, int h, int dstx, int dsty);
+
+RegionPtr
+uxa_check_copy_plane (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
+		  int srcx, int srcy, int w, int h, int dstx, int dsty,
+		  unsigned long bitPlane);
+
+void
+uxa_check_poly_point (DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
+		  DDXPointPtr pptInit);
+
+void
+uxa_check_poly_lines (DrawablePtr pDrawable, GCPtr pGC,
+		  int mode, int npt, DDXPointPtr ppt);
+
+void
+uxa_check_poly_segment (DrawablePtr pDrawable, GCPtr pGC,
+		    int nsegInit, xSegment *pSegInit);
+
+void
+uxa_check_poly_arc (DrawablePtr pDrawable, GCPtr pGC,
+		int narcs, xArc *pArcs);
+
+void
+uxa_check_poly_fill_rect (DrawablePtr pDrawable, GCPtr pGC,
+		     int nrect, xRectangle *prect);
+
+void
+uxa_check_image_glyph_blt (DrawablePtr pDrawable, GCPtr pGC,
+		      int x, int y, unsigned int nglyph,
+		      CharInfoPtr *ppci, pointer pglyphBase);
+
+void
+uxa_check_poly_glyph_blt (DrawablePtr pDrawable, GCPtr pGC,
+		     int x, int y, unsigned int nglyph,
+		     CharInfoPtr *ppci, pointer pglyphBase);
+
+void
+uxa_check_push_pixels (GCPtr pGC, PixmapPtr pBitmap,
+		   DrawablePtr pDrawable,
+		   int w, int h, int x, int y);
+
+void
+uxa_check_get_spans (DrawablePtr pDrawable,
+		 int wMax,
+		 DDXPointPtr ppt,
+		 int *pwidth,
+		 int nspans,
+		 char *pdstStart);
+
+void
+uxa_check_add_traps (PicturePtr	pPicture,
+		  INT16		x_off,
+		  INT16		y_off,
+		  int		ntrap,
+		  xTrap		*traps);
+
+/* uxa-accel.c */
+
+static _X_INLINE Bool
+uxa_gc_reads_destination(DrawablePtr pDrawable, unsigned long planemask,
+		      unsigned int fillStyle, unsigned char alu)
+{
+    return ((alu != GXcopy && alu != GXclear &&alu != GXset &&
+	     alu != GXcopyInverted) || fillStyle == FillStippled ||
+	    !UXA_PM_IS_SOLID(pDrawable, planemask));
+}
+
+void
+uxa_copy_window(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc);
+
+Bool
+uxa_fill_region_tiled (DrawablePtr	pDrawable, RegionPtr pRegion, PixmapPtr pTile,
+		    DDXPointPtr pPatOrg, CARD32 planemask, CARD32 alu);
+
+void
+uxa_shm_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth, unsigned int format,
+	       int w, int h, int sx, int sy, int sw, int sh, int dx, int dy,
+	       char *data);
+
+void
+uxa_get_image (DrawablePtr pDrawable, int x, int y, int w, int h,
+	     unsigned int format, unsigned long planeMask, char *d);
+
+extern const GCOps uxa_ops;
+
+#ifdef MITSHM
+extern ShmFuncs uxa_shm_funcs;
+
+/* XXX these come from shmint.h, which isn't exported by the server */
+void
+ShmRegisterFuncs(ScreenPtr pScreen, ShmFuncsPtr funcs);
+
+void
+ShmSetPixmapFormat(ScreenPtr pScreen, int format);
+
+void
+fbShmPutImage(XSHM_PUT_IMAGE_ARGS);
+
+#endif
+
+#ifdef RENDER
+
+/* XXX these are in fbpict.h, which is not installed */
+void
+fbComposite (CARD8      op,
+	     PicturePtr pSrc,
+	     PicturePtr pMask,
+	     PicturePtr pDst,
+	     INT16      xSrc,
+	     INT16      ySrc,
+	     INT16      xMask,
+	     INT16      yMask,
+	     INT16      xDst,
+	     INT16      yDst,
+	     CARD16     width,
+	     CARD16     height);
+
+void
+fbAddTraps (PicturePtr	pPicture,
+	    INT16	xOff,
+	    INT16	yOff,
+	    int		ntrap,
+	    xTrap	*traps);
+
+void
+uxa_check_composite (CARD8      op,
+		  PicturePtr pSrc,
+		  PicturePtr pMask,
+		  PicturePtr pDst,
+		  INT16      xSrc,
+		  INT16      ySrc,
+		  INT16      xMask,
+		  INT16      yMask,
+		  INT16      xDst,
+		  INT16      yDst,
+		  CARD16     width,
+		  CARD16     height);
+#endif
+
+/* uxa.c */
+void
+uxa_prepare_access(DrawablePtr pDrawable, int index);
+
+void
+uxa_finish_access(DrawablePtr pDrawable, int index);
+
+void
+uxa_get_drawable_deltas (DrawablePtr pDrawable, PixmapPtr pPixmap,
+		      int *xp, int *yp);
+
+Bool
+uxa_drawable_is_offscreen (DrawablePtr pDrawable);
+
+Bool
+uxa_pixmap_is_offscreen(PixmapPtr p);
+
+PixmapPtr
+uxa_get_offscreen_pixmap (DrawablePtr pDrawable, int *xp, int *yp);
+
+PixmapPtr
+uxa_get_drawable_pixmap(DrawablePtr pDrawable);
+
+RegionPtr
+uxa_copy_area(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
+	    int srcx, int srcy, int width, int height, int dstx, int dsty);
+
+void
+uxa_copy_n_to_n (DrawablePtr    pSrcDrawable,
+	     DrawablePtr    pDstDrawable,
+	     GCPtr	    pGC,
+	     BoxPtr	    pbox,
+	     int	    nbox,
+	     int	    dx,
+	     int	    dy,
+	     Bool	    reverse,
+	     Bool	    upsidedown,
+	     Pixel	    bitplane,
+	     void	    *closure);
+
+/* uxa_render.c */
+Bool
+uxa_op_reads_destination (CARD8 op);
+
+void
+uxa_composite(CARD8	op,
+	     PicturePtr pSrc,
+	     PicturePtr pMask,
+	     PicturePtr pDst,
+	     INT16	xSrc,
+	     INT16	ySrc,
+	     INT16	xMask,
+	     INT16	yMask,
+	     INT16	xDst,
+	     INT16	yDst,
+	     CARD16	width,
+	     CARD16	height);
+
+void
+uxa_composite_rects(CARD8	            op,
+		    PicturePtr		    pSrc,
+		    PicturePtr		    pDst,
+		    int			    nrect,
+		    uxa_composite_rect_t    *rects);
+
+void
+uxa_trapezoids (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+		PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+		int ntrap, xTrapezoid *traps);
+
+void
+uxa_triangles (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+	       PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+	       int ntri, xTriangle *tris);
+
+/* uxa_glyph.c */
+void
+uxa_glyphs_init(ScreenPtr pScreen);
+
+void
+uxa_glyphs_fini (ScreenPtr pScreen);
+
+void
+uxa_glyphs (CARD8	op,
+	  PicturePtr	pSrc,
+	  PicturePtr	pDst,
+	  PictFormatPtr	maskFormat,
+	  INT16		xSrc,
+	  INT16		ySrc,
+	  int		nlist,
+	  GlyphListPtr	list,
+	  GlyphPtr	*glyphs);
+
+#endif /* UXAPRIV_H */
diff --git a/uxa/uxa-render.c b/uxa/uxa-render.c
new file mode 100644
index 0000000..38e6088
--- /dev/null
+++ b/uxa/uxa-render.c
@@ -0,0 +1,1052 @@
+/*
+ * Copyright © 2001 Keith Packard
+ *
+ * Partly based on code that is Copyright © The XFree86 Project Inc.
+ *
+ * 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 Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  Keith Packard makes no
+ * representations about the suitability of this software for any purpose.  It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 <stdlib.h>
+
+#include "uxa-priv.h"
+
+#ifdef RENDER
+#include "mipict.h"
+
+#if DEBUG_TRACE_FALL
+static void uxa_composite_fallback_pict_desc(PicturePtr pict, char *string, int n)
+{
+    char format[20];
+    char size[20];
+    char loc;
+    int temp;
+
+    if (!pict) {
+	snprintf(string, n, "None");
+	return;
+    }
+
+    switch (pict->format)
+    {
+    case PICT_a8r8g8b8:
+	snprintf(format, 20, "ARGB8888");
+	break;
+    case PICT_x8r8g8b8:
+	snprintf(format, 20, "XRGB8888");
+	break;
+    case PICT_r5g6b5:
+	snprintf(format, 20, "RGB565  ");
+	break;
+    case PICT_x1r5g5b5:
+	snprintf(format, 20, "RGB555  ");
+	break;
+    case PICT_a8:
+	snprintf(format, 20, "A8      ");
+	break;
+    case PICT_a1:
+	snprintf(format, 20, "A1      ");
+	break;
+    default:
+	snprintf(format, 20, "0x%x", (int)pict->format);
+	break;
+    }
+
+    loc = uxa_get_drawable_pixmap(pict->pDrawable, &temp, &temp) ? 's' : 'm';
+
+    snprintf(size, 20, "%dx%d%s", pict->pDrawable->width,
+	     pict->pDrawable->height, pict->repeat ?
+	     " R" : "");
+
+    snprintf(string, n, "%p:%c fmt %s (%s)", pict->pDrawable, loc, format, size);
+}
+
+static void
+uxa_print_composite_fallback(CARD8 op,
+			  PicturePtr pSrc,
+			  PicturePtr pMask,
+			  PicturePtr pDst)
+{
+    char sop[20];
+    char srcdesc[40], maskdesc[40], dstdesc[40];
+
+    switch(op)
+    {
+    case PictOpSrc:
+	sprintf(sop, "Src");
+	break;
+    case PictOpOver:
+	sprintf(sop, "Over");
+	break;
+    default:
+	sprintf(sop, "0x%x", (int)op);
+	break;
+    }
+
+    uxa_composite_fallback_pict_desc(pSrc, srcdesc, 40);
+    uxa_composite_fallback_pict_desc(pMask, maskdesc, 40);
+    uxa_composite_fallback_pict_desc(pDst, dstdesc, 40);
+
+    ErrorF("Composite fallback: op %s, \n"
+	   "                    src  %s, \n"
+	   "                    mask %s, \n"
+	   "                    dst  %s, \n",
+	   sop, srcdesc, maskdesc, dstdesc);
+}
+#endif /* DEBUG_TRACE_FALL */
+
+Bool
+uxa_op_reads_destination (CARD8 op)
+{
+    /* FALSE (does not read destination) is the list of ops in the protocol
+     * document with "0" in the "Fb" column and no "Ab" in the "Fa" column.
+     * That's just Clear and Src.  ReduceCompositeOp() will already have
+     * converted con/disjoint clear/src to Clear or Src.
+     */
+    switch (op) {
+    case PictOpClear:
+    case PictOpSrc:
+	return FALSE;
+    default:
+	return TRUE;
+    }
+}
+
+
+static Bool
+uxa_get_pixel_from_rgba(CARD32	*pixel,
+		    CARD16	red,
+		    CARD16	green,
+		    CARD16	blue,
+		    CARD16	alpha,
+		    CARD32	format)
+{
+    int rbits, bbits, gbits, abits;
+    int rshift, bshift, gshift, ashift;
+
+    *pixel = 0;
+
+    if (!PICT_FORMAT_COLOR(format))
+	return FALSE;
+
+    rbits = PICT_FORMAT_R(format);
+    gbits = PICT_FORMAT_G(format);
+    bbits = PICT_FORMAT_B(format);
+    abits = PICT_FORMAT_A(format);
+
+    if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) {
+	bshift = 0;
+	gshift = bbits;
+	rshift = gshift + gbits;
+	ashift = rshift + rbits;
+    } else {  /* PICT_TYPE_ABGR */
+	rshift = 0;
+	gshift = rbits;
+	bshift = gshift + gbits;
+	ashift = bshift + bbits;
+    }
+
+    *pixel |=  ( blue >> (16 - bbits)) << bshift;
+    *pixel |=  (  red >> (16 - rbits)) << rshift;
+    *pixel |=  (green >> (16 - gbits)) << gshift;
+    *pixel |=  (alpha >> (16 - abits)) << ashift;
+
+    return TRUE;
+}
+
+static Bool
+uxa_get_rgba_from_pixel(CARD32	pixel,
+		    CARD16	*red,
+		    CARD16	*green,
+		    CARD16	*blue,
+		    CARD16	*alpha,
+		    CARD32	format)
+{
+    int rbits, bbits, gbits, abits;
+    int rshift, bshift, gshift, ashift;
+
+    if (!PICT_FORMAT_COLOR(format))
+	return FALSE;
+
+    rbits = PICT_FORMAT_R(format);
+    gbits = PICT_FORMAT_G(format);
+    bbits = PICT_FORMAT_B(format);
+    abits = PICT_FORMAT_A(format);
+
+    if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) {
+	bshift = 0;
+	gshift = bbits;
+	rshift = gshift + gbits;
+	ashift = rshift + rbits;
+    } else {  /* PICT_TYPE_ABGR */
+	rshift = 0;
+	gshift = rbits;
+	bshift = gshift + gbits;
+	ashift = bshift + bbits;
+    }
+
+    *red = ((pixel >> rshift ) & ((1 << rbits) - 1)) << (16 - rbits);
+    while (rbits < 16) {
+	*red |= *red >> rbits;
+	rbits <<= 1;
+    }
+
+    *green = ((pixel >> gshift ) & ((1 << gbits) - 1)) << (16 - gbits);
+    while (gbits < 16) {
+	*green |= *green >> gbits;
+	gbits <<= 1;
+    }
+
+    *blue = ((pixel >> bshift ) & ((1 << bbits) - 1)) << (16 - bbits);
+    while (bbits < 16) {
+	*blue |= *blue >> bbits;
+	bbits <<= 1;
+    }
+
+    if (abits) {
+	*alpha = ((pixel >> ashift ) & ((1 << abits) - 1)) << (16 - abits);
+	while (abits < 16) {
+	    *alpha |= *alpha >> abits;
+	    abits <<= 1;
+	}
+    } else
+	*alpha = 0xffff;
+
+    return TRUE;
+}
+
+static int
+uxa_try_driver_solid_fill(PicturePtr	pSrc,
+		      PicturePtr	pDst,
+		      INT16		xSrc,
+		      INT16		ySrc,
+		      INT16		xDst,
+		      INT16		yDst,
+		      CARD16		width,
+		      CARD16		height)
+{
+    uxa_screen_t    *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen);
+    RegionRec region;
+    BoxPtr pbox;
+    int nbox;
+    int dst_off_x, dst_off_y;
+    PixmapPtr pSrcPix, pDstPix;
+    CARD32 pixel;
+    CARD16 red, green, blue, alpha;
+
+    pDstPix = uxa_get_drawable_pixmap (pDst->pDrawable);
+    pSrcPix = uxa_get_drawable_pixmap (pSrc->pDrawable);
+
+    xDst += pDst->pDrawable->x;
+    yDst += pDst->pDrawable->y;
+    xSrc += pSrc->pDrawable->x;
+    ySrc += pSrc->pDrawable->y;
+
+    if (!miComputeCompositeRegion (&region, pSrc, NULL, pDst,
+				   xSrc, ySrc, 0, 0, xDst, yDst,
+				   width, height))
+	return 1;
+
+    uxa_get_drawable_deltas (pDst->pDrawable, pDstPix, &dst_off_x, &dst_off_y);
+
+    REGION_TRANSLATE(pScreen, &region, dst_off_x, dst_off_y);
+
+    pixel = uxa_get_pixmap_first_pixel (pSrcPix);
+
+    if (!uxa_pixmap_is_offscreen(pDstPix)) {
+	REGION_UNINIT(pDst->pDrawable->pScreen, &region);
+	return 0;
+    }
+
+    if (!uxa_get_rgba_from_pixel(pixel, &red, &green, &blue, &alpha,
+			 pSrc->format))
+    {
+	REGION_UNINIT(pDst->pDrawable->pScreen, &region);
+	return -1;
+    }
+
+    if (!uxa_get_pixel_from_rgba(&pixel, red, green, blue, alpha,
+			pDst->format))
+    {
+	REGION_UNINIT(pDst->pDrawable->pScreen, &region);
+	return -1;
+    }
+
+    if (!(*uxa_screen->info->PrepareSolid) (pDstPix, GXcopy, 0xffffffff, pixel))
+    {
+	REGION_UNINIT(pDst->pDrawable->pScreen, &region);
+	return -1;
+    }
+
+    nbox = REGION_NUM_RECTS(&region);
+    pbox = REGION_RECTS(&region);
+
+    while (nbox--)
+    {
+	(*uxa_screen->info->Solid) (pDstPix, pbox->x1, pbox->y1, pbox->x2, pbox->y2);
+	pbox++;
+    }
+
+    (*uxa_screen->info->DoneSolid) (pDstPix);
+    uxa_mark_sync(pDst->pDrawable->pScreen);
+
+    REGION_UNINIT(pDst->pDrawable->pScreen, &region);
+    return 1;
+}
+
+static int
+uxa_try_driver_composite_rects(CARD8	       op,
+			   PicturePtr	       pSrc,
+			   PicturePtr	       pDst,
+			   int                 nrect,
+			   uxa_composite_rect_t *rects)
+{
+    uxa_screen_t    *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen);
+    int src_off_x, src_off_y, dst_off_x, dst_off_y;
+    PixmapPtr pSrcPix, pDstPix;
+    struct _Pixmap scratch;
+
+    if (!uxa_screen->info->PrepareComposite)
+	return -1;
+
+    pSrcPix = uxa_get_drawable_pixmap(pSrc->pDrawable);
+
+    pDstPix = uxa_get_drawable_pixmap(pDst->pDrawable);
+
+    if (uxa_screen->info->CheckComposite &&
+	!(*uxa_screen->info->CheckComposite) (op, pSrc, NULL, pDst))
+    {
+	return -1;
+    }
+    
+    uxa_get_drawable_deltas (pDst->pDrawable, pDstPix, &dst_off_x, &dst_off_y);
+	
+    pSrcPix = uxa_get_offscreen_pixmap (pSrc->pDrawable, &src_off_x, &src_off_y);
+    if (!uxa_pixmap_is_offscreen(pDstPix))
+	return 0;
+    
+    if (!pSrcPix && uxa_screen->info->UploadToScratch)
+    {
+	pSrcPix = uxa_get_drawable_pixmap (pSrc->pDrawable);
+	if ((*uxa_screen->info->UploadToScratch) (pSrcPix, &scratch))
+	    pSrcPix = &scratch;
+    }
+
+    if (!pSrcPix)
+	return 0;
+
+    if (!(*uxa_screen->info->PrepareComposite) (op, pSrc, NULL, pDst, pSrcPix,
+					     NULL, pDstPix))
+	return -1;
+
+    while (nrect--)
+    {
+	INT16 xDst = rects->xDst + pDst->pDrawable->x;
+	INT16 yDst = rects->yDst + pDst->pDrawable->y;
+	INT16 xSrc = rects->xSrc + pSrc->pDrawable->x;
+	INT16 ySrc = rects->ySrc + pSrc->pDrawable->y;
+	
+	RegionRec region;
+	BoxPtr pbox;
+	int nbox;
+	
+	if (!miComputeCompositeRegion (&region, pSrc, NULL, pDst,
+				       xSrc, ySrc, 0, 0, xDst, yDst,
+				       rects->width, rects->height))
+	    goto next_rect;
+	
+	REGION_TRANSLATE(pScreen, &region, dst_off_x, dst_off_y);
+	
+	nbox = REGION_NUM_RECTS(&region);
+	pbox = REGION_RECTS(&region);
+
+	xSrc = xSrc + src_off_x - xDst - dst_off_x;
+	ySrc = ySrc + src_off_y - yDst - dst_off_y;
+	
+	while (nbox--)
+	{
+	    (*uxa_screen->info->Composite) (pDstPix,
+					 pbox->x1 + xSrc,
+					 pbox->y1 + ySrc,
+					 0, 0,
+					 pbox->x1,
+					 pbox->y1,
+					 pbox->x2 - pbox->x1,
+					 pbox->y2 - pbox->y1);
+	    pbox++;
+	}
+
+    next_rect:
+	REGION_UNINIT(pDst->pDrawable->pScreen, &region);
+
+	rects++;
+    }
+    
+    (*uxa_screen->info->DoneComposite) (pDstPix);
+    uxa_mark_sync(pDst->pDrawable->pScreen);
+	
+    return 1;
+}
+
+/**
+ * Copy a number of rectangles from source to destination in a single
+ * operation. This is specialized for building a glyph mask: we don'y
+ * have a mask argument because we don't need it for that, and we
+ * don't have he special-case fallbacks found in uxa_composite() - if the
+ * driver can support it, we use the driver functionality, otherwise we
+ * fallback straight to software.
+ */
+void
+uxa_composite_rects(CARD8	          op,
+		    PicturePtr		  pSrc,
+		    PicturePtr		  pDst,
+		    int			  nrect,
+		    uxa_composite_rect_t  *rects)
+{
+    int			   n;
+    uxa_composite_rect_t   *r;
+    
+    /************************************************************/
+    
+    ValidatePicture (pSrc);
+    ValidatePicture (pDst);
+    
+    if (uxa_try_driver_composite_rects(op, pSrc, pDst, nrect, rects) != 1) {
+	n = nrect;
+	r = rects;
+	while (n--) {
+	    uxa_check_composite (op, pSrc, NULL, pDst,
+			       r->xSrc, r->ySrc,
+			       0, 0,
+			       r->xDst, r->yDst,
+			       r->width, r->height);
+	    r++;
+	}
+    }
+    
+    /************************************************************/
+
+}
+
+static int
+uxa_try_driver_composite(CARD8		op,
+			 PicturePtr	pSrc,
+			 PicturePtr	pMask,
+			 PicturePtr	pDst,
+			 INT16		xSrc,
+			 INT16		ySrc,
+			 INT16		xMask,
+			 INT16		yMask,
+			 INT16		xDst,
+			 INT16		yDst,
+			 CARD16		width,
+			 CARD16		height)
+{
+    uxa_screen_t    *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen);
+    RegionRec region;
+    BoxPtr pbox;
+    int nbox;
+    int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y;
+    PixmapPtr pSrcPix, pMaskPix = NULL, pDstPix;
+    struct _Pixmap scratch;
+
+    pSrcPix = uxa_get_drawable_pixmap(pSrc->pDrawable);
+    pDstPix = uxa_get_drawable_pixmap(pDst->pDrawable);
+    if (pMask)
+	pMaskPix = uxa_get_drawable_pixmap(pMask->pDrawable);
+
+    xDst += pDst->pDrawable->x;
+    yDst += pDst->pDrawable->y;
+
+    if (pMask) {
+	xMask += pMask->pDrawable->x;
+	yMask += pMask->pDrawable->y;
+    }
+
+    xSrc += pSrc->pDrawable->x;
+    ySrc += pSrc->pDrawable->y;
+
+    if (uxa_screen->info->CheckComposite &&
+	!(*uxa_screen->info->CheckComposite) (op, pSrc, pMask, pDst))
+    {
+	return -1;
+    }
+
+    if (!miComputeCompositeRegion (&region, pSrc, pMask, pDst,
+				   xSrc, ySrc, xMask, yMask, xDst, yDst,
+				   width, height))
+	return 1;
+
+    uxa_get_drawable_deltas (pDst->pDrawable, pDstPix, &dst_off_x, &dst_off_y);
+
+    REGION_TRANSLATE(pScreen, &region, dst_off_x, dst_off_y);
+
+    pSrcPix = uxa_get_offscreen_pixmap (pSrc->pDrawable, &src_off_x, &src_off_y);
+    if (pMask)
+	pMaskPix = uxa_get_offscreen_pixmap (pMask->pDrawable, &mask_off_x,
+					  &mask_off_y);
+
+    if (!uxa_pixmap_is_offscreen(pDstPix)) {
+	REGION_UNINIT(pDst->pDrawable->pScreen, &region);
+	return 0;
+    }
+
+    if (!pSrcPix && (!pMask || pMaskPix) && uxa_screen->info->UploadToScratch) {
+	pSrcPix = uxa_get_drawable_pixmap (pSrc->pDrawable);
+	if ((*uxa_screen->info->UploadToScratch) (pSrcPix, &scratch))
+	    pSrcPix = &scratch;
+    } else if (pSrcPix && pMask && !pMaskPix && uxa_screen->info->UploadToScratch) {
+	pMaskPix = uxa_get_drawable_pixmap (pMask->pDrawable);
+	if ((*uxa_screen->info->UploadToScratch) (pMaskPix, &scratch))
+	    pMaskPix = &scratch;
+    }
+
+    if (!pSrcPix || (pMask && !pMaskPix)) {
+	REGION_UNINIT(pDst->pDrawable->pScreen, &region);
+	return 0;
+    }
+
+    if (!(*uxa_screen->info->PrepareComposite) (op, pSrc, pMask, pDst, pSrcPix,
+					     pMaskPix, pDstPix))
+    {
+	REGION_UNINIT(pDst->pDrawable->pScreen, &region);
+	return -1;
+    }
+
+    nbox = REGION_NUM_RECTS(&region);
+    pbox = REGION_RECTS(&region);
+
+    xMask = xMask + mask_off_x - xDst - dst_off_x;
+    yMask = yMask + mask_off_y - yDst - dst_off_y;
+
+    xSrc = xSrc + src_off_x - xDst - dst_off_x;
+    ySrc = ySrc + src_off_y - yDst - dst_off_y;
+
+    while (nbox--)
+    {
+	(*uxa_screen->info->Composite) (pDstPix,
+				     pbox->x1 + xSrc,
+				     pbox->y1 + ySrc,
+				     pbox->x1 + xMask,
+				     pbox->y1 + yMask,
+				     pbox->x1,
+				     pbox->y1,
+				     pbox->x2 - pbox->x1,
+				     pbox->y2 - pbox->y1);
+	pbox++;
+    }
+    (*uxa_screen->info->DoneComposite) (pDstPix);
+    uxa_mark_sync(pDst->pDrawable->pScreen);
+
+    REGION_UNINIT(pDst->pDrawable->pScreen, &region);
+    return 1;
+}
+
+/**
+ * uxa_try_magic_two_pass_composite_helper implements PictOpOver using two passes of
+ * simpler operations PictOpOutReverse and PictOpAdd. Mainly used for component
+ * alpha and limited 1-tmu cards.
+ *
+ * From http://anholt.livejournal.com/32058.html:
+ *
+ * The trouble is that component-alpha rendering requires two different sources
+ * for blending: one for the source value to the blender, which is the
+ * per-channel multiplication of source and mask, and one for the source alpha
+ * for multiplying with the destination channels, which is the multiplication
+ * of the source channels by the mask alpha. So the equation for Over is:
+ *
+ * dst.A = src.A * mask.A + (1 - (src.A * mask.A)) * dst.A
+ * dst.R = src.R * mask.R + (1 - (src.A * mask.R)) * dst.R
+ * dst.G = src.G * mask.G + (1 - (src.A * mask.G)) * dst.G
+ * dst.B = src.B * mask.B + (1 - (src.A * mask.B)) * dst.B
+ *
+ * But we can do some simpler operations, right? How about PictOpOutReverse,
+ * which has a source factor of 0 and dest factor of (1 - source alpha). We
+ * can get the source alpha value (srca.X = src.A * mask.X) out of the texture
+ * blenders pretty easily. So we can do a component-alpha OutReverse, which
+ * gets us:
+ *
+ * dst.A = 0 + (1 - (src.A * mask.A)) * dst.A
+ * dst.R = 0 + (1 - (src.A * mask.R)) * dst.R
+ * dst.G = 0 + (1 - (src.A * mask.G)) * dst.G
+ * dst.B = 0 + (1 - (src.A * mask.B)) * dst.B
+ *
+ * OK. And if an op doesn't use the source alpha value for the destination
+ * factor, then we can do the channel multiplication in the texture blenders
+ * to get the source value, and ignore the source alpha that we wouldn't use.
+ * We've supported this in the Radeon driver for a long time. An example would
+ * be PictOpAdd, which does:
+ *
+ * dst.A = src.A * mask.A + dst.A
+ * dst.R = src.R * mask.R + dst.R
+ * dst.G = src.G * mask.G + dst.G
+ * dst.B = src.B * mask.B + dst.B
+ *
+ * Hey, this looks good! If we do a PictOpOutReverse and then a PictOpAdd right
+ * after it, we get:
+ *
+ * dst.A = src.A * mask.A + ((1 - (src.A * mask.A)) * dst.A)
+ * dst.R = src.R * mask.R + ((1 - (src.A * mask.R)) * dst.R)
+ * dst.G = src.G * mask.G + ((1 - (src.A * mask.G)) * dst.G)
+ * dst.B = src.B * mask.B + ((1 - (src.A * mask.B)) * dst.B)
+ */
+
+static int
+uxa_try_magic_two_pass_composite_helper(CARD8 op,
+				  PicturePtr pSrc,
+				  PicturePtr pMask,
+				  PicturePtr pDst,
+				  INT16 xSrc,
+				  INT16 ySrc,
+				  INT16 xMask,
+				  INT16 yMask,
+				  INT16 xDst,
+				  INT16 yDst,
+				  CARD16 width,
+				  CARD16 height)
+{
+    uxa_screen_t    *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen);
+
+    assert(op == PictOpOver);
+
+    if (uxa_screen->info->CheckComposite &&
+	(!(*uxa_screen->info->CheckComposite)(PictOpOutReverse, pSrc, pMask,
+					   pDst) ||
+	 !(*uxa_screen->info->CheckComposite)(PictOpAdd, pSrc, pMask, pDst)))
+    {
+	return -1;
+    }
+
+    /* Now, we think we should be able to accelerate this operation. First,
+     * composite the destination to be the destination times the source alpha
+     * factors.
+     */
+    uxa_composite(PictOpOutReverse, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask,
+		 xDst, yDst, width, height);
+
+    /* Then, add in the source value times the destination alpha factors (1.0).
+     */
+    uxa_composite(PictOpAdd, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask,
+		 xDst, yDst, width, height);
+
+    return 1;
+}
+
+void
+uxa_composite(CARD8	op,
+	     PicturePtr pSrc,
+	     PicturePtr pMask,
+	     PicturePtr pDst,
+	     INT16	xSrc,
+	     INT16	ySrc,
+	     INT16	xMask,
+	     INT16	yMask,
+	     INT16	xDst,
+	     INT16	yDst,
+	     CARD16	width,
+	     CARD16	height)
+{
+    uxa_screen_t    *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen);
+    int ret = -1;
+    Bool saveSrcRepeat = pSrc->repeat;
+    Bool saveMaskRepeat = pMask ? pMask->repeat : 0;
+    RegionRec region;
+
+    /* We currently don't support acceleration of gradients, or other pictures
+     * with a NULL pDrawable.
+     */
+    if (uxa_screen->swappedOut ||
+	pSrc->pDrawable == NULL || (pMask != NULL && pMask->pDrawable == NULL))
+    {
+	goto fallback;
+    }
+
+    /* Remove repeat in source if useless */
+    if (pSrc->repeat && !pSrc->transform && xSrc >= 0 &&
+	(xSrc + width) <= pSrc->pDrawable->width && ySrc >= 0 &&
+	(ySrc + height) <= pSrc->pDrawable->height)
+	    pSrc->repeat = 0;
+
+    if (!pMask)
+    {
+      if ((op == PictOpSrc &&
+	   ((pSrc->format == pDst->format) ||
+	    (pSrc->format==PICT_a8r8g8b8 && pDst->format==PICT_x8r8g8b8) ||
+	    (pSrc->format==PICT_a8b8g8r8 && pDst->format==PICT_x8b8g8r8))) ||
+	  (op == PictOpOver && !pSrc->alphaMap && !pDst->alphaMap &&
+	   pSrc->format == pDst->format &&
+	   (pSrc->format==PICT_x8r8g8b8 || pSrc->format==PICT_x8b8g8r8)))
+	{
+	    if (pSrc->pDrawable->width == 1 &&
+		pSrc->pDrawable->height == 1 &&
+		pSrc->repeat)
+	    {
+		ret = uxa_try_driver_solid_fill(pSrc, pDst, xSrc, ySrc, xDst, yDst,
+					    width, height);
+		if (ret == 1)
+		    goto done;
+	    }
+	    else if (pSrc->pDrawable != NULL &&
+		     !pSrc->repeat &&
+		     !pSrc->transform)
+	    {
+		xDst += pDst->pDrawable->x;
+		yDst += pDst->pDrawable->y;
+		xSrc += pSrc->pDrawable->x;
+		ySrc += pSrc->pDrawable->y;
+
+		if (!miComputeCompositeRegion (&region, pSrc, pMask, pDst,
+					       xSrc, ySrc, xMask, yMask, xDst,
+					       yDst, width, height))
+		    goto done;
+
+
+		uxa_copy_n_to_n (pSrc->pDrawable, pDst->pDrawable, NULL,
+			     REGION_RECTS(&region), REGION_NUM_RECTS(&region),
+			     xSrc - xDst, ySrc - yDst,
+			     FALSE, FALSE, 0, NULL);
+		REGION_UNINIT(pDst->pDrawable->pScreen, &region);
+		goto done;
+	    }
+	    else if (pSrc->pDrawable != NULL &&
+		     pSrc->pDrawable->type == DRAWABLE_PIXMAP &&
+		     !pSrc->transform &&
+		     pSrc->repeatType == RepeatNormal)
+	    {
+		DDXPointRec patOrg;
+
+		/* Let's see if the driver can do the repeat in one go */
+		if (uxa_screen->info->PrepareComposite && !pSrc->alphaMap &&
+		    !pDst->alphaMap)
+		{
+		    ret = uxa_try_driver_composite(op, pSrc, pMask, pDst, xSrc,
+						ySrc, xMask, yMask, xDst, yDst,
+						width, height);
+		    if (ret == 1)
+			goto done;
+		}
+
+		/* Now see if we can use uxa_fill_region_tiled() */
+		xDst += pDst->pDrawable->x;
+		yDst += pDst->pDrawable->y;
+		xSrc += pSrc->pDrawable->x;
+		ySrc += pSrc->pDrawable->y;
+
+		if (!miComputeCompositeRegion (&region, pSrc, pMask, pDst, xSrc,
+					       ySrc, xMask, yMask, xDst, yDst,
+					       width, height))
+		    goto done;
+
+		/* pattern origin is the point in the destination drawable
+		 * corresponding to (0,0) in the source */
+		patOrg.x = xDst - xSrc;
+		patOrg.y = yDst - ySrc;
+
+		ret = uxa_fill_region_tiled(pDst->pDrawable, &region,
+					 (PixmapPtr)pSrc->pDrawable,
+					 &patOrg, FB_ALLONES, GXcopy);
+
+		REGION_UNINIT(pDst->pDrawable->pScreen, &region);
+
+		if (ret)
+		    goto done;
+	    }
+	}
+    }
+
+    /* Remove repeat in mask if useless */
+    if (pMask && pMask->repeat && !pMask->transform && xMask >= 0 &&
+	(xMask + width) <= pMask->pDrawable->width && yMask >= 0 &&
+	(yMask + height) <= pMask->pDrawable->height)
+	    pMask->repeat = 0;
+
+    if (uxa_screen->info->PrepareComposite &&
+	!pSrc->alphaMap && (!pMask || !pMask->alphaMap) && !pDst->alphaMap)
+    {
+	Bool isSrcSolid;
+
+	ret = uxa_try_driver_composite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask,
+				    yMask, xDst, yDst, width, height);
+	if (ret == 1)
+	    goto done;
+
+	/* For generic masks and solid src pictures, mach64 can do Over in two
+	 * passes, similar to the component-alpha case.
+	 */
+	isSrcSolid = pSrc->pDrawable->width == 1 &&
+		     pSrc->pDrawable->height == 1 &&
+		     pSrc->repeat;
+
+	/* If we couldn't do the Composite in a single pass, and it was a
+	 * component-alpha Over, see if we can do it in two passes with
+	 * an OutReverse and then an Add.
+	 */
+	if (ret == -1 && op == PictOpOver && pMask &&
+	    (pMask->componentAlpha || isSrcSolid)) {
+	    ret = uxa_try_magic_two_pass_composite_helper(op, pSrc, pMask, pDst,
+						    xSrc, ySrc,
+						    xMask, yMask, xDst, yDst,
+						    width, height);
+	    if (ret == 1)
+		goto done;
+	}
+    }
+
+fallback:
+#if DEBUG_TRACE_FALL
+    uxa_print_composite_fallback (op, pSrc, pMask, pDst);
+#endif
+
+    uxa_check_composite (op, pSrc, pMask, pDst, xSrc, ySrc,
+		      xMask, yMask, xDst, yDst, width, height);
+
+done:
+    pSrc->repeat = saveSrcRepeat;
+    if (pMask)
+	pMask->repeat = saveMaskRepeat;
+}
+#endif
+
+/**
+ * Same as miCreateAlphaPicture, except it uses uxa_check_poly_fill_rect instead
+ * of PolyFillRect to initialize the pixmap after creating it, to prevent
+ * the pixmap from being migrated.
+ *
+ * See the comments about uxa_trapezoids and uxa_triangles.
+ */
+static PicturePtr
+uxa_create_alpha_picture (ScreenPtr     pScreen,
+                       PicturePtr    pDst,
+                       PictFormatPtr pPictFormat,
+                       CARD16        width,
+                       CARD16        height)
+{
+    PixmapPtr	    pPixmap;
+    PicturePtr	    pPicture;
+    GCPtr	    pGC;
+    int		    error;
+    xRectangle	    rect;
+
+    if (width > 32767 || height > 32767)
+	return 0;
+
+    if (!pPictFormat)
+    {
+	if (pDst->polyEdge == PolyEdgeSharp)
+	    pPictFormat = PictureMatchFormat (pScreen, 1, PICT_a1);
+	else
+	    pPictFormat = PictureMatchFormat (pScreen, 8, PICT_a8);
+	if (!pPictFormat)
+	    return 0;
+    }
+
+    pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
+					pPictFormat->depth, 0);
+    if (!pPixmap)
+	return 0;
+    pGC = GetScratchGC (pPixmap->drawable.depth, pScreen);
+    if (!pGC)
+    {
+	(*pScreen->DestroyPixmap) (pPixmap);
+	return 0;
+    }
+    ValidateGC (&pPixmap->drawable, pGC);
+    rect.x = 0;
+    rect.y = 0;
+    rect.width = width;
+    rect.height = height;
+    uxa_check_poly_fill_rect (&pPixmap->drawable, pGC, 1, &rect);
+    FreeScratchGC (pGC);
+    pPicture = CreatePicture (0, &pPixmap->drawable, pPictFormat,
+			      0, 0, serverClient, &error);
+    (*pScreen->DestroyPixmap) (pPixmap);
+    return pPicture;
+}
+
+/**
+ * uxa_trapezoids is essentially a copy of miTrapezoids that uses
+ * uxa_create_alpha_picture instead of miCreateAlphaPicture.
+ *
+ * The problem with miCreateAlphaPicture is that it calls PolyFillRect
+ * to initialize the contents after creating the pixmap, which
+ * causes the pixmap to be moved in for acceleration. The subsequent
+ * call to RasterizeTrapezoid won't be accelerated however, which
+ * forces the pixmap to be moved out again.
+ *
+ * uxa_create_alpha_picture avoids this roundtrip by using uxa_check_poly_fill_rect
+ * to initialize the contents.
+ */
+void
+uxa_trapezoids (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+               PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+               int ntrap, xTrapezoid *traps)
+{
+    ScreenPtr		pScreen = pDst->pDrawable->pScreen;
+    PictureScreenPtr    ps = GetPictureScreen(pScreen);
+    BoxRec		bounds;
+    Bool		direct = op == PictOpAdd && miIsSolidAlpha (pSrc);
+
+    if (maskFormat || direct) {
+	miTrapezoidBounds (ntrap, traps, &bounds);
+
+	if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
+	    return;
+    }
+
+    /*
+     * Check for solid alpha add
+     */
+    if (direct)
+    {
+	DrawablePtr pDraw = pDst->pDrawable;
+	PixmapPtr pixmap = uxa_get_drawable_pixmap (pDraw);
+	int xoff, yoff;
+
+	uxa_get_drawable_deltas(pDraw, pixmap, &xoff, &yoff);
+
+	xoff += pDraw->x;
+	yoff += pDraw->y;
+
+	uxa_prepare_access(pDraw, UXA_PREPARE_DEST);
+
+	for (; ntrap; ntrap--, traps++)
+	    (*ps->RasterizeTrapezoid) (pDst, traps, 0, 0);
+
+	uxa_finish_access(pDraw, UXA_PREPARE_DEST);
+    }
+    else if (maskFormat)
+    {
+	PicturePtr	pPicture;
+	INT16		xDst, yDst;
+	INT16		xRel, yRel;
+
+	xDst = traps[0].left.p1.x >> 16;
+	yDst = traps[0].left.p1.y >> 16;
+
+	pPicture = uxa_create_alpha_picture (pScreen, pDst, maskFormat,
+	                                  bounds.x2 - bounds.x1,
+	                                  bounds.y2 - bounds.y1);
+	if (!pPicture)
+	    return;
+
+	uxa_prepare_access(pPicture->pDrawable, UXA_PREPARE_DEST);
+	for (; ntrap; ntrap--, traps++)
+	    (*ps->RasterizeTrapezoid) (pPicture, traps,
+				       -bounds.x1, -bounds.y1);
+	uxa_finish_access(pPicture->pDrawable, UXA_PREPARE_DEST);
+
+	xRel = bounds.x1 + xSrc - xDst;
+	yRel = bounds.y1 + ySrc - yDst;
+	CompositePicture (op, pSrc, pPicture, pDst,
+			  xRel, yRel, 0, 0, bounds.x1, bounds.y1,
+			  bounds.x2 - bounds.x1,
+			  bounds.y2 - bounds.y1);
+	FreePicture (pPicture, 0);
+    }
+    else
+    {
+	if (pDst->polyEdge == PolyEdgeSharp)
+	    maskFormat = PictureMatchFormat (pScreen, 1, PICT_a1);
+	else
+	    maskFormat = PictureMatchFormat (pScreen, 8, PICT_a8);
+	for (; ntrap; ntrap--, traps++)
+	    uxa_trapezoids (op, pSrc, pDst, maskFormat, xSrc, ySrc, 1, traps);
+    }
+}
+
+/**
+ * uxa_triangles is essentially a copy of miTriangles that uses
+ * uxa_create_alpha_picture instead of miCreateAlphaPicture.
+ *
+ * The problem with miCreateAlphaPicture is that it calls PolyFillRect
+ * to initialize the contents after creating the pixmap, which
+ * causes the pixmap to be moved in for acceleration. The subsequent
+ * call to AddTriangles won't be accelerated however, which forces the pixmap
+ * to be moved out again.
+ *
+ * uxa_create_alpha_picture avoids this roundtrip by using uxa_check_poly_fill_rect
+ * to initialize the contents.
+ */
+void
+uxa_triangles (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+	      PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+	      int ntri, xTriangle *tris)
+{
+    ScreenPtr		pScreen = pDst->pDrawable->pScreen;
+    PictureScreenPtr    ps = GetPictureScreen(pScreen);
+    BoxRec		bounds;
+    Bool		direct = op == PictOpAdd && miIsSolidAlpha (pSrc);
+
+    if (maskFormat || direct) {
+	miTriangleBounds (ntri, tris, &bounds);
+
+	if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
+	    return;
+    }
+
+    /*
+     * Check for solid alpha add
+     */
+    if (direct)
+    {
+	DrawablePtr pDraw = pDst->pDrawable;
+	uxa_prepare_access(pDraw, UXA_PREPARE_DEST);
+	(*ps->AddTriangles) (pDst, 0, 0, ntri, tris);
+	uxa_finish_access(pDraw, UXA_PREPARE_DEST);
+    }
+    else if (maskFormat)
+    {
+	PicturePtr	pPicture;
+	INT16		xDst, yDst;
+	INT16		xRel, yRel;
+	
+	xDst = tris[0].p1.x >> 16;
+	yDst = tris[0].p1.y >> 16;
+
+	pPicture = uxa_create_alpha_picture (pScreen, pDst, maskFormat,
+					  bounds.x2 - bounds.x1,
+					  bounds.y2 - bounds.y1);
+	if (!pPicture)
+	    return;
+
+	uxa_prepare_access(pPicture->pDrawable, UXA_PREPARE_DEST);
+	(*ps->AddTriangles) (pPicture, -bounds.x1, -bounds.y1, ntri, tris);
+	uxa_finish_access(pPicture->pDrawable, UXA_PREPARE_DEST);
+	
+	xRel = bounds.x1 + xSrc - xDst;
+	yRel = bounds.y1 + ySrc - yDst;
+	CompositePicture (op, pSrc, pPicture, pDst,
+			  xRel, yRel, 0, 0, bounds.x1, bounds.y1,
+			  bounds.x2 - bounds.x1, bounds.y2 - bounds.y1);
+	FreePicture (pPicture, 0);
+    }
+    else
+    {
+	if (pDst->polyEdge == PolyEdgeSharp)
+	    maskFormat = PictureMatchFormat (pScreen, 1, PICT_a1);
+	else
+	    maskFormat = PictureMatchFormat (pScreen, 8, PICT_a8);
+	
+	for (; ntri; ntri--, tris++)
+	    uxa_triangles (op, pSrc, pDst, maskFormat, xSrc, ySrc, 1, tris);
+    }
+}
diff --git a/uxa/uxa-unaccel.c b/uxa/uxa-unaccel.c
new file mode 100644
index 0000000..2719420
--- /dev/null
+++ b/uxa/uxa-unaccel.c
@@ -0,0 +1,370 @@
+/*
+ *
+ * Copyright © 1999 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 Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  Keith Packard makes no
+ * representations about the suitability of this software for any purpose.  It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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.
+ */
+
+#include "uxa-priv.h"
+
+#ifdef RENDER
+#include "mipict.h"
+#endif
+
+/*
+ * These functions wrap the low-level fb rendering functions and
+ * synchronize framebuffer/accelerated drawing by stalling until
+ * the accelerator is idle
+ */
+
+/**
+ * Calls uxa_prepare_access with UXA_PREPARE_SRC for the tile, if that is the
+ * current fill style.
+ *
+ * Solid doesn't use an extra pixmap source, and Stippled/OpaqueStippled are
+ * 1bpp and never in fb, so we don't worry about them.
+ * We should worry about them for completeness sake and going forward.
+ */
+void
+uxa_prepare_access_gc(GCPtr pGC)
+{
+    if (pGC->stipple)
+        uxa_prepare_access(&pGC->stipple->drawable, UXA_PREPARE_MASK);
+    if (pGC->fillStyle == FillTiled)
+	uxa_prepare_access(&pGC->tile.pixmap->drawable, UXA_PREPARE_SRC);
+}
+
+/**
+ * Finishes access to the tile in the GC, if used.
+ */
+void
+uxa_finish_access_gc(GCPtr pGC)
+{
+    if (pGC->fillStyle == FillTiled)
+	uxa_finish_access(&pGC->tile.pixmap->drawable, UXA_PREPARE_MASK);
+    if (pGC->stipple)
+        uxa_finish_access(&pGC->stipple->drawable, UXA_PREPARE_SRC);
+}
+
+#if DEBUG_TRACE_FALL
+char
+uxa_drawable_location(DrawablePtr pDrawable)
+{
+    return uxa_drawable_is_offscreen(pDrawable) ? 's' : 'm';
+}
+#endif /* DEBUG_TRACE_FALL */
+
+void
+uxa_check_fill_spans (DrawablePtr pDrawable, GCPtr pGC, int nspans,
+		   DDXPointPtr ppt, int *pwidth, int fSorted)
+{
+    UXA_FALLBACK(("to %p (%c)\n", pDrawable, uxa_drawable_location(pDrawable)));
+    uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+    uxa_prepare_access_gc (pGC);
+    fbFillSpans (pDrawable, pGC, nspans, ppt, pwidth, fSorted);
+    uxa_finish_access_gc (pGC);
+    uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+}
+
+void
+uxa_check_set_spans (DrawablePtr pDrawable, GCPtr pGC, char *psrc,
+		 DDXPointPtr ppt, int *pwidth, int nspans, int fSorted)
+{
+    UXA_FALLBACK(("to %p (%c)\n", pDrawable, uxa_drawable_location(pDrawable)));
+    uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+    fbSetSpans (pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted);
+    uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+}
+
+void
+uxa_check_put_image (DrawablePtr pDrawable, GCPtr pGC, int depth,
+		 int x, int y, int w, int h, int leftPad, int format,
+		 char *bits)
+{
+    UXA_FALLBACK(("to %p (%c)\n", pDrawable, uxa_drawable_location(pDrawable)));
+    uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+    fbPutImage (pDrawable, pGC, depth, x, y, w, h, leftPad, format, bits);
+    uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+}
+
+RegionPtr
+uxa_check_copy_area (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
+		 int srcx, int srcy, int w, int h, int dstx, int dsty)
+{
+    RegionPtr ret;
+
+    UXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst,
+		  uxa_drawable_location(pSrc), uxa_drawable_location(pDst)));
+    uxa_prepare_access (pDst, UXA_PREPARE_DEST);
+    uxa_prepare_access (pSrc, UXA_PREPARE_SRC);
+    ret = fbCopyArea (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty);
+    uxa_finish_access (pSrc, UXA_PREPARE_SRC);
+    uxa_finish_access (pDst, UXA_PREPARE_DEST);
+
+    return ret;
+}
+
+RegionPtr
+uxa_check_copy_plane (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
+		  int srcx, int srcy, int w, int h, int dstx, int dsty,
+		  unsigned long bitPlane)
+{
+    RegionPtr ret;
+
+    UXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst,
+		  uxa_drawable_location(pSrc), uxa_drawable_location(pDst)));
+    uxa_prepare_access (pDst, UXA_PREPARE_DEST);
+    uxa_prepare_access (pSrc, UXA_PREPARE_SRC);
+    ret = fbCopyPlane (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty,
+		       bitPlane);
+    uxa_finish_access (pSrc, UXA_PREPARE_SRC);
+    uxa_finish_access (pDst, UXA_PREPARE_DEST);
+
+    return ret;
+}
+
+void
+uxa_check_poly_point (DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
+		  DDXPointPtr pptInit)
+{
+    UXA_FALLBACK(("to %p (%c)\n", pDrawable, uxa_drawable_location(pDrawable)));
+    uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+    fbPolyPoint (pDrawable, pGC, mode, npt, pptInit);
+    uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+}
+
+void
+uxa_check_poly_lines (DrawablePtr pDrawable, GCPtr pGC,
+		  int mode, int npt, DDXPointPtr ppt)
+{
+    UXA_FALLBACK(("to %p (%c), width %d, mode %d, count %d\n",
+		  pDrawable, uxa_drawable_location(pDrawable),
+		  pGC->lineWidth, mode, npt));
+
+    if (pGC->lineWidth == 0) {
+	uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+	uxa_prepare_access_gc (pGC);
+	fbPolyLine (pDrawable, pGC, mode, npt, ppt);
+	uxa_finish_access_gc (pGC);
+	uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+	return;
+    }
+    /* fb calls mi functions in the lineWidth != 0 case. */
+    fbPolyLine (pDrawable, pGC, mode, npt, ppt);
+}
+
+void
+uxa_check_poly_segment (DrawablePtr pDrawable, GCPtr pGC,
+		    int nsegInit, xSegment *pSegInit)
+{
+    UXA_FALLBACK(("to %p (%c) width %d, count %d\n", pDrawable,
+		  uxa_drawable_location(pDrawable), pGC->lineWidth, nsegInit));
+    if (pGC->lineWidth == 0) {
+	uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+	uxa_prepare_access_gc (pGC);
+	fbPolySegment (pDrawable, pGC, nsegInit, pSegInit);
+	uxa_finish_access_gc (pGC);
+	uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+	return;
+    }
+    /* fb calls mi functions in the lineWidth != 0 case. */
+    fbPolySegment (pDrawable, pGC, nsegInit, pSegInit);
+}
+
+void
+uxa_check_poly_arc (DrawablePtr pDrawable, GCPtr pGC,
+		int narcs, xArc *pArcs)
+{
+    UXA_FALLBACK(("to %p (%c)\n", pDrawable, uxa_drawable_location(pDrawable)));
+
+    /* Disable this as fbPolyArc can call miZeroPolyArc which in turn
+     * can call accelerated functions, that as yet, haven't been notified
+     * with uxa_finish_access().
+     */
+#if 0
+    if (pGC->lineWidth == 0)
+    {
+	uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+	uxa_prepare_access_gc (pGC);
+	fbPolyArc (pDrawable, pGC, narcs, pArcs);
+	uxa_finish_access_gc (pGC);
+	uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+	return;
+    }
+#endif
+    miPolyArc (pDrawable, pGC, narcs, pArcs);
+}
+
+void
+uxa_check_poly_fill_rect (DrawablePtr pDrawable, GCPtr pGC,
+		     int nrect, xRectangle *prect)
+{
+    UXA_FALLBACK(("to %p (%c)\n", pDrawable, uxa_drawable_location(pDrawable)));
+
+    uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+    uxa_prepare_access_gc (pGC);
+    fbPolyFillRect (pDrawable, pGC, nrect, prect);
+    uxa_finish_access_gc (pGC);
+    uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+}
+
+void
+uxa_check_image_glyph_blt (DrawablePtr pDrawable, GCPtr pGC,
+		      int x, int y, unsigned int nglyph,
+		      CharInfoPtr *ppci, pointer pglyphBase)
+{
+    UXA_FALLBACK(("to %p (%c)\n", pDrawable,
+		  uxa_drawable_location(pDrawable)));
+    uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+    uxa_prepare_access_gc (pGC);
+    fbImageGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
+    uxa_finish_access_gc (pGC);
+    uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+}
+
+void
+uxa_check_poly_glyph_blt (DrawablePtr pDrawable, GCPtr pGC,
+		     int x, int y, unsigned int nglyph,
+		     CharInfoPtr *ppci, pointer pglyphBase)
+{
+    UXA_FALLBACK(("to %p (%c), style %d alu %d\n", pDrawable,
+		  uxa_drawable_location(pDrawable), pGC->fillStyle, pGC->alu));
+    uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+    uxa_prepare_access_gc (pGC);
+    fbPolyGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
+    uxa_finish_access_gc (pGC);
+    uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+}
+
+void
+uxa_check_push_pixels (GCPtr pGC, PixmapPtr pBitmap,
+		   DrawablePtr pDrawable,
+		   int w, int h, int x, int y)
+{
+    UXA_FALLBACK(("from %p to %p (%c,%c)\n", pBitmap, pDrawable,
+		  uxa_drawable_location(&pBitmap->drawable),
+		  uxa_drawable_location(pDrawable)));
+    uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+    uxa_prepare_access (&pBitmap->drawable, UXA_PREPARE_SRC);
+    uxa_prepare_access_gc (pGC);
+    fbPushPixels (pGC, pBitmap, pDrawable, w, h, x, y);
+    uxa_finish_access_gc (pGC);
+    uxa_finish_access (&pBitmap->drawable, UXA_PREPARE_SRC);
+    uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+}
+
+void
+uxa_check_get_spans (DrawablePtr pDrawable,
+		 int wMax,
+		 DDXPointPtr ppt,
+		 int *pwidth,
+		 int nspans,
+		 char *pdstStart)
+{
+    UXA_FALLBACK(("from %p (%c)\n", pDrawable, uxa_drawable_location(pDrawable)));
+    uxa_prepare_access (pDrawable, UXA_PREPARE_SRC);
+    fbGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
+    uxa_finish_access (pDrawable, UXA_PREPARE_SRC);
+}
+
+void
+uxa_check_composite (CARD8      op,
+                   PicturePtr pSrc,
+                   PicturePtr pMask,
+                   PicturePtr pDst,
+                   INT16      xSrc,
+                   INT16      ySrc,
+                   INT16      xMask,
+                   INT16      yMask,
+                   INT16      xDst,
+                   INT16      yDst,
+                   CARD16     width,
+                   CARD16     height)
+{
+    UXA_FALLBACK(("from picts %p/%p to pict %p\n",
+		 pSrc, pMask, pDst));
+
+    uxa_prepare_access (pDst->pDrawable, UXA_PREPARE_DEST);
+    if (pSrc->pDrawable != NULL)
+	uxa_prepare_access (pSrc->pDrawable, UXA_PREPARE_SRC);
+    if (pMask && pMask->pDrawable != NULL)
+	uxa_prepare_access (pMask->pDrawable, UXA_PREPARE_MASK);
+    fbComposite (op,
+                 pSrc,
+                 pMask,
+                 pDst,
+                 xSrc,
+                 ySrc,
+                 xMask,
+                 yMask,
+                 xDst,
+                 yDst,
+                 width,
+                 height);
+    if (pMask && pMask->pDrawable != NULL)
+	uxa_finish_access (pMask->pDrawable, UXA_PREPARE_MASK);
+    if (pSrc->pDrawable != NULL)
+	uxa_finish_access (pSrc->pDrawable, UXA_PREPARE_SRC);
+    uxa_finish_access (pDst->pDrawable, UXA_PREPARE_DEST);
+}
+
+void
+uxa_check_add_traps (PicturePtr	pPicture,
+		  INT16		x_off,
+		  INT16		y_off,
+		  int		ntrap,
+		  xTrap		*traps)
+{
+    UXA_FALLBACK(("to pict %p (%c)\n",
+		  uxa_drawable_location(pPicture->pDrawable)));
+    uxa_prepare_access(pPicture->pDrawable, UXA_PREPARE_DEST);
+    fbAddTraps (pPicture, x_off, y_off, ntrap, traps);
+    uxa_finish_access(pPicture->pDrawable, UXA_PREPARE_DEST);
+}
+
+/**
+ * Gets the 0,0 pixel of a pixmap.  Used for doing solid fills of tiled pixmaps
+ * that happen to be 1x1.  Pixmap must be at least 8bpp.
+ *
+ * XXX This really belongs in fb, so it can be aware of tiling and etc.
+ */
+CARD32
+uxa_get_pixmap_first_pixel (PixmapPtr pPixmap)
+{
+    CARD32 pixel;
+    void *fb;
+
+    uxa_prepare_access (&pPixmap->drawable, UXA_PREPARE_SRC);
+    fb = pPixmap->devPrivate.ptr;
+
+    switch (pPixmap->drawable.bitsPerPixel) {
+    case 32:
+	pixel = *(CARD32 *)fb;
+	break;
+    case 16:
+	pixel = *(CARD16 *)fb;
+	break;
+    default:
+	pixel = *(CARD8 *)fb;
+	break;
+    }
+    uxa_finish_access(&pPixmap->drawable, UXA_PREPARE_SRC);
+
+    return pixel;
+}
diff --git a/uxa/uxa.c b/uxa/uxa.c
new file mode 100644
index 0000000..9745f8b
--- /dev/null
+++ b/uxa/uxa.c
@@ -0,0 +1,573 @@
+/*
+ * Copyright © 2001 Keith Packard
+ *
+ * Partly based on code that is Copyright © The XFree86 Project Inc.
+ *
+ * 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 Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  Keith Packard makes no
+ * representations about the suitability of this software for any purpose.  It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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.
+ */
+
+/** @file
+ * This file covers the initialization and teardown of UXA, and has various
+ * functions not responsible for performing rendering, pixmap migration, or
+ * memory management.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <stdlib.h>
+
+#include "uxa-priv.h"
+#include <X11/fonts/fontstruct.h>
+#include "dixfontstr.h"
+#include "uxa.h"
+
+DevPrivateKey uxa_screen_key = &uxa_screen_key;
+
+/**
+ * uxa_get_drawable_pixmap() returns a backing pixmap for a given drawable.
+ *
+ * @param pDrawable the drawable being requested.
+ *
+ * This function returns the backing pixmap for a drawable, whether it is a
+ * redirected window, unredirected window, or already a pixmap.  Note that
+ * coordinate translation is needed when drawing to the backing pixmap of a
+ * redirected window, and the translation coordinates are provided by calling
+ * uxa_get_drawable_pixmap() on the drawable.
+ */
+PixmapPtr
+uxa_get_drawable_pixmap(DrawablePtr pDrawable)
+{
+     if (pDrawable->type == DRAWABLE_WINDOW)
+	return pDrawable->pScreen->GetWindowPixmap ((WindowPtr) pDrawable);
+     else
+	return (PixmapPtr) pDrawable;
+}	
+
+/**
+ * Sets the offsets to add to coordinates to make them address the same bits in
+ * the backing drawable. These coordinates are nonzero only for redirected
+ * windows.
+ */
+void
+uxa_get_drawable_deltas (DrawablePtr pDrawable, PixmapPtr pPixmap,
+			 int *xp, int *yp)
+{
+#ifdef COMPOSITE
+    if (pDrawable->type == DRAWABLE_WINDOW) {
+	*xp = -pPixmap->screen_x;
+	*yp = -pPixmap->screen_y;
+	return;
+    }
+#endif
+
+    *xp = 0;
+    *yp = 0;
+}
+
+/**
+ * uxa_pixmap_is_offscreen() is used to determine if a pixmap is in offscreen
+ * memory, meaning that acceleration could probably be done to it, and that it
+ * will need to be wrapped by PrepareAccess()/FinishAccess() when accessing it
+ * with the CPU.
+ *
+ * Note that except for UploadToScreen()/DownloadFromScreen() (which explicitly
+ * deal with moving pixmaps in and out of system memory), UXA will give drivers
+ * pixmaps as arguments for which uxa_pixmap_is_offscreen() is TRUE.
+ *
+ * @return TRUE if the given drawable is in framebuffer memory.
+ */
+Bool
+uxa_pixmap_is_offscreen(PixmapPtr p)
+{
+    ScreenPtr	    pScreen = p->drawable.pScreen;
+    uxa_screen_t    *uxa_screen = uxa_get_screen(pScreen);
+
+    if (uxa_screen->info->PixmapIsOffscreen)
+	return uxa_screen->info->PixmapIsOffscreen(p);
+
+    return FALSE;
+}
+
+/**
+ * uxa_drawable_is_offscreen() is a convenience wrapper for uxa_pixmap_is_offscreen().
+ */
+Bool
+uxa_drawable_is_offscreen (DrawablePtr pDrawable)
+{
+    return uxa_pixmap_is_offscreen (uxa_get_drawable_pixmap (pDrawable));
+}
+
+/**
+  * Returns the pixmap which backs a drawable, and the offsets to add to
+  * coordinates to make them address the same bits in the backing drawable.
+  */
+PixmapPtr
+uxa_get_offscreen_pixmap (DrawablePtr drawable, int *xp, int *yp)
+{
+    PixmapPtr   pixmap = uxa_get_drawable_pixmap (drawable);
+
+    uxa_get_drawable_deltas (drawable, pixmap, xp, yp);
+
+    if (uxa_pixmap_is_offscreen (pixmap))
+	return pixmap;
+    else
+	return NULL;
+}
+
+
+
+/**
+ * uxa_prepare_access() is UXA's wrapper for the driver's PrepareAccess() handler.
+ *
+ * It deals with waiting for synchronization with the card, determining if
+ * PrepareAccess() is necessary, and working around PrepareAccess() failure.
+ */
+void
+uxa_prepare_access(DrawablePtr pDrawable, int index)
+{
+    ScreenPtr	    pScreen = pDrawable->pScreen;
+    uxa_screen_t    *uxa_screen = uxa_get_screen(pScreen);
+    PixmapPtr	    pPixmap = uxa_get_drawable_pixmap (pDrawable);
+    Bool	    offscreen = uxa_pixmap_is_offscreen(pPixmap);
+
+    if (!offscreen)
+	return;
+
+    /* XXX should be pPixmap eventually */
+    uxa_wait_sync (pScreen);
+
+    if (uxa_screen->info->PrepareAccess)
+	(*uxa_screen->info->PrepareAccess) (pPixmap, index);
+}
+
+/**
+ * uxa_finish_access() is UXA's wrapper for the driver's FinishAccess() handler.
+ *
+ * It deals with calling the driver's FinishAccess() only if necessary.
+ */
+void
+uxa_finish_access(DrawablePtr pDrawable, int index)
+{
+    ScreenPtr	    pScreen = pDrawable->pScreen;
+    uxa_screen_t    *uxa_screen = uxa_get_screen(pScreen);
+    PixmapPtr	    pPixmap = uxa_get_drawable_pixmap (pDrawable);
+
+    if (uxa_screen->info->FinishAccess == NULL)
+	return;
+
+    if (!uxa_pixmap_is_offscreen (pPixmap))
+	return;
+
+    (*uxa_screen->info->FinishAccess) (pPixmap, index);
+}
+
+/**
+ * uxa_validate_gc() sets the ops to UXA's implementations, which may be
+ * accelerated or may sync the card and fall back to fb.
+ */
+static void
+uxa_validate_gc (GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
+{
+    /* fbValidateGC will do direct access to pixmaps if the tiling has changed.
+     * Preempt fbValidateGC by doing its work and masking the change out, so
+     * that we can do the Prepare/FinishAccess.
+     */
+#ifdef FB_24_32BIT
+    if ((changes & GCTile) && fbGetRotatedPixmap(pGC)) {
+	(*pGC->pScreen->DestroyPixmap) (fbGetRotatedPixmap(pGC));
+	fbGetRotatedPixmap(pGC) = 0;
+    }
+	
+    if (pGC->fillStyle == FillTiled) {
+	PixmapPtr	pOldTile, pNewTile;
+
+	pOldTile = pGC->tile.pixmap;
+	if (pOldTile->drawable.bitsPerPixel != pDrawable->bitsPerPixel)
+	{
+	    pNewTile = fbGetRotatedPixmap(pGC);
+	    if (!pNewTile ||
+		pNewTile ->drawable.bitsPerPixel != pDrawable->bitsPerPixel)
+	    {
+		if (pNewTile)
+		    (*pGC->pScreen->DestroyPixmap) (pNewTile);
+		/* fb24_32ReformatTile will do direct access of a newly-
+		 * allocated pixmap.  This isn't a problem yet, since we don't
+		 * put pixmaps in FB until at least one accelerated UXA op.
+		 */
+		uxa_prepare_access(&pOldTile->drawable, UXA_PREPARE_SRC);
+		pNewTile = fb24_32ReformatTile (pOldTile,
+						pDrawable->bitsPerPixel);
+		uxa_finish_access(&pOldTile->drawable, UXA_PREPARE_SRC);
+	    }
+	    if (pNewTile)
+	    {
+		fbGetRotatedPixmap(pGC) = pOldTile;
+		pGC->tile.pixmap = pNewTile;
+		changes |= GCTile;
+	    }
+	}
+    }
+#endif
+    if (changes & GCTile) {
+	if (!pGC->tileIsPixel && FbEvenTile (pGC->tile.pixmap->drawable.width *
+					     pDrawable->bitsPerPixel))
+	{
+	    uxa_prepare_access(&pGC->tile.pixmap->drawable, UXA_PREPARE_SRC);
+	    fbPadPixmap (pGC->tile.pixmap);
+	    uxa_finish_access(&pGC->tile.pixmap->drawable, UXA_PREPARE_SRC);
+	}
+	/* Mask out the GCTile change notification, now that we've done FB's
+	 * job for it.
+	 */
+	changes &= ~GCTile;
+    }
+
+    uxa_prepare_access_gc(pGC);
+    fbValidateGC (pGC, changes, pDrawable);
+    uxa_finish_access_gc(pGC);
+
+    pGC->ops = (GCOps *) &uxa_ops;
+}
+
+static GCFuncs	uxaGCFuncs = {
+    uxa_validate_gc,
+    miChangeGC,
+    miCopyGC,
+    miDestroyGC,
+    miChangeClip,
+    miDestroyClip,
+    miCopyClip
+};
+
+/**
+ * uxa_create_gc makes a new GC and hooks up its funcs handler, so that
+ * uxa_validate_gc() will get called.
+ */
+static int
+uxa_create_gc (GCPtr pGC)
+{
+    if (!fbCreateGC (pGC))
+	return FALSE;
+
+    pGC->funcs = &uxaGCFuncs;
+
+    return TRUE;
+}
+
+void
+uxa_prepare_access_window(WindowPtr pWin)
+{
+    if (pWin->backgroundState == BackgroundPixmap) 
+        uxa_prepare_access(&pWin->background.pixmap->drawable, UXA_PREPARE_SRC);
+
+    if (pWin->borderIsPixel == FALSE)
+        uxa_prepare_access(&pWin->border.pixmap->drawable, UXA_PREPARE_SRC);
+}
+
+void
+uxa_finish_access_window(WindowPtr pWin)
+{
+    if (pWin->backgroundState == BackgroundPixmap) 
+        uxa_finish_access(&pWin->background.pixmap->drawable, UXA_PREPARE_SRC);
+
+    if (pWin->borderIsPixel == FALSE)
+        uxa_finish_access(&pWin->border.pixmap->drawable, UXA_PREPARE_SRC);
+}
+
+static Bool
+uxa_change_window_attributes(WindowPtr pWin, unsigned long mask)
+{
+    Bool ret;
+
+    uxa_prepare_access_window(pWin);
+    ret = fbChangeWindowAttributes(pWin, mask);
+    uxa_finish_access_window(pWin);
+    return ret;
+}
+
+static RegionPtr
+uxa_bitmap_to_region(PixmapPtr pPix)
+{
+  RegionPtr ret;
+  uxa_prepare_access(&pPix->drawable, UXA_PREPARE_SRC);
+  ret = fbPixmapToRegion(pPix);
+  uxa_finish_access(&pPix->drawable, UXA_PREPARE_SRC);
+  return ret;
+}
+
+/**
+ * uxa_close_screen() unwraps its wrapped screen functions and tears down UXA's
+ * screen private, before calling down to the next CloseSccreen.
+ */
+static Bool
+uxa_close_screen(int i, ScreenPtr pScreen)
+{
+    uxa_screen_t	*uxa_screen = uxa_get_screen(pScreen);
+#ifdef RENDER
+    PictureScreenPtr	ps = GetPictureScreenIfSet(pScreen);
+#endif
+
+    uxa_glyphs_fini(pScreen);
+
+    pScreen->CreateGC = uxa_screen->SavedCreateGC;
+    pScreen->CloseScreen = uxa_screen->SavedCloseScreen;
+    pScreen->GetImage = uxa_screen->SavedGetImage;
+    pScreen->GetSpans = uxa_screen->SavedGetSpans;
+    pScreen->CreatePixmap = uxa_screen->SavedCreatePixmap;
+    pScreen->DestroyPixmap = uxa_screen->SavedDestroyPixmap;
+    pScreen->CopyWindow = uxa_screen->SavedCopyWindow;
+    pScreen->ChangeWindowAttributes = uxa_screen->SavedChangeWindowAttributes;
+    pScreen->BitmapToRegion = uxa_screen->SavedBitmapToRegion;
+#ifdef RENDER
+    if (ps) {
+	ps->Composite = uxa_screen->SavedComposite;
+	ps->Glyphs = uxa_screen->SavedGlyphs;
+	ps->Trapezoids = uxa_screen->SavedTrapezoids;
+	ps->AddTraps = uxa_screen->SavedAddTraps;
+	ps->Triangles = uxa_screen->SavedTriangles;
+    }
+#endif
+
+    xfree (uxa_screen);
+
+    return (*pScreen->CloseScreen) (i, pScreen);
+}
+
+/**
+ * This function allocates a driver structure for UXA drivers to fill in.  By
+ * having UXA allocate the structure, the driver structure can be extended
+ * without breaking ABI between UXA and the drivers.  The driver's
+ * responsibility is to check beforehand that the UXA module has a matching
+ * major number and sufficient minor.  Drivers are responsible for freeing the
+ * driver structure using xfree().
+ *
+ * @return a newly allocated, zero-filled driver structure
+ */
+uxa_driver_t *
+uxa_driver_alloc(void)
+{
+    return xcalloc(1, sizeof(uxa_driver_t));
+}
+
+/**
+ * @param pScreen screen being initialized
+ * @param pScreenInfo UXA driver record
+ *
+ * uxa_driver_init sets up UXA given a driver record filled in by the driver.
+ * pScreenInfo should have been allocated by uxa_driver_alloc().  See the
+ * comments in _UxaDriver for what must be filled in and what is optional.
+ *
+ * @return TRUE if UXA was successfully initialized.
+ */
+Bool
+uxa_driver_init(ScreenPtr screen, uxa_driver_t *uxa_driver)
+{
+    uxa_screen_t	*uxa_screen;
+#ifdef RENDER
+    PictureScreenPtr	ps;
+#endif
+
+    if (!uxa_driver)
+	return FALSE;
+
+    if (uxa_driver->uxa_major != UXA_VERSION_MAJOR ||
+	uxa_driver->uxa_minor > UXA_VERSION_MINOR)
+    {
+	LogMessage(X_ERROR, "UXA(%d): driver's UXA version requirements "
+		   "(%d.%d) are incompatible with UXA version (%d.%d)\n",
+		   screen->myNum,
+		   uxa_driver->uxa_major, uxa_driver->uxa_minor,
+		   UXA_VERSION_MAJOR, UXA_VERSION_MINOR);
+	return FALSE;
+    }
+
+    if (!uxa_driver->PrepareSolid) {
+	LogMessage(X_ERROR, "UXA(%d): uxa_driver_t::PrepareSolid must be "
+		   "non-NULL\n", screen->myNum);
+	return FALSE;
+    }
+
+    if (!uxa_driver->PrepareCopy) {
+	LogMessage(X_ERROR, "UXA(%d): uxa_driver_t::PrepareCopy must be "
+		   "non-NULL\n", screen->myNum);
+	return FALSE;
+    }
+
+    if (!uxa_driver->WaitMarker) {
+	LogMessage(X_ERROR, "UXA(%d): uxa_driver_t::WaitMarker must be "
+		   "non-NULL\n", screen->myNum);
+	return FALSE;
+    }
+
+    /* If the driver doesn't set any max pitch values, we'll just assume
+     * that there's a limitation by pixels, and that it's the same as
+     * maxX.
+     *
+     * We want maxPitchPixels or maxPitchBytes to be set so we can check
+     * pixmaps against the max pitch in uxaCreatePixmap() -- it matters
+     * whether a pixmap is rejected because of its pitch or
+     * because of its width.
+     */
+    if (!uxa_driver->maxPitchPixels && !uxa_driver->maxPitchBytes)
+    {
+        uxa_driver->maxPitchPixels = uxa_driver->maxX;
+    }
+
+#ifdef RENDER
+    ps = GetPictureScreenIfSet(screen);
+#endif
+
+    uxa_screen = xcalloc (sizeof (uxa_screen_t), 1);
+
+    if (!uxa_screen) {
+        LogMessage(X_WARNING, "UXA(%d): Failed to allocate screen private\n",
+		   screen->myNum);
+	return FALSE;
+    }
+
+    uxa_screen->info = uxa_driver;
+
+    dixSetPrivate(&screen->devPrivates, uxa_screen_key, uxa_screen);
+
+//    exaDDXDriverInit(screen);
+
+    /*
+     * Replace various fb screen functions
+     */
+    uxa_screen->SavedCloseScreen = screen->CloseScreen;
+    screen->CloseScreen = uxa_close_screen;
+
+    uxa_screen->SavedCreateGC = screen->CreateGC;
+    screen->CreateGC = uxa_create_gc;
+
+    uxa_screen->SavedGetImage = screen->GetImage;
+    screen->GetImage = uxa_get_image;
+
+    uxa_screen->SavedGetSpans = screen->GetSpans;
+    screen->GetSpans = uxa_check_get_spans;
+
+    uxa_screen->SavedCopyWindow = screen->CopyWindow;
+    screen->CopyWindow = uxa_copy_window;
+
+    uxa_screen->SavedChangeWindowAttributes = screen->ChangeWindowAttributes;
+    screen->ChangeWindowAttributes = uxa_change_window_attributes;
+
+    uxa_screen->SavedBitmapToRegion = screen->BitmapToRegion;
+    screen->BitmapToRegion = uxa_bitmap_to_region;
+
+#ifdef RENDER
+    if (ps) {
+        uxa_screen->SavedComposite = ps->Composite;
+	ps->Composite = uxa_composite;
+
+	uxa_screen->SavedGlyphs = ps->Glyphs;
+	ps->Glyphs = uxa_glyphs;
+	
+	uxa_screen->SavedTriangles = ps->Triangles;
+	ps->Triangles = uxa_triangles;
+
+	uxa_screen->SavedTrapezoids = ps->Trapezoids;
+	ps->Trapezoids = uxa_trapezoids;
+
+	uxa_screen->SavedAddTraps = ps->AddTraps;
+	ps->AddTraps = uxa_check_add_traps;
+    }
+#endif
+
+#ifdef MITSHM
+    /* Re-register with the MI funcs, which don't allow shared pixmaps.
+     * Shared pixmaps are almost always a performance loss for us, but this
+     * still allows for SHM PutImage.
+     */
+    ShmRegisterFuncs(screen, &uxa_shm_funcs);
+#endif
+
+    uxa_glyphs_init(screen);
+
+    LogMessage(X_INFO, "UXA(%d): Driver registered support for the following"
+	       " operations:\n", screen->myNum);
+    assert(uxa_driver->PrepareSolid != NULL);
+    LogMessage(X_INFO, "        Solid\n");
+    assert(uxa_driver->PrepareCopy != NULL);
+    LogMessage(X_INFO, "        Copy\n");
+    if (uxa_driver->PrepareComposite != NULL) {
+	LogMessage(X_INFO, "        Composite (RENDER acceleration)\n");
+    }
+    if (uxa_driver->UploadToScreen != NULL) {
+	LogMessage(X_INFO, "        UploadToScreen\n");
+    }
+    if (uxa_driver->DownloadFromScreen != NULL) {
+	LogMessage(X_INFO, "        DownloadFromScreen\n");
+    }
+
+    return TRUE;
+}
+
+/**
+ * uxa_driver_fini tears down UXA on a given screen.
+ *
+ * @param pScreen screen being torn down.
+ */
+void
+uxa_driver_fini (ScreenPtr pScreen)
+{
+    /*right now does nothing*/
+}
+
+/**
+ * uxa_mark_sync() should be called after any asynchronous drawing by the hardware.
+ *
+ * @param pScreen screen which drawing occurred on
+ *
+ * uxa_mark_sync() sets a flag to indicate that some asynchronous drawing has
+ * happened and a WaitSync() will be necessary before relying on the contents of
+ * offscreen memory from the CPU's perspective.  It also calls an optional
+ * driver MarkSync() callback, the return value of which may be used to do partial
+ * synchronization with the hardware in the future.
+ */
+void uxa_mark_sync(ScreenPtr pScreen)
+{
+    uxa_screen_t    *uxa_screen = uxa_get_screen(pScreen);
+
+    uxa_screen->info->needsSync = TRUE;
+    if (uxa_screen->info->MarkSync != NULL) {
+        uxa_screen->info->lastMarker = (*uxa_screen->info->MarkSync)(pScreen);
+    }
+}
+
+/**
+ * uxa_wait_sync() ensures that all drawing has been completed.
+ *
+ * @param pScreen screen being synchronized.
+ *
+ * Calls down into the driver to ensure that all previous drawing has completed.
+ * It should always be called before relying on the framebuffer contents
+ * reflecting previous drawing, from a CPU perspective.
+ */
+void uxa_wait_sync(ScreenPtr pScreen)
+{
+    uxa_screen_t    *uxa_screen = uxa_get_screen(pScreen);
+
+    if (uxa_screen->info->needsSync && !uxa_screen->swappedOut) {
+        (*uxa_screen->info->WaitMarker)(pScreen, uxa_screen->info->lastMarker);
+        uxa_screen->info->needsSync = FALSE;
+    }
+}
diff --git a/uxa/uxa.h b/uxa/uxa.h
new file mode 100644
index 0000000..57e84f3
--- /dev/null
+++ b/uxa/uxa.h
@@ -0,0 +1,671 @@
+/*
+ * Copyright © 2000, 2008 Keith Packard
+ *             2004 Eric Anholt
+ *             2005 Zack Rusin
+ *
+ * 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 copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. 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.
+ */
+
+/** @file
+ * UXA - the unified memory acceleration architecture.
+ *
+ * This is the header containing the public API of UXA for uxa drivers.
+ */
+
+#ifndef UXA_H
+#define UXA_H
+
+#include "scrnintstr.h"
+#include "pixmapstr.h"
+#include "windowstr.h"
+#include "gcstruct.h"
+#include "picturestr.h"
+#include "fb.h"
+
+#define UXA_VERSION_MAJOR   1
+#define UXA_VERSION_MINOR   0
+#define UXA_VERSION_RELEASE 0
+
+/**
+ * The UxaDriver structure is allocated through uxa_driver_alloc(), and then
+ * fllled in by drivers.
+ */
+typedef struct _UxaDriver {
+    /**
+     * uxa_major and uxa_minor should be set by the driver to the version of
+     * UXA which the driver was compiled for (or configures itself at runtime
+     * to support).  This allows UXA to extend the structure for new features
+     * without breaking ABI for drivers compiled against older versions.
+     */
+    int uxa_major, uxa_minor;
+
+    /**
+     * The flags field is bitfield of boolean values controlling UXA's behavior.
+     *
+     * The flags include UXA_TWO_BITBLT_DIRECTIONS.
+     */
+    int flags;
+
+    /** @{ */
+    /**
+     * maxX controls the X coordinate limitation for rendering from the card.
+     * The driver should never receive a request for rendering beyond maxX
+     * in the X direction from the origin of a pixmap.
+     */
+    int maxX;
+
+    /**
+     * maxY controls the Y coordinate limitation for rendering from the card.
+     * The driver should never receive a request for rendering beyond maxY
+     * in the Y direction from the origin of a pixmap.
+     */
+    int maxY;
+    /** @} */
+
+    /* private */
+    Bool	      needsSync;
+    int               lastMarker;
+
+    /** @name Solid
+     * @{
+     */
+    /**
+     * PrepareSolid() sets up the driver for doing a solid fill.
+     * @param pPixmap Destination pixmap
+     * @param alu raster operation
+     * @param planemask write mask for the fill
+     * @param fg "foreground" color for the fill
+     *
+     * This call should set up the driver for doing a series of solid fills
+     * through the Solid() call.  The alu raster op is one of the GX*
+     * graphics functions listed in X.h, and typically maps to a similar
+     * single-byte "ROP" setting in all hardware.  The planemask controls
+     * which bits of the destination should be affected, and will only represent
+     * the bits up to the depth of pPixmap.  The fg is the pixel value of the
+     * foreground color referred to in ROP descriptions.
+     *
+     * Note that many drivers will need to store some of the data in the driver
+     * private record, for sending to the hardware with each drawing command.
+     *
+     * The PrepareSolid() call is required of all drivers, but it may fail for any
+     * reason.  Failure results in a fallback to software rendering.
+     */
+    Bool        (*PrepareSolid) (PixmapPtr      pPixmap,
+                                 int            alu,
+                                 Pixel          planemask,
+                                 Pixel          fg);
+
+    /**
+     * Solid() performs a solid fill set up in the last PrepareSolid() call.
+     *
+     * @param pPixmap destination pixmap
+     * @param x1 left coordinate
+     * @param y1 top coordinate
+     * @param x2 right coordinate
+     * @param y2 bottom coordinate
+     *
+     * Performs the fill set up by the last PrepareSolid() call, covering the
+     * area from (x1,y1) to (x2,y2) in pPixmap.  Note that the coordinates are
+     * in the coordinate space of the destination pixmap, so the driver will
+     * need to set up the hardware's offset and pitch for the destination
+     * coordinates according to the pixmap's offset and pitch within
+     * framebuffer.
+     *
+     * This call is required if PrepareSolid() ever succeeds.
+     */
+    void        (*Solid) (PixmapPtr      pPixmap, int x1, int y1, int x2, int y2);
+
+    /**
+     * DoneSolid() finishes a set of solid fills.
+     *
+     * @param pPixmap destination pixmap.
+     *
+     * The DoneSolid() call is called at the end of a series of consecutive
+     * Solid() calls following a successful PrepareSolid().  This allows drivers
+     * to finish up emitting drawing commands that were buffered, or clean up
+     * state from PrepareSolid().
+     *
+     * This call is required if PrepareSolid() ever succeeds.
+     */
+    void        (*DoneSolid) (PixmapPtr      pPixmap);
+    /** @} */
+
+    /** @name Copy
+     * @{
+     */
+    /**
+     * PrepareCopy() sets up the driver for doing a copy within video 
+     * memory.
+     *
+     * @param pSrcPixmap source pixmap
+     * @param pDstPixmap destination pixmap
+     * @param dx X copy direction
+     * @param dy Y copy direction
+     * @param alu raster operation
+     * @param planemask write mask for the fill
+     *
+     * This call should set up the driver for doing a series of copies from the
+     * the pSrcPixmap to the pDstPixmap.  The dx flag will be positive if the
+     * hardware should do the copy from the left to the right, and dy will be
+     * positive if the copy should be done from the top to the bottom.  This
+     * is to deal with self-overlapping copies when pSrcPixmap == pDstPixmap.
+     * If your hardware can only support blits that are (left to right, top to
+     * bottom) or (right to left, bottom to top), then you should set
+     * #UXA_TWO_BITBLT_DIRECTIONS, and UXA will break down Copy operations to
+     * ones that meet those requirements.  The alu raster op is one of the GX*
+     * graphics functions listed in X.h, and typically maps to a similar
+     * single-byte "ROP" setting in all hardware.  The planemask controls which
+     * bits of the destination should be affected, and will only represent the
+     * bits up to the depth of pPixmap.
+     *
+     * Note that many drivers will need to store some of the data in the driver
+     * private record, for sending to the hardware with each drawing command.
+     *
+     * The PrepareCopy() call is required of all drivers, but it may fail for any
+     * reason.  Failure results in a fallback to software rendering.
+     */
+    Bool        (*PrepareCopy) (PixmapPtr       pSrcPixmap,
+                                PixmapPtr       pDstPixmap,
+                                int             dx,
+                                int             dy,
+                                int             alu,
+                                Pixel           planemask);
+
+    /**
+     * Copy() performs a copy set up in the last PrepareCopy call.
+     *
+     * @param pDstPixmap destination pixmap
+     * @param srcX source X coordinate
+     * @param srcY source Y coordinate
+     * @param dstX destination X coordinate
+     * @param dstY destination Y coordinate
+     * @param width width of the rectangle to be copied
+     * @param height height of the rectangle to be copied.
+     *
+     * Performs the copy set up by the last PrepareCopy() call, copying the
+     * rectangle from (srcX, srcY) to (srcX + width, srcY + width) in the source
+     * pixmap to the same-sized rectangle at (dstX, dstY) in the destination
+     * pixmap.  Those rectangles may overlap in memory, if
+     * pSrcPixmap == pDstPixmap.  Note that this call does not receive the
+     * pSrcPixmap as an argument -- if it's needed in this function, it should
+     * be stored in the driver private during PrepareCopy().  As with Solid(),
+     * the coordinates are in the coordinate space of each pixmap, so the driver
+     * will need to set up source and destination pitches and offsets from those
+     * pixmaps, probably using uxaGetPixmapOffset() and uxa_get_pixmap_pitch().
+     *
+     * This call is required if PrepareCopy ever succeeds.
+     */
+    void        (*Copy) (PixmapPtr       pDstPixmap,
+                         int    srcX,
+                         int    srcY,
+                         int    dstX,
+                         int    dstY,
+                         int    width,
+                         int    height);
+
+    /**
+     * DoneCopy() finishes a set of copies.
+     *
+     * @param pPixmap destination pixmap.
+     *
+     * The DoneCopy() call is called at the end of a series of consecutive
+     * Copy() calls following a successful PrepareCopy().  This allows drivers
+     * to finish up emitting drawing commands that were buffered, or clean up
+     * state from PrepareCopy().
+     *
+     * This call is required if PrepareCopy() ever succeeds.
+     */
+    void        (*DoneCopy) (PixmapPtr       pDstPixmap);
+    /** @} */
+
+    /** @name Composite
+     * @{
+     */
+    /**
+     * CheckComposite() checks to see if a composite operation could be
+     * accelerated.
+     *
+     * @param op Render operation
+     * @param pSrcPicture source Picture
+     * @param pMaskPicture mask picture
+     * @param pDstPicture destination Picture
+     *
+     * The CheckComposite() call checks if the driver could handle acceleration
+     * of op with the given source, mask, and destination pictures.  This allows
+     * drivers to check source and destination formats, supported operations,
+     * transformations, and component alpha state, and send operations it can't
+     * support to software rendering early on.  This avoids costly pixmap
+     * migration to the wrong places when the driver can't accelerate
+     * operations.  Note that because migration hasn't happened, the driver
+     * can't know during CheckComposite() what the offsets and pitches of the
+     * pixmaps are going to be.
+     *
+     * See PrepareComposite() for more details on likely issues that drivers
+     * will have in accelerating Composite operations.
+     *
+     * The CheckComposite() call is recommended if PrepareComposite() is
+     * implemented, but is not required.
+     */
+    Bool        (*CheckComposite) (int          op,
+                                   PicturePtr   pSrcPicture,
+                                   PicturePtr   pMaskPicture,
+                                   PicturePtr   pDstPicture);
+
+    /**
+     * PrepareComposite() sets up the driver for doing a Composite operation
+     * described in the Render extension protocol spec.
+     *
+     * @param op Render operation
+     * @param pSrcPicture source Picture
+     * @param pMaskPicture mask picture
+     * @param pDstPicture destination Picture
+     * @param pSrc source pixmap
+     * @param pMask mask pixmap
+     * @param pDst destination pixmap
+     *
+     * This call should set up the driver for doing a series of Composite
+     * operations, as described in the Render protocol spec, with the given
+     * pSrcPicture, pMaskPicture, and pDstPicture.  The pSrc, pMask, and
+     * pDst are the pixmaps containing the pixel data, and should be used for
+     * setting the offset and pitch used for the coordinate spaces for each of
+     * the Pictures.
+     *
+     * Notes on interpreting Picture structures:
+     * - The Picture structures will always have a valid pDrawable.
+     * - The Picture structures will never have alphaMap set.
+     * - The mask Picture (and therefore pMask) may be NULL, in which case the
+     *   operation is simply src OP dst instead of src IN mask OP dst, and
+     *   mask coordinates should be ignored.
+     * - pMarkPicture may have componentAlpha set, which greatly changes
+     *   the behavior of the Composite operation.  componentAlpha has no effect
+     *   when set on pSrcPicture or pDstPicture.
+     * - The source and mask Pictures may have a transformation set
+     *   (Picture->transform != NULL), which means that the source coordinates
+     *   should be transformed by that transformation, resulting in scaling,
+     *   rotation, etc.  The PictureTransformPoint() call can transform
+     *   coordinates for you.  Transforms have no effect on Pictures when used
+     *   as a destination.
+     * - The source and mask pictures may have a filter set.  PictFilterNearest
+     *   and PictFilterBilinear are defined in the Render protocol, but others
+     *   may be encountered, and must be handled correctly (usually by
+     *   PrepareComposite failing, and falling back to software).  Filters have
+     *   no effect on Pictures when used as a destination.
+     * - The source and mask Pictures may have repeating set, which must be
+     *   respected.  Many chipsets will be unable to support repeating on
+     *   pixmaps that have a width or height that is not a power of two.
+     *
+     * If your hardware can't support source pictures (textures) with
+     * non-power-of-two pitches, you should set #UXA_OFFSCREEN_ALIGN_POT.
+     *
+     * Note that many drivers will need to store some of the data in the driver
+     * private record, for sending to the hardware with each drawing command.
+     *
+     * The PrepareComposite() call is not required.  However, it is highly
+     * recommended for performance of antialiased font rendering and performance
+     * of cairo applications.  Failure results in a fallback to software
+     * rendering.
+     */
+    Bool        (*PrepareComposite) (int                op,
+                                     PicturePtr         pSrcPicture,
+                                     PicturePtr         pMaskPicture,
+                                     PicturePtr         pDstPicture,
+                                     PixmapPtr          pSrc,
+                                     PixmapPtr          pMask,
+                                     PixmapPtr          pDst);
+
+    /**
+     * Composite() performs a Composite operation set up in the last
+     * PrepareComposite() call.
+     *
+     * @param pDstPixmap destination pixmap
+     * @param srcX source X coordinate
+     * @param srcY source Y coordinate
+     * @param maskX source X coordinate
+     * @param maskY source Y coordinate
+     * @param dstX destination X coordinate
+     * @param dstY destination Y coordinate
+     * @param width destination rectangle width
+     * @param height destination rectangle height
+     *
+     * Performs the Composite operation set up by the last PrepareComposite()
+     * call, to the rectangle from (dstX, dstY) to (dstX + width, dstY + height)
+     * in the destination Pixmap.  Note that if a transformation was set on
+     * the source or mask Pictures, the source rectangles may not be the same
+     * size as the destination rectangles and filtering.  Getting the coordinate
+     * transformation right at the subpixel level can be tricky, and rendercheck
+     * can test this for you.
+     *
+     * This call is required if PrepareComposite() ever succeeds.
+     */
+    void        (*Composite) (PixmapPtr         pDst,
+                              int       srcX,
+                              int        srcY,
+                              int        maskX,
+                              int        maskY,
+                              int        dstX,
+                              int        dstY,
+                              int        width,
+                              int        height);
+
+    /**
+     * DoneComposite() finishes a set of Composite operations.
+     *
+     * @param pPixmap destination pixmap.
+     *
+     * The DoneComposite() call is called at the end of a series of consecutive
+     * Composite() calls following a successful PrepareComposite().  This allows
+     * drivers to finish up emitting drawing commands that were buffered, or
+     * clean up state from PrepareComposite().
+     *
+     * This call is required if PrepareComposite() ever succeeds.
+     */
+    void        (*DoneComposite) (PixmapPtr         pDst);
+    /** @} */
+
+    /**
+     * UploadToScreen() loads a rectangle of data from src into pDst.
+     *
+     * @param pDst destination pixmap
+     * @param x destination X coordinate.
+     * @param y destination Y coordinate
+     * @param width width of the rectangle to be copied
+     * @param height height of the rectangle to be copied
+     * @param src pointer to the beginning of the source data
+     * @param src_pitch pitch (in bytes) of the lines of source data.
+     *
+     * UploadToScreen() copies data in system memory beginning at src (with
+     * pitch src_pitch) into the destination pixmap from (x, y) to
+     * (x + width, y + height).  This is typically done with hostdata uploads,
+     * where the CPU sets up a blit command on the hardware with instructions
+     * that the blit data will be fed through some sort of aperture on the card.
+     *
+     * If UploadToScreen() is performed asynchronously, it is up to the driver
+     * to call uxa_mark_sync().  This is in contrast to most other acceleration
+     * calls in UXA.
+     *
+     * UploadToScreen() can aid in pixmap migration, but is most important for
+     * the performance of uxa_glyphs() (antialiased font drawing) by allowing
+     * pipelining of data uploads, avoiding a sync of the card after each glyph.
+     * 
+     * @return TRUE if the driver successfully uploaded the data.  FALSE
+     * indicates that UXA should fall back to doing the upload in software.
+     *
+     * UploadToScreen() is not required, but is recommended if Composite
+     * acceleration is supported.
+     */
+    Bool        (*UploadToScreen) (PixmapPtr            pDst,
+				   int                  x,
+				   int                  y,
+				   int                  w,
+				   int                  h,
+                                   char                 *src,
+                                   int                  src_pitch);
+
+    /**
+     * UploadToScratch() is used to upload a pixmap to a scratch area for
+     * acceleration.
+     *
+     * @param pSrc source pixmap in host memory
+     * @param pDst fake, scratch pixmap to be set up in offscreen memory.
+     *
+     * The UploadToScratch() call was added to support Xati before Xati had
+     * support for hostdata uploads and before uxa_glyphs() was written.  It
+     * behaves incorrectly (uses an invalid pixmap as pDst),
+     * and UploadToScreen() should be implemented instead.
+     *
+     * Drivers implementing UploadToScratch() had to set up space (likely in a
+     * statically allocated area) in offscreen memory, copy pSrc to that
+     * scratch area, and adust pDst->devKind for the pitch and
+     * pDst->devPrivate.ptr for the pointer to that scratch area.  The driver
+     * was responsible for syncing (as it was implemented using memcpy() in
+     * Xati), and only the data from the last UploadToScratch() was guaranteed
+     * to be valid at any given time.
+     *
+     * UploadToScratch() should not be implemented by drivers, and will likely
+     * be removed in a future version of UXA.
+     */
+    Bool        (*UploadToScratch) (PixmapPtr           pSrc,
+                                    PixmapPtr           pDst);
+
+    /**
+     * DownloadFromScreen() loads a rectangle of data from pSrc into dst
+     *
+     * @param pSrc source pixmap
+     * @param x source X coordinate.
+     * @param y source Y coordinate
+     * @param width width of the rectangle to be copied
+     * @param height height of the rectangle to be copied
+     * @param dst pointer to the beginning of the destination data
+     * @param dst_pitch pitch (in bytes) of the lines of destination data.
+     *
+     * DownloadFromScreen() copies data from offscreen memory in pSrc from
+     * (x, y) to (x + width, y + height), to system memory starting at
+     * dst (with pitch dst_pitch).  This would usually be done
+     * using scatter-gather DMA, supported by a DRM call, or by blitting to AGP
+     * and then synchronously reading from AGP.  Because the implementation
+     * might be synchronous, UXA leaves it up to the driver to call
+     * uxa_mark_sync() if DownloadFromScreen() was asynchronous.  This is in
+     * contrast to most other acceleration calls in UXA.
+     *
+     * DownloadFromScreen() can aid in the largest bottleneck in pixmap
+     * migration, which is the read from framebuffer when evicting pixmaps from
+     * framebuffer memory.  Thus, it is highly recommended, even though
+     * implementations are typically complicated.
+     * 
+     * @return TRUE if the driver successfully downloaded the data.  FALSE
+     * indicates that UXA should fall back to doing the download in software.
+     *
+     * DownloadFromScreen() is not required, but is highly recommended.
+     */
+    Bool (*DownloadFromScreen)(PixmapPtr pSrc,
+                               int x,  int y,
+                               int w,  int h,
+                               char *dst,  int dst_pitch);
+
+    /**
+     * MarkSync() requests that the driver mark a synchronization point,
+     * returning an driver-defined integer marker which could be requested for
+     * synchronization to later in WaitMarker().  This might be used in the
+     * future to avoid waiting for full hardware stalls before accessing pixmap
+     * data with the CPU, but is not important in the current incarnation of
+     * UXA.
+     *
+     * Note that drivers should call uxa_mark_sync() when they have done some
+     * acceleration, rather than their own MarkSync() handler, as otherwise UXA
+     * will be unaware of the driver's acceleration and not sync to it during
+     * fallbacks.
+     *
+     * MarkSync() is optional.
+     */
+    int		(*MarkSync)   (ScreenPtr pScreen);
+
+    /**
+     * WaitMarker() waits for all rendering before the given marker to have
+     * completed.  If the driver does not implement MarkSync(), marker is
+     * meaningless, and all rendering by the hardware should be completed before
+     * WaitMarker() returns.
+     *
+     * Note that drivers should call uxa_wait_sync() to wait for all acceleration
+     * to finish, as otherwise UXA will be unaware of the driver having
+     * synchronized, resulting in excessive WaitMarker() calls.
+     *
+     * WaitMarker() is required of all drivers.
+     */
+    void	(*WaitMarker) (ScreenPtr pScreen, int marker);
+
+    /** @{ */
+    /**
+     * PrepareAccess() is called before CPU access to an offscreen pixmap.
+     *
+     * @param pPix the pixmap being accessed
+     * @param index the index of the pixmap being accessed.
+     *
+     * PrepareAccess() will be called before CPU access to an offscreen pixmap.
+     * This can be used to set up hardware surfaces for byteswapping or
+     * untiling, or to adjust the pixmap's devPrivate.ptr for the purpose of
+     * making CPU access use a different aperture.
+     *
+     * The index is one of #UXA_PREPARE_DEST, #UXA_PREPARE_SRC, or
+     * #UXA_PREPARE_MASK, indicating which pixmap is in question.  Since only up
+     * to three pixmaps will have PrepareAccess() called on them per operation,
+     * drivers can have a small, statically-allocated space to maintain state
+     * for PrepareAccess() and FinishAccess() in.  Note that the same pixmap may
+     * have PrepareAccess() called on it more than once, for uxample when doing
+     * a copy within the same pixmap (so it gets PrepareAccess as()
+     * #UXA_PREPARE_DEST and then as #UXA_PREPARE_SRC).
+     *
+     * PrepareAccess() may fail.  An uxample might be the case of hardware that
+     * can set up 1 or 2 surfaces for CPU access, but not 3.  If PrepareAccess()
+     * fails, UXA will migrate the pixmap to system memory.
+     * DownloadFromScreen() must be implemented and must not fail if a driver
+     * wishes to fail in PrepareAccess().  PrepareAccess() must not fail when
+     * pPix is the visible screen, because the visible screen can not be
+     * migrated.
+     *
+     * @return TRUE if PrepareAccess() successfully prepared the pixmap for CPU
+     * drawing.
+     * @return FALSE if PrepareAccess() is unsuccessful and UXA should use
+     * DownloadFromScreen() to migate the pixmap out.
+     */
+    Bool	(*PrepareAccess)(PixmapPtr pPix, int index);
+
+    /**
+     * FinishAccess() is called after CPU access to an offscreen pixmap.
+     *
+     * @param pPix the pixmap being accessed
+     * @param index the index of the pixmap being accessed.
+     *
+     * FinishAccess() will be called after finishing CPU access of an offscreen
+     * pixmap set up by PrepareAccess().  Note that the FinishAccess() will not be
+     * called if PrepareAccess() failed and the pixmap was migrated out.
+     */
+    void	(*FinishAccess)(PixmapPtr pPix, int index);
+
+    /**
+     * PixmapIsOffscreen() is an optional driver replacement to
+     * uxa_pixmap_is_offscreen(). Set to NULL if you want the standard behaviour
+     * of uxa_pixmap_is_offscreen().
+     *
+     * @param pPix the pixmap
+     * @return TRUE if the given drawable is in framebuffer memory.
+     *
+     * uxa_pixmap_is_offscreen() is used to determine if a pixmap is in offscreen
+     * memory, meaning that acceleration could probably be done to it, and that it
+     * will need to be wrapped by PrepareAccess()/FinishAccess() when accessing it
+     * with the CPU.
+     *
+     *
+     */
+    Bool	(*PixmapIsOffscreen)(PixmapPtr pPix);
+
+	/** @name PrepareAccess() and FinishAccess() indices
+	 * @{
+	 */
+	/**
+	 * UXA_PREPARE_DEST is the index for a pixmap that may be drawn to or
+	 * read from.
+	 */ 
+	#define UXA_PREPARE_DEST	0
+	/**
+	 * UXA_PREPARE_SRC is the index for a pixmap that may be read from
+	 */
+	#define UXA_PREPARE_SRC		1
+	/**
+	 * UXA_PREPARE_SRC is the index for a second pixmap that may be read
+	 * from.
+	 */
+	#define UXA_PREPARE_MASK	2
+	/** @} */
+
+    /**
+     * maxPitchPixels controls the pitch limitation for rendering from
+     * the card.
+     * The driver should never receive a request for rendering a pixmap
+     * that has a pitch (in pixels) beyond maxPitchPixels.
+     *
+     * Setting this field is optional -- if your hardware doesn't have
+     * a pitch limitation in pixels, don't set this. If neither this value
+     * nor maxPitchBytes is set, then maxPitchPixels is set to maxX.
+     * If set, it must not be smaller than maxX.
+     *
+     * @sa maxPitchBytes
+     */
+    int maxPitchPixels;
+
+    /**
+     * maxPitchBytes controls the pitch limitation for rendering from
+     * the card.
+     * The driver should never receive a request for rendering a pixmap
+     * that has a pitch (in bytes) beyond maxPitchBytes.
+     *
+     * Setting this field is optional -- if your hardware doesn't have
+     * a pitch limitation in bytes, don't set this.
+     * If set, it must not be smaller than maxX * 4.
+     * There's no default value for maxPitchBytes.
+     *
+     * @sa maxPitchPixels
+     */
+    int maxPitchBytes;
+
+    /** @} */
+} uxa_driver_t;
+
+/** @name UXA driver flags
+ * @{
+ */
+/**
+ * UXA_TWO_BITBLT_DIRECTIONS indicates to UXA that the driver can only
+ * support copies that are (left-to-right, top-to-bottom) or
+ * (right-to-left, bottom-to-top).
+ */
+#define UXA_TWO_BITBLT_DIRECTIONS	(1 << 2)
+
+/** @} */
+
+uxa_driver_t *
+uxa_driver_alloc(void);
+
+Bool
+uxa_driver_init(ScreenPtr screen, uxa_driver_t *uxa_driver);
+
+void
+uxa_driver_fini(ScreenPtr pScreen);
+
+void
+uxa_mark_sync(ScreenPtr pScreen);
+
+void
+uxa_wait_sync(ScreenPtr pScreen);
+
+void
+uxaEnableDisableFBAccess (int index, Bool enable);
+
+CARD32
+uxa_get_pixmap_first_pixel (PixmapPtr pPixmap);
+
+/**
+ * Returns TRUE if the given planemask covers all the significant bits in the
+ * pixel values for pDrawable.
+ */
+#define UXA_PM_IS_SOLID(_pDrawable, _pm) \
+	(((_pm) & FbFullMask((_pDrawable)->depth)) == \
+	 FbFullMask((_pDrawable)->depth))
+
+#endif /* UXA_H */
commit c2f0df4dc97c87539b66525a277c7d1e2c421f61
Merge: 4f1f308... 750bd0b...
Author: Jesse Barnes <jbarnes at jbarnes-t61.(none)>
Date:   Tue Aug 5 13:03:46 2008 -0700

    Merge branch 'drm-gem' of ssh://git.freedesktop.org/git/xorg/driver/xf86-video-intel into drm-gem

commit 4f1f30854260e18b8b9c4103eebbad5dcf729ce6
Merge: e9e6b47... 2aaa207...
Author: Jesse Barnes <jbarnes at jbarnes-t61.(none)>
Date:   Tue Aug 5 13:02:47 2008 -0700

    Merge branch 'master' into drm-gem
    
    Conflicts:
    
    	src/i830_driver.c

diff --cc src/Makefile.am
index e3bbdce,382c0aa..2932233
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@@ -177,8 -174,9 +176,9 @@@ INTEL_G4B = 				
  	exa_wm_ca.g4b			\
  	exa_wm_ca_srcalpha.g4b		\
  	exa_wm_write.g4b 		\
+ 	exa_wm_yuv_rgb.g4b		\
  	exa_wm_xy.g4b
 -	
 +
  EXTRA_DIST = 		\
  	$(XMODE_SRCS)	\
  	$(INTEL_G4A)	\
diff --cc src/i830_driver.c
index dcbaa04,f5aa114..4cede90
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@@ -3368,20 -3298,18 +3376,20 @@@ I830LeaveVT(int scrnIndex, int flags
     if (I830IsPrimary(pScrn))
        i830_unbind_all_memory(pScrn);
  
 -   /* Tell the kernel to evict all buffer objects and block new buffer
 -    * allocations until we relese the lock.
 -    */
 -#ifdef XF86DRI_MM
 -   if (pI830->directRenderingOpen) {
 -      if (pI830->memory_manager != NULL && pScrn->vtSema) {
 -	 drmMMLock(pI830->drmSubFD, DRM_BO_MEM_TT, 1, 0);
 -      }
 +#ifdef XF86DRI
 +   if (pI830->memory_manager) {
 +      int ret;
 +
 +      /* Tell the kernel to evict all buffer objects and block GTT usage while
 +       * we're no longer in control of the chip.
 +       */
 +      ret = drmCommandNone(pI830->drmSubFD, DRM_I915_GEM_LEAVEVT);
 +      if (ret != 0)
 +	 FatalError("DRM_I915_LEAVEVT failed: %s\n", strerror(ret));
     }
 -#endif /* XF86DRI_MM */
 +#endif /* XF86DRI */
  
-    if (IS_I965G(pI830))
+    if (pI830->useEXA && IS_I965G(pI830))
        gen4_render_state_cleanup(pScrn);
  
     if (pI830->AccelInfoRec)
@@@ -3432,9 -3358,7 +3440,9 @@@ I830EnterVT(int scrnIndex, int flags
     /* Update the screen pixmap in case the buffer moved */
     i830_update_front_offset(pScrn);
  
 +   intel_batch_init(pScrn);
 +
-    if (IS_I965G(pI830))
+    if (pI830->useEXA && IS_I965G(pI830))
        gen4_render_state_init(pScrn);
  
     if (i830_check_error_state(pScrn)) {
commit 750bd0bde09adf956c17bbb49c5a6020f12e60a4
Author: Carl Worth <cworth at cworth.org>
Date:   Tue Jul 29 15:22:39 2008 -0700

    Call DRM_I915_GEM_THROTTLE from I830BlockHandler
    
    This prevents the CPU from ridiculously outrunning the GPU.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index a453d90..195bc5c 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2507,6 +2507,9 @@ I830BlockHandler(int i,
        intel_batch_flush(pScrn);
 
        pI830->need_mi_flush = FALSE;
+#ifdef XF86DRI
+       drmCommandNone(pI830->drmSubFD, DRM_I915_GEM_THROTTLE);
+#endif
     }
 
     /*
commit a893f176dda0b64f7dadfda6bf0331240037851e
Author: Carl Worth <cworth at cworth.org>
Date:   Fri Jul 25 15:56:35 2008 -0700

    Add call to intel_bufmgr_gem_enable_reuse
    
    This instructs GEM to reuse buffer objects and improves the
    performance of my favorite 'x11perf -aa10text' from about
    169k to about 188k glyphs/sec.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index dcbaa04..a453d90 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2760,6 +2760,7 @@ i830_init_bufmgr(ScrnInfoPtr pScrn)
 	 batch_size = 4096;
 
       pI830->bufmgr = intel_bufmgr_gem_init(pI830->drmSubFD, batch_size);
+      intel_bufmgr_gem_enable_reuse(pI830->bufmgr);
    } else {
       pI830->bufmgr = intel_bufmgr_fake_init(pI830->fake_bufmgr_mem->offset,
 					     pI830->FbBase +
commit b3c1a148679a4d943e556f996ef6b9004f549a41
Author: Carl Worth <cworth at cworth.org>
Date:   Fri Jul 25 15:18:28 2008 -0700

    Eliminate unnecessary flush from i965_composite
    
    This improves 'x11perf -aa10text' performance from ~144k to ~169k

diff --git a/src/i965_render.c b/src/i965_render.c
index 93e2888..6eafd44 100644
--- a/src/i965_render.c
+++ b/src/i965_render.c
@@ -1447,21 +1447,6 @@ i965_composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
     ErrorF("sync after 3dprimitive\n");
     I830Sync(pScrn);
 #endif
-    /* we must be sure that the pipeline is flushed before next exa draw,
-       because that will be new state, binding state and instructions*/
-    {
-	BEGIN_BATCH(4);
-	OUT_BATCH(BRW_PIPE_CONTROL |
-		  BRW_PIPE_CONTROL_NOWRITE |
-		  BRW_PIPE_CONTROL_WC_FLUSH |
-		  BRW_PIPE_CONTROL_IS_FLUSH |
-		  (1 << 10) |  /* XXX texture cache flush for BLC/CTG */
-		  2);
-	OUT_BATCH(0); /* Destination address */
-	OUT_BATCH(0); /* Immediate data low DW */
-	OUT_BATCH(0); /* Immediate data high DW */
-	ADVANCE_BATCH();
-    }
 }
 
 /**
commit 1abf4d3a7a203ff5d6e5ceda29573e7fd69ddf8e
Author: Carl Worth <cworth at cworth.org>
Date:   Fri Jul 25 14:48:45 2008 -0700

    Switch to using a buffer object for the vertex buffer

diff --git a/src/i965_render.c b/src/i965_render.c
index 1cbfe24..93e2888 100644
--- a/src/i965_render.c
+++ b/src/i965_render.c
@@ -37,6 +37,7 @@
 #include "xf86.h"
 #include "i830.h"
 #include "i915_reg.h"
+#include "i915_drm.h"
 
 /* bring in brw structs */
 #include "brw_defines.h"
@@ -60,7 +61,7 @@ do { 							\
 #endif
 
 #define MAX_VERTEX_PER_COMPOSITE    24
-#define MAX_VERTEX_BUFFERS	    256
+#define VERTEX_BUFFER_SIZE	    (16 * MAX_VERTEX_PER_COMPOSITE)
 
 struct blendinfo {
     Bool dst_alpha;
@@ -502,14 +503,14 @@ typedef struct _gen4_state {
 				     [BRW_BLENDFACTOR_COUNT];
     struct brw_cc_viewport cc_viewport;
     PAD64 (brw_cc_viewport, 0);
-
-    float vb[MAX_VERTEX_PER_COMPOSITE * MAX_VERTEX_BUFFERS];
 } gen4_state_t;
 
 /** Private data for gen4 render accel implementation. */
 struct gen4_render_state {
     gen4_state_t *card_state;
     uint32_t card_state_offset;
+    dri_bo *vb_bo;
+    int vb_bo_busy;
 
     int binding_table_index;
     int surface_state_index;
@@ -1270,12 +1271,11 @@ i965_composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
 {
     ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
-    gen4_state_t *card_state = pI830->gen4_render_state->card_state;
     struct gen4_render_state *render_state = pI830->gen4_render_state;
     Bool has_mask;
     Bool is_affine_src, is_affine_mask, is_affine;
     float src_x[3], src_y[3], src_w[3], mask_x[3], mask_y[3], mask_w[3];
-    float *vb = card_state->vb;
+    float *vb;
     int i;
 
     is_affine_src = i830_transform_is_affine (pI830->transform[0]);
@@ -1352,11 +1352,25 @@ i965_composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
 	}
     }
 
-    if (render_state->vb_offset + MAX_VERTEX_PER_COMPOSITE >= ARRAY_SIZE(card_state->vb)) {
-	i830WaitSync(pScrn);
+    /* Arrange for a buffer object with sufficient space for our
+     * vertices, and that isn't "busy", that is, it is not already
+     * referenced by a batch that has been flushed. */
+    if (! render_state->vb_bo || render_state->vb_bo_busy ||
+	render_state->vb_offset + MAX_VERTEX_PER_COMPOSITE > VERTEX_BUFFER_SIZE)
+    {
+	if (render_state->vb_bo)
+	    dri_bo_unreference (render_state->vb_bo);
+
+	render_state->vb_bo = dri_bo_alloc (pI830->bufmgr, "vb",
+					    VERTEX_BUFFER_SIZE * sizeof (float),
+					    4096);
 	render_state->vb_offset = 0;
     }
 
+    /* Map the vertex buffer object so we can write to it. */
+    dri_bo_map (render_state->vb_bo, 1);
+    vb = render_state->vb_bo->virtual;
+
     i = render_state->vb_offset;
     /* rect (x2,y2) */
     vb[i++] = (float)(dstX + w);
@@ -1399,7 +1413,9 @@ i965_composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
 	if (!is_affine)
 	    vb[i++] = mask_w[0];
     }
-    assert (i * 4 <= sizeof(card_state->vb));
+    assert (i <= VERTEX_BUFFER_SIZE);
+
+    dri_bo_unmap (render_state->vb_bo);
 
     BEGIN_BATCH(12);
     OUT_BATCH(MI_FLUSH);
@@ -1408,7 +1424,7 @@ i965_composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
     OUT_BATCH((0 << VB0_BUFFER_INDEX_SHIFT) |
 	      VB0_VERTEXDATA |
 	      (render_state->vertex_size << VB0_BUFFER_PITCH_SHIFT));
-    OUT_BATCH(render_state->card_state_offset + offsetof(gen4_state_t, vb) +
+    OUT_RELOC(render_state->vb_bo, I915_GEM_DOMAIN_VERTEX, 0,
 	      render_state->vb_offset * 4);
     OUT_BATCH(3);
     OUT_BATCH(0); // ignore for VERTEXDATA, but still there
@@ -1446,11 +1462,6 @@ i965_composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
 	OUT_BATCH(0); /* Immediate data high DW */
 	ADVANCE_BATCH();
     }
-
-    /* Mark sync so we can wait for it before setting up the VB on the next
-     * rectangle.
-     */
-    i830MarkSync(pScrn);
 }
 
 /**
commit e5fab0b7681be06a5a3be4bbd769ba5c435e2128
Author: Carl Worth <cworth at cworth.org>
Date:   Fri Jul 25 13:44:29 2008 -0700

    Add OUT_RELOC macro and backing intel_batch_emit_reloc function

diff --git a/src/i830_batchbuffer.h b/src/i830_batchbuffer.h
index 2b898c2..c9b8421 100644
--- a/src/i830_batchbuffer.h
+++ b/src/i830_batchbuffer.h
@@ -60,6 +60,20 @@ intel_batch_emit_dword(I830Ptr pI830, uint32_t dword)
 }
 
 static inline void
+intel_batch_emit_reloc (I830Ptr  pI830,
+			dri_bo  *bo,
+			uint32_t read_domains,
+			uint32_t write_domains,
+			uint32_t delta)
+{
+    assert(intel_batch_space(pI830) >= 4);
+    *(uint32_t *)(pI830->batch_ptr + pI830->batch_used) = bo->offset + delta;
+    intel_bo_emit_reloc (pI830->batch_bo, read_domains, write_domains, delta,
+			 pI830->batch_used, bo);
+    pI830->batch_used += 4;
+}
+
+static inline void
 intel_batch_emit_reloc_pixmap(I830Ptr pI830, PixmapPtr pPixmap, uint32_t delta)
 {
     assert(pI830->batch_ptr != NULL);
@@ -71,6 +85,9 @@ intel_batch_emit_reloc_pixmap(I830Ptr pI830, PixmapPtr pPixmap, uint32_t delta)
 
 #define OUT_BATCH(dword) intel_batch_emit_dword(pI830, dword)
 
+#define OUT_RELOC(bo, read_domains, write_domains, delta) \
+	intel_batch_emit_reloc (pI830, bo, read_domains, write_domains, delta)
+
 #define OUT_RELOC_PIXMAP(pPixmap, delta)	\
 	intel_batch_emit_reloc_pixmap(pI830, pPixmap, delta)
 
commit e9e6b4738573ffa3822ae68088bd53a645eedbce
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Jul 30 14:15:57 2008 -0700

    intel-gem: Use new getparam to detect kernel GEM support.

diff --git a/src/i830_memory.c b/src/i830_memory.c
index 2e238e2..b62bda0 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -384,6 +384,8 @@ i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset, unsigned long size)
     i830_memory *start, *end;
 #ifdef XF86DRI
     int dri_major, dri_minor, dri_patch;
+    struct drm_i915_getparam gp;
+    int has_gem;
 #endif
 
     start = xcalloc(1, sizeof(*start));
@@ -424,12 +426,19 @@ i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset, unsigned long size)
 #ifdef XF86DRI
     DRIQueryVersion(&dri_major, &dri_minor, &dri_patch);
 
+    has_gem = 0;
+    gp.param = I915_PARAM_HAS_GEM;
+    gp.value = &has_gem;
+
+    (void)drmCommandWriteRead(pI830->drmSubFD, DRM_I915_GETPARAM,
+			      &gp, sizeof(gp));
+
     /* Now that we have our manager set up, initialize the kernel MM if
      * possible, covering almost all of the aperture.  We need libdri interface
      * 5.4 or newer so we can rely on the lock being held after DRIScreenInit,
      * rather than after DRIFinishScreenInit.
      */
-    if (pI830->directRenderingEnabled && pI830->drmMinor >= 7 &&
+    if (pI830->directRenderingEnabled && has_gem &&
 	(dri_major > 5 || (dri_major == 5 && dri_minor >= 4)))
     {
 	int mmsize;
commit d77d42e543ee82e801a8563a911826521c0ba557
Author: Eric Anholt <eric at anholt.net>
Date:   Sat Jul 26 16:10:05 2008 -0700

    intel-gem: Give a better error message if the kernel rejects the tiling mode.

diff --git a/src/i830_memory.c b/src/i830_memory.c
index 222882c..2e238e2 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -914,7 +914,8 @@ i830_allocate_memory_tiled(ScrnInfoPtr pScrn, const char *name,
 	if (ret != 0 || set_tiling.tiling_mode == I915_TILING_NONE) {
 		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 			   "Failed to set tiling on %s: %s\n",
-			   mem->name, strerror(errno));
+			   mem->name,
+			   ret == 0 ? "rejected by kernel" : strerror(errno));
 		i830_free_memory(pScrn, mem);
 		return i830_allocate_memory(pScrn, name, size, alignment,
 					    flags);
commit 286ff63f83db8ea16514512385e6f8c6875871ef
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Jul 17 17:06:28 2008 -0700

    Don't set up the HWS page in GEM mode now that the kernel manages it.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 03861a9..dcbaa04 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -3477,7 +3477,7 @@ I830EnterVT(int scrnIndex, int flags)
 	* operation which accessing that page, like irq install, etc.
 	*/
        if (pI830->starting) {
-	   if (HWS_NEED_GFX(pI830) && !I830DRISetHWS(pScrn)) {
+	   if (pI830->hw_status != NULL && !I830DRISetHWS(pScrn)) {
 		   xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 			   "Fail to setup hardware status page.\n");
 		   I830DRICloseScreen(pScrn->pScreen);
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 08a2201..222882c 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -462,10 +462,6 @@ i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset, unsigned long size)
 	/* Can't do GEM on stolen memory */
 	mmsize -= pI830->stolen_size;
 
-	/* new chipsets need non-stolen status page */
-	if (HWS_NEED_GFX(pI830) && HWS_NEED_NONSTOLEN(pI830))
-	    mmsize -= HWSTATUS_PAGE_SIZE;
-
 	/* Create the aperture allocation */
 	pI830->memory_manager =
 	    i830_allocate_aperture(pScrn, "DRI memory manager",
@@ -1717,7 +1713,7 @@ i830_allocate_3d_memory(ScrnInfoPtr pScrn)
 
     DPRINTF(PFX, "i830_allocate_3d_memory\n");
 
-    if (HWS_NEED_GFX(pI830)) {
+    if (!pI830->memory_manager && HWS_NEED_GFX(pI830)) {
 	if (!i830_allocate_hwstatus(pScrn))
 	    return FALSE;
     }
commit f4ab1f6ad47b8f9a33d45b35c1cb2ba9610b96a6
Author: Carl Worth <cworth at cworth.org>
Date:   Fri Jul 18 14:31:45 2008 -0700

    Add intel_statuspage to .gitignore

diff --git a/src/reg_dumper/.gitignore b/src/reg_dumper/.gitignore
index b0f9b6f..0adc8b2 100644
--- a/src/reg_dumper/.gitignore
+++ b/src/reg_dumper/.gitignore
@@ -2,3 +2,4 @@ intel_hotplug
 intel_idle
 intel_reg_dumper
 intel_stepping
+intel_statuspage
commit c0dce28892d7a31ebcca615f87ba8d4fa6872204
Merge: a6ad504... b8ca1c7...
Author: Keith Packard <keithp at keithp.com>
Date:   Fri Jul 18 10:49:50 2008 -0700

    Merge commit 'origin/master' into drm-gem

commit a6ad50402cb879b08de95f94959bb1f59701c1ff
Merge: e9916b9... c4565a9...
Author: Carl Worth <cworth at cworth.org>
Date:   Thu Jul 17 00:38:54 2008 -0700

    Merge branch 'master' into drm-gem
    
    Conflicts:
    
    	configure.ac
    	src/reg_dumper/Makefile.am

diff --cc configure.ac
index e62502c,2dabd4f..254fef4
--- a/configure.ac
+++ b/configure.ac
@@@ -196,12 -196,15 +196,16 @@@ if test "x$GCC" = "xyes"; the
  	-Wnested-externs -fno-strict-aliasing"
  fi
  
 +PKG_CHECK_MODULES(DRM, [libdrm >= 2.4.0])
  AM_CONDITIONAL(DRI, test x$DRI = xyes)
  if test "$DRI" = yes; then
 -        PKG_CHECK_MODULES(DRI, [libdrm xf86driproto glproto])
 +        PKG_CHECK_MODULES(DRI, [xf86driproto glproto])
          AC_DEFINE(XF86DRI,1,[Enable DRI driver support])
          AC_DEFINE(XF86DRI_DEVEL,1,[Enable developmental DRI driver support])
+ 	PKG_CHECK_MODULES(DRI_MM, [libdrm >= 2.4.0],[DRI_MM=yes], [DRI_MM=no])
+ 	if test "x$DRI_MM" = xyes; then
+ 		AC_DEFINE(XF86DRI_MM,1,[Extended DRI memory management])
+ 	fi
  	if test "$have_damage_h" = yes; then
  		AC_DEFINE(DAMAGE,1,[Use Damage extension])
  	fi
diff --cc src/i830_memory.c
index 3d6e245,0a2faeb..08a2201
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@@ -459,10 -456,11 +459,11 @@@ i830_allocator_init(ScrnInfoPtr pScrn, 
  	}
  	if (pI830->fb_compression)
  	    mmsize -= MB(6) + ROUND_TO_PAGE(FBC_LL_SIZE + FBC_LL_PAD);
 -	/* Can't do TTM on stolen memory */
 +	/* Can't do GEM on stolen memory */
  	mmsize -= pI830->stolen_size;
  
- 	if (HWS_NEED_GFX(pI830) && IS_IGD_GM(pI830))
+ 	/* new chipsets need non-stolen status page */
+ 	if (HWS_NEED_GFX(pI830) && HWS_NEED_NONSTOLEN(pI830))
  	    mmsize -= HWSTATUS_PAGE_SIZE;
  
  	/* Create the aperture allocation */
diff --cc src/reg_dumper/Makefile.am
index 1c8db20,d49a59b..1127581
--- a/src/reg_dumper/Makefile.am
+++ b/src/reg_dumper/Makefile.am
@@@ -1,4 -1,4 +1,4 @@@
- noinst_PROGRAMS = intel_reg_dumper intel_idle intel_stepping intel_statuspage
 -noinst_PROGRAMS = intel_reg_dumper intel_idle intel_stepping intel_hotplug
++noinst_PROGRAMS = intel_reg_dumper intel_idle intel_stepping intel_statuspage intel_hotplug
  
  intel_reg_dumper_SOURCES = \
  	main.c \
@@@ -15,11 -21,7 +21,12 @@@ intel_hotplug_SOURCES = 
  intel_stepping_SOURCES = \
  	stepping.c
  
 +intel_statuspage_SOURCES = \
 +	statuspage.c \
 +	reg_dumper.h \
 +	util.c
 +
+ intel_hotplug_LDADD = $(PCIACCESS_LIBS)
  intel_reg_dumper_LDADD = $(PCIACCESS_LIBS)
  intel_idle_LDADD = $(PCIACCESS_LIBS)
  intel_stepping_LDADD = $(PCIACCESS_LIBS)
commit e9916b9d496fd0b4df717892dda33f81a2e2990a
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Jul 11 18:59:05 2008 -0700

    Set tiling state for buffers allocated using GEM.

diff --git a/src/i830_memory.c b/src/i830_memory.c
index c357621..3d6e245 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -901,6 +901,31 @@ i830_allocate_memory_tiled(ScrnInfoPtr pScrn, const char *name,
     mem->pitch = pitch;
     mem->fence_nr = -1;
 
+#ifdef XF86DRI
+    if (mem->gem_handle != 0) {
+	struct drm_i915_gem_set_tiling set_tiling;
+	int ret;
+
+	set_tiling.handle = mem->gem_handle;
+	if (tile_format == TILE_XMAJOR)
+	    set_tiling.tiling_mode = I915_TILING_X;
+	else
+	    set_tiling.tiling_mode = I915_TILING_Y;
+
+	ret = ioctl(pI830->drmSubFD, DRM_IOCTL_I915_GEM_SET_TILING,
+		    &set_tiling);
+	if (ret != 0 || set_tiling.tiling_mode == I915_TILING_NONE) {
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			   "Failed to set tiling on %s: %s\n",
+			   mem->name, strerror(errno));
+		i830_free_memory(pScrn, mem);
+		return i830_allocate_memory(pScrn, name, size, alignment,
+					    flags);
+	    return FALSE;
+	}
+    }
+#endif
+
     return mem;
 }
 
commit 9d7929436488969ca4fd1fef4d2e92be5e1a93aa
Author: Keith Packard <keithp at keithp.com>
Date:   Fri Jun 20 00:23:45 2008 -0700

    Flush pending batch in block handler
    
    Make sure any pending rendering commands are delivered to the hardware
    before the server goes to sleep.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 580cbbc..5525aec 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2496,7 +2496,7 @@ I830BlockHandler(int i,
 	* rendering results may not hit the framebuffer until significantly
 	* later.
 	*/
-       if (!pI830->noAccel && pI830->need_mi_flush)
+       if (!pI830->noAccel && (pI830->need_mi_flush || pI830->batch_used))
 	  I830EmitFlush(pScrn);
 
        /* Flush the batch, so that any rendering is executed in a timely
commit 2f8a0aa8cd24ede824aa52102b45a295f1b6b5be
Author: Keith Packard <keithp at keithp.com>
Date:   Tue May 20 20:29:25 2008 -0700

    Remove some unreliable regs for i915

diff --git a/src/reg_dumper/idle.c b/src/reg_dumper/idle.c
index 46a2fd5..dbfa58e 100644
--- a/src/reg_dumper/idle.c
+++ b/src/reg_dumper/idle.c
@@ -43,11 +43,13 @@ struct idle_flags {
 };
 
 struct idle_flags i915_idle_flags[] = {
+#if 0
     {IDCT_DONE, "IDCT"},
     {IQ_DONE, "IQ"},
     {PR_DONE, "PR"},
     {VLD_DONE, "VLD"},
     {IP_DONE, "IP"},
+#endif
     {FBC_DONE, "FBC"},
     {BINNER_DONE, "BINNER"},
     {SF_DONE, "SF"},
@@ -66,7 +68,9 @@ struct idle_flags i915_idle_flags[] = {
     {PS_DONE, "PS"},
     {CC_DONE, "CC"},
     {MAP_FILTER_DONE, "map filter"},
+#if 0
     {MAP_L2_IDLE, "map L2"},
+#endif
 
     {0, "total"},
     {0, "other"},
@@ -105,8 +109,8 @@ setup_other_flags(I830Ptr pI830,
 	other_idle_flags &= ~idle_flags[i].instdone_flag;
 	total_idle_flags |= idle_flags[i].instdone_flag;
     }
-    idle_flags[i - 1].instdone_flag = total_idle_flags;
-    idle_flags[i].instdone_flag = other_idle_flags;
+    idle_flags[idle_flag_count - 2].instdone_flag = total_idle_flags;
+    idle_flags[idle_flag_count - 1].instdone_flag = other_idle_flags;
 }
 
 int main(int argc, char **argv)
commit d775ddc64dc8349b8ef9e85b0be9e93cb1997fea
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Jun 13 10:03:24 2008 -0700

    [gem] Catch -EINTR from blocking GEM ioctl and restart.

diff --git a/src/i830_batchbuffer.c b/src/i830_batchbuffer.c
index 2f53d2f..07ea082 100644
--- a/src/i830_batchbuffer.c
+++ b/src/i830_batchbuffer.c
@@ -111,8 +111,10 @@ intel_batch_flush(ScrnInfoPtr pScrn)
 	exec->DR1 = 0;
 	exec->DR4 = 0xffffffff;
 
-	ret = drmCommandWriteRead(pI830->drmSubFD, DRM_I915_GEM_EXECBUFFER,
-				  exec, sizeof(*exec));
+	do {
+	    ret = drmCommandWriteRead(pI830->drmSubFD, DRM_I915_GEM_EXECBUFFER,
+				      exec, sizeof(*exec));
+	} while (ret == -EINTR);
 	if (ret != 0)
 	    FatalError("Failed to submit batchbuffer: %s\n", strerror(errno));
     } else {
commit 02d7141ac395446613edba0f2e2a951e750e4e9f
Author: Dave Airlie <airlied at redhat.com>
Date:   Fri Jun 13 11:30:58 2008 +1000

    [gem] remove one more unused bit

diff --git a/src/i830_dri.c b/src/i830_dri.c
index 85b0709..2f3c5d3 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -1505,7 +1505,6 @@ I830DRIClipNotify(ScreenPtr pScreen, WindowPtr *ppWin, int num)
 static int
 i830_name_buffer (ScrnInfoPtr pScrn, i830_memory *mem)
 {
-#if HAVE_DRM_GEM
     if (mem && mem->gem_handle)
     {
 	I830Ptr			pI830 = I830PTR(pScrn);
@@ -1526,7 +1525,6 @@ i830_name_buffer (ScrnInfoPtr pScrn, i830_memory *mem)
 	}
 	return mem->gem_name;
     }
-#endif
     return -1;
 }
 
commit f07acbdaac95931d184ea2c557edb632e577eb47
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Jun 12 13:47:35 2008 -0700

    Require libdrm 2.4.0 always since we need the bufmgr code.
    
    This lets us remove a lot of conditional compile stuff in the DRI case, as
    if we're doing DRI and have 2.4.0, we can rely on GEM ioctls existing.

diff --git a/configure.ac b/configure.ac
index 898c70b..e62502c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -196,36 +196,15 @@ if test "x$GCC" = "xyes"; then
 	-Wnested-externs -fno-strict-aliasing"
 fi
 
+PKG_CHECK_MODULES(DRM, [libdrm >= 2.4.0])
 AM_CONDITIONAL(DRI, test x$DRI = xyes)
 if test "$DRI" = yes; then
-        PKG_CHECK_MODULES(DRI, [libdrm xf86driproto glproto])
+        PKG_CHECK_MODULES(DRI, [xf86driproto glproto])
         AC_DEFINE(XF86DRI,1,[Enable DRI driver support])
         AC_DEFINE(XF86DRI_DEVEL,1,[Enable developmental DRI driver support])
-	PKG_CHECK_MODULES(DRI_MM, [libdrm >= 2.3.1],[DRI_MM=yes], [DRI_MM=no])
-	if test "x$DRI_MM" = xyes; then
-		AC_DEFINE(XF86DRI_MM,1,[Extended DRI memory management])
-	fi
 	if test "$have_damage_h" = yes; then
 		AC_DEFINE(DAMAGE,1,[Use Damage extension])
 	fi
-
-	save_CFLAGS="$CFLAGS"
-	CFLAGS="$XORG_CFLAGS $DRI_CFLAGS"
-	AC_CHECK_TYPE(drm_i915_flip_t,
-		      [AC_DEFINE(HAVE_I915_FLIP, 1,
-			         [Have drm_i915_flip_t and related definitions])],
-		      [], [
-#include <inttypes.h>
-#include <i915_drm.h>
-])
-	AC_CHECK_DECL(DRM_IOCTL_GEM_CREATE,
-		      [AC_DEFINE(HAVE_DRM_GEM, 1,
-			         [Have DRM Graphics Execution Manager])],
-		      [], [
-#include <inttypes.h>
-#include <drm.h>
-])
-	CFLAGS="$save_CFLAGS"
 fi
 
 AM_CONDITIONAL(VIDEO_DEBUG, test x$VIDEO_DEBUG = xyes)
diff --git a/src/Makefile.am b/src/Makefile.am
index 7ab1f08..6b812f9 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -30,7 +30,8 @@ SUBDIRS = xvmc bios_reader ch7017 ch7xxx ivch sil164 tfp410 $(REGDUMPER)
 # _ladir passes a dummy rpath to libtool so the thing will actually link
 # TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
 
-AM_CFLAGS = @WARN_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@ @PCIACCESS_CFLAGS@ \
+AM_CFLAGS = @WARN_CFLAGS@ @XORG_CFLAGS@ @DRM_CFLAGS@ @DRI_CFLAGS@ \
+	@PCIACCESS_CFLAGS@ \
 	@XMODES_CFLAGS@ -DI830_XV -DI830_USE_XAA -DI830_USE_EXA
 
 intel_drv_la_LTLIBRARIES = intel_drv.la
@@ -151,7 +152,6 @@ INTEL_G4I =				\
 	exa_wm.g4i			\
 	exa_wm_affine.g4i		\
 	exa_wm_projective.g4i
-	
 
 INTEL_G4B = 				\
 	packed_yuv_sf.g4b		\
@@ -173,7 +173,7 @@ INTEL_G4B = 				\
 	exa_wm_ca_srcalpha.g4b		\
 	exa_wm_write.g4b 		\
 	exa_wm_xy.g4b
-	
+
 EXTRA_DIST = 		\
 	$(XMODE_SRCS)	\
 	$(INTEL_G4A)	\
diff --git a/src/i830.h b/src/i830.h
index 96843f0..5c6fa82 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -69,9 +69,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #ifdef XF86DRI
 #include "xf86drm.h"
-#ifdef XF86DRI_MM
-#include "xf86mm.h"
-#endif
 #include "sarea.h"
 #define _XF86DRI_SERVER_
 #include "dri.h"
@@ -195,12 +192,10 @@ struct _i830_memory {
     i830_memory *prev;
     /** @} */
 
-#ifdef XF86DRI_MM
     uint32_t gem_handle;
     uint32_t alignment;
     uint32_t gem_name;
     Bool lifetime_fixed_offset;
-#endif
 };
 
 typedef struct {
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 5a53670..85b0709 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -86,23 +86,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #include "i915_drm.h"
 
-/* This block and the corresponding configure test can be removed when
- * libdrm >= 2.3.1 is required.
- */
-#ifndef HAVE_I915_FLIP
-
-#define DRM_VBLANK_FLIP 0x8000000
-
-typedef struct drm_i915_flip {
-   int pipes;
-} drm_i915_flip_t;
-
-#undef DRM_IOCTL_I915_FLIP
-#define DRM_IOCTL_I915_FLIP DRM_IOW(DRM_COMMAND_BASE + DRM_I915_FLIP, \
-				    drm_i915_flip_t)
-
-#endif
-
 #include "dristruct.h"
 
 static Bool I830InitVisualConfigs(ScreenPtr pScreen);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index e7994df..580cbbc 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -209,11 +209,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #ifdef XF86DRI
 #include "dri.h"
 #include <sys/ioctl.h>
-#ifdef XF86DRI_MM
-#include "xf86mm.h"
 #include "i915_drm.h"
 #endif
-#endif
 
 #ifdef I830_USE_EXA
 const char *I830exaSymbols[] = {
@@ -303,7 +300,7 @@ typedef enum {
    OPTION_LVDS24BITMODE,
    OPTION_FBC,
    OPTION_TILING,
-#ifdef XF86DRI_MM
+#ifdef XF86DRI
    OPTION_INTELTEXPOOL,
 #endif
    OPTION_LVDSFIXEDMODE,
@@ -331,7 +328,7 @@ static OptionInfoRec I830Options[] = {
    {OPTION_LVDS24BITMODE, "LVDS24Bit",	OPTV_BOOLEAN,	{0},	FALSE},
    {OPTION_FBC,		"FramebufferCompression", OPTV_BOOLEAN, {0}, TRUE},
    {OPTION_TILING,	"Tiling",	OPTV_BOOLEAN,	{0},	TRUE},
-#ifdef XF86DRI_MM
+#ifdef XF86DRI
    {OPTION_INTELTEXPOOL,"Legacy3D",     OPTV_BOOLEAN,	{0},	FALSE},
 #endif
    {OPTION_LVDSFIXEDMODE, "LVDSFixedMode", OPTV_BOOLEAN,	{0},	FALSE},
@@ -1573,7 +1570,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags)
 
 	 from = X_PROBED;
 
-#ifdef XF86DRI_MM
+#ifdef XF86DRI
 	 if (!IS_I965G(pI830)) {
 	    Bool tmp;
 
@@ -3369,7 +3366,7 @@ I830LeaveVT(int scrnIndex, int flags)
    if (I830IsPrimary(pScrn))
       i830_unbind_all_memory(pScrn);
 
-#ifdef XF86DRI_MM
+#ifdef XF86DRI
    if (pI830->memory_manager) {
       int ret;
 
@@ -3380,7 +3377,7 @@ I830LeaveVT(int scrnIndex, int flags)
       if (ret != 0)
 	 FatalError("DRM_I915_LEAVEVT failed: %s\n", strerror(ret));
    }
-#endif /* XF86DRI_MM */
+#endif /* XF86DRI */
 
    if (IS_I965G(pI830))
       gen4_render_state_cleanup(pScrn);
@@ -3411,7 +3408,7 @@ I830EnterVT(int scrnIndex, int flags)
 
    pI830->leaving = FALSE;
 
-#ifdef XF86DRI_MM
+#ifdef XF86DRI
    if (pI830->memory_manager) {
       int ret;
 
@@ -3422,7 +3419,7 @@ I830EnterVT(int scrnIndex, int flags)
       if (ret != 0)
 	 FatalError("DRM_I915_ENTERVT failed: %s\n", strerror(ret));
    }
-#endif /* XF86DRI_MM */
+#endif /* XF86DRI */
 
    if (I830IsPrimary(pScrn))
       if (!i830_bind_all_memory(pScrn))
diff --git a/src/i830_memory.c b/src/i830_memory.c
index d1a3e58..c357621 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -108,7 +108,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #include "i830.h"
 #include "i810_reg.h"
-#ifdef XF86DRI_MM
+#ifdef XF86DRI
 #include "i915_drm.h"
 #endif
 
@@ -165,7 +165,7 @@ i830_bind_memory(ScrnInfoPtr pScrn, i830_memory *mem)
     if (mem == NULL || mem->bound)
 	return TRUE;
 
-#if HAVE_DRM_GEM
+#ifdef XF86DRI
     if (mem->gem_handle != 0) {
 	I830Ptr pI830 = I830PTR(pScrn);
 	struct drm_i915_gem_pin pin;
@@ -218,7 +218,7 @@ i830_unbind_memory(ScrnInfoPtr pScrn, i830_memory *mem)
     if (mem->tiling != TILE_NONE)
 	i830_clear_tiling(pScrn, mem->fence_nr);
 
-#if HAVE_DRM_GEM
+#ifdef XF86DRI
     if (mem->gem_handle != 0) {
 	I830Ptr pI830 = I830PTR(pScrn);
 	struct drm_i915_gem_unpin unpin;
@@ -256,7 +256,7 @@ i830_free_memory(ScrnInfoPtr pScrn, i830_memory *mem)
     /* Free any AGP memory. */
     i830_unbind_memory(pScrn, mem);
 
-#if HAVE_DRM_GEM
+#ifdef XF86DRI
     if (mem->gem_handle != 0) {
 	I830Ptr pI830 = I830PTR(pScrn);
 	struct drm_gem_close close;
@@ -319,12 +319,10 @@ i830_reset_allocations(ScrnInfoPtr pScrn)
     }
 
     /* Free any allocations in buffer objects */
-#ifdef XF86DRI_MM
     if (pI830->memory_manager) {
 	while (pI830->bo_list != NULL)
 	    i830_free_memory(pScrn, pI830->bo_list);
     }
-#endif
 
     /* Null out the pointers for all the allocations we just freed.  This is
      * kind of gross, but at least it's just one place now.
@@ -375,7 +373,7 @@ i830_free_3d_memory(ScrnInfoPtr pScrn)
  * given range.
  *
  * This sets up the kernel memory manager to manage as much of the memory
- * as we think it can, while leaving enough to us to fulfill our non-TTM
+ * as we think it can, while leaving enough to us to fulfill our non-GEM
  * static allocations.  Some of these exist because of the need for physical
  * addresses to reference.
  */
@@ -384,7 +382,7 @@ i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset, unsigned long size)
 {
     I830Ptr pI830 = I830PTR(pScrn);
     i830_memory *start, *end;
-#if HAVE_DRM_GEM
+#ifdef XF86DRI
     int dri_major, dri_minor, dri_patch;
 #endif
 
@@ -423,7 +421,7 @@ i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset, unsigned long size)
 
     pI830->memory_list = start;
 
-#if HAVE_DRM_GEM
+#ifdef XF86DRI
     DRIQueryVersion(&dri_major, &dri_minor, &dri_patch);
 
     /* Now that we have our manager set up, initialize the kernel MM if
@@ -461,7 +459,7 @@ i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset, unsigned long size)
 	}
 	if (pI830->fb_compression)
 	    mmsize -= MB(6) + ROUND_TO_PAGE(FBC_LL_SIZE + FBC_LL_PAD);
-	/* Can't do TTM on stolen memory */
+	/* Can't do GEM on stolen memory */
 	mmsize -= pI830->stolen_size;
 
 	if (HWS_NEED_GFX(pI830) && IS_IGD_GM(pI830))
@@ -496,7 +494,7 @@ i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset, unsigned long size)
 	    pI830->memory_manager = NULL;
 	}
     }
-#endif /* XF86DRI_MM */
+#endif /* XF86DRI */
 
     return TRUE;
 }
@@ -509,14 +507,12 @@ i830_allocator_fini(ScrnInfoPtr pScrn)
     /* Free most of the allocations */
     i830_reset_allocations(pScrn);
 
-#ifdef XF86DRI_MM
     /* The memory manager is more special */
     if (pI830->memory_manager) {
 	 /* XXX drmMMTakedown(pI830->drmSubFD, DRM_BO_MEM_TT);*/
 	 i830_free_memory(pScrn, pI830->memory_manager);
 	 pI830->memory_manager = NULL;
     }
-#endif /* XF86DRI_MM */
 
     /* Free the start/end markers */
     free(pI830->memory_list->next);
@@ -726,7 +722,7 @@ i830_allocate_agp_memory(ScrnInfoPtr pScrn, i830_memory *mem, int flags)
     return TRUE;
 }
 
-#if HAVE_DRM_GEM
+#ifdef XF86DRI
 static i830_memory *
 i830_allocate_memory_bo(ScrnInfoPtr pScrn, const char *name,
 			unsigned long size, unsigned long align, int flags)
@@ -794,7 +790,7 @@ i830_allocate_memory_bo(ScrnInfoPtr pScrn, const char *name,
 
     return mem;
 }
-#endif /* XF86DRI_MM */
+#endif /* XF86DRI */
 
 /* Allocates video memory at the given size and alignment.
  *
@@ -820,7 +816,7 @@ i830_allocate_memory(ScrnInfoPtr pScrn, const char *name,
 {
     i830_memory *mem;
 
-#if HAVE_DRM_GEM
+#ifdef XF86DRI
     I830Ptr pI830 = I830PTR(pScrn);
 
     if (pI830->memory_manager && !(flags & NEED_PHYSICAL_ADDR) &&
@@ -828,7 +824,7 @@ i830_allocate_memory(ScrnInfoPtr pScrn, const char *name,
     {
 	return i830_allocate_memory_bo(pScrn, name, size, alignment, flags);
     } else
-#endif	
+#endif /* XF86DRI */
     {
 	mem = i830_allocate_aperture(pScrn, name, size, alignment, flags);
 	if (mem == NULL)
@@ -958,7 +954,6 @@ i830_describe_allocations(ScrnInfoPtr pScrn, int verbosity, const char *prefix)
 		   "%s0x%08lx:            end of aperture\n",
 		   prefix, pI830->FbMapSize);
 
-#ifdef XF86DRI_MM
     if (pI830->memory_manager) {
 	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
 		       "%sBO memory allocation layout:\n", prefix);
@@ -988,7 +983,6 @@ i830_describe_allocations(ScrnInfoPtr pScrn, int verbosity, const char *prefix)
 		       "%s0x%08lx:            end of memory manager\n",
 		       prefix, pI830->memory_manager->end);
     }
-#endif /* XF86DRI_MM */
 }
 
 static Bool
@@ -1455,7 +1449,7 @@ i830_allocate_2d_memory(ScrnInfoPtr pScrn)
     if (!pI830->noAccel && !pI830->useEXA) {
 	/* The lifetime fixed offset of xaa scratch is probably not required,
 	 * but we do some setup using it at XAAInit() time.  And XAA may not
-	 * end up being supported with TTM anyway.
+	 * end up being supported with GEM anyway.
 	 */
 	pI830->xaa_scratch =
 	    i830_allocate_memory(pScrn, "xaa scratch", MAX_SCRATCH_BUFFER_SIZE,
@@ -1967,12 +1961,10 @@ i830_bind_all_memory(ScrnInfoPtr pScrn)
 		FatalError("Couldn't bind memory for %s\n", mem->name);
 	    }
 	}
-#ifdef XF86DRI_MM
 	for (mem = pI830->bo_list; mem != NULL; mem = mem->next) {
 	    if (!mem->lifetime_fixed_offset && !i830_bind_memory(pScrn, mem))
 		FatalError("Couldn't bind memory for BO %s\n", mem->name);
 	}
-#endif
     }
     if (!pI830->SWCursor)
 	i830_update_cursor_offsets(pScrn);
@@ -1997,7 +1989,6 @@ i830_unbind_all_memory(ScrnInfoPtr pScrn)
 	{
 	    i830_unbind_memory(pScrn, mem);
 	}
-#ifdef XF86DRI_MM
 	for (mem = pI830->bo_list; mem != NULL; mem = mem->next) {
 	    /* Don't unpin objects which require that their offsets never
 	     * change.
@@ -2005,7 +1996,6 @@ i830_unbind_all_memory(ScrnInfoPtr pScrn)
 	    if (!mem->lifetime_fixed_offset)
 		i830_unbind_memory(pScrn, mem);
 	}
-#endif
 
 	pI830->gtt_acquired = FALSE;
 
diff --git a/src/xvmc/Makefile.am b/src/xvmc/Makefile.am
index 345160f..2f75cc5 100644
--- a/src/xvmc/Makefile.am
+++ b/src/xvmc/Makefile.am
@@ -4,7 +4,7 @@ lib_LTLIBRARIES=libI810XvMC.la libIntelXvMC.la
 libI810XvMC_la_SOURCES = I810XvMC.c \
 			 I810XvMC.h
 
-libI810XvMC_la_CFLAGS = @WARN_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@ \
+libI810XvMC_la_CFLAGS = @WARN_CFLAGS@ @XORG_CFLAGS@ @DRM_CFLAGS@ @DRI_CFLAGS@ \
 	-I$(top_srcdir)/src -DTRUE=1 -DFALSE=0
 libI810XvMC_la_LDFLAGS = -version-number 1:0:0
 libI810XvMC_la_LIBADD = @DRI_LIBS@ 
@@ -22,7 +22,8 @@ libIntelXvMC_la_SOURCES = intel_xvmc.c \
                          xf86dri.h \
                          xf86dristr.h
 
-libIntelXvMC_la_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@ @XVMCLIB_CFLAGS@ -I$(top_srcdir)/src -DTRUE=1 -DFALSE=0
+libIntelXvMC_la_CFLAGS = @XORG_CFLAGS@ @DRM_CFLAGS@ @DRI_CFLAGS@ \
+	@XVMCLIB_CFLAGS@ -I$(top_srcdir)/src -DTRUE=1 -DFALSE=0
 libIntelXvMC_la_LDFLAGS = -version-number 1:0:0
 libIntelXvMC_la_LIBADD = @DRI_LIBS@
 endif
commit 754df0aa55c4b5f0c3c415ad97d7612504410229
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Jun 11 14:43:38 2008 -0700

    [gem] Chase move of create ioctl from generic to device-specific.

diff --git a/src/i830_memory.c b/src/i830_memory.c
index 3613167..d1a3e58 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -734,7 +734,7 @@ i830_allocate_memory_bo(ScrnInfoPtr pScrn, const char *name,
     I830Ptr pI830 = I830PTR(pScrn);
     i830_memory *mem;
     int ret;
-    struct drm_gem_create create;
+    struct drm_i915_gem_create create;
 
     assert((flags & NEED_PHYSICAL_ADDR) == 0);
 
@@ -755,7 +755,7 @@ i830_allocate_memory_bo(ScrnInfoPtr pScrn, const char *name,
     memset(&create, 0, sizeof(create));
     create.size = size;
 
-    ret = ioctl(pI830->drmSubFD, DRM_IOCTL_GEM_CREATE, &create);
+    ret = ioctl(pI830->drmSubFD, DRM_IOCTL_I915_GEM_CREATE, &create);
     if (ret) {
 	xfree(mem->name);
 	xfree(mem);
commit 339f00e340c3a9c8ac8f17147e37906494ef370b
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Jun 10 16:14:06 2008 -0700

    [gem] Don't set up the ring in GEM mode, as that'll be handled by the kernel.

diff --git a/src/i830_accel.c b/src/i830_accel.c
index a71ea47..c3cd08e 100644
--- a/src/i830_accel.c
+++ b/src/i830_accel.c
@@ -54,12 +54,15 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  *
  */
 
+#include <errno.h>
+
 #include "xf86.h"
 #include "xaarop.h"
 #include "i830.h"
 #include "i810_reg.h"
 #include "i830_debug.h"
 #include "i830_ring.h"
+#include "i915_drm.h"
 
 unsigned long
 intel_get_pixmap_offset(PixmapPtr pPix)
@@ -190,7 +193,35 @@ I830Sync(ScrnInfoPtr pScrn)
 
    intel_batch_flush(pScrn);
 
-   i830_wait_ring_idle(pScrn);
+   if (pI830->directRenderingEnabled) {
+       struct drm_i915_irq_emit emit;
+       struct drm_i915_irq_wait wait;
+       int ret;
+
+       /* Most of the uses of I830Sync while using GEM should actually be
+	* using set_domain on a specific buffer.  We're not there yet, so fake
+	* it up using irq_emit/wait.  It's still better than spinning on
+	* register reads for idle.
+	*/
+       emit.irq_seq = &wait.irq_seq;
+       ret = drmCommandWrite(pI830->drmSubFD, DRM_I830_IRQ_EMIT, &emit,
+			    sizeof(emit));
+       if (ret != 0)
+	   FatalError("Failure to emit IRQ: %s\n", strerror(-ret));
+
+       do {
+	   ret = drmCommandWrite(pI830->drmSubFD, DRM_I830_IRQ_WAIT, &wait,
+				 sizeof(wait));
+       } while (ret == -EINTR);
+
+       if (ret != 0)
+	   FatalError("Failure to wait for IRQ: %s\n", strerror(-ret));
+
+       if (!pI830->memory_manager)
+	   i830_refresh_ring(pScrn);
+   } else {
+       i830_wait_ring_idle(pScrn);
+   }
 
    pI830->nextColorExpandBuf = 0;
 }
diff --git a/src/i830_batchbuffer.c b/src/i830_batchbuffer.c
index 416f4d0..2f53d2f 100644
--- a/src/i830_batchbuffer.c
+++ b/src/i830_batchbuffer.c
@@ -115,8 +115,6 @@ intel_batch_flush(ScrnInfoPtr pScrn)
 				  exec, sizeof(*exec));
 	if (ret != 0)
 	    FatalError("Failed to submit batchbuffer: %s\n", strerror(errno));
-
-	i830_refresh_ring(pScrn);
     } else {
 	dri_process_relocs(pI830->batch_bo);
 
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 8ec51fc..5a53670 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -175,22 +175,31 @@ I830InitDma(ScrnInfoPtr pScrn)
    memset(&info, 0, sizeof(drmI830Init));
    info.func = I830_INIT_DMA;
 
-   info.ring_start = ring->mem->offset + pI830->LinearAddr;
-   info.ring_end = ring->mem->end + pI830->LinearAddr;
-   info.ring_size = ring->mem->size;
+   /* Initialize fields that are used in the absence of GEM */
+   if (!pI830->memory_manager) {
+       info.ring_start = ring->mem->offset + pI830->LinearAddr;
+       info.ring_end = ring->mem->end + pI830->LinearAddr;
+       info.ring_size = ring->mem->size;
+
+       /* Not used as of the middle of GEM development. */
+       info.mmio_offset = (unsigned int)pI830DRI->regs;
+
+       /* Not used as of before GEM development */
+       info.front_offset = pI830->front_buffer->offset;
+       info.back_offset = pI830->back_buffer->offset;
+       info.depth_offset = pI830->depth_buffer->offset;
+       info.pitch = pScrn->displayWidth;
+       info.back_pitch = pScrn->displayWidth;
+       info.depth_pitch = pScrn->displayWidth;
+       info.w = pScrn->virtualX;
+       info.h = pScrn->virtualY;
+   }
 
-   info.mmio_offset = (unsigned int)pI830DRI->regs;
 
    info.sarea_priv_offset = sizeof(XF86DRISAREARec);
 
-   info.front_offset = pI830->front_buffer->offset;
-   info.back_offset = pI830->back_buffer->offset;
-   info.depth_offset = pI830->depth_buffer->offset;
-   info.w = pScrn->virtualX;
-   info.h = pScrn->virtualY;
-   info.pitch = pScrn->displayWidth;
-   info.back_pitch = pScrn->displayWidth;
-   info.depth_pitch = pScrn->displayWidth;
+   /* This should probably have been moved alongside offset/pitch in the sarea.
+    */
    info.cpp = pI830->cpp;
 
    if (drmCommandWrite(pI830->drmSubFD, DRM_I830_INIT,
@@ -799,17 +808,20 @@ I830DRIDoMappings(ScreenPtr pScreen)
    xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Registers = 0x%08x\n",
 	      (int)pI830DRI->regs);
 
-   if (drmAddMap(pI830->drmSubFD,
-		 (drm_handle_t)pI830->LpRing->mem->offset + pI830->LinearAddr,
-		 pI830->LpRing->mem->size, DRM_AGP, 0,
-		 (drmAddress) &pI830->ring_map) < 0) {
-      xf86DrvMsg(pScreen->myNum, X_ERROR,
-		 "[drm] drmAddMap(ring_map) failed. Disabling DRI\n");
-      DRICloseScreen(pScreen);
-      return FALSE;
+   if (!pI830->memory_manager) {
+       if (drmAddMap(pI830->drmSubFD,
+		     (drm_handle_t)pI830->LpRing->mem->offset +
+		     pI830->LinearAddr,
+		     pI830->LpRing->mem->size, DRM_AGP, 0,
+		     (drmAddress) &pI830->ring_map) < 0) {
+	   xf86DrvMsg(pScreen->myNum, X_ERROR,
+		      "[drm] drmAddMap(ring_map) failed. Disabling DRI\n");
+	   DRICloseScreen(pScreen);
+	   return FALSE;
+       }
+       xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] ring buffer = 0x%08x\n",
+		  (int)pI830->ring_map);
    }
-   xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] ring buffer = 0x%08x\n",
-	      (int)pI830->ring_map);
 
    if (!I830InitDma(pScrn)) {
       DRICloseScreen(pScreen);
@@ -960,6 +972,7 @@ I830DRICloseScreen(ScreenPtr pScreen)
       xfree(pI830->pVisualConfigs);
    if (pI830->pVisualConfigsPriv)
       xfree(pI830->pVisualConfigsPriv);
+   pI830->directRenderingEnabled = FALSE;
 }
 
 static Bool
@@ -1065,7 +1078,8 @@ I830DRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
       if (!pScrn->vtSema)
      	 return;
       pI830->LockHeld = 1;
-      i830_refresh_ring(pScrn);
+      if (!pI830->memory_manager)
+	  i830_refresh_ring(pScrn);
 
 #ifdef DAMAGE
       if (!pI830->pDamage && pI830->allowPageFlip) {
@@ -1763,7 +1777,8 @@ I830DRILock(ScrnInfoPtr pScrn)
    if (pI830->directRenderingEnabled && !pI830->LockHeld) {
       DRILock(screenInfo.screens[pScrn->scrnIndex], 0);
       pI830->LockHeld = 1;
-      i830_refresh_ring(pScrn);
+      if (!pI830->memory_manager)
+	  i830_refresh_ring(pScrn);
       return TRUE;
    }
    else
diff --git a/src/i830_driver.c b/src/i830_driver.c
index bce00af..e7994df 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -211,6 +211,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include <sys/ioctl.h>
 #ifdef XF86DRI_MM
 #include "xf86mm.h"
+#include "i915_drm.h"
 #endif
 #endif
 
@@ -3005,7 +3006,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
 #endif
 
    if (!pI830->noAccel) {
-      if (pI830->LpRing->mem->size == 0) {
+      if (pI830->memory_manager == NULL && pI830->LpRing->mem->size == 0) {
 	  xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		     "Disabling acceleration because the ring buffer "
 		      "allocation failed.\n");
@@ -3357,7 +3358,8 @@ I830LeaveVT(int scrnIndex, int flags)
       intel_bufmgr_fake_evict_all(pI830->bufmgr);
    intel_batch_teardown(pScrn);
 
-   i830_stop_ring(pScrn, TRUE);
+   if (!pI830->memory_manager)
+      i830_stop_ring(pScrn, TRUE);
 
    if (pI830->debug_modes) {
       i830CompareRegsToSnapshot(pScrn, "After LeaveVT");
@@ -3367,15 +3369,16 @@ I830LeaveVT(int scrnIndex, int flags)
    if (I830IsPrimary(pScrn))
       i830_unbind_all_memory(pScrn);
 
-   /* Tell the kernel to evict all buffer objects and block new buffer
-    * allocations until we relese the lock.
-    */
 #ifdef XF86DRI_MM
-   if (pI830->directRenderingOpen) {
-      /* XXX:
-      if (pI830->memory_manager != NULL && pScrn->vtSema) {
-	 drmMMLock(pI830->drmSubFD, DRM_BO_MEM_TT, 1, 0);
-      }*/
+   if (pI830->memory_manager) {
+      int ret;
+
+      /* Tell the kernel to evict all buffer objects and block GTT usage while
+       * we're no longer in control of the chip.
+       */
+      ret = drmCommandNone(pI830->drmSubFD, DRM_I915_GEM_LEAVEVT);
+      if (ret != 0)
+	 FatalError("DRM_I915_LEAVEVT failed: %s\n", strerror(ret));
    }
 #endif /* XF86DRI_MM */
 
@@ -3409,15 +3412,15 @@ I830EnterVT(int scrnIndex, int flags)
    pI830->leaving = FALSE;
 
 #ifdef XF86DRI_MM
-   if (pI830->directRenderingEnabled) {
-      /* Unlock the memory manager first of all so that we can pin our
-       * buffer objects
+   if (pI830->memory_manager) {
+      int ret;
+
+      /* Tell the kernel that we're back in control and ready for GTT
+       * usage.
        */
-      /*
-      if (pI830->memory_manager != NULL && pScrn->vtSema) {
-	 drmMMUnlock(pI830->drmSubFD, DRM_BO_MEM_TT, 1);
-      }
-      */
+      ret = drmCommandNone(pI830->drmSubFD, DRM_I915_GEM_ENTERVT);
+      if (ret != 0)
+	 FatalError("DRM_I915_ENTERVT failed: %s\n", strerror(ret));
    }
 #endif /* XF86DRI_MM */
 
@@ -3440,8 +3443,11 @@ I830EnterVT(int scrnIndex, int flags)
 		 "Existing errors found in hardware state.\n");
    }
 
-   i830_stop_ring(pScrn, FALSE);
-   i830_start_ring(pScrn);
+   /* Re-set up the ring. */
+   if (!pI830->memory_manager) {
+      i830_stop_ring(pScrn, FALSE);
+      i830_start_ring(pScrn);
+   }
    if (!pI830->SWCursor)
       I830InitHWCursor(pScrn);
 
@@ -3504,7 +3510,8 @@ I830EnterVT(int scrnIndex, int flags)
 
 	 I830DRIResume(screenInfo.screens[scrnIndex]);
 
-	 i830_refresh_ring(pScrn);
+	 if (!pI830->memory_manager)
+	    i830_refresh_ring(pScrn);
 	 I830Sync(pScrn);
 
 	 sarea->texAge++;
diff --git a/src/i830_memory.c b/src/i830_memory.c
index db99d97..3613167 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -996,7 +996,7 @@ i830_allocate_ringbuffer(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
 
-    if (pI830->noAccel || pI830->LpRing->mem != NULL)
+    if (pI830->noAccel || pI830->memory_manager || pI830->LpRing->mem != NULL)
 	return TRUE;
 
     /* We don't have any mechanism in the DRM yet to alert it that we've moved
@@ -1632,8 +1632,10 @@ i830_allocate_texture_memory(ScrnInfoPtr pScrn)
 		       size / 1024);
 	    return FALSE;
 	}
-	/* The offset must stay constant currently because we don't ever update
-	 * the DRI maps after screen init.
+	/* Now that the DRM uses the sarea to get the offsets of the buffers,
+	 * and we update the classic DRM mappings and the sarea contents on
+	 * changes, the NEED_LIFETIME_FIXED is no longer true and should be
+	 * made conditional on DRM version.
 	 */
 	pI830->textures = i830_allocate_memory(pScrn, "classic textures", size,
 					       GTT_PAGE_SIZE,
commit e930c0dc5b5f98d256a4167ed70ba813c88924d2
Author: Eric Anholt <eric at anholt.net>
Date:   Sat Jun 7 13:57:59 2008 -0700

    Use bufmgr_gem when available instead of the fake bufmgr.
    
    This is a bit unstable still sometimes.

diff --git a/src/i830_batchbuffer.c b/src/i830_batchbuffer.c
index 976a405..416f4d0 100644
--- a/src/i830_batchbuffer.c
+++ b/src/i830_batchbuffer.c
@@ -98,36 +98,59 @@ intel_batch_flush(ScrnInfoPtr pScrn)
     dri_bo_unmap(pI830->batch_bo);
     pI830->batch_ptr = NULL;
 
-    dri_process_relocs(pI830->batch_bo);
-
-    if (pI830->directRenderingEnabled) {
-	struct drm_i915_batchbuffer batch;
+    if (pI830->memory_manager) {
+	struct drm_i915_gem_execbuffer *exec;
 	int ret;
 
-	batch.start = pI830->batch_bo->offset;
-	batch.used = pI830->batch_used;
-	batch.cliprects = NULL;
-	batch.num_cliprects = 0;
-	batch.DR1 = 0;
-	batch.DR4 = 0xffffffff;
+	exec = dri_process_relocs(pI830->batch_bo);
+
+	exec->batch_start_offset = 0;
+	exec->batch_len = pI830->batch_used;
+	exec->cliprects_ptr = 0;
+	exec->num_cliprects = 0;
+	exec->DR1 = 0;
+	exec->DR4 = 0xffffffff;
 
-	ret = drmCommandWrite(pI830->drmSubFD, DRM_I915_BATCHBUFFER,
-			      &batch, sizeof(batch));
+	ret = drmCommandWriteRead(pI830->drmSubFD, DRM_I915_GEM_EXECBUFFER,
+				  exec, sizeof(*exec));
 	if (ret != 0)
 	    FatalError("Failed to submit batchbuffer: %s\n", strerror(errno));
+
+	i830_refresh_ring(pScrn);
     } else {
-	if (!IS_I830(pI830) && !IS_845G(pI830)) {
-	    BEGIN_LP_RING(2);
-	    OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));
-	    OUT_RING(pI830->batch_bo->offset);
-	    ADVANCE_LP_RING();
+	dri_process_relocs(pI830->batch_bo);
+
+	if (pI830->directRenderingEnabled) {
+	    struct drm_i915_batchbuffer batch;
+	    int ret;
+
+	    batch.start = pI830->batch_bo->offset;
+	    batch.used = pI830->batch_used;
+	    batch.cliprects = NULL;
+	    batch.num_cliprects = 0;
+	    batch.DR1 = 0;
+	    batch.DR4 = 0xffffffff;
+
+	    ret = drmCommandWrite(pI830->drmSubFD, DRM_I915_BATCHBUFFER,
+				  &batch, sizeof(batch));
+	    if (ret != 0)
+		FatalError("Failed to submit batchbuffer: %s\n", strerror(errno));
+
+	    i830_refresh_ring(pScrn);
 	} else {
-	    BEGIN_LP_RING(4);
-	    OUT_RING(MI_BATCH_BUFFER);
-	    OUT_RING(pI830->batch_bo->offset);
-	    OUT_RING(pI830->batch_bo->offset + pI830->batch_used - 4);
-	    OUT_RING(MI_NOOP);
-	    ADVANCE_LP_RING();
+	    if (!IS_I830(pI830) && !IS_845G(pI830)) {
+		BEGIN_LP_RING(2);
+		OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));
+		OUT_RING(pI830->batch_bo->offset);
+		ADVANCE_LP_RING();
+	    } else {
+		BEGIN_LP_RING(4);
+		OUT_RING(MI_BATCH_BUFFER);
+		OUT_RING(pI830->batch_bo->offset);
+		OUT_RING(pI830->batch_bo->offset + pI830->batch_used - 4);
+		OUT_RING(MI_NOOP);
+		ADVANCE_LP_RING();
+	    }
 	}
     }
 
diff --git a/src/i830_driver.c b/src/i830_driver.c
index cb9644e..bce00af 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2750,13 +2750,25 @@ i830_init_bufmgr(ScrnInfoPtr pScrn)
    I830Ptr pI830 = I830PTR(pScrn);
 
    assert(pI830->FbBase != NULL);
-   pI830->bufmgr = intel_bufmgr_fake_init(pI830->fake_bufmgr_mem->offset,
-					  pI830->FbBase +
-					  pI830->fake_bufmgr_mem->offset,
-					  pI830->fake_bufmgr_mem->size,
-					  i830_fake_fence_emit,
-					  i830_fake_fence_wait,
-					  pScrn);
+   if (pI830->memory_manager) {
+      int batch_size;
+
+      batch_size = 4096 * 4;
+
+      /* The 865 has issues with larger-than-page-sized batch buffers. */
+      if (IS_I865G(pI830))
+	 batch_size = 4096;
+
+      pI830->bufmgr = intel_bufmgr_gem_init(pI830->drmSubFD, batch_size);
+   } else {
+      pI830->bufmgr = intel_bufmgr_fake_init(pI830->fake_bufmgr_mem->offset,
+					     pI830->FbBase +
+					     pI830->fake_bufmgr_mem->offset,
+					     pI830->fake_bufmgr_mem->size,
+					     i830_fake_fence_emit,
+					     i830_fake_fence_wait,
+					     pScrn);
+   }
 }
 
 
@@ -3338,7 +3350,11 @@ I830LeaveVT(int scrnIndex, int flags)
 
    RestoreHWState(pScrn);
 
-   intel_bufmgr_fake_evict_all(pI830->bufmgr);
+   /* Evict everything from the bufmgr, as we're about to lose ownership of
+    * the graphics memory.
+    */
+   if (!pI830->memory_manager)
+      intel_bufmgr_fake_evict_all(pI830->bufmgr);
    intel_batch_teardown(pScrn);
 
    i830_stop_ring(pScrn, TRUE);
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 57e4f2e..db99d97 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -1375,12 +1375,14 @@ i830_allocate_2d_memory(ScrnInfoPtr pScrn)
 	return FALSE;
     }
 
-    pI830->fake_bufmgr_mem = i830_allocate_memory(pScrn, "fake bufmgr",
-						  MB(1), GTT_PAGE_SIZE, 0);
-    if (pI830->fake_bufmgr_mem == NULL) {
-	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		   "Failed to allocate fake bufmgr space.\n");
-	return FALSE;
+    if (pI830->memory_manager == NULL) {
+	pI830->fake_bufmgr_mem = i830_allocate_memory(pScrn, "fake bufmgr",
+						      MB(1), GTT_PAGE_SIZE, 0);
+	if (pI830->fake_bufmgr_mem == NULL) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		       "Failed to allocate fake bufmgr space.\n");
+	    return FALSE;
+	}
     }
 
     /* even in XAA, 965G needs state mem buffer for rendering */
commit ecf19e1cda60a938d41413075ae6e00f24e0ec1a
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Jun 6 15:27:44 2008 -0700

    Change most usage of pixmap offsets to using a reloc macro.
    
    This is based on airlied's RING->BATCH commit.  The 965 code still needs to
    be fixed up for relocations.

diff --git a/src/i830.h b/src/i830.h
index 403cd63..96843f0 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -690,6 +690,9 @@ typedef struct _I830Rec {
 #define I830_SELECT_DEPTH	2
 #define I830_SELECT_THIRD	3
 
+unsigned long intel_get_pixmap_offset(PixmapPtr pPix);
+unsigned long intel_get_pixmap_pitch(PixmapPtr pPix);
+
 /* Batchbuffer support macros and functions */
 #include "i830_batchbuffer.h"
 
@@ -764,8 +767,6 @@ extern Bool I830DRISetHWS(ScrnInfoPtr pScrn);
 extern Bool I830DRIInstIrqHandler(ScrnInfoPtr pScrn);
 #endif
 
-unsigned long intel_get_pixmap_offset(PixmapPtr pPix);
-unsigned long intel_get_pixmap_pitch(PixmapPtr pPix);
 extern Bool I830AccelInit(ScreenPtr pScreen);
 extern void I830SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir,
 					   int ydir, int rop,
diff --git a/src/i830_batchbuffer.h b/src/i830_batchbuffer.h
index 9179326..2b898c2 100644
--- a/src/i830_batchbuffer.h
+++ b/src/i830_batchbuffer.h
@@ -59,8 +59,21 @@ intel_batch_emit_dword(I830Ptr pI830, uint32_t dword)
     pI830->batch_used += 4;
 }
 
+static inline void
+intel_batch_emit_reloc_pixmap(I830Ptr pI830, PixmapPtr pPixmap, uint32_t delta)
+{
+    assert(pI830->batch_ptr != NULL);
+    assert(intel_batch_space(pI830) >= 4);
+    *(uint32_t *)(pI830->batch_ptr + pI830->batch_used) =
+	intel_get_pixmap_offset(pPixmap) + delta;
+    pI830->batch_used += 4;
+}
+
 #define OUT_BATCH(dword) intel_batch_emit_dword(pI830, dword)
 
+#define OUT_RELOC_PIXMAP(pPixmap, delta)	\
+	intel_batch_emit_reloc_pixmap(pI830, pPixmap, delta)
+
 union intfloat {
 	float f;
 	unsigned int ui;
diff --git a/src/i830_exa.c b/src/i830_exa.c
index 2c807c5..75ccd74 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -162,7 +162,7 @@ I830EXAPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg)
 {
     ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
-    unsigned long offset, pitch;
+    unsigned long pitch;
 
     if (!EXA_PM_IS_SOLID(&pPixmap->drawable, planemask))
 	I830FALLBACK("planemask is not solid");
@@ -172,11 +172,8 @@ I830EXAPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg)
 
     i830_exa_check_pitch_2d(pPixmap);
 
-    offset = exaGetPixmapOffset(pPixmap);
     pitch = exaGetPixmapPitch(pPixmap);
 
-    if (offset % pI830->EXADriverPtr->pixmapOffsetAlign != 0)
-	I830FALLBACK("pixmap offset not aligned");
     if (pitch % pI830->EXADriverPtr->pixmapPitchAlign != 0)
 	I830FALLBACK("pixmap pitch not aligned");
 
@@ -202,10 +199,9 @@ I830EXASolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
 {
     ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
-    unsigned long offset, pitch;
+    unsigned long pitch;
     uint32_t cmd;
 
-    offset = exaGetPixmapOffset(pPixmap);
     pitch = exaGetPixmapPitch(pPixmap);
 
     {
@@ -227,7 +223,7 @@ I830EXASolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
 	OUT_BATCH(pI830->BR[13] | pitch);
 	OUT_BATCH((y1 << 16) | (x1 & 0xffff));
 	OUT_BATCH((y2 << 16) | (x2 & 0xffff));
-	OUT_BATCH(offset);
+	OUT_RELOC_PIXMAP(pPixmap, 0);
 	OUT_BATCH(pI830->BR[16]);
 	ADVANCE_BATCH();
     }
@@ -285,14 +281,12 @@ I830EXACopy(PixmapPtr pDstPixmap, int src_x1, int src_y1, int dst_x1,
     I830Ptr pI830 = I830PTR(pScrn);
     uint32_t cmd;
     int dst_x2, dst_y2;
-    unsigned int dst_off, dst_pitch, src_off, src_pitch;
+    unsigned int dst_pitch, src_pitch;
 
     dst_x2 = dst_x1 + w;
     dst_y2 = dst_y1 + h;
 
-    dst_off = exaGetPixmapOffset(pDstPixmap);
     dst_pitch = exaGetPixmapPitch(pDstPixmap);
-    src_off = exaGetPixmapOffset(pI830->pSrcPixmap);
     src_pitch = exaGetPixmapPitch(pI830->pSrcPixmap);
 
     {
@@ -322,10 +316,10 @@ I830EXACopy(PixmapPtr pDstPixmap, int src_x1, int src_y1, int dst_x1,
 	OUT_BATCH(pI830->BR[13] | dst_pitch);
 	OUT_BATCH((dst_y1 << 16) | (dst_x1 & 0xffff));
 	OUT_BATCH((dst_y2 << 16) | (dst_x2 & 0xffff));
-	OUT_BATCH(dst_off);
+	OUT_RELOC_PIXMAP(pDstPixmap, 0);
 	OUT_BATCH((src_y1 << 16) | (src_x1 & 0xffff));
 	OUT_BATCH(src_pitch);
-	OUT_BATCH(src_off);
+	OUT_RELOC_PIXMAP(pI830->pSrcPixmap, 0);
 
 	ADVANCE_BATCH();
     }
diff --git a/src/i830_render.c b/src/i830_render.c
index 3a959e8..d5cab3f 100644
--- a/src/i830_render.c
+++ b/src/i830_render.c
@@ -275,10 +275,9 @@ i830_texture_setup(PicturePtr pPict, PixmapPtr pPix, int unit)
 
     ScrnInfoPtr pScrn = xf86Screens[pPict->pDrawable->pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
-    uint32_t format, offset, pitch, filter;
+    uint32_t format, pitch, filter;
     uint32_t wrap_mode = TEXCOORDMODE_CLAMP_BORDER;
 
-    offset = intel_get_pixmap_offset(pPix);
     pitch = intel_get_pixmap_pitch(pPix);
     pI830->scale_units[unit][0] = pPix->drawable.width;
     pI830->scale_units[unit][1] = pPix->drawable.height;
@@ -314,7 +313,7 @@ i830_texture_setup(PicturePtr pPict, PixmapPtr pPix, int unit)
 
 	BEGIN_BATCH(10);
 	OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | LOAD_TEXTURE_MAP(unit) | 4);
-	OUT_BATCH((offset & TM0S0_ADDRESS_MASK) | TM0S0_USE_FENCE);
+	OUT_RELOC_PIXMAP(pPix, TM0S0_USE_FENCE);
 	OUT_BATCH(((pPix->drawable.height - 1) << TM0S1_HEIGHT_SHIFT) |
 		  ((pPix->drawable.width - 1) << TM0S1_WIDTH_SHIFT) | format);
 	OUT_BATCH((pitch/4 - 1) << TM0S2_PITCH_SHIFT | TM0S2_MAP_2D);
@@ -394,7 +393,7 @@ i830_prepare_composite(int op, PicturePtr pSrcPicture,
 {
     ScrnInfoPtr pScrn = xf86Screens[pSrcPicture->pDrawable->pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
-    uint32_t dst_format, dst_offset, dst_pitch;
+    uint32_t dst_format, dst_pitch;
     Bool is_affine_src, is_affine_mask;
     Bool is_nearest = FALSE;
 
@@ -408,7 +407,6 @@ i830_prepare_composite(int op, PicturePtr pSrcPicture,
 
     if (!i830_get_dest_format(pDstPicture, &dst_format))
 	return FALSE;
-    dst_offset = intel_get_pixmap_offset(pDst);
     dst_pitch = intel_get_pixmap_pitch(pDst);
 
     if (!i830_texture_setup(pSrcPicture, pSrc, 0))
@@ -446,7 +444,7 @@ i830_prepare_composite(int op, PicturePtr pSrcPicture,
 	OUT_BATCH(_3DSTATE_BUF_INFO_CMD);
 	OUT_BATCH(BUF_3D_ID_COLOR_BACK| BUF_3D_USE_FENCE |
 		  BUF_3D_PITCH(dst_pitch));
-	OUT_BATCH(BUF_3D_ADDR(dst_offset));
+	OUT_RELOC_PIXMAP(pDst, 0);
 	OUT_BATCH(MI_NOOP);
 
 	OUT_BATCH(_3DSTATE_DST_BUF_VARS_CMD);
diff --git a/src/i915_render.c b/src/i915_render.c
index 4a02cf5..54197bf 100644
--- a/src/i915_render.c
+++ b/src/i915_render.c
@@ -250,11 +250,10 @@ i915_texture_setup(PicturePtr pPict, PixmapPtr pPix, int unit)
 {
     ScrnInfoPtr pScrn = xf86Screens[pPict->pDrawable->pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
-    uint32_t format, offset, pitch, filter;
+    uint32_t format, pitch, filter;
     int w, h, i;
     uint32_t wrap_mode = TEXCOORDMODE_CLAMP_BORDER;
 
-    offset = intel_get_pixmap_offset(pPix);
     pitch = intel_get_pixmap_pitch(pPix);
     w = pPict->pDrawable->width;
     h = pPict->pDrawable->height;
@@ -288,7 +287,7 @@ i915_texture_setup(PicturePtr pPict, PixmapPtr pPix, int unit)
         I830FALLBACK("Bad filter 0x%x\n", pPict->filter);
     }
 
-    pI830->mapstate[unit * 3 + 0] = offset;
+    pI830->mapstate[unit * 3 + 0] = 0; /* offset filled in at emit time */
     pI830->mapstate[unit * 3 + 1] = format |
 	MS3_USE_FENCE_REGS |
 	((pPix->drawable.height - 1) << MS3_HEIGHT_SHIFT) |
@@ -316,7 +315,7 @@ i915_prepare_composite(int op, PicturePtr pSrcPicture,
 {
     ScrnInfoPtr pScrn = xf86Screens[pSrcPicture->pDrawable->pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
-    uint32_t dst_format, dst_offset, dst_pitch;
+    uint32_t dst_format, dst_pitch;
     uint32_t blendctl;
     int out_reg = FS_OC;
     FS_LOCALS(20);
@@ -333,7 +332,6 @@ i915_prepare_composite(int op, PicturePtr pSrcPicture,
 
     if (!i915_get_dest_format(pDstPicture, &dst_format))
 	return FALSE;
-    dst_offset = intel_get_pixmap_offset(pDst);
     dst_pitch = intel_get_pixmap_pitch(pDst);
 
     if (!i915_texture_setup(pSrcPicture, pSrc, 0))
@@ -362,7 +360,7 @@ i915_prepare_composite(int op, PicturePtr pSrcPicture,
 	BEGIN_BATCH(10);
 	OUT_BATCH(_3DSTATE_MAP_STATE | 3);
 	OUT_BATCH(0x00000001); /* map 0 */
-	OUT_BATCH(pI830->mapstate[0]);
+	OUT_RELOC_PIXMAP(pSrc, 0);
 	OUT_BATCH(pI830->mapstate[1]);
 	OUT_BATCH(pI830->mapstate[2]);
 
@@ -376,10 +374,10 @@ i915_prepare_composite(int op, PicturePtr pSrcPicture,
 	BEGIN_BATCH(16);
 	OUT_BATCH(_3DSTATE_MAP_STATE | 6);
 	OUT_BATCH(0x00000003); /* map 0,1 */
-	OUT_BATCH(pI830->mapstate[0]);
+	OUT_RELOC_PIXMAP(pSrc, 0);
 	OUT_BATCH(pI830->mapstate[1]);
 	OUT_BATCH(pI830->mapstate[2]);
-	OUT_BATCH(pI830->mapstate[3]);
+	OUT_RELOC_PIXMAP(pMask, 0);
 	OUT_BATCH(pI830->mapstate[4]);
 	OUT_BATCH(pI830->mapstate[5]);
 
@@ -400,7 +398,7 @@ i915_prepare_composite(int op, PicturePtr pSrcPicture,
 	OUT_BATCH(_3DSTATE_BUF_INFO_CMD);
 	OUT_BATCH(BUF_3D_ID_COLOR_BACK| BUF_3D_USE_FENCE|
 		  BUF_3D_PITCH(dst_pitch));
-	OUT_BATCH(BUF_3D_ADDR(dst_offset));
+	OUT_RELOC_PIXMAP(pDst, 0);
 
 	OUT_BATCH(_3DSTATE_DST_BUF_VARS_CMD);
 	OUT_BATCH(dst_format);
diff --git a/src/i915_video.c b/src/i915_video.c
index aeb3729..e27854e 100644
--- a/src/i915_video.c
+++ b/src/i915_video.c
@@ -130,7 +130,7 @@ I915DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id,
    OUT_BATCH(_3DSTATE_BUF_INFO_CMD);
    OUT_BATCH(BUF_3D_ID_COLOR_BACK | BUF_3D_USE_FENCE |
 	     BUF_3D_PITCH(intel_get_pixmap_pitch(pPixmap)));
-   OUT_BATCH(BUF_3D_ADDR(intel_get_pixmap_offset(pPixmap)));
+   OUT_RELOC_PIXMAP(pPixmap, 0);
    ADVANCE_BATCH();
 
    if (!planar) {
commit bade7d7d2505a10a8a7d24b084aff9742e2d6d64
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Jun 6 14:03:25 2008 -0700

    Use the DRM for submitting batchbuffers when available.
    
    There are some concerns with this, as the DRM will be setting the nonsecure
    flag on the batchbuffer, and the server may be submitting some secure-only
    commands.  It appears to work on the 915GM test system currently.

diff --git a/src/i830_batchbuffer.c b/src/i830_batchbuffer.c
index 82758a2..976a405 100644
--- a/src/i830_batchbuffer.c
+++ b/src/i830_batchbuffer.c
@@ -100,18 +100,35 @@ intel_batch_flush(ScrnInfoPtr pScrn)
 
     dri_process_relocs(pI830->batch_bo);
 
-    if (!IS_I830(pI830) && !IS_845G(pI830)) {
-	BEGIN_LP_RING(2);
-	OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));
-	OUT_RING(pI830->batch_bo->offset);
-	ADVANCE_LP_RING();
+    if (pI830->directRenderingEnabled) {
+	struct drm_i915_batchbuffer batch;
+	int ret;
+
+	batch.start = pI830->batch_bo->offset;
+	batch.used = pI830->batch_used;
+	batch.cliprects = NULL;
+	batch.num_cliprects = 0;
+	batch.DR1 = 0;
+	batch.DR4 = 0xffffffff;
+
+	ret = drmCommandWrite(pI830->drmSubFD, DRM_I915_BATCHBUFFER,
+			      &batch, sizeof(batch));
+	if (ret != 0)
+	    FatalError("Failed to submit batchbuffer: %s\n", strerror(errno));
     } else {
-	BEGIN_LP_RING(4);
-	OUT_RING(MI_BATCH_BUFFER);
-	OUT_RING(pI830->batch_bo->offset);
-	OUT_RING(pI830->batch_bo->offset + pI830->batch_used - 4);
-	OUT_RING(MI_NOOP);
-	ADVANCE_LP_RING();
+	if (!IS_I830(pI830) && !IS_845G(pI830)) {
+	    BEGIN_LP_RING(2);
+	    OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));
+	    OUT_RING(pI830->batch_bo->offset);
+	    ADVANCE_LP_RING();
+	} else {
+	    BEGIN_LP_RING(4);
+	    OUT_RING(MI_BATCH_BUFFER);
+	    OUT_RING(pI830->batch_bo->offset);
+	    OUT_RING(pI830->batch_bo->offset + pI830->batch_used - 4);
+	    OUT_RING(MI_NOOP);
+	    ADVANCE_LP_RING();
+	}
     }
 
     dri_post_submit(pI830->batch_bo);
commit 6e94affcc2240e668bcf1aa41f3c8b19929d144b
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Jun 6 14:01:05 2008 -0700

    Avoid needless flush emits in the blockhandler.
    
    The EmitFlush in i830_dri.c was added as a pageflipping workaround, and was
    noted to not even be sufficient then.  There's no reason for it to be there,
    so it's removed.  After that, we just have to not emit an MI_FLUSH if we
    already had, and cursor movement no longer bashes memory manager.

diff --git a/src/i830.h b/src/i830.h
index ccf91a0..403cd63 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -463,6 +463,8 @@ typedef struct _I830Rec {
 #endif
 #endif
 
+   Bool need_mi_flush;
+
    Bool NeedRingBufferLow;
    Bool allowPageFlip;
    Bool TripleBuffer;
diff --git a/src/i830_batchbuffer.c b/src/i830_batchbuffer.c
index 19d642d..82758a2 100644
--- a/src/i830_batchbuffer.c
+++ b/src/i830_batchbuffer.c
@@ -32,10 +32,12 @@
 
 #include <assert.h>
 #include <stdlib.h>
+#include <errno.h>
 
 #include "xf86.h"
 #include "i830.h"
 #include "i830_ring.h"
+#include "i915_drm.h"
 
 static void
 intel_next_batch(ScrnInfoPtr pScrn)
@@ -116,4 +118,10 @@ intel_batch_flush(ScrnInfoPtr pScrn)
 
     dri_bo_unreference(pI830->batch_bo);
     intel_next_batch(pScrn);
+
+    /* Mark that we need to flush whatever potential rendering we've done in the
+     * blockhandler.  We could set this less often, but it's probably not worth
+     * the work.
+     */
+    pI830->need_mi_flush = TRUE;
 }
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 95e1e72..8ec51fc 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -1067,8 +1067,6 @@ I830DRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
       pI830->LockHeld = 1;
       i830_refresh_ring(pScrn);
 
-      I830EmitFlush(pScrn);
-
 #ifdef DAMAGE
       if (!pI830->pDamage && pI830->allowPageFlip) {
 	 PixmapPtr pPix  = pScreen->GetScreenPixmap(pScreen);
@@ -1122,8 +1120,6 @@ I830DRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
       }
 #endif
 
-      I830EmitFlush(pScrn);
-
 #ifdef DAMAGE
       /* Try flipping back to the front page if necessary */
       if (sPriv && !sPriv->pf_enabled && sPriv->pf_current_page != 0) {
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 3a9d425..cb9644e 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2496,17 +2496,17 @@ I830BlockHandler(int i,
     if (pScrn->vtSema && !pI830->noAccel) {
        /* Emit a flush of the rendering cache, or on the 965 and beyond
 	* rendering results may not hit the framebuffer until significantly
-	* later.  In the direct rendering case this is already done just
-	* after the page flipping updates, so there's no need to duplicate
-	* the effort here.
+	* later.
 	*/
-       if (!pI830->noAccel && !pI830->directRenderingEnabled)
+       if (!pI830->noAccel && pI830->need_mi_flush)
 	  I830EmitFlush(pScrn);
 
        /* Flush the batch, so that any rendering is executed in a timely
 	* fashion.
 	*/
        intel_batch_flush(pScrn);
+
+       pI830->need_mi_flush = FALSE;
     }
 
     /*
commit b2216e7bc2f1a35f9fc1794bad83208cd5c583d1
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Jun 4 16:31:16 2008 -0700

    Use batchbuffers instead of ring emits for general commands.
    
    The batchbuffers are managed using libdrm and bufmgr_fake, and dispatched from
    the ring from userland.

diff --git a/src/Makefile.am b/src/Makefile.am
index 0784c06..7ab1f08 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -89,6 +89,8 @@ intel_drv_la_SOURCES = \
          i830_accel.c \
          i830_bios.c \
          i830_bios.h \
+         i830_batchbuffer.c \
+         i830_batchbuffer.h \
          i830_common.h \
 	 i830_crt.c \
          i830_cursor.c \
diff --git a/src/i810_reg.h b/src/i810_reg.h
index d8e0cb2..6a82c19 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -2379,6 +2379,13 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #define STATE3D_COLOR_FACTOR	((0x3<<29)|(0x1d<<24)|(0x01<<16))
 
+/* Batch */
+#define MI_BATCH_BUFFER		((0x30 << 23) | 1)
+#define MI_BATCH_BUFFER_START	(0x31 << 23)
+#define MI_BATCH_BUFFER_END	(0xA << 23)
+#define MI_BATCH_NON_SECURE		(1)
+#define MI_BATCH_NON_SECURE_I965	(1 << 8)
+
 /* STATE3D_FOG_MODE stuff */
 #define ENABLE_FOG_SOURCE	(1<<27)
 #define ENABLE_FOG_CONST	(1<<24)
diff --git a/src/i830.h b/src/i830.h
index 9cce5bc..ccf91a0 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -81,6 +81,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "damage.h"
 #endif
 #endif
+#include "dri_bufmgr.h"
+#include "intel_bufmgr.h"
 
 #ifdef I830_USE_EXA
 #include "exa.h"
@@ -95,7 +97,6 @@ Bool I830XAAInit(ScreenPtr pScreen);
 typedef struct _I830OutputRec I830OutputRec, *I830OutputPtr;
 
 #include "common.h"
-#include "i830_ring.h"
 #include "i830_sdvo.h"
 #include "i2c_vid.h"
 
@@ -401,6 +402,8 @@ typedef struct _I830Rec {
    i830_memory *exa_offscreen;
    i830_memory *gen4_render_state_mem;
 #endif
+   i830_memory *fake_bufmgr_mem;
+
    /* Regions allocated either from the above pools, or from agpgart. */
    I830RingBuffer *LpRing;
 
@@ -411,6 +414,17 @@ typedef struct _I830Rec {
    /** Offset in the ring for the next DWORD emit */
    uint32_t ring_next;
 
+   dri_bufmgr *bufmgr;
+
+   uint8_t *batch_ptr;
+   /** Byte offset in batch_ptr for the next dword to be emitted. */
+   unsigned int batch_used;
+   /** Position in batch_ptr at the start of the current BEGIN_BATCH */
+   unsigned int batch_emit_start;
+   /** Number of bytes to be emitted in the current BEGIN_BATCH. */
+   uint32_t batch_emitting;
+   dri_bo *batch_bo;
+
 #ifdef I830_XV
    /* For Xvideo */
    i830_memory *overlay_regs;
@@ -674,6 +688,9 @@ typedef struct _I830Rec {
 #define I830_SELECT_DEPTH	2
 #define I830_SELECT_THIRD	3
 
+/* Batchbuffer support macros and functions */
+#include "i830_batchbuffer.h"
+
 /* I830 specific functions */
 extern int I830WaitLpRing(ScrnInfoPtr pScrn, int n, int timeout_millis);
 extern void I830SetPIOAccess(I830Ptr pI830);
@@ -898,13 +915,6 @@ Bool i830_pixmap_tiled(PixmapPtr p);
     if (pitch > KB(8)) I830FALLBACK("pitch exceeds 3d limit 8K\n");\
 } while(0)
 
-/* Batchbuffer compatibility handling */
-#define BEGIN_BATCH(n) BEGIN_LP_RING(n)
-#define ENSURE_BATCH(n)
-#define OUT_BATCH(d) OUT_RING(d)
-#define OUT_BATCH_F(x) OUT_RING_F(x)
-#define ADVANCE_BATCH() ADVANCE_LP_RING()
-
 extern const int I830PatternROP[16];
 extern const int I830CopyROP[16];
 
diff --git a/src/i830_accel.c b/src/i830_accel.c
index 7784c62..a71ea47 100644
--- a/src/i830_accel.c
+++ b/src/i830_accel.c
@@ -59,6 +59,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "i830.h"
 #include "i810_reg.h"
 #include "i830_debug.h"
+#include "i830_ring.h"
 
 unsigned long
 intel_get_pixmap_offset(PixmapPtr pPix)
@@ -168,7 +169,6 @@ void
 I830Sync(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830 = I830PTR(pScrn);
-   int flags = MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE;
 
    if (I810_DEBUG & (DEBUG_VERBOSE_ACCEL | DEBUG_VERBOSE_SYNC))
       ErrorF("I830Sync\n");
@@ -186,24 +186,12 @@ I830Sync(ScrnInfoPtr pScrn)
 
    if (pI830->entityPrivate && !pI830->entityPrivate->RingRunning) return;
 
-   if (IS_I965G(pI830))
-      flags = 0;
+   I830EmitFlush(pScrn);
 
-   /* Send a flush instruction and then wait till the ring is empty.
-    * This is stronger than waiting for the blitter to finish as it also
-    * flushes the internal graphics caches.
-    */
-   
-   {
-      BEGIN_BATCH(2);
-      OUT_BATCH(MI_FLUSH | flags);
-      OUT_BATCH(MI_NOOP);		/* pad to quadword */
-      ADVANCE_BATCH();
-   }
+   intel_batch_flush(pScrn);
 
    i830_wait_ring_idle(pScrn);
 
-   pI830->LpRing->space = pI830->LpRing->mem->size - 8;
    pI830->nextColorExpandBuf = 0;
 }
 
diff --git a/src/i830_batchbuffer.c b/src/i830_batchbuffer.c
new file mode 100644
index 0000000..19d642d
--- /dev/null
+++ b/src/i830_batchbuffer.c
@@ -0,0 +1,119 @@
+/* -*- c-basic-offset: 4 -*- */
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * 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.
+ *
+ * Authors:
+ *    Eric Anholt <eric at anholt.net>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include "xf86.h"
+#include "i830.h"
+#include "i830_ring.h"
+
+static void
+intel_next_batch(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    /* The 865 has issues with larger-than-page-sized batch buffers. */
+    if (IS_I865G(pI830))
+	pI830->batch_bo = dri_bo_alloc(pI830->bufmgr, "batch", 4096, 4096);
+    else
+	pI830->batch_bo = dri_bo_alloc(pI830->bufmgr, "batch", 4096 * 4, 4096);
+
+    dri_bo_map(pI830->batch_bo, 1);
+    pI830->batch_used = 0;
+    pI830->batch_ptr = pI830->batch_bo->virtual;
+}
+
+void
+intel_batch_init(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    pI830->batch_emit_start = 0;
+    pI830->batch_emitting = 0;
+
+    intel_next_batch(pScrn);
+}
+
+void
+intel_batch_teardown(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    if (pI830->batch_ptr != NULL) {
+	dri_bo_unmap(pI830->batch_bo);
+	pI830->batch_ptr = NULL;
+    }
+}
+
+void
+intel_batch_flush(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    if (pI830->batch_used == 0)
+	return;
+
+    /* Emit a padding dword if we aren't going to be quad-word aligned. */
+    if ((pI830->batch_used & 4) == 0) {
+	*(uint32_t *)(pI830->batch_ptr + pI830->batch_used) = MI_NOOP;
+	pI830->batch_used += 4;
+    }
+
+    /* Mark the end of the batchbuffer. */
+    *(uint32_t *)(pI830->batch_ptr + pI830->batch_used) = MI_BATCH_BUFFER_END;
+    pI830->batch_used += 4;
+
+    dri_bo_unmap(pI830->batch_bo);
+    pI830->batch_ptr = NULL;
+
+    dri_process_relocs(pI830->batch_bo);
+
+    if (!IS_I830(pI830) && !IS_845G(pI830)) {
+	BEGIN_LP_RING(2);
+	OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));
+	OUT_RING(pI830->batch_bo->offset);
+	ADVANCE_LP_RING();
+    } else {
+	BEGIN_LP_RING(4);
+	OUT_RING(MI_BATCH_BUFFER);
+	OUT_RING(pI830->batch_bo->offset);
+	OUT_RING(pI830->batch_bo->offset + pI830->batch_used - 4);
+	OUT_RING(MI_NOOP);
+	ADVANCE_LP_RING();
+    }
+
+    dri_post_submit(pI830->batch_bo);
+
+    dri_bo_unreference(pI830->batch_bo);
+    intel_next_batch(pScrn);
+}
diff --git a/src/i830_batchbuffer.h b/src/i830_batchbuffer.h
new file mode 100644
index 0000000..9179326
--- /dev/null
+++ b/src/i830_batchbuffer.h
@@ -0,0 +1,106 @@
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+Copyright © 2002 David Dawes
+
+All Rights Reserved.
+
+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, sub license, 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 NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS 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.
+
+**************************************************************************/
+
+#ifndef _INTEL_BATCHBUFFER_H
+#define _INTEL_BATCHBUFFER_H
+
+#define BATCH_RESERVED		16
+
+void intel_batch_init(ScrnInfoPtr pScrn);
+void intel_batch_teardown(ScrnInfoPtr pScrn);
+void intel_batch_flush(ScrnInfoPtr pScrn);
+
+static inline int
+intel_batch_space(I830Ptr pI830)
+{
+    return (pI830->batch_bo->size - BATCH_RESERVED) - (pI830->batch_used);
+}
+
+static inline void
+intel_batch_require_space(ScrnInfoPtr pScrn, I830Ptr pI830, GLuint sz)
+{
+    assert(sz < pI830->batch_bo->size - 8);
+    if (intel_batch_space(pI830) < sz)
+	intel_batch_flush(pScrn);
+}
+
+static inline void
+intel_batch_emit_dword(I830Ptr pI830, uint32_t dword)
+{
+    assert(pI830->batch_ptr != NULL);
+    assert(intel_batch_space(pI830) >= 4);
+    *(uint32_t *)(pI830->batch_ptr + pI830->batch_used) = dword;
+    pI830->batch_used += 4;
+}
+
+#define OUT_BATCH(dword) intel_batch_emit_dword(pI830, dword)
+
+union intfloat {
+	float f;
+	unsigned int ui;
+};
+
+#define OUT_BATCH_F(x) do {			\
+	union intfloat tmp;			\
+	tmp.f = (float)(x);			\
+	OUT_BATCH(tmp.ui);			\
+} while(0)
+
+#define BEGIN_BATCH(n)							\
+do {									\
+    if (pI830->batch_emitting != 0)					\
+	FatalError("%s: BEGIN_BATCH called without closing "		\
+		   "ADVANCE_BATCH\n", __FUNCTION__);			\
+    pI830->batch_emitting = (n) * 4;					\
+    intel_batch_require_space(pScrn, pI830, pI830->batch_emitting);	\
+    pI830->batch_emit_start = pI830->batch_used;			\
+} while (0)
+
+#define ADVANCE_BATCH() do {						\
+    if (pI830->batch_emitting == 0)					\
+	FatalError("%s: ADVANCE_BATCH called with no matching "		\
+		   "BEGIN_BATCH\n", __FUNCTION__);			\
+    if (pI830->batch_used > pI830->batch_emit_start + pI830->batch_emitting) \
+	FatalError("%s: ADVANCE_BATCH: exceeded allocation %d/%d\n ",	\
+		   __FUNCTION__,					\
+		   pI830->batch_used - pI830->batch_emit_start,		\
+		   pI830->batch_emitting);				\
+    if (pI830->batch_used < pI830->batch_emit_start + pI830->batch_emitting) \
+	FatalError("%s: ADVANCE_BATCH: under-used allocation %d/%d\n ", \
+		   __FUNCTION__,					\
+		   pI830->batch_used - pI830->batch_emit_start,		\
+		   pI830->batch_emitting);				\
+    if ((pI830->batch_emitting > 8) && (I810_DEBUG & DEBUG_ALWAYS_SYNC)) { \
+	/* Note: not actually syncing, just flushing each batch. */	\
+	intel_batch_flush(pScrn);					\
+    }									\
+    pI830->batch_emitting = 0;						\
+} while (0)
+
+#endif /* _INTEL_BATCHBUFFER_H */
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 35df0c7..3a9d425 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1838,7 +1838,7 @@ i830_stop_ring(ScrnInfoPtr pScrn, Bool flush)
       temp = INREG(LP_RING + RING_LEN);
       if (temp & RING_VALID) {
 	 i830_refresh_ring(pScrn);
-	 I830Sync(pScrn);
+	 i830_wait_ring_idle(pScrn);
       }
 
       OUTREG(LP_RING + RING_LEN, 0);
@@ -2493,14 +2493,21 @@ I830BlockHandler(int i,
     pI830->BlockHandler = pScreen->BlockHandler;
     pScreen->BlockHandler = I830BlockHandler;
 
-    /* Emit a flush of the rendering cache, or on the 965 and beyond
-     * rendering results may not hit the framebuffer until significantly
-     * later.  In the direct rendering case this is already done just
-     * after the page flipping updates, so there's no need to duplicate
-     * the effort here.
-     */
-    if (pScrn->vtSema && !pI830->noAccel && !pI830->directRenderingEnabled)
-	I830EmitFlush(pScrn);
+    if (pScrn->vtSema && !pI830->noAccel) {
+       /* Emit a flush of the rendering cache, or on the 965 and beyond
+	* rendering results may not hit the framebuffer until significantly
+	* later.  In the direct rendering case this is already done just
+	* after the page flipping updates, so there's no need to duplicate
+	* the effort here.
+	*/
+       if (!pI830->noAccel && !pI830->directRenderingEnabled)
+	  I830EmitFlush(pScrn);
+
+       /* Flush the batch, so that any rendering is executed in a timely
+	* fashion.
+	*/
+       intel_batch_flush(pScrn);
+    }
 
     /*
      * Check for FIFO underruns at block time (which amounts to just
@@ -2704,6 +2711,55 @@ i830_memory_init(ScrnInfoPtr pScrn)
     return FALSE;
 }
 
+/**
+ * Returns a cookie to be waited on.  This is just a stub implementation, and
+ * should be hooked up to the emit/wait irq functions when available (DRI
+ * enabled).
+ */
+static unsigned int
+i830_fake_fence_emit(void *priv)
+{
+   static unsigned int fence = 0;
+
+   /* Match DRM in not using half the range. The fake bufmgr relies on this. */
+   if (++fence >= 0x8000000)
+      fence = 1;
+
+   return fence;
+}
+
+/**
+ * Waits on a cookie representing a request to be passed.
+ *
+ * Stub implementation that should be replaced with DRM functions when
+ * available.
+ */
+static int
+i830_fake_fence_wait(void *priv, unsigned int fence)
+{
+   ScrnInfoPtr pScrn = priv;
+
+   i830_wait_ring_idle(pScrn);
+
+   return 0;
+}
+
+static void
+i830_init_bufmgr(ScrnInfoPtr pScrn)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+
+   assert(pI830->FbBase != NULL);
+   pI830->bufmgr = intel_bufmgr_fake_init(pI830->fake_bufmgr_mem->offset,
+					  pI830->FbBase +
+					  pI830->fake_bufmgr_mem->offset,
+					  pI830->fake_bufmgr_mem->size,
+					  i830_fake_fence_emit,
+					  i830_fake_fence_wait,
+					  pScrn);
+}
+
+
 static Bool
 I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
 {
@@ -3033,6 +3089,8 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
    pI830->xoffset = (pScrn->fbOffset / pI830->cpp) % pScrn->displayWidth;
    pI830->yoffset = (pScrn->fbOffset / pI830->cpp) / pScrn->displayWidth;
 
+   i830_init_bufmgr(pScrn);
+
    vgaHWSetMmioFuncs(hwp, pI830->MMIOBase, 0);
    vgaHWGetIOBase(hwp);
    DPRINTF(PFX, "assert( if(!vgaHWMapMem(pScrn)) )\n");
@@ -3276,8 +3334,13 @@ I830LeaveVT(int scrnIndex, int flags)
 
    xf86_hide_cursors (pScrn);
 
+   I830Sync(pScrn);
+
    RestoreHWState(pScrn);
 
+   intel_bufmgr_fake_evict_all(pI830->bufmgr);
+   intel_batch_teardown(pScrn);
+
    i830_stop_ring(pScrn, TRUE);
 
    if (pI830->debug_modes) {
@@ -3351,6 +3414,8 @@ I830EnterVT(int scrnIndex, int flags)
    /* Update the screen pixmap in case the buffer moved */
    i830_update_front_offset(pScrn);
 
+   intel_batch_init(pScrn);
+
    if (IS_I965G(pI830))
       gen4_render_state_init(pScrn);
 
@@ -3478,6 +3543,9 @@ I830CloseScreen(int scrnIndex, ScreenPtr pScreen)
       I830LeaveVT(scrnIndex, 0);
    }
 
+   dri_bufmgr_destroy(pI830->bufmgr);
+   pI830->bufmgr = NULL;
+
    if (pI830->devicesTimer)
       TimerCancel(pI830->devicesTimer);
    pI830->devicesTimer = NULL;
diff --git a/src/i830_memory.c b/src/i830_memory.c
index dc48967..57e4f2e 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -350,6 +350,7 @@ i830_reset_allocations(ScrnInfoPtr pScrn)
     pI830->textures = NULL;
 #endif
     pI830->LpRing->mem = NULL;
+    pI830->fake_bufmgr_mem = NULL;
 }
 
 void
@@ -1374,6 +1375,14 @@ i830_allocate_2d_memory(ScrnInfoPtr pScrn)
 	return FALSE;
     }
 
+    pI830->fake_bufmgr_mem = i830_allocate_memory(pScrn, "fake bufmgr",
+						  MB(1), GTT_PAGE_SIZE, 0);
+    if (pI830->fake_bufmgr_mem == NULL) {
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		   "Failed to allocate fake bufmgr space.\n");
+	return FALSE;
+    }
+
     /* even in XAA, 965G needs state mem buffer for rendering */
     if (IS_I965G(pI830) && !pI830->noAccel &&
 	pI830->gen4_render_state_mem == NULL)
diff --git a/src/i830_ring.h b/src/i830_ring.h
index c2078fb..c296d41 100644
--- a/src/i830_ring.h
+++ b/src/i830_ring.h
@@ -42,11 +42,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     pI830->ring_next &= pI830->LpRing->tail_mask;			\
 } while (0)
 
-union intfloat {
-	float f;
-	unsigned int ui;
-};
-
 #define OUT_RING_F(x) do {			\
 	union intfloat tmp;			\
 	tmp.f = (float)(x);			\
diff --git a/src/i915_3d.h b/src/i915_3d.h
index 1a0bd45..d3330e5 100644
--- a/src/i915_3d.h
+++ b/src/i915_3d.h
@@ -446,12 +446,12 @@ do {									\
 #define FS_END()							\
 do {									\
     int _i, _pad = (_cur_shader_commands & 0x1) ? 0 : 1;		\
-    BEGIN_LP_RING(_cur_shader_commands * 3 + 1 + _pad);			\
-    OUT_RING(_3DSTATE_PIXEL_SHADER_PROGRAM |				\
+    BEGIN_BATCH(_cur_shader_commands * 3 + 1 + _pad);			\
+    OUT_BATCH(_3DSTATE_PIXEL_SHADER_PROGRAM |				\
 	     (_cur_shader_commands * 3 - 1));				\
     for (_i = 0; _i < _cur_shader_commands * 3; _i++)			\
-	OUT_RING(_shader_buf[_i]);					\
+	OUT_BATCH(_shader_buf[_i]);					\
     if (_pad != 0)							\
-	OUT_RING(MI_NOOP);						\
-    ADVANCE_LP_RING();							\
+	OUT_BATCH(MI_NOOP);						\
+    ADVANCE_BATCH();							\
 } while (0);
commit d0fda9d24c5fe4870cdbd2ba0213091165666a8e
Merge: cc98d41... 79f94ee...
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Jun 10 11:32:49 2008 -0700

    Merge branch 'master' into drm-gem

commit cc98d41df63f1ee2561440fab3aa471a80a12920
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Jun 9 12:00:14 2008 -0700

    Add a little program to dump out the first 64 dwords of the status page.

diff --git a/src/i810_reg.h b/src/i810_reg.h
index 279677c..d8e0cb2 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -491,6 +491,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  *   - new bits for i810
  *   - new register hwstam (mask)
  */
+#define HWS_PGA		     0x2080
 #define PWRCTXA		     0x2088 /* 965GM+ only */
 #define   PWRCTX_EN	     (1<<0)
 #define HWSTAM               0x2098 /* p290 */
diff --git a/src/reg_dumper/Makefile.am b/src/reg_dumper/Makefile.am
index b840b24..1c8db20 100644
--- a/src/reg_dumper/Makefile.am
+++ b/src/reg_dumper/Makefile.am
@@ -1,4 +1,4 @@
-noinst_PROGRAMS = intel_reg_dumper intel_idle intel_stepping
+noinst_PROGRAMS = intel_reg_dumper intel_idle intel_stepping intel_statuspage
 
 intel_reg_dumper_SOURCES = \
 	main.c \
@@ -15,9 +15,15 @@ intel_idle_SOURCES = \
 intel_stepping_SOURCES = \
 	stepping.c
 
+intel_statuspage_SOURCES = \
+	statuspage.c \
+	reg_dumper.h \
+	util.c
+
 intel_reg_dumper_LDADD = $(PCIACCESS_LIBS)
 intel_idle_LDADD = $(PCIACCESS_LIBS)
 intel_stepping_LDADD = $(PCIACCESS_LIBS)
+intel_statuspage_LDADD = $(PCIACCESS_LIBS)
 
 AM_CFLAGS = $(PCIACCESS_CFLAGS) $(WARN_CFLAGS) \
 	-I$(srcdir)/.. -DREG_DUMPER
diff --git a/src/reg_dumper/reg_dumper.h b/src/reg_dumper/reg_dumper.h
index 9a723b9..241b241 100644
--- a/src/reg_dumper/reg_dumper.h
+++ b/src/reg_dumper/reg_dumper.h
@@ -88,3 +88,4 @@ typedef struct _scrn {
 char *XNFprintf(const char *format, ...);
 void xf86DrvMsg(int scrnIndex, int severity, const char *format, ...);
 void i830DumpRegs(ScrnInfoPtr pScrn);
+void intel_i830rec_init(I830Ptr pI830);
diff --git a/src/reg_dumper/statuspage.c b/src/reg_dumper/statuspage.c
new file mode 100644
index 0000000..d6106a5
--- /dev/null
+++ b/src/reg_dumper/statuspage.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright © 2007 Intel Corporation
+ *
+ * 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.
+ *
+ * Authors:
+ *    Eric Anholt <eric at anholt.net>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <pciaccess.h>
+#include <err.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "reg_dumper.h"
+#include "../i810_reg.h"
+
+int main(int argc, char **argv)
+{
+    I830Rec i830;
+    I830Ptr pI830 = &i830;
+    int devmem;
+    uint32_t hws_offset;
+    volatile uint32_t *hws;
+
+    intel_i830rec_init(pI830);
+
+    if (HWS_NEED_GFX(pI830))
+	errx(1, "status page in graphics virtual unsupported.\n");
+
+    hws_offset = INREG(HWS_PGA);
+
+    devmem = open("/dev/mem", O_RDWR, 0);
+    if (devmem == -1)
+	err(1, "Couldn't open /dev/mem");
+
+    hws = mmap(NULL, 4096, PROT_READ, MAP_SHARED, devmem, hws_offset);
+    if (hws == MAP_FAILED)
+	err(1, "Couldn't map /dev/mem at 0x%08x", hws_offset);
+
+    close(devmem);
+
+    for (;;) {
+	int i;
+
+	printf("\n");
+
+	for (i = 0; i < 64; i += 4) {
+	    printf("0x%04x: 0x%08x 0x%08x 0x%08x 0x%08x\n", i * 4,
+		   hws[i], hws[i + 1], hws[i + 2], hws[i + 3]);
+	}
+
+	sleep(1);
+    }
+
+    return 0;
+}
diff --git a/src/reg_dumper/util.c b/src/reg_dumper/util.c
new file mode 100644
index 0000000..6dd1e48
--- /dev/null
+++ b/src/reg_dumper/util.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright © 2008 Intel Corporation
+ *
+ * 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.
+ *
+ * Authors:
+ *    Eric Anholt <eric at anholt.net>
+ *
+ */
+
+/** @file util.c
+ *
+ * Utility functions for the various tools in the reg_dumper directory.
+ */
+
+#include <err.h>
+#include <pciaccess.h>
+
+#include "reg_dumper.h"
+
+/**
+ * Sets up the pI830 for use by common.h-style macros, particularly
+ * INREG/OUTERG.
+ */
+void intel_i830rec_init(I830Ptr pI830)
+{
+    struct pci_device *dev;
+    int err, mmio_bar;
+    void *mmio;
+
+    err = pci_system_init();
+    if (err != 0) {
+	fprintf(stderr, "Couldn't initialize PCI system: %s\n", strerror(err));
+	exit(1);
+    }
+
+    /* Grab the graphics card */
+    dev = pci_device_find_by_slot(0, 0, 2, 0);
+    if (dev == NULL)
+	errx(1, "Couldn't find graphics card");
+
+    err = pci_device_probe(dev);
+    if (err != 0) {
+	fprintf(stderr, "Couldn't probe graphics card: %s\n", strerror(err));
+	exit(1);
+    }
+
+    if (dev->vendor_id != 0x8086)
+	errx(1, "Graphics card is non-intel");
+
+    pI830->PciInfo = &pI830->pci_info_rec;
+    pI830->PciInfo->chipType = dev->device_id;
+
+    pI830->pci_dev = dev;
+
+    mmio_bar = IS_I9XX(pI830) ? 0 : 1;
+
+    err = pci_device_map_range (dev,
+				dev->regions[mmio_bar].base_addr,
+				dev->regions[mmio_bar].size,
+				PCI_DEV_MAP_FLAG_WRITABLE,
+				&mmio);
+
+    if (err != 0) {
+	fprintf(stderr, "Couldn't map MMIO region: %s\n", strerror(err));
+	exit(1);
+    }
+    pI830->mmio = mmio;
+}
commit 432d07fb175b385715eb3ccf97a303d2ad7bfe11
Merge: 3a967b8... bff180e...
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Jun 5 14:57:18 2008 -0700

    Merge branch 'master' into drm-gem

commit 3a967b8359bd6c05a10111076cdb02df15cbf2e8
Author: Eric Anholt <eric at anholt.net>
Date:   Mon May 12 13:51:11 2008 -0700

    [gem] Note if pinning a buffer fails.

diff --git a/src/i830_memory.c b/src/i830_memory.c
index 16ae23d..2596e45 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -174,8 +174,12 @@ i830_bind_memory(ScrnInfoPtr pScrn, i830_memory *mem)
 	pin.alignment = mem->alignment;
 
 	ret = ioctl(pI830->drmSubFD, DRM_IOCTL_I915_GEM_PIN, &pin);
-	if (ret != 0)
+	if (ret != 0) {
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			   "Failed to pin %s: %s\n",
+			   mem->name, strerror(errno));
 	    return FALSE;
+	}
 
 	mem->bound = TRUE;
 	mem->offset = pin.offset;
commit ced4b4bb0c44b55feb5e32ddb860f1c1dc3bbde5
Author: Eric Anholt <eric at anholt.net>
Date:   Thu May 22 22:10:25 2008 -0700

    [gem] Reduce console spam from debugging.

diff --git a/src/i830_memory.c b/src/i830_memory.c
index e8ffce3..16ae23d 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -172,9 +172,7 @@ i830_bind_memory(ScrnInfoPtr pScrn, i830_memory *mem)
 
 	pin.handle = mem->gem_handle;
 	pin.alignment = mem->alignment;
-	xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
-		    "alignment %d size %d\n", mem->alignment, (int) mem->size);
-	
+
 	ret = ioctl(pI830->drmSubFD, DRM_IOCTL_I915_GEM_PIN, &pin);
 	if (ret != 0)
 	    return FALSE;
commit c81050c0058e32098259b5078515807038beb7d6
Merge: 9c9a5d0... e9532f3...
Author: Keith Packard <keithp at keithp.com>
Date:   Sat May 17 23:26:14 2008 -0700

    Merge commit 'origin/master' into drm-gem

commit 9c9a5d0e48c6e911574695fc417d2dc1a0fd1c20
Author: Keith Packard <keithp at keithp.com>
Date:   Tue May 13 12:24:50 2008 -0700

    Add check for GEM, use that to enable driver GEM support

diff --git a/configure.ac b/configure.ac
index 00f075e..f814ade 100644
--- a/configure.ac
+++ b/configure.ac
@@ -218,6 +218,13 @@ if test "$DRI" = yes; then
 #include <inttypes.h>
 #include <i915_drm.h>
 ])
+	AC_CHECK_DECL(DRM_IOCTL_GEM_CREATE,
+		      [AC_DEFINE(HAVE_DRM_GEM, 1,
+			         [Have DRM Graphics Execution Manager])],
+		      [], [
+#include <inttypes.h>
+#include <drm.h>
+])
 	CFLAGS="$save_CFLAGS"
 fi
 
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 10d65ed..95e1e72 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -1512,7 +1512,7 @@ I830DRIClipNotify(ScreenPtr pScreen, WindowPtr *ppWin, int num)
 static int
 i830_name_buffer (ScrnInfoPtr pScrn, i830_memory *mem)
 {
-#ifdef XF86DRI_MM
+#if HAVE_DRM_GEM
     if (mem && mem->gem_handle)
     {
 	I830Ptr			pI830 = I830PTR(pScrn);
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 0b172cf..e8ffce3 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -164,7 +164,7 @@ i830_bind_memory(ScrnInfoPtr pScrn, i830_memory *mem)
     if (mem == NULL || mem->bound)
 	return TRUE;
 
-#ifdef XF86DRI_MM
+#if HAVE_DRM_GEM
     if (mem->gem_handle != 0) {
 	I830Ptr pI830 = I830PTR(pScrn);
 	struct drm_i915_gem_pin pin;
@@ -215,7 +215,7 @@ i830_unbind_memory(ScrnInfoPtr pScrn, i830_memory *mem)
     if (mem->tiling != TILE_NONE)
 	i830_clear_tiling(pScrn, mem->fence_nr);
 
-#ifdef XF86DRI_MM
+#if HAVE_DRM_GEM
     if (mem->gem_handle != 0) {
 	I830Ptr pI830 = I830PTR(pScrn);
 	struct drm_i915_gem_unpin unpin;
@@ -253,7 +253,7 @@ i830_free_memory(ScrnInfoPtr pScrn, i830_memory *mem)
     /* Free any AGP memory. */
     i830_unbind_memory(pScrn, mem);
 
-#ifdef XF86DRI_MM
+#if HAVE_DRM_GEM
     if (mem->gem_handle != 0) {
 	I830Ptr pI830 = I830PTR(pScrn);
 	struct drm_gem_close close;
@@ -379,7 +379,7 @@ i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset, unsigned long size)
 {
     I830Ptr pI830 = I830PTR(pScrn);
     i830_memory *start, *end;
-#ifdef XF86DRI_MM
+#if HAVE_DRM_GEM
     int dri_major, dri_minor, dri_patch;
 #endif
 
@@ -418,7 +418,7 @@ i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset, unsigned long size)
 
     pI830->memory_list = start;
 
-#ifdef XF86DRI_MM
+#if HAVE_DRM_GEM
     DRIQueryVersion(&dri_major, &dri_minor, &dri_patch);
 
     /* Now that we have our manager set up, initialize the kernel MM if
@@ -721,7 +721,7 @@ i830_allocate_agp_memory(ScrnInfoPtr pScrn, i830_memory *mem, int flags)
     return TRUE;
 }
 
-#ifdef XF86DRI_MM
+#if HAVE_DRM_GEM
 static i830_memory *
 i830_allocate_memory_bo(ScrnInfoPtr pScrn, const char *name,
 			unsigned long size, unsigned long align, int flags)
@@ -815,7 +815,7 @@ i830_allocate_memory(ScrnInfoPtr pScrn, const char *name,
 {
     i830_memory *mem;
 
-#ifdef XF86DRI_MM
+#if HAVE_DRM_GEM
     I830Ptr pI830 = I830PTR(pScrn);
 
     if (pI830->memory_manager && !(flags & NEED_PHYSICAL_ADDR) &&
commit 089011daf3da8db3bd16d50e1d6a6457da82300e
Author: Keith Packard <keithp at keithp.com>
Date:   Mon May 12 12:18:19 2008 -0700

    Track name changes in GEM ioctls.
    
    allocate → create
    unreference → close
    name → flink

diff --git a/src/i830_dri.c b/src/i830_dri.c
index 1cd1732..10d65ed 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -1516,20 +1516,20 @@ i830_name_buffer (ScrnInfoPtr pScrn, i830_memory *mem)
     if (mem && mem->gem_handle)
     {
 	I830Ptr			pI830 = I830PTR(pScrn);
-	struct drm_gem_name	name;
+	struct drm_gem_flink	flink;
 	int			ret;
 	
 	if (!mem->gem_name)
 	{
-	    name.handle = mem->gem_handle;
-	    ret = ioctl(pI830->drmSubFD, DRM_IOCTL_GEM_NAME, &name);
+	    flink.handle = mem->gem_handle;
+	    ret = ioctl(pI830->drmSubFD, DRM_IOCTL_GEM_FLINK, &flink);
 	    if (ret != 0)
 	    {
 		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 			   "[drm] failed to name buffer %d\n", -errno);
 		return -1;
 	    }
-	    mem->gem_name = name.name;
+	    mem->gem_name = flink.name;
 	}
 	return mem->gem_name;
     }
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 6f3c06b..0b172cf 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -173,7 +173,7 @@ i830_bind_memory(ScrnInfoPtr pScrn, i830_memory *mem)
 	pin.handle = mem->gem_handle;
 	pin.alignment = mem->alignment;
 	xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
-		    "alignment %d size %d\n", mem->alignment, mem->size);
+		    "alignment %d size %d\n", mem->alignment, (int) mem->size);
 	
 	ret = ioctl(pI830->drmSubFD, DRM_IOCTL_I915_GEM_PIN, &pin);
 	if (ret != 0)
@@ -256,10 +256,10 @@ i830_free_memory(ScrnInfoPtr pScrn, i830_memory *mem)
 #ifdef XF86DRI_MM
     if (mem->gem_handle != 0) {
 	I830Ptr pI830 = I830PTR(pScrn);
-	struct drm_gem_unreference unref;
+	struct drm_gem_close close;
 
-	unref.handle = mem->gem_handle;
-	ioctl(pI830->drmSubFD, DRM_IOCTL_GEM_UNREFERENCE, &unref);
+	close.handle = mem->gem_handle;
+	ioctl(pI830->drmSubFD, DRM_IOCTL_GEM_CLOSE, &close);
 	if (pI830->bo_list == mem) {
 	    pI830->bo_list = mem->next;
 	    if (mem->next)
@@ -729,7 +729,7 @@ i830_allocate_memory_bo(ScrnInfoPtr pScrn, const char *name,
     I830Ptr pI830 = I830PTR(pScrn);
     i830_memory *mem;
     int ret;
-    struct drm_gem_alloc alloc;
+    struct drm_gem_create create;
 
     assert((flags & NEED_PHYSICAL_ADDR) == 0);
 
@@ -747,16 +747,16 @@ i830_allocate_memory_bo(ScrnInfoPtr pScrn, const char *name,
 	return NULL;
     }
 
-    memset(&alloc, 0, sizeof(alloc));
-    alloc.size = size;
+    memset(&create, 0, sizeof(create));
+    create.size = size;
 
-    ret = ioctl(pI830->drmSubFD, DRM_IOCTL_GEM_ALLOC, &alloc);
+    ret = ioctl(pI830->drmSubFD, DRM_IOCTL_GEM_CREATE, &create);
     if (ret) {
 	xfree(mem->name);
 	xfree(mem);
 	return NULL;
     }
-    mem->gem_handle = alloc.handle;
+    mem->gem_handle = create.handle;
 
     /* Give buffer obviously wrong offset/end until it's pinned. */
     mem->offset = -1;
@@ -770,10 +770,10 @@ i830_allocate_memory_bo(ScrnInfoPtr pScrn, const char *name,
     /* Bind it if we currently control the VT */
     if (pScrn->vtSema) {
 	if (!i830_bind_memory(pScrn, mem)) {
-	    struct drm_gem_unreference unref;
+	    struct drm_gem_close close;
 
-	    unref.handle = mem->gem_handle;
-	    ioctl(pI830->drmSubFD, DRM_IOCTL_GEM_UNREFERENCE, &unref);
+	    close.handle = mem->gem_handle;
+	    ioctl(pI830->drmSubFD, DRM_IOCTL_GEM_CLOSE, &close);
 	    xfree(mem->name);
 	    xfree(mem);
 	    return NULL;
commit 10f1d835b8ac7bf3153ac39d295ad2a72c4aa076
Author: Keith Packard <keithp at keithp.com>
Date:   Mon May 12 12:15:09 2008 -0700

    Record alignment requirements in mem structure for use by GEM.
    
    GEM needs memory alignment requirements sent at pin time, which is a bit
    after the allocation itself. Store the required alignment in the memory
    object for later use by pin.

diff --git a/src/i830.h b/src/i830.h
index 6cce043..f694d60 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -196,6 +196,8 @@ struct _i830_memory {
 
 #ifdef XF86DRI_MM
     uint32_t gem_handle;
+    uint32_t alignment;
+    uint32_t gem_name;
     Bool lifetime_fixed_offset;
 #endif
 };
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 239ed6b..1cd1732 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -1519,12 +1519,19 @@ i830_name_buffer (ScrnInfoPtr pScrn, i830_memory *mem)
 	struct drm_gem_name	name;
 	int			ret;
 	
-	name.handle = mem->gem_handle;
-	ret = ioctl(pI830->drmSubFD, DRM_IOCTL_GEM_NAME, &name);
-	if (ret == 0)
-	    return name.name;
-	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		   "[drm] failed to name buffer %d\n", -errno);
+	if (!mem->gem_name)
+	{
+	    name.handle = mem->gem_handle;
+	    ret = ioctl(pI830->drmSubFD, DRM_IOCTL_GEM_NAME, &name);
+	    if (ret != 0)
+	    {
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			   "[drm] failed to name buffer %d\n", -errno);
+		return -1;
+	    }
+	    mem->gem_name = name.name;
+	}
+	return mem->gem_name;
     }
 #endif
     return -1;
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 550b4d8..6f3c06b 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -171,19 +171,10 @@ i830_bind_memory(ScrnInfoPtr pScrn, i830_memory *mem)
 	int ret;
 
 	pin.handle = mem->gem_handle;
-	pin.alignment = 0;
-	if (mem->tiling) {
-	    if (IS_I965G(pI830))
-		pin.alignment = 0;
-	    else {
-		if (IS_I9XX (pI830))
-		    pin.alignment = 1024 * 1024;
-		else
-		    pin.alignment = 512 * 1024;
-		if (pin.alignment < mem->size)
-		    pin.alignment = mem->size;
-	    }
-	}
+	pin.alignment = mem->alignment;
+	xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
+		    "alignment %d size %d\n", mem->alignment, mem->size);
+	
 	ret = ioctl(pI830->drmSubFD, DRM_IOCTL_I915_GEM_PIN, &pin);
 	if (ret != 0)
 	    return FALSE;
@@ -638,6 +629,7 @@ i830_allocate_aperture(ScrnInfoPtr pScrn, const char *name,
     size = ALIGN(size, GTT_PAGE_SIZE);
     mem->size = size;
     mem->allocated_size = size;
+    mem->alignment = alignment;
 
     if (alignment < GTT_PAGE_SIZE)
 	alignment = GTT_PAGE_SIZE;
@@ -771,6 +763,7 @@ i830_allocate_memory_bo(ScrnInfoPtr pScrn, const char *name,
     mem->end = -1;
     mem->size = size;
     mem->allocated_size = size;
+    mem->alignment = align;
     if (flags & NEED_LIFETIME_FIXED)
 	mem->lifetime_fixed_offset = TRUE;
 
commit 417f86d80525d2f5038628afba8f70f8c0fecca3
Author: Keith Packard <keithp at keithp.com>
Date:   Mon May 5 13:36:19 2008 -0700

    Move a declaration under #ifndef HAVE_FREE_SHADOW

diff --git a/src/i830_driver.c b/src/i830_driver.c
index aca01db..6e5e92c 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -3135,8 +3135,8 @@ I830LeaveVT(int scrnIndex, int flags)
 {
    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
    I830Ptr pI830 = I830PTR(pScrn);
-   xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
 #ifndef HAVE_FREE_SHADOW
+   xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
    int o;
 #endif
 
commit 587dc5bfc4ef32942bd7511f932a3a2e2fcdccb0
Author: Keith Packard <keithp at keithp.com>
Date:   Mon May 5 13:35:22 2008 -0700

    Fix up ring dumping code for non-i965

diff --git a/src/i810_reg.h b/src/i810_reg.h
index 834b948..837865d 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -375,7 +375,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 /* Current active ring head address: 
  */
-#define ACTHD                 0x2074
+#define ACTHD_I965                 0x2074
+#define ACTHD			   0x20C8
 
 /* Current primary/secondary DMA fetch addresses:
  */
diff --git a/src/i830_debug.c b/src/i830_debug.c
index 074e8b9..e90ea22 100644
--- a/src/i830_debug.c
+++ b/src/i830_debug.c
@@ -1442,13 +1442,12 @@ i830_dump_cmds (ScrnInfoPtr		pScrn,
 	    /* check for MI_BATCH_BUFFER_START */
 	    if ((data & batch_start_mask) == batch_start_cmd)
 	    {
-		uint32_t    batch = ptr[1];
+		uint32_t    batch = ptr[1] & ~3;
 		if (batch < pI830->FbMapSize) {
 		    ErrorF ("\t%08x: %08x\n", (ring + 4) & mask, batch);
 		    ErrorF ("Batch buffer at 0x%08x {\n", batch);
 		    i830_dump_cmds (pScrn, pI830->FbBase, batch,
-				    pI830->FbMapSize - batch,
-				    0xffffffff, acthd);
+				    batch + 256, 0xffffffff, acthd);
 		    ErrorF ("}\n");
 		    ring = (ring + (count - 1) * 4) & mask;
 		}
@@ -1472,8 +1471,8 @@ i830_dump_ring(ScrnInfoPtr pScrn, uint32_t acthd)
     mask = pI830->LpRing->tail_mask;
     
     virt = pI830->LpRing->virtual_start;
-    ErrorF ("Ring at virtual %p head 0x%x tail 0x%x count %d\n",
-	    virt, head, tail, (((tail + mask + 1) - head) & mask) >> 2);
+    ErrorF ("Ring at virtual %p head 0x%x tail 0x%x count %d acthd 0x%x\n",
+	    virt, head, tail, (((tail + mask + 1) - head) & mask) >> 2, acthd);
 
     /* walk back by instructions */
     for (cmd = (head - 256) & mask;
@@ -1518,7 +1517,7 @@ i830_dump_error_state(ScrnInfoPtr pScrn)
 
     ErrorF("hwstam: 0x%04x ier: 0x%04x imr: 0x%04x iir: 0x%04x\n",
 	   INREG16(HWSTAM), INREG16(IER), INREG16(IMR), INREG16(IIR));
-    i830_dump_ring (pScrn, 0);
+    i830_dump_ring (pScrn, INREG(ACTHD));
 }
 
 void
@@ -1555,7 +1554,7 @@ i965_dump_error_state(ScrnInfoPtr pScrn)
 	   "imr: 0x%08x iir: 0x%08x\n",
 	   INREG(HWSTAM), INREG(IER), INREG(IMR), INREG(IIR));
 
-    acthd = INREG(ACTHD);
+    acthd = INREG(ACTHD_I965);
     ErrorF("acthd: 0x%08x dma_fadd_p: 0x%08x\n",
 	   acthd, INREG(DMA_FADD_P));
     ErrorF("ecoskpd: 0x%08x excc: 0x%08x\n",
commit 65877d32bb2cd71ccc8d6a66244f029fc3577f69
Merge: b9d12da... fff17b9...
Author: Keith Packard <keithp at keithp.com>
Date:   Mon May 5 12:05:00 2008 -0700

    Merge branch 'master' into drm-gem

commit b9d12da91eb1afb05bd78a40e15f4333e697093d
Author: Keith Packard <keithp at keithp.com>
Date:   Mon May 5 10:44:09 2008 -0700

    Use GEM for buffer naming now.

diff --git a/src/i830_dri.c b/src/i830_dri.c
index 1c5de8f..239ed6b 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -65,6 +65,9 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include <stdio.h>
 #include <string.h>
 #include <assert.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <errno.h>
 
 #include "xf86.h"
 #include "xf86_OSproc.h"
@@ -1506,6 +1509,27 @@ I830DRIClipNotify(ScreenPtr pScreen, WindowPtr *ppWin, int num)
 }
 #endif /* DRI_SUPPORTS_CLIP_NOTIFY */
 
+static int
+i830_name_buffer (ScrnInfoPtr pScrn, i830_memory *mem)
+{
+#ifdef XF86DRI_MM
+    if (mem && mem->gem_handle)
+    {
+	I830Ptr			pI830 = I830PTR(pScrn);
+	struct drm_gem_name	name;
+	int			ret;
+	
+	name.handle = mem->gem_handle;
+	ret = ioctl(pI830->drmSubFD, DRM_IOCTL_GEM_NAME, &name);
+	if (ret == 0)
+	    return name.name;
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "[drm] failed to name buffer %d\n", -errno);
+    }
+#endif
+    return -1;
+}
+
 /**
  * Update the SAREA fields with current buffer information.
  *
@@ -1537,22 +1561,10 @@ i830_update_sarea(ScrnInfoPtr pScrn, drmI830Sarea *sarea)
 
    sarea->log_tex_granularity = pI830->TexGranularity;
 
-   sarea->front_bo_handle = -1;
-   sarea->back_bo_handle = -1;
-   sarea->third_bo_handle = -1;
-   sarea->depth_bo_handle = -1;
-#ifdef XF86DRI_MM
-   /* XXX
-   if (pI830->front_buffer->bo.size)
-       sarea->front_bo_handle = pI830->front_buffer->bo.handle;
-   if (pI830->back_buffer->bo.size)
-       sarea->back_bo_handle = pI830->back_buffer->bo.handle;
-   if (pI830->third_buffer != NULL && pI830->third_buffer->bo.size)
-       sarea->third_bo_handle = pI830->third_buffer->bo.handle;
-   if (pI830->depth_buffer->bo.size)
-       sarea->depth_bo_handle = pI830->depth_buffer->bo.handle;
-   */
-#endif
+   sarea->front_bo_handle = i830_name_buffer (pScrn, pI830->front_buffer);
+   sarea->back_bo_handle = i830_name_buffer (pScrn, pI830->back_buffer);
+   sarea->third_bo_handle = i830_name_buffer (pScrn, pI830->third_buffer);
+   sarea->depth_bo_handle = i830_name_buffer (pScrn, pI830->depth_buffer);
 
    /* The rotation is now handled entirely by the X Server, so just leave the
     * DRI unaware.
commit 0741020f3725c32c48ad15535b9c0549e4092c23
Author: Keith Packard <keithp at keithp.com>
Date:   Mon May 5 10:17:01 2008 -0700

    Set pin alignment for gem on non-965
    
    non-965 tiled frame buffers have fairly strict alignment requirements, 512K
    on 8xx and 1MB on 9xx, plus they must be aligned to the size of the
    allocation.

diff --git a/src/i830_memory.c b/src/i830_memory.c
index cee46a8..550b4d8 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -171,6 +171,19 @@ i830_bind_memory(ScrnInfoPtr pScrn, i830_memory *mem)
 	int ret;
 
 	pin.handle = mem->gem_handle;
+	pin.alignment = 0;
+	if (mem->tiling) {
+	    if (IS_I965G(pI830))
+		pin.alignment = 0;
+	    else {
+		if (IS_I9XX (pI830))
+		    pin.alignment = 1024 * 1024;
+		else
+		    pin.alignment = 512 * 1024;
+		if (pin.alignment < mem->size)
+		    pin.alignment = mem->size;
+	    }
+	}
 	ret = ioctl(pI830->drmSubFD, DRM_IOCTL_I915_GEM_PIN, &pin);
 	if (ret != 0)
 	    return FALSE;
commit 271abfd0ec29851273d8ca5241d963be5c64e43c
Author: Eric Anholt <eric at anholt.net>
Date:   Fri May 2 10:06:13 2008 -0700

    Add initial GEM hacks to bring the server up.

diff --git a/src/i830.h b/src/i830.h
index 4e82036..8bc0af4 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -195,7 +195,7 @@ struct _i830_memory {
     /** @} */
 
 #ifdef XF86DRI_MM
-    drmBO bo;
+    uint32_t gem_handle;
     Bool lifetime_fixed_offset;
 #endif
 };
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 4361ad0..1c5de8f 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -1542,6 +1542,7 @@ i830_update_sarea(ScrnInfoPtr pScrn, drmI830Sarea *sarea)
    sarea->third_bo_handle = -1;
    sarea->depth_bo_handle = -1;
 #ifdef XF86DRI_MM
+   /* XXX
    if (pI830->front_buffer->bo.size)
        sarea->front_bo_handle = pI830->front_buffer->bo.handle;
    if (pI830->back_buffer->bo.size)
@@ -1550,6 +1551,7 @@ i830_update_sarea(ScrnInfoPtr pScrn, drmI830Sarea *sarea)
        sarea->third_bo_handle = pI830->third_buffer->bo.handle;
    if (pI830->depth_buffer->bo.size)
        sarea->depth_bo_handle = pI830->depth_buffer->bo.handle;
+   */
 #endif
 
    /* The rotation is now handled entirely by the X Server, so just leave the
diff --git a/src/i830_driver.c b/src/i830_driver.c
index ea37e6d..63fc8cb 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -3184,9 +3184,10 @@ I830LeaveVT(int scrnIndex, int flags)
     */
 #ifdef XF86DRI_MM
    if (pI830->directRenderingOpen) {
+      /* XXX:
       if (pI830->memory_manager != NULL && pScrn->vtSema) {
 	 drmMMLock(pI830->drmSubFD, DRM_BO_MEM_TT, 1, 0);
-      }
+      }*/
    }
 #endif /* XF86DRI_MM */
 
@@ -3224,9 +3225,11 @@ I830EnterVT(int scrnIndex, int flags)
       /* Unlock the memory manager first of all so that we can pin our
        * buffer objects
        */
+      /*
       if (pI830->memory_manager != NULL && pScrn->vtSema) {
 	 drmMMUnlock(pI830->drmSubFD, DRM_BO_MEM_TT, 1);
       }
+      */
    }
 #endif /* XF86DRI_MM */
 
@@ -3353,14 +3356,6 @@ I830CloseScreen(int scrnIndex, ScreenPtr pScreen)
 
    if (pScrn->vtSema == TRUE) {
       I830LeaveVT(scrnIndex, 0);
-#ifdef XF86DRI_MM
-      if (pI830->directRenderingEnabled) {
- 	 if (pI830->memory_manager != NULL) {
-	    drmMMUnlock(pI830->drmSubFD, DRM_BO_MEM_TT, 1);
-	 }
-      }
-#endif /* XF86DRI_MM */
-
    }
 
    if (pI830->devicesTimer)
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 84db0ef..cee46a8 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -101,12 +101,16 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include <string.h>
 #include <errno.h>
 #include <sys/types.h>
+#include <sys/ioctl.h>
 
 #include "xf86.h"
 #include "xf86_OSproc.h"
 
 #include "i830.h"
 #include "i810_reg.h"
+#ifdef XF86DRI_MM
+#include "i915_drm.h"
+#endif
 
 #define ALIGN(i,m)    (((i) + (m) - 1) & ~((m) - 1))
 
@@ -161,27 +165,19 @@ i830_bind_memory(ScrnInfoPtr pScrn, i830_memory *mem)
 	return TRUE;
 
 #ifdef XF86DRI_MM
-    if (mem->bo.size != 0) {
+    if (mem->gem_handle != 0) {
 	I830Ptr pI830 = I830PTR(pScrn);
+	struct drm_i915_gem_pin pin;
 	int ret;
 
-	ret = drmBOSetStatus(pI830->drmSubFD, &mem->bo,
-			     DRM_BO_FLAG_MEM_VRAM |
-			     DRM_BO_FLAG_MEM_TT |
-			     DRM_BO_FLAG_READ |
-			     DRM_BO_FLAG_WRITE |
-			     DRM_BO_FLAG_NO_EVICT,
-			     DRM_BO_MASK_MEM |
-			     DRM_BO_FLAG_READ |
-			     DRM_BO_FLAG_WRITE |
-			     DRM_BO_FLAG_NO_EVICT,
-			     0, 0, 0);
+	pin.handle = mem->gem_handle;
+	ret = ioctl(pI830->drmSubFD, DRM_IOCTL_I915_GEM_PIN, &pin);
 	if (ret != 0)
 	    return FALSE;
 
 	mem->bound = TRUE;
-	mem->offset = mem->bo.offset;
-	mem->end = mem->bo.offset + mem->size;
+	mem->offset = pin.offset;
+	mem->end = mem->offset + mem->size;
     }
 #endif
 
@@ -216,13 +212,13 @@ i830_unbind_memory(ScrnInfoPtr pScrn, i830_memory *mem)
 	i830_clear_tiling(pScrn, mem->fence_nr);
 
 #ifdef XF86DRI_MM
-    if (mem->bo.size != 0) {
+    if (mem->gem_handle != 0) {
 	I830Ptr pI830 = I830PTR(pScrn);
+	struct drm_i915_gem_unpin unpin;
 	int ret;
 
-	ret = drmBOSetStatus(pI830->drmSubFD, &mem->bo,
-			     0, DRM_BO_FLAG_NO_EVICT,
-			     0, 0, 0);
+	unpin.handle = mem->gem_handle;
+	ret = ioctl(pI830->drmSubFD, DRM_IOCTL_I915_GEM_UNPIN, &unpin);
 
 	if (ret == 0) {
 	    mem->bound = FALSE;
@@ -254,10 +250,12 @@ i830_free_memory(ScrnInfoPtr pScrn, i830_memory *mem)
     i830_unbind_memory(pScrn, mem);
 
 #ifdef XF86DRI_MM
-    if (mem->bo.size != 0) {
+    if (mem->gem_handle != 0) {
 	I830Ptr pI830 = I830PTR(pScrn);
+	struct drm_gem_unreference unref;
 
-	drmBOUnreference(pI830->drmSubFD, &mem->bo);
+	unref.handle = mem->gem_handle;
+	ioctl(pI830->drmSubFD, DRM_IOCTL_GEM_UNREFERENCE, &unref);
 	if (pI830->bo_list == mem) {
 	    pI830->bo_list = mem->next;
 	    if (mem->next)
@@ -467,13 +465,15 @@ i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset, unsigned long size)
 				   ALIGN_BOTH_ENDS | NEED_NON_STOLEN);
 
 	if (pI830->memory_manager != NULL) {
+	    struct drm_i915_gem_init init;
 	    int ret;
 
+	    init.gtt_start = pI830->memory_manager->offset;
+	    init.gtt_end = pI830->memory_manager->offset +
+		pI830->memory_manager->size;
+
 	    /* Tell the kernel to manage it */
-	    ret = drmMMInit(pI830->drmSubFD,
-			    pI830->memory_manager->offset / GTT_PAGE_SIZE,
-			    pI830->memory_manager->size / GTT_PAGE_SIZE,
-			    DRM_BO_MEM_TT);
+	    ret = ioctl(pI830->drmSubFD, DRM_IOCTL_I915_GEM_INIT, &init);
 	    if (ret != 0) {
 		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 			   "Failed to initialize kernel memory manager\n");
@@ -503,7 +503,7 @@ i830_allocator_fini(ScrnInfoPtr pScrn)
 #ifdef XF86DRI_MM
     /* The memory manager is more special */
     if (pI830->memory_manager) {
-	 drmMMTakedown(pI830->drmSubFD, DRM_BO_MEM_TT);
+	 /* XXX drmMMTakedown(pI830->drmSubFD, DRM_BO_MEM_TT);*/
 	 i830_free_memory(pScrn, pI830->memory_manager);
 	 pI830->memory_manager = NULL;
     }
@@ -723,8 +723,8 @@ i830_allocate_memory_bo(ScrnInfoPtr pScrn, const char *name,
 {
     I830Ptr pI830 = I830PTR(pScrn);
     i830_memory *mem;
-    unsigned long mask;
     int ret;
+    struct drm_gem_alloc alloc;
 
     assert((flags & NEED_PHYSICAL_ADDR) == 0);
 
@@ -742,25 +742,17 @@ i830_allocate_memory_bo(ScrnInfoPtr pScrn, const char *name,
 	return NULL;
     }
 
-    /*
-     * Create buffers in local memory to avoid having the creation order
-     * determine the TT offset. Driver acceleration
-     * cannot handle changed front buffer TT offsets yet ,
-     * so let's keep our fingers crossed.
-     */
-
-    mask = DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | DRM_BO_FLAG_MAPPABLE |
-	DRM_BO_FLAG_MEM_LOCAL;
-    if (flags & ALLOW_SHARING)
-	mask |= DRM_BO_FLAG_SHAREABLE;
+    memset(&alloc, 0, sizeof(alloc));
+    alloc.size = size;
 
-    ret = drmBOCreate(pI830->drmSubFD, size, align / GTT_PAGE_SIZE, NULL,
-		      mask, 0, &mem->bo);
+    ret = ioctl(pI830->drmSubFD, DRM_IOCTL_GEM_ALLOC, &alloc);
     if (ret) {
 	xfree(mem->name);
 	xfree(mem);
 	return NULL;
     }
+    mem->gem_handle = alloc.handle;
+
     /* Give buffer obviously wrong offset/end until it's pinned. */
     mem->offset = -1;
     mem->end = -1;
@@ -772,7 +764,10 @@ i830_allocate_memory_bo(ScrnInfoPtr pScrn, const char *name,
     /* Bind it if we currently control the VT */
     if (pScrn->vtSema) {
 	if (!i830_bind_memory(pScrn, mem)) {
-	    drmBOUnreference(pI830->drmSubFD, &mem->bo);
+	    struct drm_gem_unreference unref;
+
+	    unref.handle = mem->gem_handle;
+	    ioctl(pI830->drmSubFD, DRM_IOCTL_GEM_UNREFERENCE, &unref);
 	    xfree(mem->name);
 	    xfree(mem);
 	    return NULL;


More information about the xorg-commit mailing list